AWS EKS Cluster, Node Group et Terraform

Ou comment automatiser un cluster Kubernetes autoscalable sur AWS.

Philippe Vidal
Jan 13 · 7 min read

Introduction

De nombreux labs et quelques infrastructures de production ont vu le jour autour de cette technologie ainsi que la mise en place de Continuous Integration / Continuous Delivery associés à ceux-ci.

Force est de constater que l’écosystème AWS autour de EKS (et des containers) a beaucoup évolué et est extrêmement dynamique.
Il a apporté son lot de bonnes nouvelles, parmi lesquelles:

  • Le CNI pour l’utilisation du VPC au sein du cluster K8S.
  • Les CSI drivers (EBS + EFS).
  • Le Cluster Autoscaler.
  • AWS ALB Ingress Controller.
  • AWS IAM Authenticator for Kubernetes.

J’en oublie probablement un tas d’autre que vous utilisez au quotidien.

Aussi, me pris t’il l’envie de mettre cela en place en y incluant la nouvelle ressource Terraform aws_eks_node_group et de pipeliner tout cela sous GitLab-CI par là-même occasion.

Implémentation

AWS

Les credentials nécessaires au déploiement des ressources AWS via Terraform dans GitLab seront fournis via le rôle IAM de l’instance runner GitLab.

GitLab Repositories

Ici, et sans aucune contrainte autre que le plaisir de le faire (et d’organiser le travail), j’ai créé 3 repositories:

  • Un pour le code de « base » comprenant la partie réseau (VPC), les permissions de base (IAM), une zone DNS (Route53) et un certificat (ACM).
  • Un pour le code du cluster EKS (master + nodes + add-ons).
  • Un pour une première application (jeu : 2048-game) usant de l’ALB Ingress Controller.

Nous avons donc 3 repos qui représenteront 3 projets Terraform.
La structure de ceux-ci est classique :

Base repository (VPC, IAM, Route53)
EKS repository (EKS, IAM, K8S add-ons)
2048-game repository (Kustomize, Route53)

Pour le présent article, il n’y a pas de gestion spécifique du gitflow et donc de gestion d’environnement associé. On fait tout sur master pour un seul environnement.

GitLab Pipelines

ex : 2048-game repository

On fait en sorte d’avoir une pipeline qui prenne en compte à la fois du Terraform et du Kubernetes.

ex : Pipeline du repository EKS

On gère aussi les Environment GitLab pour avoir des informations utiles sur les étapes majeures de notre pipeline (commit, URL).

ex : 2048-game repository Environment page

Nous avons maintenant nos outils nécessaires en place pour déployer notre cluster EKS. Alors, GO !

base

En effet, au moment du déploiement des ressources liées au VPC, nous n’avons pas déployé et n’avons pas conscience qu’une ressource tierce (EKS) va venir modifier les tags de plusieurs de nos ressources locales.

Les TAGs étant connus et identifiables (prefix en kubernetes.io) j’use d’un paramètre lié au provider me permettant d’ignorer globalement des TAGs ayant un prefix précis.

Sans cela, le projet Terraform base passerait son temps à écraser les TAGs mis en place par le projet Terraform eks. Ce dernier ne pourrait alors plus fonctionner correctement.

Je déploie aussi dans ce projet Terraform des ressources AWS Route53 et un certificat depuis l’AWS Certificat Manager ainsi que des ressources IAM.

eks

Je vais faire en sorte de déployer un cluster EKS managé (master), un Node Group managé par AZ de la région eu-west-1 (pour le bon fonctionnement de Cluster-Autoscaler) et finalement, la brique d’ALB Ingress Controller.

Je finaliserai cette partie avec quelques IAM/RBAC customs afin de donner des droits aux intervenants sur le cluster EKS en fonction des credentials AWS qu’ils possèdent (Rôle IAM et/ou utilisateur IAM).

Ayant un CLI AWS récent (> 1.16.308), je profite de l’usage de la nouvelle commande aws eks get-tokenen lieu et place de l’ aws-iam-authenticator pour cet usage.

La partie cluster EKS (master) est assez simple.

Ici, j’active les 2 endpoint pour d’une part, pourvoir interagir avec le cluster EKS depuis internet via le endpoint_public_access (celui activé par défaut) et d’autre part, permettre aux Worker Nodes de communiquer avec le master à travers le endpoint_private_access de manière plus sécurisée (pas par défaut).

Il y a aussi toutes les ressources Terraform nécessaires à son bon déploiement :

Viens ensuite la partie Node Group. Il existe 2 écoles, celle qui ne font qu’un seul Node Group qui s’étale sur plusieurs AZ (sans Cluster-Autoscaler) avec une gestion externe à Kubernetes des politiques de mise à l’échelle des Node Groups et celle qui font un Node Group par AZ comme l’oblige à faire le Cluster-Autoscaler (ici).

J’opte pour cette deuxième solution du fait que je souhaite mettre à l’échelle mon cluster Kubernetes de manière la plus native et kubernetes friendly.

Je lui adjoins les ressources AWS nécessaires à son bon fonctionnement et déploiement.

Je déploie une ressource AWS OpenID Connect permettant de pouvoir faire le lien entre des rôles AWS IAM et des services accountsKubernetes pour un usage au sein des applications K8S de ressources AWS (S3 par exemple).

Le thumbprint_list est une valeur connue mais non implicite (explication donnée ici). Il n’y a pas à date de data source Terraform permettant de récupérer cette valeur.

Il ne nous reste plus qu’à déployer les stacks Cluster-Autoscaler et ALB-Ingress-Controller et les références IAM / RBAC pour l’administration du cluster.

Il faut simplement préparer des templates Terraform correspondant aux fichiers YAML de déploiement Kubernetes pour ces composants.

Les nourrir dynamiquement des variables nécessaires présentes dans les ressources managées par Terraform:

  • Les ARN des rôles IAM pour les servicesaccounts.
  • Le nom du cluster EKS
  • L’ID du VPC.
  • La région AWS.

Et lancer leur déploiement au travers une null_resource ayant pour objectif de déployer les fichiers YAML générés par Terraform dans le cluster Kubernetes EKS fraichement installé.

Le depends_on force l’execution de cette ressource après l’apparition des Node Groups pour ne pas que les déploiements Kubernetes bloquent (j’ai eu le cas sur l’ALB Ingress Controller qui ne se déployait pas car il avait trop essayé de se déployer avant la disponibilité des Worker Nodes).

Le triggers fait en sorte que si l’une des configurations Kubernetes générée change, alors elle sera redéployée.

Nous aurons ici à subir le fait qu’une ressource local_file est constamment en création dans Terraform (Note indiquée dans la doc Terraform).

Je déploie ensuite les ressources nécessaires à l’association IAM / RBAC. J’ai fait simple pour le cadre de ce test. Un rôle ReadOnly sur tout EKS ( ClusterRole ) et un compte Administrateur sur un namespace spécifique ( Role ).

Le plus gros problème, c’est qu’il n’y pas de moyen simple d’automatiser la mise à jour de la ConfigMap aws-auth. J’utilise donc un template Terraform avec une convention de nommage forte pour définir l’ensemble des droits associés entre IAM et RBAC de Kubernetes.

Ici, il ne faudra surtout pas oublier de reporter la configuration concernant le mapping entre le rôle IAM des Worker Nodes et le group K8S associé. Sans cela, le cluster ne sera plus fonctionnel.

Cela implique aussi de définir à des endroits différents la pile applicative K8S et les droits qui lui sont associés.

2048-game

Ici, il faut en amont créer le namespace et les identités permettant l’administration de ce namespace. Il faut pour cela revenir dans le projet Terraform EKS et modifier la partie liée aux IAM / RBAC.

Terraform
Kubernetes

Dans le repository de l’application K8S, nous aurons une partie dédiée aux ressources Kubernetes (deployment, ingress, service) via kustomize et une partie dédiée aux ressources Terraform (record Route53) qui mappe via AWS SSM Parameter Store l’ALB crée par l’ingress controller.

Voici la ligne de commande qui envoie après déploiement de l’application K8S l’information concernant le fqdn de l’ALB déployé via l’ ingress dans AWS SSM :

Nous utilisons cette valeur dans une petit projet Terraform de création de record DNS :


A ce stade, nous avons un cluster Kubernetes pleinement fonctionnel sur AWS via des services managés et une gestion des droits AWS possible au niveau des droits du cluster et des ressources AWS disponibles pour les applications.

Nous avons un ALB Ingress Controller prêt à recevoir des demandes de ingress spécifiques.

Et une application Kubernetes usant de cet ingress .

C’est donc maintenant fini pour cette story.

Merci pour votre lecture. Si cet article vous a plu, merci de le partager et de clicker sur “les claps” 👏

skale-5

Infogéreur 100 % DevOps de vos applications sur les Cloud…

Thanks to Yann

Philippe Vidal

Written by

skale-5

skale-5

Infogéreur 100 % DevOps de vos applications sur les Cloud AWS, GCP et AZURE. Nous sommes aussi certifiés KUBERNETES. Nous migrons les applications (Move2cloud), nous concevons les architectures Cloud natives, nous assurons la disponibilité 24/7 en intégrant réellement le DevOps.

More From Medium

More on Techbysk5 from skale-5

More on Techbysk5 from skale-5

How to redirect logs to stdout?

Dec 6, 2019 · 2 min read

1

More on Kubernetes from skale-5

More on Kubernetes from skale-5

Kubernetes expliqué à ma fille

More on Techbysk5 from skale-5

More on Techbysk5 from skale-5

19 Memes about Kubernetes

Dec 3, 2019 · 2 min read

50

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade