blog » self-hosted » orchestration » setup-bundled-k3s-traefik-for-dns-01

Configurer le Traefik intégré à K3s pour DNS-01

K3s est livré avec Traefik par défaut. Vous pouvez le remplacer, mais configurer le point d'entrée (ingress) intégré est plus simple.

DNS-01 est le seul défi ACME qui supporte les certificats génériques (wildcard certificate). Si vous voulez *.mondomaine.com, c’est le seul chemin possible.

Avant de plonger dans les détails spécifiques à K3s, voici la version courte de DNS-01 : l’Autorité de Certification (AC) envoie un jeton (token) à votre serveur ; votre serveur le signe avec sa clé privée, puis publie la signature en tant qu’enregistrement (record) TXT sur _acme-challenge.mondomaine.com. L’AC interroge votre DNS, vérifie la valeur, conclut « oui, cette machine contrôle le domaine et la clé privée », et signe votre clé publique.

Installation de K3s

L’installation tient en une seule ligne, ce qui est exactement le bon nombre de lignes :

curl -sfL https://get.k3s.io | sh -

Si vous lisez ceci dans quelques années, vérifiez le K3s Quick Start pour confirmer qu’il n’y a pas eu de changements.

Configuration statique de Traefik & certificatesResolvers

Il y a deux types de configuration Traefik :

Pour DNS-01, il faut étendre la configuration statique. Traefik regroupe les paramètres ACME sous certificatesResolvers. Définir un resolver ressemble à ceci :

certificatesResolvers:
  le-dns:
    acme:
      email: acme@exemple.com
      storage: /data/acme.json
      dnsChallenge:
        provider: ovh

J’utilise le fournisseur DNS ovh, mais vous pouvez trouver la liste des fournisseur DNS supportés dans la documentation Lego.

Volume persistant pour le stockage ACME

Traefik a besoin d’un répertoire /data en écriture pour stocker les certificats ACME. Activer la persistance ressemble à ceci :

persistence:
  enabled: true
  path: /data
  size: 128Mi
  accessMode: ReadWriteOnce
  storageClass: local-path

Identifiants DNS & Secret Kubernetes

Traefik doit communiquer avec votre fournisseur DNS pour créer les enregistrements TXT. Cela nécessite des identifiants. Les variables d’environnement exactes dépendent du fournisseur DNS ; Lego les documente toutes.

Exemple : OVH

Documentation : https://go-acme.github.io/lego/dns/ovh/

Vous devez connaître votre endpoint OVH : ovh-eu pour l’Europe ou ovh-ca pour le Canada. Dans mon cas, c’est ovh-ca. Il faut aussi générer une “Application Key”, une “Application Secret”, et une “Consumer Key”. Tout cela se génère dans votre tableau de bord OVH sous « Identity, Security, and Operations / API Keys ». Voici à quoi ça ressemble :

OVH API Keys Dashboard

Après avoir cliqué sur « Create an API key », vous devrez remplir un formulaire :

Par exemple :

OVH API Keys Creation Page

Une fois cela fait, créez un secret Kubernetes contenant les variables requises :

kubectl create secret generic ovh-dns-secret \
  --from-literal=OVH_ENDPOINT=<ovh-eu ou ovh-ca> \
  --from-literal=OVH_APPLICATION_KEY=<votre application key OVH> \
  --from-literal=OVH_APPLICATION_SECRET=<votre application secret OVH> \
  --from-literal=OVH_CONSUMER_KEY=<votre consumer key OVH> \
  -n kube-system

Ajouter ces variables dans la configuration statique de Traefik ressemble ensuite à :

env:
  - name: OVH_ENDPOINT
    valueFrom:
      secretKeyRef:
        name: ovh-dns-secret
        key: OVH_ENDPOINT
  - name: OVH_APPLICATION_KEY
    valueFrom:
      secretKeyRef:
        name: ovh-dns-secret
        key: OVH_APPLICATION_KEY
  - name: OVH_APPLICATION_SECRET
    valueFrom:
      secretKeyRef:
        name: ovh-dns-secret
        key: OVH_APPLICATION_SECRET
  - name: OVH_CONSUMER_KEY
    valueFrom:
      secretKeyRef:
        name: ovh-dns-secret
        key: OVH_CONSUMER_KEY

Modifier la configuration statique de Traefik intégré (spécifique à K3s)

K3s gère Traefik via un chart Helm. Pour remplacer les valeurs par défaut, la documentation réseau de K3s nous dit de créer un HelmChartConfig sous /var/lib/rancher/k3s/server/manifests/traefik-config.yaml :

apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: traefik
  namespace: kube-system
spec:
  valuesContent: |-
    env:
      - name: OVH_ENDPOINT
        valueFrom:
          secretKeyRef:
            name: ovh-dns-secret
            key: OVH_ENDPOINT
      - name: OVH_APPLICATION_KEY
        valueFrom:
          secretKeyRef:
            name: ovh-dns-secret
            key: OVH_APPLICATION_KEY
      - name: OVH_APPLICATION_SECRET
        valueFrom:
          secretKeyRef:
            name: ovh-dns-secret
            key: OVH_APPLICATION_SECRET
      - name: OVH_CONSUMER_KEY
        valueFrom:
          secretKeyRef:
            name: ovh-dns-secret
            key: OVH_CONSUMER_KEY

    persistence:
      enabled: true
      path: /data
      size: 128Mi
      accessMode: ReadWriteOnce
      storageClass: local-path

    certificatesResolvers:
      le-dns:
        acme:
          email: acme@exemple.com
          storage: /data/acme.json
          keyType: EC384
          dnsChallenge:
            provider: ovh
            propagation:
              delayBeforeChecks: 10

Redémarrez Traefik :

kubectl -n kube-system rollout restart deploy traefik

Vous pouvez maintenant référencer le « resolver » dans vos « IngressRoute » en ajoutant :

tls:
  certResolver: le-dns

certResolver global (optionnel)

Si vous voulez que Traefik gère HTTPS par défaut, vous pouvez configurer les « entrypoints » sous websecure globalement :

apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: traefik
  namespace: kube-system
spec:
  valuesContent: |-
    # ...

    entryPoints:
      # ...

      websecure:
        address: ":443"
        http:
          tls:
            certResolver: le-dns
            domains:
              - main: "mondomaine.com"
                sans:
                  - "*.mondomaine.com"

Cela vous donne des certificats génériques (wildcard) automatiquement et vous n’avez plus besoin du bloc tls dans vos IngressRoutes.

Et voilà ! Traefik gère maintenant DNS-01 automatiquement avec l’ingress intégré à K3s. Une fois configuré, c’est totalement autonome.

Mon Chatbot
Bonjour! Je suis disponible pour répondre à toutes questions sur Mathieu. Comment puis-je vous aider?