AGIC le lien entre AKS et Azure Application Gateway ?

Avec l’évolution des architectures microservices, Kubernetes est devenu l’un des logiciels prédominant dans le déploiement de conteneurs. Je vous propose donc un tour d’horizon de Kubernetes dans Azure. Pour cela, nous verrons au fur et à mesure de cet article comment interconnecter les services managés d’Azure: Application Gateway et Azure Kubernetes Services (AKS).

En utilisant un applicatif nommé Azure Gateway Ingress Controller (AGIC), nous verrons qu'il est possible de déléguer la configuration de l’Application Gateway à Azure. Après des explications sur le fonctionnement général et les avantages de cette solution nous verrons, via un exemple, comment automatiser le déploiement de tous ces services sous Terraform. Avant de rentrer directement dans le vif du sujet autour d’AGIC, il est important de redéfinir/représenter les services Azure que nous utiliserons.

Azure Kubernetes Services (AKS) :

Azure Kubernetes Services est un service managé d’Azure. Il permet de déployer un cluster Kubernetes sur des machines virtuelles gérées par Azure. Cela permet alors de se concentrer uniquement sur le côté applicatif tout en diminuant la charge opérationnelle et en optimisant l’utilisation des ressources avec une sécurité accrue.

L’un des principaux avantages d’AKS est qu’il offre une fonctionnalité de réparation automatique des nœuds tout en garantissant une à mise à l’échelle automatique. Comme dans la plupart des services managés d’Azure, il est possible de les interconnecter avec l’Active Directory (AAD). Cela permet de propager l'identité Azure jusque dans les pods de l’AKS (voir AADPodIdentity ou AADWorkloadIdentity pour plus de détails).

Azure Application Gateway :

Azure Application Gateway est un équilibreur de charge couche 7 (HTTP/HTTPS). Cela permet de gérer le trafic vers les applications web tout en y ajoutant des fonctionnalités de sécurité: TLS, Web Application Firewall (WAF). Ce service, entièrement managé par Azure, permet de facilement contrôler le trafic mais surtout il s'interconnecte facilement avec d’autres services managés (AKS, Web App…). Dans notre cas l'objectif est d'interconnecter un cluster AKS et une Application Gateway.

Azure Gateway Ingress Controller (AGIC) :

Azure Gateway Ingress Controller est un projet lancé dès le 22 Octobre 2017 par Microsoft. Son objectif est de permettre à Azure Application Gateway d'être utilisé comme ingress pour un cluster AKS. Pour comprendre le fonctionnement, il faut déployer l’AGIC comme un ensemble de ressources (Deployment, Ingress, Customs Ressources…) dans un cluster AKS puis l’AGIC analyse la configuration actuelle du cluster (ressources ingress, services…). Cela permet à AGIC de déduire des “routes” pour lesquelles il faut ouvrir le trafic depuis l'Application Gateway.

En fonction des changements apportés à cette ingress, des appels API à Azure seront réalisés avec des templates ARM afin de modifier la configuration de l’Application Gateway. On peut voir cela de façon plus graphique ci-dessous :


Exemple :

Dans cette partie je vais vous montrer comment mettre en place une infrastructure, via un langage d’Infrastructure as Code (IaC), comprenant: un AKS, une Application Gateway et un ingress controller AGIC. Pour cela, il est nécessaire d’avoir les pré-requis suivants sur la machine de déploiement :

  • Helm >= 3.10.1
  • Kubernetes >= 4.5.7
  • Terraform >= 1.3.2

Le déploiement se fait en plusieurs grandes étapes :

  • Déployer une Application Gateway: pas besoin de préciser les backend pools, rules… L’ensemble est ensuite reconfiguré par l’AGIC.
  • Déployer un cluster AKS: aucune configuration particulière mise à part l’intégration avec un CNI (Container Network Interface) Azure (chaque pod a une IP privée dans un subnet)
  • Installer AADPodIdentity et MIC exception sur le cluster: permet de gérer l’identité des pods via l’AAD
  • Déployer Azure Gateway Ingress Controller
  • Déployer une application utilisant un ingress controller (AGIC)

L’ensemble de ces étapes est possible manuellement via le portail Azure ou bien en ligne de commande. Dans notre cas, il est plus intéressant de l’automatiser. C’est pourquoi nous utiliserons Terraform. Il est possible de voir l’intégralité de l’exemple en suivant ce lien: code source terraform.

Après avoir appliqué le code Terraform, nous pouvons différencier deux grandes phases : avant et après le déploiement de l’AGIC dans le cluster AKS.

Avant:

Nous remarquons que l’Application Gateway correspond bien à la configuration minimale que nous avons décrite dans le code Terraform : un backend pool null (ne contenant pas de target) et un listener sur le port 80.

Backend Pool:


Listener:

Après:

Une fois que l’AGIC est en place sur l’AKS, à chaque ressource ingress controller créée la configuration de l’Application Gateway sera modifiée via template ARM. On le voit dans notre exemple puisque nous avons créé un site web écoutant sur le port 80.

Backend Pool:

Ici des backend pools sont ajoutés:

Listener:

Des listeners sont mis en place pour gérer le trafic :


Probes:

Pour chaque route créée par l’AGIC, des probes sont créés directement en appelant le site web sur son adresse IP privée comme ci-dessous :

On peut remarquer que l’ensemble des modifications sont faites automatiquement. Cela a réellement un avantage opérationnel car une fois l’infrastructure mise en place, plus besoin de se soucier de la configuration de l’Application Gateway tout est automatique (à condition de bien déployer l’ingress controller AGIC).

On peut logiquement se demander comment cela s’interface sur le cluster AKS. Après l’installation de l’ensemble des dépendances, il y a au total 4 pods nécessaires au bon fonctionnement :

  • 2 MIC exception (Managed Identity Controller) :  ce sont des contrôlleurs qui surveillent les modifications apportés aux pods AzureIdentity et AzureIdentityBinding. A la réception d'évènement, MIC modifie les identités impactées et associes les nouvelles identités au Virtual Machine Scale Set.
  • 1 NMI (Node Managed Identity) : c'est un pod qui s'exécute en tant que DaemonSet sur chaque nœud du cluster AKS. Il intercepte les demandes de token au service de métadonnées d'Azure (comme un proxy). Il vérifie si le pod a accès à l'identité pour laquelle il demande un token et récupère ensuite le token d'accès auprès de l'AAD.
  • 1 AGIC

En plus de ces pods il faut bien entendu le site web (aks-helloworld). On peut voir l’ensemble des pods de l’exemple ci-dessous:

En inspectant plus en détails le pod AGIC et ses logs, on observe que celui-ci se synchronise très régulièrement avec la configuration de l’Application Gateway. A chaque détection d’un nouvel ingress controller, ce pod va recalculer le nouveau template ARM depuis l’existant et appliquer la nouvelle configuration:

Pour aller plus loin :

Jusqu’à présent, nous avons créé et interconnecté un cluster AKS et une Application Gateway. Cependant le cluster n’est actuellement pas accessible via résolution DNS mais surtout nous n’avons pas une architecture hautement disponible.

Chiffrement TLS:

Une fois l’ensemble du cluster mis en place avec l’AGIC, il est possible de modifier l’ingress controller afin de chiffrer le trafic. Cela peut se faire aisément avec “cert-manager”. L’objectif est de déployer via Helm les pods nécessaires afin que le challenge (http, dns…) soit validé par le cluster lui-même. Cela permet de ne plus se soucier du renouvellement des certificats mais surtout de ne pas se préoccuper de sa création et de son stockage.

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-issuer
  namespace: cert-manager
spec:
  acme:
    email: ${email_issuer}
    server: https://acme-staging-v02.api.letsencrypt.org/directory # Used for staging only
    # server: https://acme-v02.api.letsencrypt.org/directory # Used for prod environnement
    privateKeySecretRef:
      name: letsencrypt
    solvers:
      - http01:
          ingress:
            class: azure/application-gateway
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: application-gateway-ingress
  annotations:
    kubernetes.io/ingress.class: azure/application-gateway
    appgw.ingress.kubernetes.io/request-timeout: "20"
    appgw.ingress.kubernetes.io/health-probe-status-codes: "200-399, 401"
    cert-manager.io/cluster-issuer: letsencrypt-issuer
    cert-manager.io/acme-challenge-type: http01
spec:
  tls:
    - hosts:
        - ${dns_name}
      secretName: letsencrypt
  rules:
    - host: ${dns_name}
      http:
        paths:
          - path: /
            backend:
              service:
                name: <your_service>
                port:
                  number: 80 # Exposed port. If tls is defined the Application Gateway will listen on port 443 (HTTPS) and redirect to port 80 in the AKS cluster
            pathType: Prefix

Mise en place d’une architecture multi-région :

Actuellement, l’Application Gateway est un load balancer régional. Il ne supporte qu’une seule région. Pour mettre en place une architecture hautement disponible, il faut rajouter le composant Azure Traffic Manager. C’est un load balancer basé sur le nom DNS. Cela permet de mettre en place un routage sur différentes régions. Il suffit de remplacer dans votre DNS la redirection de votre service vers le nom de domaine du Traffic Manager. Dans un second temps, il faudra créer le routage DNS directement dans le composant Traffic Manager pour rediriger le trafic vers vos Application Gateway.

Conclusion :

L’utilisation d’AKS avec AGIC et d’une Application Gateway permet de se concentrer au maximum sur vos applications car la gestion du trafic une fois mise en place se fera automatiquement en fonction de vos déploiements Kubernetes. En plus de tous les avantages présentés ci-dessus, cette architecture est scalable “à l’infini” tout en pouvant devenir multi région avec Traffic Manager.

Sources :