BLOG | NGINX

Activation de la gestion DNS et des certificats en libre-service dans Kubernetes

NGINX-Partie-de-F5-horiz-black-type-RGB
Vignette de Jason Schmidt
Jason Schmidt
Publié le 1er novembre 2022

L’objectif ultime du développement d’applications est, bien sûr, d’exposer des applications sur Internet. Pour un développeur, Kubernetes simplifie ce processus dans une certaine mesure en fournissant le contrôleur Ingress comme mécanisme de routage des requêtes vers l'application. Mais tout n’est pas aussi libre-service que vous le souhaiteriez probablement : vous avez toujours besoin d’un enregistrement dans le système de noms de domaine (DNS) pour mapper le nom de domaine de l’application à l’adresse IP du contrôleur d’entrée et d’un certificat TLS pour sécuriser les connexions à l’aide de HTTPS. Dans la plupart des organisations, vous ne possédez pas vous-même le DNS ou le TLS et devez donc vous coordonner avec le ou les groupes opérationnels qui le font.

Les choses ne sont pas forcément plus faciles pour les opérateurs. Dans la plupart des organisations, le besoin de mettre à jour les enregistrements DNS est suffisamment rare pour que les procédures (à la fois les règles métier et les étapes techniques réelles) aient tendance à être rares, voire inexistantes. Cela signifie que lorsque vous devez ajouter un enregistrement DNS, vous devez d'abord trouver la documentation, demander à un collègue ou (dans le pire des cas) le comprendre. Vous devez également vous assurer que vous respectez toutes les règles de sécurité de l’entreprise et que l’entrée est correctement étiquetée pour les pare-feu.

Heureusement, il existe un moyen de faciliter la vie des développeurs et des opérateurs. Dans cet article, nous montrons comment les opérateurs peuvent configurer un déploiement Kubernetes pour permettre aux développeurs de mettre à jour les enregistrements DNS et de générer des certificats TLS dans un environnement Kubernetes en libre-service. En construisant l’infrastructure à l’avance, vous pouvez garantir que toutes les exigences commerciales et techniques nécessaires sont satisfaites.

Présentation et prérequis

Une fois la solution en place, tout ce qu’un développeur doit faire pour exposer une application à Internet est de créer un contrôleur d’entrée en suivant un modèle fourni qui inclut un nom de domaine complet (FQDN) dans un domaine géré par l’installation Kubernetes. Kubernetes utilise le modèle pour allouer une adresse IP au contrôleur Ingress, créer l'enregistrement DNS A pour mapper le FQDN à l'adresse IP, générer des certificats TLS pour le FQDN et les ajouter au contrôleur Ingress. Le nettoyage est tout aussi simple : lorsque l'entrée est supprimée, les enregistrements DNS sont nettoyés.

La solution s'appuie sur les technologies suivantes (nous fournissons des instructions d'installation et de configuration ci-dessous) :

Avant de configurer la solution, vous avez besoin de :

  • Une installation cloud Kubernetes avec un objet de sortie ( LoadBalancer ). La solution utilise Linode, mais d'autres fournisseurs de cloud fonctionnent également.
  • Un nom de domaine hébergé chez Cloudflare , que nous avons choisi car il est l'un des fournisseurs DNS pris en charge pour cert-manager et prend en charge ExternalDNS ( en version bêta au moment de la rédaction). Nous recommandons fortement que le domaine ne soit pas utilisé à des fins de production ou à toute autre fin critique.
  • Accès à l'API Cloudflare, incluse dans l'offre gratuite.
  • Helm pour l'installation et le déploiement de Kubernetes.
  • kubectl comme interface de ligne de commande pour Kubernetes.
  • En option, K9s , une interface utilisateur tangible (TUI) bien construite qui offre un moyen plus structuré d’interagir avec Kubernetes.

Nous supposons également que vous avez une compréhension de base de Kubernetes (comment appliquer un manifeste, utiliser un graphique Helm et émettre des commandes kubectl pour afficher la sortie et résoudre les problèmes). Comprendre les concepts de base de Let's Encrypt est utile mais pas obligatoire ; pour un aperçu, consultez notre blog . Vous n'avez pas non plus besoin de savoir comment fonctionne cert-manager , mais si vous souhaitez savoir comment il (et les certificats en général) fonctionne avec NGINX Ingress Controller, consultez mon article récent, Automatisation de la gestion des certificats dans un environnement Kubernetes .

Nous avons testé la solution sur macOS et Linux. Nous n'avons pas testé sur le sous-système Windows pour Linux version 2 (WSL2), mais nous ne prévoyons aucun problème.

Note: La solution est destinée à servir d'exemple de preuve de concept et non à être utilisée en production. En particulier, il n’intègre pas toutes les meilleures pratiques en matière d’exploitation et de sécurité. Pour plus d'informations sur ces sujets, consultez la documentation cert-manager et ExternalDNS .

Déploiement de la solution

Suivez les étapes de ces sections pour déployer la solution :

Télécharger le logiciel
  1. Téléchargez votre jeton API Cloudflare .
  2. Cloner le référentiel NGINX Ingress Controller :

    $ git clone https://github.com/nginxinc/kubernetes-ingress.git Clonage dans « kubernetes-ingress »... à distance : Énumération des objets : 45176, terminé. à distance : Compter les objets : 100% (373/373), terminé. à distance : Compression d'objets : 100% (274/274), terminé. à distance : Total 45176 (delta 173), réutilisé 219 (delta 79), pack-réutilisé 44803 Objets reçus : 100 % (45176/45176), 60,45 Mio | 26,81 Mio/s, terminé.
    Résolution des deltas : 100% (26592/26592), terminé.
  3. Vérifiez que vous pouvez vous connecter au cluster Kubernetes.

    Le plan de contrôle Kubernetes s'exécute à l'adresse https://ba35bacf-b072-4600-9a04-e04...6a3d.us-west-2.linodelke.net:443 KubeDNS s'exécute à l'adresse https://ba35bacf-b072-4600-9a04-e04...6a3d.us-west-2.linodelke.net:443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy Pour déboguer et diagnostiquer davantage les problèmes de cluster, utilisez « kubectl cluster-info dump ».

Déployer le contrôleur d'entrée NGINX

  1. À l’aide de Helm, déployez NGINX Ingress Controller. Notez que nous ajoutons trois options de configuration non standard :

    • controller.enableCustomResources – Demande à Helm d’installer les définitions de ressources personnalisées (CRD) utilisées pour créer les ressources personnalisées NGINX VirtualServer et VirtualServerRoute .
    • controller.enableCertManager – Configure NGINX Ingress Controller pour communiquer avec les composants cert-manager .
    • controller.enableExternalDNS – Configure le contrôleur d’entrée pour communiquer avec les composants ExternalDNS.
    NOM : nginx-kic DERNIÈRE DATE DE DÉPLOIEMENT : Jour Lun JJ hh : mm : ss AAAA ESPACE DE NOM : nginx-ingress STATUT : déployé RÉVISION : 1 SUITE DE TESTS : Aucun REMARQUES :
    Le contrôleur d'entrée NGINX a été installé.
  2. Vérifiez que NGINX Ingress Controller est en cours d'exécution et notez la valeur dans le champ EXTERNAL-IP : il s'agit de l'adresse IP de NGINX Ingress Controller (ici, www.xxx.yyy.zzz ). La sortie est répartie sur deux lignes pour plus de lisibilité.

    $ kubectl get services --namespace nginx-ingress NOM TYPE CLUSTER-IP ... nginx-kic-nginx-ingress LoadBalancer 10.128.152.88 ... ... ÂGE DES PORTS IP EXTERNES ... www.xxx.yyy.zzz 80:32457/TCP,443:31971/TCP 3h8m

Déployer cert-manager

Dans la solution, cert-manager utilise le type de défi DNS-01 lors de l'obtention d'un certificat TLS, ce qui nécessite que le jeton API Cloudflare soit fourni lors de la création de la ressource ClusterIssuer . Dans la solution, le jeton API est fourni sous forme de secret Kubernetes.

  1. En utilisant Helm, déployez cert-manager :

    $ helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --version v1.9.1 --set installCRDs=true NOM : cert-manager DERNIÈRE UTILISATION : Jour Lun JJ hh : mm : ss AAAA ESPACE DE NOM : cert-manager STATUT : déployé RÉVISION : 1 SUITE DE TESTS : Aucune REMARQUE : cert-manager v1.9.1 a été déployé avec succès !
  2. Déployez le jeton d'API Cloudflare en tant que secret Kubernetes, en le remplaçant par <votre-jeton-API>:

    $ kubectl apply -f - <<EOFapiVersion: v1
    type: Métadonnées secrètes : nom : Espace de noms Cloudflare-api-token-secret : type de gestionnaire de certificats : Opaque
    stringData :
    api-token : "<votre-jeton-API>"
    Énoncé des faits
    secret/Cloudflare-api-token-secret créé
  3. Créez un objet ClusterIssuer, en spécifiant Cloudflare-api-token-secret (défini à l’étape précédente) comme emplacement pour récupérer le jeton. Si vous le souhaitez, vous pouvez remplacer example-issuer dans le champ metadata.name (et example-issuer-account-key dans le champ spec.acme.privateKeySecretRef.name ) par un nom différent.

    $ kubectl apply -f - <<EOFapiVersion: cert-manager.io/v1
    type: Métadonnées ClusterIssuer : nom : example-issuer espace de noms : cert-manager spec : acme : e-mail : example@example.com serveur : https://acme-v02.api.letsencrypt.org/directory privateKeySecretRef : nom : example-issuer-account-key solveurs : - dns01 :
              Cloudflare : apiTokenSecretRef : nom : Clé secrète du jeton d'API Cloudflare : jeton d'API EOF clusterissuer.cert-manager.io/example-issuer créé
  4. Vérifiez que le ClusterIssuer est déployé et prêt (la valeur dans le champ READY est True ).

    $ kubectl get clusterissuer NOM PRÊT ÂGE exemple-émetteur Vrai 3h9m

Déployer un DNS externe

Comme cert-manager, le projet ExternalDNS nécessite un jeton API Cloudflare pour gérer le DNS. Le même jeton peut être utilisé pour les deux projets, mais cela n'est pas obligatoire.

  1. Créez les CRD ExternalDNS pour NGINX Ingress Controller pour permettre l’intégration entre les projets.

    $ kubectl create -f ./kubernetes-ingress/deployments/common/crds/externaldns.nginx.org_dnsendpoints.yaml customresourcedefinition.apiextensions.k8s.io/dnsendpoints.externaldns.nginx.org créé
  2. Créez le service DNS externe ( external-dns ). Parce que le manifeste est assez long, nous le divisons ici en deux parties. La première partie configure les comptes, les rôles et les autorisations :

    • Crée un objet ServiceAccount appelé external-dns pour gérer toutes les opérations d'écriture et de mise à jour pour la gestion du DNS.
    • Crée un objet ClusterRole (également appelé external-dns ) qui définit les autorisations requises.
    • Lie le ClusterRole au ServiceAccount.
    $ kubectl apply -f - <<EOFapiVersion: v1
    type: Métadonnées du compte de service : nom : external-dns --- apiVersion : rbac.authorization.k8s.io/v1 type : ClusterRole métadonnées : nom : règles DNS externes : - apiGroups : [""] ressources : ["services","endpoints","pods"] verbes : ["get","watch","list"] - apiGroups : ["extensions","networking.k8s.io"] ressources : ["ingresses"] verbes : ["get","watch","list"] - apiGroups : ["externaldns.nginx.org"] ressources : ["dnsendpoints"] verbes : ["get","watch","list"] - apiGroups : ["externaldns.nginx.org"] ressources : ["dnsendpoints/status"] verbes : ["update"] - apiGroups : [""] ressources : ["nodes"] verbes : ["list","watch"] --- apiVersion : rbac.authorization.k8s.io/v1 kind : Métadonnées ClusterRoleBinding : nom : external-dns-viewer roleRef : apiGroup : rbac.authorization.k8s.io kind : Nom du rôle de cluster : externe-dns sujets : - type : Nom du compte de service : external-dns espace de noms : par défaut EOF serviceaccount/external-dns créé clusterrole.rbac.authorization.k8s.io/external-dns créé clusterrolebinding.rbac.authorization.k8s.io/external-dns-viewer créé

    La deuxième partie du manifeste crée le déploiement ExternalDNS :

    • Crée un filtre de domaine, qui limite la portée des dommages possibles causés par ExternalDNS lors de la gestion des domaines. Par exemple, vous pouvez spécifier les noms de domaine des environnements de préparation pour empêcher les modifications des environnements de production. Dans cet exemple, nous définissons domain-filter sur example.com .
    • Définit la variable d’environnement CF_API_TOKEN sur votre jeton API Cloudflare. Pour <votre-jeton-API>, remplacez soit le jeton réel, soit un secret contenant le jeton. Dans ce dernier cas, vous devez également projeter le secret dans le conteneur à l’aide d’une variable d’environnement.
    • Définit la variable d'environnement FREE_TIER sur « true » (approprié sauf si vous disposez d'un abonnement Cloudflare payant).
    $  kubectl apply -f - <<EOF 
    ---
    apiVersion: apps/v1
    kind: Métadonnées de déploiement : nom : spécification DNS externe : stratégie : type : Recréer le sélecteur : matchLabels : application : modèle DNS externe : métadonnées : étiquettes : application : spécification DNS externe : serviceAccountName : conteneurs DNS externe : - nom : image DNS externe : k8s.gcr.io/external-dns/external-dns:v0.12.0 args : - --source=service - --source=ingress - --source=crd - --crd-source-apiversion=externaldns.nginx.org/v1 - --crd-source-kind=DNSEndpoint - --domain-filter=example.com - --provider=Cloudflare env : - nom : CF_API_TOKEN
    valeur : "<votre-jeton-API>"
              - nom: Valeur FREE_TIER : « true » EOF serviceaccount/external-dns créé clusterrole.rbac.authorization.k8s.io/external-dns créé clusterrolebinding.rbac.authorization.k8s.io/external-dns-viewer créé deployment.apps/external-dns créé

Déployer l'exemple d'application

Utilisez l’exemple d’application standard NGINX Ingress Controller appelé Cafe à des fins de test.

  1. Déployez l'application Café.

    $ kubectl apply -f ./kubernetes-ingress/examples/ingress-resources/complete-example/cafe.yaml déploiement.apps/coffee créé service/coffee-svc créé déploiement.apps/tea créé service/tea-svc créé
  2. Déployez NGINX Ingress Controller pour l'application Cafe. Notez les paramètres suivants :

    • gentil: VirtualServer – Nous utilisons la ressource personnalisée NGINX VirtualServer, et non la ressource Kubernetes Ingress standard.
    • spec.host – Remplacez cafe.example.com par le nom de l’hôte que vous déployez. L'hôte doit se trouver dans le domaine géré avec ExternalDNS.
    • spec.tls.cert-manager.cluster-issuer – Si vous avez utilisé les valeurs spécifiées dans cet article, il s'agit de example-issuer . Si nécessaire, remplacez le nom que vous avez choisi à l’étape 3 de Déployer cert-manager .
    • spec.externalDNS.enable – La valeur true indique à ExternalDNS de créer un enregistrement DNS A.

    Notez que le temps nécessaire à cette étape dépend fortement du fournisseur DNS, car Kubernetes interagit avec l’API DNS du fournisseur.

    $ kubectl apply -f - <<EOFapiVersion: k8s.nginx.org/v1
    type: Métadonnées du serveur virtuel : nom : café spécifications : hôte : cafe.example.com tls : secret : cafe-secret cert-manager : cluster-issuer : example-issuer externalDNS : enable : true en amont : - nom : thé service : tea-svc port : 80 - nom : service de café : port de service de café : 80 routes : - chemin : /thé action : passe : thé - chemin : /café action : passe : café EOF virtualserver.k8s.nginx.org/cafe créé

Valider la solution

  1. Vérifiez l'enregistrement DNS A , en particulier que dans le bloc SECTION RÉPONSE, le FQDN (ici, cafe.example.com ) est mappé à l'adresse IP correcte ( www.xxx.yyy.zzz ).

    $ dig cafe.example.com ; <<>> DiG 9.10.6 <<>> cafe.example.com ;; options globales : +cmd ;; Réponse obtenue : ;; ->>HEADER<<- opcode : REQUÊTE, statut : PAS D'ERREUR, id: 22633 ;; drapeaux : qr rd ra ; REQUÊTE : 1, RÉPONSE : 1. AUTORITÉ : 0, SUPPLÉMENTAIRE : 1 ;; OPTER LA PSEUDOSECTION : ; EDNS : version : 0, drapeaux : ; udp : 4096 ;; SECTION QUESTION : ;cafe.example.com.		DANS UNE SECTION RÉPONSE : cafe.example.com.	279 IN A www.xxx.yyy.zzz ;; Heure de la requête : 1 msec ;; SERVEUR : 2607:fb91:119b:4ac4:2e0: xxxx :fe1e:1359#53(2607:fb91:119b:4ac4:2e0: xxxx :fe1e:1359) ;; QUAND : Jour Lun JJ hh : mm : ss TZ AAAA ;; TAILLE MSG reçu : 67
  2. Vérifiez que le certificat est valide (la valeur dans le champ READY est True ).

    $ kubectl get certificates NOM PRÊT SECRET ÂGE cafe-secret Vrai cafe-secret 8m51s
  3. Vérifiez que vous pouvez accéder à l'application.

    $ curl https://cafe.example.com/coffee Adresse du serveur : 10.2.2.4:8080 Nom du serveur : coffee-7c86d7d67c-lsfs6 Date : JJ/Lun/AAAA:hh:mm:ss +décalage TZ URI : /coffee ID de la requête : 91077575f19e6e735a91b9d06e9684cd $ curl https://cafe.example.com/tea Adresse du serveur : 10.2.2.5:8080 Nom du serveur : tea-5c457db9-ztpns Date : JJ/Lun/AAAA:hh:mm:ss +TZ-offset URI : /tea ID de la requête : 2164c245a495d22c11e900aa0103b00f

Que se passe-t-il lorsqu'un développeur déploie le contrôleur d'entrée NGINX

Beaucoup de choses se passent sous les couvertures une fois la solution en place. Le diagramme montre ce qui se passe lorsqu’un développeur déploie le contrôleur d’entrée NGINX avec une ressource personnalisée NGINX VirtualServer. Veuillez noter que certains détails opérationnels sont omis.

  1. Le développeur déploie une ressource VirtualServer à l'aide du CRD NGINX
  2. Kubernetes crée le serveur virtuel à l'aide du contrôleur d'entrée NGINX
  3. NGINX Ingress Controller appelle ExternalDNS pour créer un enregistrement DNS A
  4. ExternalDNS crée l'enregistrement A dans DNS
  5. NGINX Ingress Controller appelle cert-manager pour demander un certificat TLS
  6. cert-manager ajoute un enregistrement DNS à utiliser pendant le défi DNS-01
  7. cert-manager contacte Let’s Encrypt pour relever le défi
  8. Let’s Encrypt valide le défi contre le DNS
  9. Let’s Encrypt délivre le certificat TLS
  10. cert-manager fournit le certificat TLS au contrôleur d'entrée NGINX
  11. Le contrôleur d'entrée NGINX achemine les requêtes externes sécurisées par TLS vers les pods d'application

Dépannage

Compte tenu de la complexité de Kubernetes ainsi que des composants que nous utilisons, il est difficile de fournir un guide de dépannage complet. Cela dit, il existe quelques suggestions de base pour vous aider à déterminer le problème.

  • Utilisez les commandes kubectl get et kubectl describe pour valider la configuration des objets déployés.
  • Utilisez le kubectl journaux <composant> commande permettant d'afficher les fichiers journaux des différents composants déployés.
  • Utilisez K9s pour inspecter l'installation ; le logiciel met en évidence les problèmes en jaune ou en rouge (selon la gravité) et fournit une interface pour accéder aux journaux et aux détails sur les objets.

Si vous rencontrez toujours des problèmes, retrouvez-nous sur le Slack de la communauté NGINX et demandez de l'aide ! Nous avons une communauté dynamique et sommes toujours heureux de résoudre les problèmes.

Pour essayer le contrôleur d'entrée NGINX basé sur NGINX Plus, démarrez votre essai gratuit de 30 jours dès aujourd'hui ou contactez-nous pour discuter de vos cas d'utilisation .


« Cet article de blog peut faire référence à des produits qui ne sont plus disponibles et/ou qui ne sont plus pris en charge. Pour obtenir les informations les plus récentes sur les produits et solutions F5 NGINX disponibles, explorez notre famille de produits NGINX . NGINX fait désormais partie de F5. Tous les liens NGINX.com précédents redirigeront vers un contenu NGINX similaire sur F5.com."