Activer la gestion en libre-service du DNS et des certificats dans Kubernetes

NGINX | 01 novembre 2022

L’objectif ultime du développement d’applications est, bien entendu, de rendre celles-ci accessibles sur Internet. Pour les développeurs, Kubernetes simplifie dans une certaine mesure ce processus en fournissant le contrôleur Ingress comme mécanisme d’acheminement des requêtes vers l’application. Mais tout n’est pas aussi automatisé que vous le souhaiteriez probablement : vous avez encore besoin d’un enregistrement dans le système de noms de domaine (DNS) pour associer le nom de domaine de l’application à l’adresse IP du contrôleur Ingress, ainsi que d’un certificat TLS pour sécuriser les connexions via HTTPS. Dans la plupart des organisations, vous ne gérez pas vous-même le DNS ni le TLS et devez donc vous coordonner avec l’équipe opérationnelle (ou les équipes !) qui s’en charge.

La tâche n’est pas nécessairement plus simple pour les équipes d’exploitation. Dans la plupart des organisations, les mises à jour des enregistrements DNS sont suffisamment rares pour que les procédures — qu’il s’agisse des règles métier ou des étapes techniques à suivre — soient souvent sommaires, voire inexistantes. Ainsi, lorsque vous devez ajouter un enregistrement DNS, vous devez d’abord trouver la documentation, demander de l’aide à un collègue ou, dans le pire des cas, déterminer vous-même la marche à suivre. Vous devez également veiller à respecter toutes les règles de sécurité de l’entreprise et vous assurer que l’Ingress est correctement étiqueté pour les pare-feu.

Heureusement, il existe un moyen de simplifier la vie des développeurs comme des opérateurs. Dans cet article, nous expliquons comment les opérateurs peuvent configurer un déploiement Kubernetes afin de permettre aux développeurs de mettre à jour eux-mêmes les enregistrements DNS et de générer des certificats TLS dans un environnement Kubernetes. En mettant en place l’infrastructure en amont, vous pouvez vous assurer que toutes les exigences métier et techniques nécessaires sont respectées.

Présentation et prérequis

Une fois la solution en place, pour exposer une application sur Internet, il suffit au développeur de créer un contrôleur Ingress à partir d’un modèle fourni, qui inclut un nom de domaine complet (FQDN) appartenant à un domaine géré par l’installation Kubernetes. Kubernetes utilise ce modèle pour attribuer une adresse IP au contrôleur Ingress, créer l’enregistrement DNS A qui associe 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’Ingress est supprimé, les enregistrements DNS le sont également.

La solution s’appuie sur les technologies suivantes (les instructions d’installation et de configuration sont fournies ci-dessous) :

Avant de configurer la solution, vous avez besoin des éléments suivants :

  • Une installation Kubernetes dans le cloud avec un objet de sortie (LoadBalancer). La solution utilise Linode, mais d’autres fournisseurs de cloud sont également compatibles.
  • Un nom de domaine hébergé chez Cloudflare, que nous avons choisi parce qu’il fait partie des fournisseurs DNS pris en charge par cert-manager et qu’il prend en charge ExternalDNS (en version bêta au moment de la rédaction). Nous recommandons vivement de ne pas utiliser ce domaine en production ni à toute autre fin critique.
  • Accès à l’API Cloudflare, inclus dans l’offre gratuite.
  • Helm pour installer et déployer Kubernetes.
  • kubectl comme interface en ligne de commande pour Kubernetes.
  • Facultativement, K9s, une interface utilisateur en mode texte (TUI) bien conçue qui offre une manière plus structurée d’interagir avec Kubernetes.

Nous supposons également que vous possédez des connaissances de base sur Kubernetes (comment appliquer un manifeste, utiliser un chart Helm et exécuter des commandes kubectl pour afficher les résultats et résoudre les problèmes). Il est utile, mais pas indispensable, de comprendre les concepts de base de Let’s Encrypt ; pour une présentation générale, consultez notre blog. Vous n’avez pas non plus besoin de savoir comment fonctionne cert-manager, mais si vous souhaitez comprendre comment celui-ci (et les certificats en général) fonctionne avec NGINX Ingress Controller, consultez mon récent article, Automatisation de la gestion des certificats dans un environnement Kubernetes.

Nous avons testé la solution sous macOS et Linux. Nous ne l’avons pas testée sous Windows Subsystem for Linux version 2 (WSL2), mais nous ne prévoyons aucun problème.

Remarque : Cette solution est fournie à titre d’exemple de validation de concept et n’est pas destinée à être utilisée en production. Elle ne met notamment pas en œuvre toutes les bonnes pratiques en matière d’exploitation et de sécurité. Pour plus d’informations sur ces sujets, consultez la documentation de cert-manager et d’ExternalDNS.

Déploiement de la solution

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

Télécharger le logiciel

  1. Téléchargez votre jeton d’API Cloudflare.
  2. Clonez le dépôt du contrôleur Ingress NGINX :
$ git clone https://github.com/nginxinc/kubernetes-ingress.gitCloning into 'kubernetes-ingress'...
remote: Enumerating objects: 45176, done.
remote: Counting objects: 100% (373/373), done.
remote: Compressing objects: 100% (274/274), done.
remote: Total 45176 (delta 173), reused 219 (delta 79), pack-reused 44803
Receiving objects: 100% (45176/45176), 60.45 MiB | 26.81 MiB/s, done.
Resolving deltas: 100% (26592/26592), done.
  1. Vérifiez que vous pouvez vous connecter au cluster Kubernetes.
$ kubectl cluster-infoKubernetes control plane is running at https://ba35bacf-b072-4600-9a04-e04...6a3d.us-west-2.linodelke.net:443
KubeDNS is running at https://ba35bacf-b072-4600-9a04-e04...6a3d.us-west-2.linodelke.net:443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
 
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

Déployer le contrôleur Ingress NGINX

  1. À l’aide de Helm, déployez le contrôleur Ingress NGINX. Notez que nous ajoutons trois options de configuration non standard :
$ helm install nginx-kic nginx-stable/nginx-ingress --namespace nginx-ingress --set controller.enableCustomResources=true --create-namespace --set controller.enableCertManager=true --set controller.enableExternalDNS=trueNAME: nginx-kic
LAST DEPLOYED: Day Mon DD hh:mm:ss YYYY
NAMESPACE: nginx-ingress
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
The NGINX Ingress Controller has been installed.
  • controller.enableCustomResources – Indique à 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 de cert-manager.
  • controller.enableExternalDNS – Configure le contrôleur Ingress pour qu’il communique avec les composants ExternalDNS.
  1. Vérifiez que NGINX Ingress Controller est en cours d’exécution et notez la valeur du 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 en faciliter la lecture.
$ kubectl get services --namespace nginx-ingressNAME                      TYPE           CLUSTER-IP      ...
nginx-kic-nginx-ingress   LoadBalancer   10.128.152.88   ... 

   ... EXTERNAL-IP       PORT(S)                      AGE
   ... www.xxx.yyy.zzz   80:32457/TCP,443:31971/TCP   3h8m

Déployer cert-manager

Dans cette solution, cert-manager utilise le type de challenge « DNS-01 » lors de l’obtention d’un certificat TLS, ce qui nécessite de fournir le jeton d’API Cloudflare pendant la création de la ressource ClusterIssuer. Dans cette solution, le jeton d’API est fourni sous la forme d’un Secret Kubernetes.

  1. À l’aide de Helm, déployez cert-manager :
$ helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --version v1.9.1 --set installCRDs=trueNAME: cert-manager
LAST DEPLOYED: Day Mon DD hh:mm:ss YYYY
NAMESPACE: cert-manager
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
cert-manager v1.9.1 has been deployed successfully!
  1. Déployez le jeton d’API Cloudflare en tant que Secret Kubernetes, en remplaçant <your-API-token> par votre jeton :
$ kubectl apply -f - <<EOFapiVersion: v1 kind: Secret metadata: name: Cloudflare-api-token-secret namespace: cert-manager type: Opaque stringData: api-token: "<your-API-token>" EOF
secret/Cloudflare-api-token-secret created
  1. Créez un objet ClusterIssuer en indiquant Cloudflare-api-token-secret (défini à l’étape précédente) comme emplacement où récupérer le jeton. Si vous le souhaitez, vous pouvez remplacer example-issuer dans le champ metadata.name (ainsi que example-issuer-account-key dans le champ spec.acme.privateKeySecretRef.name) par un autre nom.
$ kubectl apply -f - <<EOFapiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: example-issuer namespace: cert-manager spec: acme: email: example@example.com server: https://acme-v02.api.letsencrypt.org/directory privateKeySecretRef: name: example-issuer-account-key solvers: - dns01: Cloudflare: apiTokenSecretRef: name: Cloudflare-api-token-secret key: api-token EOF
clusterissuer.cert-manager.io/example-issuer created
  1. Vérifiez que le ClusterIssuer est déployé et prêt (la valeur du champ « READY » est « True »).
$ kubectl get clusterissuerNAME             READY   AGE
example-issuer   True    3h9m

Déployer ExternalDNS

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

  1. Créez les CRD ExternalDNS pour NGINX Ingress Controller afin de permettre l’intégration entre les projets.
$ kubectl create -f ./kubernetes-ingress/deployments/common/crds/externaldns.nginx.org_dnsendpoints.yamlcustomresourcedefinition.apiextensions.k8s.io/dnsendpoints.externaldns.nginx.org created
  1. Créez le service DNS externe (external-dns). Le manifeste étant assez long, nous le divisons ici en deux parties. La première partie configure les comptes, les rôles et les autorisations :
$ kubectl apply -f - <<EOFapiVersion: v1 kind: ServiceAccount metadata: name: external-dns --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: external-dns rules: - apiGroups: [""] resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions","networking.k8s.io"] resources: ["ingresses"] verbs: ["get","watch","list"] - apiGroups: ["externaldns.nginx.org"] resources: ["dnsendpoints"] verbs: ["get","watch","list"] - apiGroups: ["externaldns.nginx.org"] resources: ["dnsendpoints/status"] verbs: ["update"] - apiGroups: [""] resources: ["nodes"] verbs: ["list","watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: external-dns-viewer roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: external-dns subjects: - kind: ServiceAccount name: external-dns namespace: default EOF
serviceaccount/external-dns created
clusterrole.rbac.authorization.k8s.io/external-dns created
clusterrolebinding.rbac.authorization.k8s.io/external-dns-viewer created
  1. La deuxième partie du manifeste crée le déploiement ExternalDNS :
$  kubectl apply -f - <<EOF --- apiVersion: apps/v1 kind: Deployment metadata: name: external-dns spec: strategy: type: Recreate selector: matchLabels: app: external-dns template: metadata: labels: app: external-dns spec: serviceAccountName: external-dns containers: - name: external-dns image: 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: - name: CF_API_TOKEN value: "<your-API-token>" - name: FREE_TIER value: "true" EOF
serviceaccount/external-dns created
clusterrole.rbac.authorization.k8s.io/external-dns created
clusterrolebinding.rbac.authorization.k8s.io/external-dns-viewer created
deployment.apps/external-dns created
  • Crée un objet ServiceAccount nommé « external-dns » pour gérer toutes les opérations d’écriture et de mise à jour liées à la gestion du DNS.
  • Crée un objet ClusterRole (également appelé « external-dns ») qui définit les autorisations requises.
  • Associe le ClusterRole au ServiceAccount.
  • Crée un filtre de domaine qui limite l’étendue des dommages potentiels causés par ExternalDNS lors de la gestion des domaines. Par exemple, vous pouvez spécifier les noms de domaine des environnements de préproduction afin d’empêcher toute modification 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 d’API Cloudflare. Pour « <your-API-token> », indiquez soit le jeton lui-même, soit un Secret contenant ce 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" (valeur appropriée, sauf si vous disposez d’un abonnement Cloudflare payant).

Déployer l’application d’exemple

Utilisez l’application d’exemple standard du contrôleur Ingress NGINX appelée « Cafe » à des fins de test.

  1. Déployez l’application Cafe.
$ kubectl apply -f ./kubernetes-ingress/examples/ingress-resources/complete-example/cafe.yamldeployment.apps/coffee created
service/coffee-svc created
deployment.apps/tea created
service/tea-svc created
  1. Déployez NGINX Ingress Controller pour l’application Cafe. Tenez compte des paramètres suivants : notez que le temps nécessaire à cette étape dépend fortement du fournisseur DNS, car Kubernetes interagit avec l’API DNS de celui-ci.
$ kubectl apply -f - <<EOFapiVersion: k8s.nginx.org/v1 kind: VirtualServer metadata: name: cafe spec: host: cafe.example.com tls: secret: cafe-secret cert-manager: cluster-issuer: example-issuer externalDNS: enable: true upstreams: - name: tea service: tea-svc port: 80 - name: coffee service: coffee-svc port: 80 routes: - path: /tea action: pass: tea - path: /coffee action: pass: coffee EOF
virtualserver.k8s.nginx.org/cafe created
  • kind: VirtualServer – Nous utilisons la ressource personnalisée VirtualServer de NGINX, et non la ressource Ingress standard de Kubernetes.
  • spec.host – Remplacez cafe.example.com par le nom de l’hôte que vous déployez. L’hôte doit appartenir au domaine géré avec ExternalDNS.
  • spec.tls.cert-manager.cluster-issuer – Si vous avez utilisé les valeurs indiquées dans cet article, il s’agit de example-issuer. Si nécessaire, remplacez-le par le nom que vous avez choisi à l’étape 3 de la section « Déployer cert‑manager ».
  • spec.externalDNS.enable – La valeur true indique à ExternalDNS de créer un enregistrement DNS A.

Valider la solution

  1. Vérifiez l’enregistrement DNS A – en particulier que, dans le bloc ANSWER SECTION, le nom de domaine complet (ici, cafe.example.com) est associé à la bonne adresse IP (www.xxx.yyy.zzz).
$ dig cafe.example.com 
; <<>> DiG 9.10.6 <<>> cafe.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22633
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
 
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;cafe.example.com.		IN	A
 
;; ANSWER SECTION:
cafe.example.com.	279	IN	A	www.xxx.yyy.zzz
 
;; Query time: 1 msec
;; SERVER: 2607:fb91:119b:4ac4:2e0:xxxx:fe1e:1359#53(2607:fb91:119b:4ac4:2e0:xxxx:fe1e:1359)
;; WHEN: Day Mon DD hh:mm:ss TZ YYYY
;; MSG SIZE  rcvd: 67
  1. Vérifiez que le certificat est valide (la valeur du champ « READY » est « True »).
$ kubectl get certificatesNAME          READY   SECRET        AGE
cafe-secret   True    cafe-secret   8m51s
  1. Vérifiez que vous pouvez accéder à l’application.
$ curl https://cafe.example.com/coffeeServer address: 10.2.2.4:8080
Server name: coffee-7c86d7d67c-lsfs6
Date: DD/Mon/YYYY:hh:mm:ss +TZ-offset
URI: /coffee
Request ID: 91077575f19e6e735a91b9d06e9684cd
$ curl https://cafe.example.com/tea
Server address: 10.2.2.5:8080
Server name: tea-5c457db9-ztpns
Date: DD/Mon/YYYY:hh:mm:ss +TZ-offset
URI: /tea
Request ID: 2164c245a495d22c11e900aa0103b00f

Que se passe-t-il lorsqu’un développeur déploie NGINX Ingress Controller ?

Une fois la solution en place, de nombreuses opérations s’effectuent en arrière-plan. Le schéma montre ce qui se passe lorsqu’un développeur déploie le contrôleur Ingress NGINX avec une ressource personnalisée NGINX VirtualServer. Notez que certains détails opérationnels ne sont pas représentés.

Ce qui se passe lorsqu’un développeur déploie NGINX Ingress Controller avec une ressource personnalisée NGINX VirtualServer : (1) Le développeur déploie une ressource VirtualServer à l’aide de la CRD NGINX (2) Kubernetes crée le VirtualServer à l’aide de NGINX Ingress Controller (3) NGINX Ingress Controller appelle ExternalDNS pour créer un enregistrement DNS de type A (4) ExternalDNS crée l’enregistrement A dans le DNS (5) NGINX Ingress Controller appelle cert-manager pour demander un certificat TLS (6) cert-manager ajoute un enregistrement DNS à utiliser lors du challenge DNS-01 (7) cert-manager contacte Let’s Encrypt pour mener à bien le challenge (8) Let’s Encrypt valide le challenge auprès du DNS (9) Let’s Encrypt émet le certificat TLS (10) cert-manager fournit le certificat TLS à NGINX Ingress Controller (11) NGINX Ingress Controller achemine les requêtes externes sécurisées par TLS vers les pods de l’application

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

Dépannage

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

  • Utilisez les commandes « kubectl get » et « kubectl describe » pour valider la configuration des objets déployés.
  • Utilisez la commande « kubectl logs <component> » pour consulter les fichiers journaux des différents composants déployés.
  • Utilisez K9s pour inspecter l’installation. Le logiciel signale les problèmes en jaune ou en rouge (selon leur gravité) et fournit une interface permettant d’accéder aux journaux et aux informations détaillées sur les objets.

Si vous rencontrez toujours des problèmes, retrouvez-nous sur le Slack de la communauté NGINX et demandez de l’aide ! Notre communauté est très active et nous sommes toujours ravis de vous aider à résoudre vos problèmes.

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


Partager
Mots-clés : DNS, F5 NGINX, Tech

Articles de blog associés

Tendances actuelles des technologies cloud natives, de l’ingénierie de plateforme et de l’IA
NGINX | 13/10/2025

Tendances actuelles des technologies cloud natives, de l’ingénierie de plateforme et de l’IA

Découvrez les principaux enseignements tirés des réponses à l’enquête annuelle F5 NGINX sur les dernières tendances en matière de technologies cloud natives, de sécurité, d’ingénierie de plateforme et d’IA.

Quels contrôleurs Ingress NGINX sont affectés par les vulnérabilités CVE-2022-4886, CVE-2023-5043 et CVE-2023-5044 ?
NGINX | 03/11/2023

Quels contrôleurs Ingress NGINX sont affectés par les vulnérabilités CVE-2022-4886, CVE-2023-5043 et CVE-2023-5044 ?

Lorsque de nouvelles CVE sont signalées, il est facile de ne plus savoir si elles concernent un outil de contrôleur Ingress NGINX particulier, car il existe plusieurs projets. Cet article présente les CVE et explique comment distinguer les différents projets de contrôleurs Ingress afin de dissiper toute confusion.

Votre API est-elle en temps réel ? Testez sa latence avec l’outil rtapi de NGINX
NGINX | 11/03/2020

Votre API est-elle en temps réel ? Testez sa latence avec l’outil rtapi de NGINX

Votre API répond-elle aux requêtes en moins de 30 ms ? Si ce n’est pas le cas, il ne s’agit pas d’une API en temps réel offrant la faible latence exigée par la grande majorité des organisations. Mesurez la latence de votre API avec l’outil rtapi de NGINX et découvrez comment NGINX peut l’aider à offrir une réactivité en temps réel.

Un testeur d’expressions régulières pour NGINX et NGINX Plus
NGINX | 11/06/2019

Un testeur d’expressions régulières pour NGINX et NGINX Plus

Le testeur d’expressions régulières (regex) pour NGINX et NGINX Plus vous évite de tâtonner en vous indiquant si une expression régulière utilisée dans un bloc location ou map correspond aux valeurs comme prévu. Il génère la configuration appropriée et affiche les valeurs des groupes de capture.

Caches partagés avec les clusters de cache NGINX Plus, partie 1
NGINX | 24/01/2017

Caches partagés avec les clusters de cache NGINX Plus, partie 1

Optimisez la capacité de votre cache web en le répartissant entre plusieurs serveurs de cache web NGINX ou NGINX Plus. Découvrez comment procéder dans cet article.

Introduction aux microservices
NGINX | 19/05/2015

Introduction aux microservices

Les microservices suscitent actuellement beaucoup d’intérêt. Cet article de blog est le premier d’une série de sept consacrée à la conception, au développement et au déploiement de microservices.