Avant propos
Cet article présente le cluster EKS qui héberge les applications d’e-TF1:
Et plus précisément notre gestion de droit au sein du cluster eks ainsi que le modèle de déploiement blue/green du cluster kubernetes managé par AWS (EKS) que nous utilisons.
Brève description de kubernetes à la sauce EKS
Kubernetes est un orchestrateur de container.
Pour simplifier, il s’agit d’un logiciel qui s’occupe de gérer la vie d’un ensemble de containers docker.
Un peu de vocabulaire pour commencer:
- Un cluster kubernetes est un ensemble de machines (node) qui permettent d’exécuter des containers.
- Un Node est une machine de travail (physique ou virtuelle) d’un cluster.
- Un Pod est le composant le plus petit qui gère directement un ou plusieurs containers qui partagent la même adresse IP.
- Un Deployment définit l’état cible des pods du cluster.
- Un Daemonset est un deployment qui déploie un pod par node.
- Un Ingress est une ressource kubernetes qui gère l’accès externe aux services dans un cluster.
- Un Namespace est une segmentation dans le nommage de ressources car les noms de ressources doivent être uniques dans un namespace.
Toutes les définitions des ressources kubernetes sont stockées dans API kubernets qui est dans notre cas EKS
.
Architecture EKS e-TF1
Nous utilisons actuellement uniquement la partie control plane.
Il est également possible de faire gérer la gestion des nodes par AWS via
les managed node groups. Pour plus d’explication je vous invite à lire https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html
Au sein de notre cluster, nous avons des nodes privés qui passent par la nat gateway pour l’accès internet et des nodes publics qui permettent aux pods l’accès internet sans passer par la nat gateway.
Et nous avons des subnets dédiés pour les pod kubernetes afin de s’affranchir des problèmes de range IP dans les subnets privés ou publics.
Le déploiement & les outils utilisés
Nous déployons le contrôle plane EKS et les nodes via terraform.
Les outils additionnels déployés dans notre cluster EKS:
- aws-auth pour la gestion de droit
- External Secrets pour récupérer les secrets stockés dans secrets manager AWS
- AWS VPC CNI pour le réseau kubernetes
- LinkerD comme load balancer interne pour GRPC
- Node-Local DNS pour améliorer les performances DNS.
- ALB Ingress Controller pour créer les load balancers afin d’accéder aux services lancés dans kubernetes.
- ExternalDNS pour lier un dns aux load blalancers créés
- AWS Node Termination Handler pour détecter les interruptions d’instance spot
- Cluster Autoscaler pour permettre l’augmentation/réduction du nombre de node suivant la charge
- Descheduler pour une meilleure répartition des pods au sein du cluster kubernetes
- Metrics Server pour récupérer les metrics des containers
- FluentD pour récupérer les logs des containers
Gestion des droits au sein d’EKS
Notre besoin pour la gestion de droit est classique.
Nous avons:
- Les Ops qui ont besoin d’avoir un contrôle total sur EKS.
- Les Leads Devs qui doivent pouvoir modifier leurs ressources EKS.
- Les Devs qui ont seulement besoin de consulter.
Nous avons donc défini 3 rôles IAM.
- Le rôle IAM etf1-crossaccount-k8sadmin pour les Ops.
- Le rôle IAM etf1-crossaccount-k8sreadwrite pour les Leads Devs.
- Le rôle IAM etf1-crossaccount-k8sreadonly pour les Devs.
On configure aws-auth pour associer le rôle IAM à un/des groupes kubernetes.
Dans notre cas, nous utilisons les groupes kubernetes custom suivants:
- readwrite
- readonly
- debugmode
Voici la configmap aws-auth sur l’association rôle IAM et groupe kubernetes.
Et la définition des droits des différents groupes (clusterrolebinding/clusterrole/role).
Le clusterrole view est builtin et ressemble à ceci:
Le groupe debugmode défini par namespace
Le rôle debug-mode défini par namespace
Le groupe readwrite est également défini par namespace et est associé à 2 rôles: Le rôle edit qui est buildin et le rôle spécifique readwrite-secrets pour les external secrets
Le rôle edit builtin
Le rôle readwrite-secrets
Le déploiement du cluster EKS en mode blue/green.
Contexte eTF1
Nous voulons être capables d’apporter des changements dans le cluster EKS avec une capacité de rollback rapide en cas d’effet non désirable.
Nous avons opté pour un déploiement en mode blue/green.
C’est à dire avoir 2 infrastructures parallèles de cluster EKS et basculer le trafic entre le cluster N (blue) et le cluster N+1 (green) lors de nos changements majeurs (changement de CNI, upgrade de version, etc).
Illustration d’un blue/green
Implémentation
Notre solution se base sur l’utilisation du projet open source ExternalDNS qui permet de synchroniser les DNS avec les Load balancers.
Nous avons pour chaque cluster EKS blue/green un sous-domaine privé et un sous-domaine public.
Et nous avons un domaine privé et un domaine public partagé entre les clusters blue/green qui correspond aux domaines en production.
Schéma d’explication pour les domaines privés
Techniquement cela se matérialise par l’utilisation de quatre ExternalDNS:
- 1 ExternalDNS pour le domaine privé du cluster. (*.eks-blue.devinfra.local)
- 1 ExternalDNS pour le domaine public du cluster. (*.eks-blue.devinfra.fr)
- 1 ExternalDNS pour le domaine privé partagé. (*.devinfra.local)
- 1 ExternalDNS pour le domaine public partagé. (*.devinfra.fr)
Le fichier deploy de l’ExternalDNS privé du cluster
Le fichier Deploy de l’ExternalDNS public du cluster
Le fichier deploy de l’ExternalDNS privé partagé en production
Le fichier Deploy de l’ExternalDNS public partagé en production
Exemple de bascule blue/green eks
Dans cet exemple simplifié, nous avons un cluster EKS eks-blue et un cluster EKS eks-green.
Ils ont tous les deux un ingress privé hello et un ingress public world.
Le domaine partagé est devinfra.local pour le domaine privé et devinfra.fr pour le domaine public.
Nous avons une entrée DNS api.devinfra.local qui correspond à une API EKS en production.
L’entrée DNS hello.devinfra.local vers une application interne et l’entrée DNS world.devinfra.fr vers une application accessible depuis internet.
Les entrées DNS de production pointent vers blue.
On arrête les ExternalDNS de production sur eks-blue afin d’arrêter les mises à jour des entrées DNS de production.
On met à jour l’entrée DNS de l’API EKS sur le domaine partagé pour pointer vers l’API EKS green.
On démarre les ExternalDNS de production sur eks-green afin de mettre à jour toutes les entrées DNS
Il ne reste plus qu’à vérifier que les anciens ingress ne reçoivent plus de trafic avant de les supprimer.
On a réalisé une bascule blue/green de cluster EKS.
Mais en basculant de cluster, il y a un problème avec l’authentification kubectl car il est nécessaire de définir le cluster name du cluster EKS.
Comment avoir un cluster name dynamique
Pour cela nous avons introduit une entrée DNS de type TXT qui a pour valeur le nom du cluster.
Nous avons développé un petit script qui récupère la valeur du champ TXT et le remplace lors de l’appel à aws-iam-authenticator.
Le script entre kubectl et aws-iam-authenticator s’appelle aws-iam-authenticator-wrapper
exemple de kubeconfig (l’entrée DNS avec le champ TXT défini est eks.devinfra.info)
Conclusion
Nous sommes globalement satisfaits de EKS. Il fournit un bon support des outils dont nous avons besoin et nous a permis la mise en place d’un processus de déploiement continu nécessaire pour nos applications. Notre prochain article décrira ce que nous avons mis en place pour gérer la scalabilité. Ceci est d’autant plus important car cela nous permet non seulement de réduire les coûts mais aussi l’empreinte carbone de notre activité.