Skip to content

Gestion des URLs

Estimated time to read: 3 minutes

Avant d'installer external-dns, il est nécessaire de créer un ServiceAccount afin de lui donner accès aux différents namespaces pour détecter les nouveaux endpoints à gérer:

kubectl apply -f external-dns/external-dns-rbac.yml

ServiceAccount créé

namespace/external-dns created
serviceaccount/external-dns created
clusterrole.rbac.authorization.k8s.io/external-dns created
clusterrolebinding.rbac.authorization.k8s.io/external-dns-viewer created

Configuration de external-dns pour CloudFlare

Vous aurez besoin de 2 infos : la clé d'API et le user email référencé par Cloudfare. Ces 2 infos sont stockés dans des variables d'environnement API_KEY & API_MAIL

Elles sont déjà configurées

On est sympa, c'est déjà fait grâce au script exécuté au début du workshop. Si vous avez changer de terminal, 🔐il faut refaire.

Gestion du secret pour accéder à l'API Cloudflare

Il est nécessaire de créer un secret pour stocker l'API key d'accès à Cloudflare et un autre pour le compte de connexion

kubectl -n external-dns create secret generic cloudflare-api-token --from-literal=api-key=$API_KEY
kubectl -n external-dns create secret generic cloudflare-user-mail --from-literal=user-mail=$API_MAIL

On peut vérifier que les secrets sont bien créés et disponibles

kubectl get secrets -n external-dns

Secrets créés

NAME                   TYPE     DATA   AGE
cloudflare-api-token   Opaque   1      15s
cloudflare-user-mail   Opaque   1      11s

Installation d'external-dns

Pour déployer external-dns, il suffit de créer un Deployment installant l'image officielle d'external-dns

kubectl apply -f external-dns/external-dns-cloudflare.yml

Pour comprendre le manifest:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: external-dns-cloudflare
  namespace: external-dns
  labels:
    app.kubernetes.io/instance: external-dns-cloudflare
    app.kubernetes.io/name: external-dns
    app.kubernetes.io/version: 0.14.0
spec:
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app.kubernetes.io/instance: external-dns-cloudflare
      app.kubernetes.io/name: external-dns
  template:
    metadata:
      labels:
        app.kubernetes.io/instance: external-dns-cloudflare
        app.kubernetes.io/name: external-dns
    spec:
      serviceAccountName: external-dns
      containers:
        - name: external-dns-cloudflare
          image: registry.k8s.io/external-dns/external-dns:v0.14.0
          args:
            - --source=ingress
# 🛜 On filtre sur le domaine grunty.uk
            - --domain-filter=grunty.uk
# 🚚 Gestionnaire du DNS
            - --provider=cloudflare
# 💡 Prefix pour les enregistrements TXT (et ne pas supprimer ceux du voisin)
# 🫸 C'est un hack pour le TP, cela fonctionne car on à un seul noeud
# 🫸 Dans la vrai vie on utilise un prefix spécifique au cluster
            - --txt-prefix=$(UID)-
            - --txt-owner-id=$(UID)
          env:
            - name: CF_API_TOKEN
              valueFrom:
                secretKeyRef:
# 🤫 On injecte le secret précédement créé avec la clef API
                  name: cloudflare-api-token
                  key: api-key
            - name: CF_API_EMAIL
              valueFrom:
                secretKeyRef:
# 🤫 On injecte le secret précédement créé avec le username
                  name: cloudflare-user-mail
                  key: user-mail
            - name: UID
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
Documentation officielle Cloudflare

La documentation officielle pour Cloudflare est dispo

external-dns is Running

kubectl get po -n external-dns
NAME                                     READY   STATUS    RESTARTS   AGE
external-dns-cloudflare-694f6f75-nf8n8   1/1     Running   0          2s

Vérifier les logs

On peut aussi vérifier que la connexion à Cloudflare est bien ok

kubectl logs $(kubectl get po -n external-dns | grep external-dns-cloudflare | cut -d' ' -f1) -n external-dns
...
time="2023-12-20T08:52:41Z" level=info msg="Instantiating new Kubernetes client"
time="2023-12-20T08:52:41Z" level=info msg="Using inCluster-config based on serviceaccount-token"
time="2023-12-20T08:52:41Z" level=info msg="Created Kubernetes client https://10.3.0.1:443"
...

External DNS en action

On peut voir dans les logs qu'external-dns a déjà automatiquement détecté notre Ingress précédent:

kubectl logs -f $(kubectl get po -n external-dns | grep external-dns-cloudflare | cut -d' ' -f1) -n external-dns
...
time="2023-12-20T08:52:44Z" level=info msg="Changing record." action=CREATE record=new-deployment.mvt.grunty.uk ttl=1 type=A zone=be73d3e4c087b970da9bb670130a11fc
time="2023-12-20T08:52:45Z" level=info msg="Changing record." action=CREATE record=new-deployment.mvt.grunty.uk ttl=1 type=TXT zone=be73d3e4c087b970da9bb670130a11fc
time="2023-12-20T08:52:45Z" level=info msg="Changing record." action=CREATE record=a-new-deployment.mvt.grunty.uk ttl=1 type=TXT zone=be73d3e4c087b970da9bb670130a11fc
...

On peut vérifier que notre nom de domaine est bien reconnu

dig new-deployment.$TF_VAR_OVH_CLOUD_PROJECT_KUBE_NAME.grunty.uk @ara.ns.cloudflare.com

DNS est configuré avec notre IP publique

;; ANSWER SECTION:
new-deployment.<votre_trigramme>.grunty.uk. 300 IN  A   57.128.120.31 (1)
  1. 🛜 l'IP sera différente

On a changé l'image Docker entre temps

Ne vous étonnez pas si vous ne voyez plus le magnifique cinéma ASCII du départ.

On a changé l'image Docker pour que ce que l'on affiche soit lisible lorsque l'on fait un cUrl

On peut aussi valider que le navigateur reconnait notre URL en visitant http://new-deployment.{votre_trigramme}.grunty.uk/

ou via un cURL comme à l'étape précédente

curl new-deployment.<votre_trigramme>.grunty.uk
Server address: 10.2.1.6:80
Server name: new-deployment-5998d8dbcc-kdbrk
Date: 20/Dec/2023:09:45:13 +0000
URI: /
Request ID: 82d85003846eed6c62744103d7ac2bda

C'est beaucoup plus pratique !! 🥳

Mais ... ce n'est pas très sécurisé le HTTP, le chef de brigade de la sécurité nous rappelle à l'ordre 🫣

Si on ajoute quelques mL de sécurité avec des certificats pour notre HTTPs ➡️