kubernetes_argocd_traefik

17 novembre 2022

Vous avez besoin de tester des features sur un environnement existant ? Ou vous avez des contraintes de certificats TLS ou de finops pour votre workflow GitOps ?

 

Nous allons voir comment utiliser ArgoCD et Traefik pour mettre en place une solution de header routing pour une application dans Kubernetes.

Installation de l’environnement

ℹ️ Les sources de cet article sont dans ce repository Gitlab; je vous propose de le cloner.

Dans cet article, nous allons mettre en place une solution de header routing, c’est une manière de router le trafic à partir des headers de la requête HTTP en plus (ou en remplacement) de la méthode “traditionnelle” de routage par Host HTTP.

Il y a quelques prérequis à la mise en place de cette méthode dans Kubernetes. Mais le premier des prérequis est d’avoir un cluster Kubernetes.

Si comme moi vous n’en avez pas à disposition, vous pouvez utiliser kind (permet de déployer un cluster kube simple dans docker) : il y a une configuration prédéfinie dans le repository qui vous permettra de gagner du temps.

kind create cluster --config kind.yaml

Il existe un bon nombre de solutions pour faire du déploiement automatique et de l’ingress dans Kubernetes. Ici nous allons utiliser ArgoCD pour la partie CD et Traefik comme Ingress Controller.

💡 Traefik est simple à configurer, mais on pourrait le remplacer par Istio ou équivalent (voir la conférence de Sacha B. sur le sujet).

Commençons par installer Traefik. Pour ça nous allons partir du Helm Chart officiel et une configuration de base permettant de nommer l’ingressClass que nous allons utiliser (ici ingressClass: "traefik”) :

helm upgrade --install --create-namespace --namespace=traefik \
    --repo https://helm.traefik.io/traefik \
    -f ./values/traefik.yaml traefik traefik

Maintenant installons ArgoCD toujours avec le Helm Chart officiel et une configuration simple permettant d’utiliser l’ingress classe traefik pour l’accès au dashboard (le fichier argocd.yaml doit être modifié pour changer le hostname) :

helm upgrade --install --create-namespace --namespace=traefik \
    --repo https://helm.traefik.io/traefik \
    -f ./values/traefik.yaml traefik traefik

Le Dashboard d’argoCD devrait être maintenant accessible sur le host défini dans le fichier values/argocd.yaml avec le compte admin et le mot de passe récupéré à partir de la commande.

kubectl -n argocd get secret argocd-initial-admin-secret \
	-o jsonpath="{.data.password}" | base64 -d

💡 Pour aller plus loin, on peut manager Traefik et ArgoCD dans ArgoCD afin qu’ils soient déployés automatiquement en cas de mise à jour… Mais c’est un autre sujet 😀

Mise en place du Header Routing

À partir d’ici, nous allons utiliser ArgoCD pour déployer notre application. Nous devons donc avoir un repository Git qui sera utilisé comme source par ArgoCD.

Pour cette présentation nous allons utiliser le repository que nous avons déjà cloné.

Un chart Helm est déjà présent dans le répertoire charts/frontend : c’est un chart simple, dans lequel nous allons créer un Deployment de l’image whoami, un Service et une IngressRoute (équivalent de l’Ingress pour traefik)

Il ne vous reste plus qu’à modifier le fichier values.yaml pour changer le host de l’ingress :

nameOverride: ""
fullnameOverride: ""

ingress:
  routes:
    - match: "Host(`frontend.vcap.me`)" # 👈️ change this to your real domain name

Pour qu’ArgoCD puisse déployer notre Helm Chart, nous allons créer une ressource de type Application.

Dans le repository il y a déjà une application dans argocd/frontend.yaml, il faudra la modifier pour pointer sur votre repository :

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: argocd
  annotations:
    argocd.argoproj.io/manifest-generate-paths: .
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  destination:
    namespace: frontend
    name: in-cluster
  source:
    path: charts/frontend
		# 👇️ change this to your public repository
    repoURL: git@gitlab.com:padok/argocd-app.git
    targetRevision: main
    helm:
      valueFiles:
        - "values.yaml"
  syncPolicy:
    automated:
      selfHeal: true
      prune: true

ℹ️ Si votre repository n’est pas publique il faudra ajouter les crédentials dans ArgoCD.

Maintenant on commit et on push tout ça et on déploie notre application dans ArgoCD pour déclencher la synchronisation de notre Chart dans le cluster :

kubectl apply -n argocd -f argocd/frontend.yaml

L’application est normalement disponible via le host que vous avez défini dans le fichier de values du Helm Chart et également dans l’interface de ArgoCD.

interface_argocd

L’application est bien déployée, mais le routing est toujours basé sur le hostname. Nous allons maintenant ajouter une application et router les requêtes avec le header x-frontend-env vers cette nouvelle application. Pour ça, on va déployer la seconde application ‘frontend-dev’.

L’application frontend-dev va utiliser le fichier values-dev.yaml du Helm Chart : ce fichier ajoute une règle basée sur le header x-frontend-dev pour le routage : Headers(x-frontend-env, dev). Une fois le Helm Chart construit l’IngressRoute devrait ressembler à ça :

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: frontend-dev
  labels:
    helm.sh/chart: frontend-0.1.0
    app.kubernetes.io/name: frontend
    app.kubernetes.io/instance: frontend-dev
    app.kubernetes.io/version: "1.16.0"
    app.kubernetes.io/managed-by: Helm
  annotations:
    kubernetes.io/ingress.class: "traefik"
spec:
  entryPoints:
    - web
    - websecure
  routes:
  
    - kind: Rule
      match: "Host(`frontend.vcap.me`) && (Headers(`x-frontend-env`, `dev`))"
      services:
        - name: frontend-dev
          port: 80

Il ne reste plus qu’à tester. On commence donc par déployer l’application :

kubectl apply -n argocd -f argocd/frontend-dev.yaml

On peut maintenant tester pour voir si le routage se fait correctement avec une commande curl simple :

$ curl -s -H "X-Frontend-Env: dev" http://frontend.vcap.me/api | jq .hostname
"frontend-dev-784d84854c-bkszs"
$ curl -s http://frontend.vcap.me/api | jq .hostname
"frontend-6d5cf57b69-pjnjr"

Les retours de la commande montrent bien que selon les headers envoyés dans la requête, on ne tombe pas sur la même version de l’application (pas le même pod).

Pour aller plus loin, on pourrait automatiser ce workflow avec des ApplicationSet. Cette ressource nous permet de déclencher la création d’application à partir de plusieurs sources. Par exemple à partir de pattern de branche git…

Conclusion

Il y a plusieurs avantages à utiliser ce type de routage :

  • Backend et Frontend interdépendant : sur une application 2/3 tier, il peut être intéressant de déployer une feature front pour la tester sans avoir à déployer un nouveau backend.
  • Pas de possibilité de faire du wildcard / gestion certificat : dans certaines situations, il peut être compliqué d’avoir des certificats wildcard (Par exemple sur des LB HTTPS Google Cloud) ou d’avoir un nombre illimité de certificats pour faire du routage par hostname.
  • DevX : simplifier les tests de feature en cours de dev directement sur l’environnement de prod
  • Réduire les couts : on ne doit pas tout redéployer quand seulement une partie de l’application est en cours de test.