POC 3 AWS : Comment déployer une AMI personnalisée sur EKS

Introduction

Dans cet article nous allons montrer comment déployer une AMI personnalisée sur EKS afin de répondre à notre besoin.

Dans l’optique de faire cohabiter Kubernetes avec Ceph nous avons mis en évidence une limite du service EKS. (voir POC 2)

Nous allons ainsi étudier un cas concret : comment peut-on utiliser Ceph comme StorageClass sur un cluster EKS ?

Contexte

Nous avons reproduit un cluster EKS sur le cloud AWS afin de faciliter nos tests de sauvegarde (via velero) et cela nous a permis de mettre en évidence certaines limites d’un Kubernetes managé.

Kubernetes Managé sur AWS (EKS)

Prérequis

Je ne vais pas expliquer ici les différentes étapes afin d’avoir un VPC prêt à l’emploi, cependant il faut s’assurer que l’on respecte les best practices AWS.

Présentation de l’infrastructure

image5-2

Une fois le VPC mis en place, nous pouvons passer à la création de notre cluster EKS.

Configuration des rôles IAM via CloudFormation

Une des premières étapes consiste à créer les rôles IAM pour les NodeGroups. AWS nous fournit une stack CloudFormation déjà prête pour l'occasion.

image8-1

Ce rôle sera nécessaire pour la création du Cluster et la gestion des nodes par la suite.

La seconde étape, une fois le cluster prêt à l’emploi, est de configurer l’accès depuis notre poste.

Cet accès se fera via la commande kubectl. Afin de contacter notre cluster nous devons configurer le fichier Kubeconfig en conséquence.

Pour cela, il nous faudra :

  • l’API Server Endpoint
  • le Cluster ARN
  • le Cluster IAM ROLE ARN (ex: arn:aws:iam::44XXX:role/AllowEKSmanageCluster)
  • le certificat d'autorité

Ces paramètres peuvent être trouvés sur le tableau de bord du cluster EKS.

Exemple de fichier kubeconfig pour EKS:

apiVersion: v1
clusters:
- cluster:
    server: https://D31xxxxxx.sk1.eu-west-3.eks.amazonaws.com ## L’API Server Endpoint
    certificate-authority-data: LS0tLxxxxxxxX ## Le certificat d’autorité
  name: eks-cluster14 ## nom du cluster
contexts:
- context:
    cluster: eks14-cluster14
    user: aws
  name: aws
current-context: aws
kind: Config
preferences: {}
users:
- name: aws
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      command: aws-iam-authenticator ## Choix de la méthode d’authentification
      args:
        - "token"
        - "-i"
        - "test"

Conseil pratique

La gestion de plusieurs fichiers Kubeconfig peut vite s'avérer fastidieuse.

Il existe une commande kubectl qui permet de merger nos différentes configs :

cd .kube/ && mv config config.ORIG

KUBECONFIG=config:config1:config2:configEKS kubectl config view --merge --flatten > config

On obtient alors un fichier config unique qui contient la configuration de l’ensemble de nos accès aux différents cluster Kubernetes.

Il est également possible d’utiliser la commande eksctl utils write-kubeconfig --cluster clustername qui fait tout ça automatiquement pour nous, y compris le merge des fichiers de config.

Je vous recommande également l’usage des outils kubectx et kubens (voir ici) afin de faciliter l’administration et le switch entre nos différents environnements Kubernetes existants.

L’accès au cluster EKS devrait maintenant être opérationnel. L’étape suivante consiste à ajouter des workernodes afin de pouvoir commencer à provisionner des pods.

Pour rappel, par défaut aucun workerNode n'est lancé lors de la création de notre Cluster EKS.

Ici, nous avons 2 choix soit via un nodeGroup standard soit via un custom nodeGroup .

  • Choix 1 : NodeGroup Standard

C'est le choix recommandé par AWS, il peut être créé directement via la console EKS et inclut l’AMI EKS-Optimized standard fournie par AWS.

  • Choix 2 : Custom NodeGroup

AWS ne nous permet pas de choisir facilement quelle AMI nous voulons utiliser pour déployer nos nodeGroups. Si nous voulons des images modifiées (ex: ajouter des features/packages non proposés par AWS par défaut), cela passe par la création d'une stack CloudFormation.

Création d’une AMI pour inclure les binaires Ceph

Rappel, dans notre cas d’étude, nous souhaitons connecter notre cluster Ceph et Kubernetes ensemble afin de fournir des volumes persistants sur Kubernetes.

Nous aurions bien pu nous affranchir de créer une custom AMI pour ce POC et installer manuellement les paquets Ceph nécessaires sur nos workers mais cela n’est pas Prod-Ready pour une utilisation réelle et nous oblige à maintenir l'état de nos workers en cas de scaling de nos instances.

Pour ce faire, il est plutôt recommandé d’utiliser amazon-eks-ami qui nous permet de créer facilement une custom AMI EKS Optimized qui pourra être utilisée dans une pipeline CI/CD si le besoin se fait sentir à l'avenir et être utilisée dans notre AutoscalingGroup lors du scaleOut de nos workers.

Cet outil se base sur Packer de Hashicorp, et voici un extrait du fichier install-worker.sh que nous avons modifié :

   53 # Install necessary packages
   54 sudo yum install -y \
   55     aws-cfn-bootstrap \
   56     awscli \
   57     ... \
   61     ec2-instance-connect \
   62     nfs-utils \
   63     socat \
   64     unzip \
   65     ceph-common \
   66     wget

Ici nous incluons seulement le paquets ceph-common qui installera le binaire rbd sur l'ensemble de nos workerNodes afin que ces derniers puissent gérer les volumes RBD créent.

Pensez également à prendre soin d’ajuster les variables du fichier eks-worker-al2.json afin que cela colle à votre besoin (ex: aws_region, instance_type, associate_public_ip_address, volume_size etc).

Une fois l'exécution de amazon-eks-ami terminée, nous aurons donc une AMI personnalisée disponible sur notre compte AWS que l’on pourra appeler dans la stack CloudFormation.

Création de la stack CloudFormation pour ajouter des customs workerNodes au Cluster EKS

Le github du projet awslabs/amazon-eks-ami fournit la stack CloudFormation officielle utilisée par AWS (amazon-eks-nodegroup.yaml) pour créer les workerNodes standard.

Cette dernière, prend plusieurs paramètres en entrée dont le NodeImageId qui correspond à l’ID de l’image à utiliser (notre fameuse AMI personnalisée).

Un autre paramètre essentiel à renseigner est le paramètre BootstrapArgument, il permet d’ajouter des options pour faire rejoindre nos workers dans notre cluster EKS existant.

Ces arguments seront ajoutés aux Userdatas de l’autoscaling pour le provisionning de nos instances.

image2-1

Voir ici le fichier bootstrap.sh pour plus de détails.

Exemple de la stack CFN

image7-2

Sans cela, nos workers fraîchement démarrés ne seront jamais inclus au Cluster.

Attention, contrairement à la création d’un nodeGroup standard, nous n’aurons pas de nodeGroup visible sur la console EKS.

Exemple de tableau de bord pour un nodeGroup standard

image4-1

Nos workernodes seront visibles sur la console EC2 dans la catégorie Autoscaling et l’ajustement des paramètres se fera sur l’ASG associé et/ou sur la stack CloudFormation.

image6-2

Modification des permissions EKS pour joindre le cluster

Autre point important, il faut absolument modifier la ConfigMap aws-auth sur notre cluster EKS afin d’autoriser nos workers à rejoindre le cluster, sans cela impossible d’avoir des workers fonctionnels dans notre cluster.

Voici un Exemple

image1-2

Une fois ces étapes réalisées, nous avons nos différents workernodes présents dans notre cluster EKS fonctionnant sous l’AMI personnalisée.

image3-2

Conclusion

Cet article met évidence quelques limitations de l’usage d’un Kubernetes managé sur un cloud provider.

Cela peut être assez déroutant comme première approche pour quelqu’un ayant eu l’habitude de gérer des clusters Kubernetes on-premise.

Heureusement, ces étapes supplémentaires ne sont pas insurmontables et nous pouvons faire les modifications voulues en contournant le fonctionnement initial.