Contexte et objectifs

Présentation de la chaßne CI/CD

Avec la culture DevOps, qui consiste Ă  automatiser au maximum la chaĂźne d’intĂ©gration et rĂ©duire l’intervention humaine, diffĂ©rentes structures se sont dĂ©veloppĂ©es. Aujourd’hui, cette chaĂźne d’intĂ©gration, aussi appelĂ©e, pipeline CI/CD, est divisĂ©e en deux parties :

  • L’intĂ©gration Continue ou « Continuous Integration » (CI) permettant d’intĂ©grer continuellement de nouvelles fonctionnalitĂ©s grĂące Ă  l’exĂ©cution d’une suite d’actions, tout en supprimant ou limitant l’impact envers les utilisateurs ,
  • Le DĂ©ploiement Continu « Continuous Deployement Â» (CD) consistant Ă  dĂ©ployer les nouvelles fonctionnalitĂ©s de façon totalement automatique. À la diffĂ©rence de la premiĂšre partie de la chaĂźne d’intĂ©gration, il existe diffĂ©rents types de dĂ©ploiements :
    • Le « Continuous Delivery Â» permettant de dĂ©ployer automatiquement les fonctionnalitĂ©s, avec nĂ©anmoins, l’intervention d’un leader technique/manager afin de valider le dĂ©ploiement en production,
    • Le « Progressive Delivery Â», version plus moderne du « Continuous Delivery Â» consiste quant Ă  lui, Ă  dĂ©ployer les nouvelles fonctionnalitĂ©s progressivement pour les utilisateurs. Les plus connues sont « Canary Deployement Â», « A/B testing Â» ou encore « Observability Â».

Kubernetes

Kubernetes est devenu LA solution par excellence pour l’orchestration des conteneurs. Dans Kubernetes tout est objet, il permet notamment, la gestion avancĂ©e du cycle de vie des conteneurs avec un mode dĂ©claratif (Ă  privilĂ©gier) assurant que l’Ă©tat souhaitĂ© soit toujours atteint, la gestion de l’idempotence dans la dĂ©claration des objets, la crĂ©ation d’une couche abstraite avec la notion de services et non plus d’adressage IP et encore Ă©normĂ©ment de choses… De plus, Kubernetes permet aisĂ©ment en fonction de la demande, d’adapter les ressources manuellement et/ou automatiquement (scalabilitĂ© et Ă©lasticitĂ©) et de les rendre hautement disponibles (HA) sur diffĂ©rents types de providers (Cloud, On-premise, Machine Virtuelle, Bare Metal …).

GitOps

Définition

Le GitOps est attachĂ© Ă  la partie Delivery de chaĂźne d’IntĂ©gration Continue. Il repose sur l’outil de versioning Git, avec les plateformes telles que GitHub, GitLab ou CodeCommit(AWS)
 Avec l’approche de type GitOps, le projet Git est considĂ©rĂ© comme l’unique source de vĂ©ritĂ© pour la dĂ©claration des infrastructures ou des applications. En effet, celles-ci sont dĂ©clarĂ©es dans des manifestes directement dans le projet Git. Lorsque des modifications sont apportĂ©es au repository Git, celles-ci sont automatiquement dĂ©ployĂ©es dans le cluster. Ce redĂ©ploiement automatique est rendu possible grĂące Ă  un opĂ©rateur qui scrute en temps rĂ©el le projet Git. Cet opĂ©rateur, permet aussi de s’assurer que l’Ă©tat effectif est conforme Ă  l’Ă©tat dĂ©sirĂ© au sein du cluster, on parle alors d’observabilitĂ©. Il existe deux approches quand on Ă©voque le GitOps, la mĂ©thode classique de type « push » et la mĂ©thode de type « pull » davantage associĂ©e au GitOps.

Méthode Push Vs Pull

  • MĂ©thode push : c’est la mĂ©thode classique pour rĂ©aliser un pipeline CI/CD. AprĂšs le commit, suite Ă  la mise Ă  jour du code et le push de cette nouvelle version sur le Source Code Management (SCM), une sĂ©rie de d’actions est exĂ©cutĂ©e (exĂ©cution de tests, building d’une nouvelle image, scan des failles de sĂ©curitĂ©s, redĂ©ploiement de la nouvelle image
) grĂące Ă  des outils de CI tels que GitLab CI, Jenkins, Travis CI
 permettant d’ordonnancer les stages. Cette mĂ©thode peut aussi ĂȘtre associĂ©e Ă  l’approche de type GitOps car l’application ou l’infrastructure est dĂ©clarĂ©e dans le projet Git considĂ©rĂ© comme unique source de vĂ©ritĂ©.
Pipeline CI/CD classique (source: Weaveworks)
  • MĂ©thode pull : C’est la mĂ©thode davantage associĂ©e au pipeline CI/CD de type GitOps. En effet, le dĂ©ploiement d’une nouvelle image dans le cluster n’est pas effectuĂ© par l’outil de CI mais par un opĂ©rateur. Celui-ci correspond Ă  un deamon constamment en exĂ©cution dans le cluster Kubernetes, qui va scruter en temps rĂ©el le repository oĂč sont hĂ©bergĂ©es les images et automatiquement dĂ©tecter lorsqu’une nouvelle image est buildĂ©e, grĂące Ă  la mise Ă  jour du tag de celle-ci. La dĂ©tection d’une nouvelle image permet Ă  l’opĂ©rateur de redĂ©ployer automatiquement l’application dans sa nouvelle version. L’opĂ©rateur permet aussi d’intĂ©grer la notion d’observabilitĂ© au sein du cluster Kubernetes en s’assurant que l’Ă©tat effectif est conforme Ă  l’Ă©tat dĂ©sirĂ©. En cas de non conformitĂ© la possibilitĂ© de remonter des alertes Ă  l’aide de diffĂ©rents outils.
Pipeline CI/CD avec approche GitOps (source: Weaveworks)

Worflow GitOps avec Flux CD

Composants GitOps dans un cluster Kubernetes (source: Weaveworks)

Le projet

Présentation du projet

Dans ce tutoriel, nous dĂ©montrerons comment mettre en place et gĂ©rer un projet Git via l’application GitLab hĂ©bergĂ©e sur un hĂŽte privĂ©. Nous activerons la registry Docker native Ă  GitLab, puis nous verrons comment intĂ©grer facilement un cluster Kubernetes directement depuis l’interface web.

Dans la seconde partie de ce tutoriel, nous rĂ©aliserons un pipeline CI/CD classique avec GitLab CI et Kubernetes. Enfin, nous dĂ©ploierons l’opĂ©rateur Flux dans le cluster et nous modifierons le prĂ©cĂ©dent pipeline afin d’attribuer la gestion de la partie CD Ă  Flux et au GitOps.

Les deux pipelines seront basĂ©s sur le dĂ©ploiement d’une simple application web dĂ©veloppĂ©e en Node.js. Ici, la complexitĂ© de l’application n’est pas importante, l’essentiel est de comprendre comment construire, mettre en place les diffĂ©rentes briques et les ordonnancer.

Infrastructure Cible

Infrastructure finale cible

Configuration

1 – Mise en place de l’environnement

a – Information sur l’infrastructure

Notre infrastructure sera hĂ©bergĂ©e sur le provider cloud AWS. Nous disposerons de 4 serveurs de type instance EC2. L’ensemble de nos VMs utiliseront la distribution Linux Debian 9.

Un serveur EC2 hĂ©bergera l’application GitLab Community Edition dĂ©ployĂ©e dans un conteneur Docker. Voici les caractĂ©ristiques :

[table id=gitops-infor-srv-gitlab /]

Les 3 autres serveurs EC2 représenteront un cluster Kubernetes multi-noeuds avec un master et deux workers. Voici les caractéristiques :

[table id=gitops-infor-srv-cluster /]

b – DĂ©ploiement de l’infrastructure

Déploiement sur AWS

Afin de dĂ©ployer entiĂšrement une infrastructure fonctionnelle et prĂȘte Ă  l’emploi, je vous fournis un tutoriel complet ainsi que la stack CloudFormation. Les ressources se trouvent sur mon repository GitHub Ă  l’adresse suivante :

→ Repos GitHub : https://github.com/samiamoura/gitops-training/tree/master/aws-stack

Déploiement sur AWS Educate

Si vous suivez le cursus DevOps chez EazyTrainig et que vous avez accĂšs Ă  la plate-forme d’entraĂźnement AWS Educate, je vous fournis Ă©galement un tutoriel complet ainsi que la stack CloudFormation permettant de dĂ©ployer la mĂȘme infrastructure. Les ressources se trouvent sur mon repositroy GitHub Ă  l’adresse suivante :

→ Repos GitHub : https://github.com/samiamoura/gitops-training/tree/master/aws-educate-stack

Quel que soit le mode de dĂ©ploiement, l’infrastructure met environ 5 minutes pour ĂȘtre provisionnĂ©e et environ 5 minutes supplĂ©mentaires pour ĂȘtre fonctionnelle. Voici le schĂ©ma de l’infrastructure aprĂšs le dĂ©ploiement :

Infrastructure aprÚs les déploiement de la stack CloudFormation

2 – RĂ©cupĂ©ration du code source

a – RĂ©cupĂ©ration du code de l’application web

Tout au long de ce tutoriel, nous travaillerons avec une application web appelĂ©e  Â« shark-app ». Cette application, dĂ©veloppĂ©e en Node.js, contient deux pages web qui donnent une brĂšve prĂ©sentation sur les requins. Le serveur de l’application Ă©coute sur le port 8080.

Le code source de l’application se trouve sur mon repository GitHub Ă  l’adresse suivante :

→ Repos GitHub : https://github.com/samiamoura/gitops-training

Depuis le serveur GitLab, rĂ©cupĂ©rez le code source Ă  l’aide de la commande suivante :

git clone https://github.com/samiamoura/gitops-training.git

b – Test de l’application

Nous allons tester que l’application est fonctionnelle.

Depuis le serveur GitLab, se rendre dans le dossier « gitops-training/shark-application » Ă  l’aide de la commande suivante :

cd $HOME/gitops-training/shark-application

Buildez l’image Ă  partir du Dockerfile prĂ©sent dans le dossier Ă  l’aide de la commande suivante :

docker build -t shark-app:1.0 .

DĂ©marrez un conteneur « shark-app » Ă  partir de cette image et exposez-le sur le port 8080 de l’hĂŽte Ă  l’aide de la commande suivante :

docker run -d --name shark-app -p 8080:8080 shark-app:1.0

Testez que le conteneur « shark-app » est Up Ă  l’aide de la commande suivante :

docker container  ps | grep -i shark-app

Le rĂ©sultat doit ĂȘtre similaire Ă  :

CONTAINER ID   IMAGE            COMMAND                  CREATED         STATUS         PORTS                    NAMES
d04f583994e9   shark-app:1.0    "docker-entrypoint.s
"   3 minutes ago   Up 7 seconds   0.0.0.0:8080->8080/tcp   shark-app

Le conteneur « shark-app » est maintenant exposĂ© sur le port 8080 du serveur GitLab. Testons que l’application est fonctionnelle. Entrez l’adresse IP publique de l’hĂŽte sur le port 8080 dans un navigateur :

http://35.170.208.112:8080/

Le rĂ©sultat doit ĂȘtre similaire Ă  :

L’application est fonctionnelle.

Stoppez et supprimez le conteneur « shark-app » Ă  l’aide des commandes suivantes :

docker container stop shark-app
docker container rm shark-app

3 – Gestion du projet GitLab

Pour rappel, nous avons dĂ©ployĂ© l’application GitLab dans un conteneur Docker. L’interface web de l’application est joignable en utilisant l’adresse IP publique du serveur GitLab. Entrez l’adresse IP publique du seveur GitLab dans un navigateur.

http://35.170.208.112/

Etant donnĂ© qu’il s’agit d’une instance fraichement dĂ©ployĂ©e, vous arrivez sur une page web vous demandant de dĂ©finir le mot de passe pour l’utilisateur « root Â». DĂ©finissez un mot de passe assez robuste puis connectez-vous en tant que « root Â».

a – DĂ©finition de l’utilisateur et crĂ©ation du projet

Pour des raisons de sĂ©curitĂ©, il est recommandĂ© d’Ă©viter d’utiliser le compte « root Â» et de crĂ©er un utilisateur spĂ©cifique. Nous avons créé l’utilisateur  Â« samiamoura Â» en tant qu’administrateur. AprĂšs avoir créé un utilisateur et dĂ©fini son mot de passe, connectez-vous avec celui-ci. Lors de la premiĂšre connexion, il vous sera demandĂ© de changer le mot de passe.

Depuis l’interface web de l’application GitLab, crĂ©ez un projet avec les caractĂ©ristiques suivantes :

  • Project name : shark-application
  • Visibility Level : Public

Puis cliquez sur Create Project.

b – Activation de la Registry GitLab

GitLab possĂšde nativement une registry Docker permettant d’hĂ©berger nos images Docker directement sur l’application. Cependant, il est nĂ©cessaire d’activer cette fonctionnalitĂ© pour chaque projet.

Pour activer la registry Docker de GitLab, je vous redirige vers un article que j’ai rĂ©digĂ©, traitant en dĂ©tail ce sujet. Rendez-vous sur le paragraphe #6 de l’article Ă  l’adresse suivante :

https://www.eazytraining.fr/informatique/devops/activation-du-container-registry-docker-sur-gitlab-ce/
Article sur l’activation de la Registry GitLab

AprÚs avoir activé la registry Docker pour le projet « shark-application », vous pouvez récupérer les caractéristiques de celle-ci en cliquant, dans le menu latéral à gauche, sur Registry :

Caractéristiques du container registry GitLab

L’adresse de la registry correspond Ă  : ec2-35-170-208-112.compute-1.amazonaws.com/samiamoura/shark-application

Vous pouvez vous logguer Ă  la registry Ă  l’aide de la commande suivante :

docker login ec2-35-170-208-112.compute-1.amazonaws.com

Vous pouvez puller, tagguer et pousser des images sur la registry Ă  l’aide des commandes suivantes :

docker pull nginx:latest
docker tag nginx:latest ec2-35-170-208-112.compute-1.amazonaws.com/samiamoura/shark-application/nginx:latest
docker push ec2-35-170-208-112.compute-1.amazonaws.com/samiamoura/shark-application/nginx:latest

c – DĂ©ploiement de la clĂ© SSH

Pour interagir aisément et en toute sécurité avec notre projet hébergé sur GitLab, il est recommandé de générer une paire de clés privée/publique.

Depuis le serveur GitLab, gĂ©nĂ©rez une paire de clĂ©s privĂ©e/publique Ă  l’aide de la commande suivante :

ssh-keygen -t rsa

RĂ©cupĂ©rez le contenu de la clĂ© publique Ă  l’aide la commande suivante :

cat $HOME/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDO6qL3BTiBRMOq95HMHEuQfUpXPqRIX2va/JSiHkX1AuC56+nwxeM6itTgX2N11uzYS/SHTDMygZNMckPP6o/G8qM/EuwwFWL5xJRtBLS8L92RpR8YG5kHhwGSJkDCSj07ZYp4TW/fMbup9ZDGgkVUzbJC9Am42UvC3x/Nt9Mn8VG5syXcbU3f7mQZU+6FmOamexZhx5bOPOjKbXbYpB+5Bl1JLJYvWpf5F5ks2YFHsX7VeCgyEdbGUmTIzDgHCx8N/IL5LFPii4oln4e/ZenysUZ+fF8+JXE9BJ0wtYg6n1Mc8GNJfEIfytSyQZBBbTAnUc2ZNqlYjGnnK88DAsYb admin@ip-172-31-71-90

Depuis l’interface web GitLab, se rendre dans Settings , puis sur la page suivante, dans le menu latĂ©ral Ă  gauche, se rendre dans SSH Key. Ajoutez la clĂ© publique rĂ©cupĂ©rĂ©e prĂ©cĂ©demment et cliquez sur Add key.

Déploiement de la clé publique

d – Initialisation du projet Git

AprĂšs avoir créé notre projet et dĂ©ployĂ© la clĂ© publique sur l’application GitLab, nous allons Ă  prĂ©sent crĂ©er un dossier qui sera notre rĂ©pertoire de travail durant ce tutoriel.

Depuis le serveur GitLab, crĂ©ez un dossier « shark-application » et copiez le code source de l’application Ă  l’intĂ©rieur, Ă  l’aide des commandes suivantes :
Information : Le code source de l’application se trouve dans le dossier gitops-training clonĂ© au dĂ©but de cet article :

cd $HOME
mkdir $HOME/shark-application
cp $HOME/gitops-training/shark-application/* -r $HOME/shark-application/

Verifiez que le code source Ă  bien Ă©tĂ© copiĂ© dans le rĂ©pertoire Ă  l’aide de la commande suivante :

ls -l $HOME/shark-application
total 12
drwxr-xr-x 4 admin admin 4096 Jul 20 22:14 app
-rw-r--r-- 1 admin admin  289 Jul 20 22:14 Dockerfile

À la racine du rĂ©pertoire « shark-application », initialisez le projet Git, ajoutez le remote distant, ajoutez tous les fichiers, commitez les changements et poussez la mise Ă  jour sur le projet GitLab :
Information : Editez la variable GIT_URL avec l’url de votre projet Git.

GIT_URL=ssh://git@ec2-35-170-208-112.compute-1.amazonaws.com:2222/samiamoura/shark-application.git
cd $HOME/shark-application
git init
git remote add origin $GIT_URL
git add .
git commit -m "Initial commit"
git push -u origin master

Le code source est désormais hébergé sur notre SCM GitLab :

4 – IntĂ©gration du cluster Kubernetes au projet GitLab

GitLab permet facilement d’intĂ©grer un cluster Kubernetes Ă  n’importe quel projet via son interface web. Pour ce faire, dans cette section, nous allons crĂ©er les ressources et rĂ©cupĂ©rer les informations nĂ©cessaires.

Information : L’ensemble des commandes de cette section seront Ă  effectuer, depuis le nƓud master de notre serveur Kubernetes.

a – Autorisation des requĂȘtes rĂ©seau sortantes

Pour pouvoir intĂ©grer le cluster Kubernetes, il faut autoriser les requĂȘtes rĂ©seau sortantes. Depuis l’interface web GitLab, se rendre dans Admin Area en cliquant sur l’icĂŽne , sur la page suivante dans le menu latĂ©ral Ă  gauche, se rendre dans Settings > Network.

Sur la page de configuration Network, se rendre sur Outbound requests, cliquez sur Expand et cochez la case « Allow requests to the local network from hooks and services Â» puis sauvegarder les changements.

Autoriser les requĂȘtes rĂ©seau sortantes

b – CrĂ©ation des ressources

Pour intĂ©grer le cluster Kubernetes Ă  GitLab, nous devons crĂ©er les autorisations nĂ©cessaires. Effectivement, GitLab a besoin d’administrer le cluster pour pouvoir effectuer les opĂ©rations nĂ©cessaires. Nous utiliserons le principe de RBAC de Kuberntes pour attribuer les permissions requises Ă  l’application GitLab.

Logguez-vous en tant que super administrateur à l’aide de la commande suivante :

sudo su -
Création du ServiceAccount

CrĂ©ez un ServiceAccount gitlab-admin pour l’instance GitLab Ă  l’aide de la commande suivante :

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: gitlab-admin
  namespace: kube-system
EOF
serviceaccount/gitlab-admin created
Attribution des permissions

À prĂ©sent, nous devons associer le ServiceAccount gitlab-admin prĂ©cĂ©demment créé, au ClusterRole cluster-admin dĂ©jĂ  prĂ©sent dans notre cluster Ă  l’aide d’un ClusterRoleBinding. À noter que le ClusterRole cluster-admin, bĂ©nĂ©ficie de toutes les permissions sur l’ensemble des ressources du cluster Kubernetes.

CrĂ©ez un ClusterRoleBinding gitlab-admin Ă  l’aide de la commande suivante :

cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: gitlab-admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: gitlab-admin
  namespace: kube-system
EOF
clusterrolebinding.rbac.authorization.k8s.io/gitlab-admin created

Les ressources et autorisations nĂ©cessaires Ă  l’intĂ©gration du cluster Kubernetes sont maintenant créées.

c – RĂ©cupĂ©ration des informations

À prĂ©sent nous allons rĂ©cupĂ©rer les informations permettant de configurer l’intĂ©gration du cluster Ă  GitLab.

RĂ©cupĂ©rez l’URL de l’API Server Ă  l’aide de la commande suivante :

APIURL=$(kubectl config view -o jsonpath='{.clusters[0].cluster.server}')
echo $APIURL

Le rĂ©sultat doit ĂȘtre similaire Ă  :

https://172.31.67.215:6443

RĂ©cupĂ©rez le root Certificate Authority (CA) Ă  l’aide de la commande suivante :

kubectl config view --raw \
-o=jsonpath='{.clusters[0].cluster.certificate-authority-data}' \
| base64 --decode

Le rĂ©sultat doit ĂȘtre similaire Ă  :

-----BEGIN CERTIFICATE-----
MIICyDCCAbCgAwIBAgIBADANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwprdWJl
cm5ldGVzMB4XDTIwMDcyMDIwNTkzNFoXDTMwMDcxODIwNTkzNFowFTETMBEGA1UE
AxMKa3ViZXJuZXRlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMWz
W0AZfbwOtWFtMz2x7mpkQ0h1uD4RLihEWk1E4MyNkWg/DghZ3KUFGTRWxjUXnqQp
1F2urfM34Hl/Q8LrH56KMSIBQvuUjo8SMs0XvBiOtD3IIcjcK9zc8Q75J0W5hbUh
S460lX0OxjVHDUJKC6SJyfsVeePm3ztipUDN7AVSp30yBP1qODMbKWplmYAWSy/I
1WZPrtn+gTptzSccmrK58u/ZHzDSQBQTgXyGPeeyDmmzdX1PSj+Y3te/1gWfpArF
MVvng1xA5GR+EkOSx9CL0Tr2Qmklp+LJrdLFf9BnjHD3sD5vMwJtD4MDY8ZGApiK
iDCGd5KqTZ1MdOsAm9UCAwEAAaMjMCEwDgYDVR0PAQH/BAQDAgKkMA8GA1UdEwEB
/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBABI6EytDPnInz4pAI1xNgWQJnLLY
uaSfpm/PdX/B/RyEfytYx7rVT7r/eRmxqUu60VmPMHSjrJPDH0CYjFsXofk4GpZs
rkKFqfBcEepZ/Z64r26LypCjEgHZOm1Hkxd6u3+AJxOTtZCQ5Isx7s+o6DvlovSE
wWpcaOidlqneuEJapf1P7FyFOtPNeCdnvBH3hVY/UBqvSl40EOIFZEkE8iAkLwMh
8aT5O5i7hdQjli/gmOgahzY4BOQLUS7q4t1QzbmzbY5VFAuJq0kLArGPltRcldJp
c4+RCyT39mSnCnY/0TCNQHRR2XOSyH+eunw0CigACz8aQOd24tB3C9e1v88=
-----END CERTIFICATE-----

RĂ©cupĂ©rez le Secret associĂ© au ServiceAccount gitlab-admin puis rĂ©cupĂ©rez le token associĂ© Ă  l’aide des commandes suivantes :

SECRET=$(kubectl -n kube-system get secret | grep gitlab-admin | awk '{print $1}')
TOKEN=$(kubectl -n kube-system get secret $SECRET -o jsonpath='{.data.token}' | base64 --decode)
echo $TOKEN

Le rĂ©sultat doit ĂȘtre similaire Ă  :

eyJhbGciOiJSUzI1NiIsImtpZCI6IkY2czdtNzZrTGp3UHFabXhEdllmYU11TmZ2d3cwNGpwc2p2R3Mwbks4NlEifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJnaXRsYWItYWRtaW4tdG9rZW4tazVqOXAiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZ2l0bGFiLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiMWI1YTFmMTAtOTMyZC00ZDI4LWIxZDYtZjIyNjYyM2QzYjIzIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmdpdGxhYi1hZG1pbiJ9.kudhWIYapdYl8fvY8lxWB_FJXhxd6zc-AtlYMvPFJhoxPh2giau_DYQsLwwddoTsaDj5hPCyYVURh7mChEhO7d1tPK8G6OZnsiIOaAkuiYp74eGaH3tRywQBJb7mqAtkZE0dEB29XRILzPOlC8nXXDssmhm9Mq_NTEM4pSQDt0jQGTrfOTN0ym80xjhcGhfQm-chgCLLuSqAnRphTqw--zx_K9OTqhnRPJhcgmojmJxwYmrAZCtrHd5-P6KVwYyn0qrvKvnLlSr-rumGIdZwmSo_00HluxwuV29JbHMPOrAdM89L8CYui7hkMJApAXSM87g3ROTyGtYGj34nxpb8wg

Nous disposons Ă  prĂ©sent des informations nĂ©cessaires pour configurer l’intĂ©gration du cluster Kubernetes Ă  GitLab.

d – Configuration et intĂ©gration du cluster Kubernetes

Depuis la page principale du projet, dans le menu latéral à gauche, se rendre dans Operations > Kubernetes :

Sur la page suivante, cliquez sur Add Kubernetes cluster :

Sur la nouvelle page, cliquez sur Add existing cluster, et configurez l’intĂ©gration du cluster avec les informations rĂ©cupĂ©rĂ©es lors de la section prĂ©cĂ©dente :

  • Kubernetes cluster name : k8s cluster
  • API URL : https://172.31.67.215:6443
  • CA Certificate :
-----BEGIN CERTIFICATE-----
MIICyDCCAbCgAwIBAgIBADANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwprdWJl
cm5ldGVzMB4XDTIwMDcyMDIwNTkzNFoXDTMwMDcxODIwNTkzNFowFTETMBEGA1UE
AxMKa3ViZXJuZXRlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMWz
W0AZfbwOtWFtMz2x7mpkQ0h1uD4RLihEWk1E4MyNkWg/DghZ3KUFGTRWxjUXnqQp
1F2urfM34Hl/Q8LrH56KMSIBQvuUjo8SMs0XvBiOtD3IIcjcK9zc8Q75J0W5hbUh
S460lX0OxjVHDUJKC6SJyfsVeePm3ztipUDN7AVSp30yBP1qODMbKWplmYAWSy/I
1WZPrtn+gTptzSccmrK58u/ZHzDSQBQTgXyGPeeyDmmzdX1PSj+Y3te/1gWfpArF
MVvng1xA5GR+EkOSx9CL0Tr2Qmklp+LJrdLFf9BnjHD3sD5vMwJtD4MDY8ZGApiK
iDCGd5KqTZ1MdOsAm9UCAwEAAaMjMCEwDgYDVR0PAQH/BAQDAgKkMA8GA1UdEwEB
/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBABI6EytDPnInz4pAI1xNgWQJnLLY
uaSfpm/PdX/B/RyEfytYx7rVT7r/eRmxqUu60VmPMHSjrJPDH0CYjFsXofk4GpZs
rkKFqfBcEepZ/Z64r26LypCjEgHZOm1Hkxd6u3+AJxOTtZCQ5Isx7s+o6DvlovSE
wWpcaOidlqneuEJapf1P7FyFOtPNeCdnvBH3hVY/UBqvSl40EOIFZEkE8iAkLwMh
8aT5O5i7hdQjli/gmOgahzY4BOQLUS7q4t1QzbmzbY5VFAuJq0kLArGPltRcldJp
c4+RCyT39mSnCnY/0TCNQHRR2XOSyH+eunw0CigACz8aQOd24tB3C9e1v88=
-----END CERTIFICATE-----
  • Service Token :
eyJhbGciOiJSUzI1NiIsImtpZCI6IkY2czdtNzZrTGp3UHFabXhEdllmYU11TmZ2d3cwNGpwc2p2R3Mwbks4NlEifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJnaXRsYWItYWRtaW4tdG9rZW4tazVqOXAiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZ2l0bGFiLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiMWI1YTFmMTAtOTMyZC00ZDI4LWIxZDYtZjIyNjYyM2QzYjIzIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmdpdGxhYi1hZG1pbiJ9.kudhWIYapdYl8fvY8lxWB_FJXhxd6zc-AtlYMvPFJhoxPh2giau_DYQsLwwddoTsaDj5hPCyYVURh7mChEhO7d1tPK8G6OZnsiIOaAkuiYp74eGaH3tRywQBJb7mqAtkZE0dEB29XRILzPOlC8nXXDssmhm9Mq_NTEM4pSQDt0jQGTrfOTN0ym80xjhcGhfQm-chgCLLuSqAnRphTqw--zx_K9OTqhnRPJhcgmojmJxwYmrAZCtrHd5-P6KVwYyn0qrvKvnLlSr-rumGIdZwmSo_00HluxwuV29JbHMPOrAdM89L8CYui7hkMJApAXSM87g3ROTyGtYGj34nxpb8wg
  • RBAC-enabled cluster : cochĂ©
  • GitLab-managed cluster : dĂ©cochĂ©

Puis cliquez sur Add Kubernetes cluster. Le cluster Kuberntes est à présent intégré à notre projet GitLab.

Information : Une fois le cluster Kubernetes intĂ©grĂ©, il est possible d’installer des applications tierces telles que Helm directement sur le cluster.

Application Ă  installer sur le cluster Kubernetes

5 – Mise en place d’une chaĂźne CI/CD simple

Dans ce chapitre, nous allons mettre en place un pipeline CI/CD simple avec GitLab CI qui sera dĂ©clenchĂ© Ă  chaque fois qu’une mise Ă  jour du projet Git aura Ă©tĂ© commitĂ©e puis poussĂ©e sur le SCM GitLab. Cette approche correspond Ă  la mĂ©thode « push » dĂ©finie au dĂ©but de cet article.

Pour rĂ©aliser et exĂ©cuter des pipelines, GitLab CI prend en compte les instructions dĂ©clarĂ©es dans un fichier au format YAML. Ce fichier qui s’appelle .gitlab-ci.yml, doit ĂȘtre placĂ© Ă  la racine du projet Git. GitLab dĂ©tecte automatiquement la prĂ©sence de ce fichier et Ă  chaque mise Ă  jour du projet, les instructions sont exĂ©cutĂ©es.

Information : L’ensemble des commandes de cette section seront à effectuer depuis le serveur GitLab.

CrĂ©ez le manifeste .gitlab-ci.yml Ă  la racine du projet « shark-application » Ă  l’aide de la commande suivante :

touch $HOME/shark-application/.gitlab-ci.yml

a – Configuration du Runner GitLab

Pour pouvoir rĂ©aliser des pipelines et exĂ©cuter les instructions dĂ©finies dans le fichier .gitlab-ci.yml, GitLab utilise le principe de Runners. Les Runner sont des agents lĂ©gers et scalables qui rĂ©cupĂšrent les instructions des jobs via l’API de coordination et renvoient les rĂ©sultats Ă  l’instance GitLab.

Avant de mettre en place nos pipelines et de pouvoir les exĂ©cuter, il est nĂ©cessaire de configurer le Runner GitLab. Dans un premier temps, nous allons configurer le Runner pour que celui-ci puisse accepter d’exĂ©cuter des jobs qui ne sont pas tagguĂ©s. Effectivement, pour faire simple et ne pas trop compliquer la comprĂ©hension de cet article, nous travaillerons uniquement avec des jobs non tagguĂ©s.

Depuis l’interface web GitLab, se rendre dans Admin Area en cliquant sur l’icĂŽne  , sur la page suivante, dans le menu latĂ©ral Ă  gauche, se rendre dans Overview > Runners. Puis sur la page qui apparaĂźt, cliquez sur le crayon pour Ă©diter les caractĂ©ristiques du Runner :

Sur la page suivante, remplir le formulaire avec les caractéristiques suivantes :

  • Run untagged jobs : Indicates whether this runner can pick jobs without tags cochĂ©
  • Les autres attributs peuvent ĂȘtre laissĂ©s avec les valeurs par dĂ©faut.

Puis cliquez sur Save changes.

Sur la mĂȘme page se rendre dans la section Restrict projects for this Runner :

Cliquez sur Enable en face du projet sami/shark-application afin d’activer le Runner pour notre projet. Le rĂ©sultat doit ĂȘtre similaire Ă  :

À prĂ©sent, nous pouvons vĂ©rifier que le Runner est bien activĂ© pour notre projet. Depuis l’interface GitLab, sur la page principale du projet « shark-application », se rendre dans Settings > CI/CD. Sur la page suivante, atteindre Runners puis cliquez sur Expand afin d’afficher les informations liĂ©es au Runner. Puis en bas de de la configuration du Runner, vĂ©rifiez que la pastille du Runner est verte. Cela signifie que le Runner est fonctionnel. Si celle-ci est rouge, il vous faudra juste cliquer sur le bouton Resume.

Le résultat final doit etre similaire à :

Le Runner est maintenant activé pour notre projet sami/shark-application.

b – DĂ©finition des stages du pipeline

Le manifeste .gitlab-ci.yml doit commencer par définir les différents stages qui seront réalisés dans notre pipeline. Nous disposerons de 4 stages :

  • Le stage « build » qui permettra de builder l’image Ă  partir du Dockerfile prĂ©sent dans le rĂ©pertoire,
  • Le stage « test » permettant de rĂ©aliser des tests simples sur l’image Docker qui aura Ă©tĂ© buildĂ©e prĂ©cĂ©demment,
  • Le stage « push » nous permettra de tagguer l’image Docker et de la pousser sur la Registry GitLab,
  • Le stage « deployment » qui dĂ©ploiera l’application dans le cluster Kubernetes.

Nous reviendrons en détails sur chaque stage tout au long de ce chapitre.

Ajoutez les diffĂ©rentes stages au fichier .gitlab-ci.yml Ă  l’aide de la commande suivante :

cat <<< 'stages:
  - build
  - test
  - push
  - deployment' >> $HOME/shark-application/.gitlab-ci.yml

c – DĂ©finition du stage « build »

Dans le stage « build », nous buildons une image Docker avec le tag tmp, nous nous connectons Ă  la Registry GitLab et nous poussons l’artefact sur la Registry.

Ajoutez le stage « build » au fichier .gitlab-ci.yml Ă  l’aide de la commande suivante :

cat <<< '
build:
  image: docker:stable
  stage: build
  services:
    - docker:dind
  script:
    - docker build -t $CI_REGISTRY_IMAGE:tmp .
    - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
    - docker push $CI_REGISTRY_IMAGE:tmp
  only:
  - master' >> $HOME/shark-application/.gitlab-ci.yml

Information : Les variables d’environnement CI_BUILD_TOKEN CI_REGISTRY seront automatiquement affectĂ©es par GitLab.

d – DĂ©finition du stage « test »

Dans le stage « test », nous exĂ©cutons un conteneur Ă  partir de l’artefact qui a Ă©tĂ© produit prĂ©cĂ©demment, nous rĂ©alisons des tests simples sur l’application puis nous nettoyons l’environnement . Les tests sur l’application permettent d’effectuer :

  • Un test de disponibilitĂ© en s’assurant que l’application est joignable,
  • Un test de fonctionnalitĂ© en s’assurant que la page web principale de l’application nous retourne le bon message.

Ajoutez le stage « test » au fichier .gitlab-ci.yml Ă  l’aide de la commande suivante :

cat <<< '
test:
  image: docker:stable
  stage: test
  services:
    - docker:dind
  script:
    - docker run -d --name shark-app -p 8080:8080 $CI_REGISTRY_IMAGE:tmp
    - sleep 10s
    - TEST=$(docker run --link shark-app samiamoura/curl -s http://shark-app:8080 | grep -i "Are you ready to learn about sharks?")
    - if [ $? -eq 0 ]; then  echo \"TEST OK\"; docker rm -f shark-app ; exit 0; else echo \"TEST KO\"; docker rm -f shark-app ; exit 1; fi;
  only:
  - master' >> $HOME/shark-application/.gitlab-ci.yml

e – DĂ©finition du stage « push »

Dans le stage « push », nous rĂ©cupĂ©rons l’image buildĂ©e lors du stage « build » puis nous tagguons cette image avec deux tags diffĂ©rents :

  • Le premier tag correspond Ă  la branche sur laquelle nous travaillons, en l’occurence la branche « master »,
  • Le second tag correspond quant Ă  lui, au hash du commit que nous venons d’exĂ©cuter.

Information : Dans la section suivante, nous expliquerons, l’intĂ©rĂȘt de tagguer l’image avec deux tags diffĂ©rents.

Ajoutez le stage « push » au fichier .gitlab-ci.yml Ă  l’aide de la commande suivante :

cat <<< '
push:
  image: docker:stable
  stage: push
  services:
    - docker:dind
  script:
    - docker image pull $CI_REGISTRY_IMAGE:tmp
    - docker image tag $CI_REGISTRY_IMAGE:tmp $CI_REGISTRY_IMAGE:$CI_BUILD_REF
    - docker image tag $CI_REGISTRY_IMAGE:tmp $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
    - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
    - docker push $CI_REGISTRY_IMAGE:$CI_BUILD_REF
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
  only:
  - master' >> $HOME/shark-application/.gitlab-ci.yml

Information : Dans les versions plus rĂ©centes de l’application GitLab, la variable d’environnement CI_BUILD_REF n’existe plus. Celle-ci a Ă©tĂ© remplacĂ©e par CI_COMMIT_SHA.

f – DĂ©finition du stage « deployment »

Avant de définir le stage « deployment », nous devons dans un premier temps, définir dans des manifestes Kubernetes, les ressources qui seront déployées dans le cluster. Ces fichiers déclaratifs seront situés dans le répertoire shark-application/kubernetes.

CrĂ©ez le rĂ©pertoire shark-application/kubernetes Ă  l’aide de la commande suivante :

mkdir $HOME/shark-application/kubernetes
Création des manifestes Kubernetes

Pour dĂ©ployer l’application « shark-app » dans le cluster Kubernetes, nous allons devoir crĂ©er plusieurs fichiers dans le rĂ©pertoire shark-application/kubernetes .

Un premier fichier shark-application/kubernetes/deployment.tpl template du manifeste deployment.yml. Ce manifeste, permettant de déployer notre application, spécifie une ressource Kubernetes de type « Deployment », avec les caractéristiques suivantes :

  • Un seul replicas de pod,
  • L’image utilisĂ©e pour dĂ©ployer le pod sera de type « ec2-35-170-208-112.compute-1.amazonaws.com/samiamoura/shark-application:GIT_COMMIT ». Le tag GIT_COMMIT de l’image, sera remplacĂ© par le hash du commit actuel. Cette astuce permettra de crĂ©er ou de mettre Ă  jour l’application dĂ©jĂ  dĂ©ployĂ©e, Ă  chaque fois que le stage sera exĂ©cutĂ©. VoilĂ  la raison pour laquelle nous produisons deux tags dans le stage « push ».

CrĂ©ez le fichier shark-application/kubernetes/deployment.tpl Ă  l’aide de la commande suivante :
Information : Editez la variable REGISTRY_URL avec l’adresse de votre Registry.

REGISTRY_URL=ec2-35-170-208-112.compute-1.amazonaws.com/samiamoura/shark-application

cat <<< 'apiVersion: apps/v1
kind: Deployment
metadata:
  name: shark-app
  labels:
    app: shark-app
spec:
  selector:
    matchLabels:
      app: shark-app
  template:
    metadata:
      labels:
        app: shark-app
    spec:
      containers:
      - name: shark-app
        image: '$REGISTRY_URL':GIT_COMMIT' > $HOME/shark-application/kubernetes/deployment.tpl 

Un second fichier shark-application/kubernetes/service.yml. Ce manifeste, permettant d’exposer notre application, spĂ©cifie une ressource Kubernetes de type « Service », avec les caractĂ©ristiques suivantes :

  • Un service de type NodePort permettant d’exposer notre application sur le port 30000 de tous les hĂŽtes du cluster grĂące Ă  la fonction routing mesh de Kubernetes.

CrĂ©ez le fichier shark-application/kubernetes/service.yml Ă  l’aide de la commande suivante :

cat <<< 'apiVersion: v1
kind: Service
metadata:
  name: shark-app
spec:
  type: NodePort
  ports:
    - name: shark-app
      nodePort: 30000
      port: 80
      targetPort: 8080
      protocol: TCP
  selector:
    app: shark-app' > $HOME/shark-application/kubernetes/service.yml 
Ajout du stage « deployment »

Le stage « deployment » permet de dĂ©ployer l’application « shark-app » dans le cluster Kubernetes. Dans ce stage nous pouvons noter plusieurs choses :

  • Nous utilisons l’image samiamoura/kubectl:1.18.0 pour exĂ©cuter les commandes kubectl,
  • Les credentials pour pouvoir interagir avec l’API Serveur sont renseignĂ©s grĂące aux variables d’environnement KUBE_URL, KUBE_CA_PEM_FILE, KUBE_TOKEN. Celles-ci, sont automatiquement affectĂ©es par GitLab grĂące Ă  l’intĂ©gration de Kubernetes Ă  GitLab effectuĂ©e un peu plus tĂŽt dans le tutoriel,
  • Un objet de type « Deployment » est créé grĂące au manifeste deployment.yml gĂ©nĂ©rĂ© par le template deployment.tpl. Le tag GIT_COMMIT est remplacĂ© par le hash du commit actuel grĂące Ă  la variable d’environnement CI_BUILD_REF,
  • Les ressources « Deployment » et « Service » sont créées ou mises Ă  jour grĂące Ă  la commande « kubectl apply »
  • Ajoutez le stage « deployment » au fichier .gitlab-ci.yml Ă  l’aide de la commande suivante :
cat <<< '
deployment:
  stage: deployment
  image: samiamoura/kubectl:1.18.0
  environment: test
  script:
    - kubectl config set-cluster my-cluster --server=${KUBE_URL} --certificate-authority="${KUBE_CA_PEM_FILE}"
    - kubectl config set-credentials admin --token=${KUBE_TOKEN}
    - kubectl config set-context my-context --cluster=my-cluster --user=admin --namespace default
    - kubectl config use-context my-context
    - cat kubernetes/deployment.tpl | sed 's/GIT_COMMIT/'"$CI_BUILD_REF/" > kubernetes/deployment.yml
    - kubectl apply -f kubernetes
  only:
  - master' >> $HOME/shark-application/.gitlab-ci.yml

Voici le fichier .gitlab-ci.yml complet :

stages:
  - build
  - test
  - push
  - deployment

build:
  image: docker:stable
  stage: build
  services:
    - docker:dind
  script:
    - docker build -t $CI_REGISTRY_IMAGE:tmp .
    - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
    - docker push $CI_REGISTRY_IMAGE:tmp
  only:
  - master

test:
  image: docker:stable
  stage: test
  services:
    - docker:dind
  script:
    - docker run -d --name shark-app -p 8080:8080 $CI_REGISTRY_IMAGE:tmp
    - sleep 10s
    - TEST=$(docker run --link shark-app samiamoura/curl -s http://shark-app:8080 | grep -i "Are you ready to learn about sharks?")
    - if [ $? -eq 0 ]; then  echo \"TEST OK\"; docker rm -f shark-app ; exit 0; else echo \"TEST KO\"; docker rm -f shark-app ; exit 1; fi;
  only:
  - master

push:
  image: docker:stable
  stage: push
  services:
    - docker:dind
  script:
    - docker image pull $CI_REGISTRY_IMAGE:tmp
    - docker image tag $CI_REGISTRY_IMAGE:tmp $CI_REGISTRY_IMAGE:$CI_BUILD_REF
    - docker image tag $CI_REGISTRY_IMAGE:tmp $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
    - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
    - docker push $CI_REGISTRY_IMAGE:$CI_BUILD_REF
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
  only:
  - master

deployment:
  stage: deployment
  image: samiamoura/kubectl:1.18.0
  environment: test
  script:
    - kubectl config set-cluster my-cluster --server=${KUBE_URL} --certificate-authority="${KUBE_CA_PEM_FILE}"
    - kubectl config set-credentials admin --token=${KUBE_TOKEN}
    - kubectl config set-context my-context --cluster=my-cluster --user=admin --namespace default
    - kubectl config use-context my-context
    - cat kubernetes/deployment.tpl | sed s/GIT_COMMIT/"$CI_BUILD_REF/" > kubernetes/deployment.yml
    - kubectl apply -f kubernetes
  only:
  - master

Le ressources pour exécuter notre pipeline CI/CD sont désormais créées.

6 – ExĂ©cution du pipeline CI/CD simple

a – DĂ©ploiement de l’application

AprĂšs avoir mis Ă  jour notre projet « shark-application » avec les manifestes Kubernetes et le fichier .gitlab-ci.yml, nous devons Ă  prĂ©sent pousser ces modifications sur le SCM GitLab. Cette action dĂ©clenchera l’exĂ©cution du pipeline CI/CD.

Information : L’ensemble des commandes de cette section seront Ă  effectuer depuis le serveur GitLab.

À la racine du rĂ©pertoire « shark-application » ajoutez tous les fichiers, commitez les changement et poussez la mise Ă  jour sur le projet GitLab :

cd $HOME/shark-application
git add .
git commit -m "Add pipeline CI/CD with GitLab and Kubernetes"
git push -u origin master

Depuis l’interface GitLab, dans le menu latĂ©ral Ă  gauche du projet, se rendre dans CI/CD > Pipelines , nous pouvons constater qu’un pipeline a Ă©tĂ© dĂ©clenchĂ© suite au push :

Pipeline exécuté

Pour avoir une vue dĂ©taillĂ©e des 4 stages du pipeline, cliquez sur le l’Ă©tat du pipeline correspondant :

Les stages du pipeline

Enfin pour avoir le détail des instructions exécutées lors de chaque stage du pipeline, cliquez sur le stage correspondant :

Instructions exécutées pendant le stage « build »

b – Test de l’application

Le pipeline s’Ă©tant exĂ©cutĂ© avec succĂšs, nous pouvons tester que l’application est deployĂ©e dans le cluster Kubernetes. Pour rappel, l’application est exposĂ©e sur le port 30000 des workers Kubernetes. Pour tester l’application, entrez dans un navigateur web l’adresse IP publique de chaque worker Kubernetes ainsi que le port 30000.

http://Adresse_IP_Publique_Worker_Node:30000
  • Test sur le kubernetes worker 1

L’adresse IP Publique du worker 1 est : 35.173.110.79. Entrez l’adresse http://35.173.110.79:30000 dans un navigateur.

Le rĂ©sultat doit ĂȘtre similaire Ă  :

  • Test sur le kubernetes worker 2

L’adresse IP Publique du worker 1 est : 54.209.65.74. Entrez l’adresse http://54.209.65.74:30000 dans un navigateur.

Le rĂ©sultat doit ĂȘtre similaire Ă  :

L’application a Ă©tĂ© dĂ©ployĂ©e dans le cluster Kubernetes avec succĂšs.

c – Mise Ă  jour de l’application

Pour dĂ©montrer que notre pipeline CI/CD est fonctionnel, nous allons modifier lĂ©gĂšrement le code source de l’application. Nous remplacerons le message « This app is working » par « This app is powered by GitLab and Kubernetes » sur la page principale de l’application.

Modifiez le message sur la page principale de l’application Ă  l’aide de la commande suivante :

sed -i "s|<p>This app is working</p>|<p>This app is powered by GitLab and Kubernetes</p>|g" \
  $HOME/shark-application/app/views/index.html

À la racine du rĂ©pertoire « shark-application » ajoutez tous les fichiers, commitez les changement et poussez la mise Ă  jour sur le projet GitLab :

cd $HOME/shark-application
git add .
git commit -m "update main page with a new message"
git push -u origin master

Depuis l’interface GitLab, nous pouvons constatez qu’un nouveau pipeline a Ă©tĂ© dĂ©clenchĂ© :

Nouveau pipeline exécuté

Le pipeline s’Ă©tant exĂ©cutĂ© une nouvelle fois avec succĂšs, testons que l’application a Ă©tĂ© mise Ă  jour.

  • Test sur le kubernetes worker 1

L’adresse IP Publique du worker 1 est : 35.173.110.79. Entrez l’adresse http://35.173.110.79:30000 dans un navigateur.

Le rĂ©sultat doit ĂȘtre similaire Ă  :

Application fonctionnelle worker 1
  • Test sur le kubernetes worker 2

L’adresse IP Publique du worker 1 est : 54.209.65.74. Entrez l’adresse http://54.209.65.74:30000 dans un navigateur.

Le rĂ©sultat doit ĂȘtre similaire Ă  :

Application fonctionnelle worker 2

L’application a Ă©tĂ© mise a jour avec succĂšs.

Le pipeline CI/CD avec l’approche de type « push » est fonctionnel. Bien entendu, il pourrait beaucoup ĂȘtre amĂ©liorĂ© avec notamment la mise en place d’un gitflow multi-branche, l’intĂ©gration de tests supplĂ©mentaires, une partie sĂ©curitĂ© avec le scan des images Docker… et encore beaucoup d’autres choses.

La mĂ©thode « push » peut aussi ĂȘtre considĂ©rĂ©e comme une approche de type GitOps sans l’opĂ©rateur.

7 – IntĂ©gration du GitOps avec l’approche « pull »

Pour rappel, le GitOps repose sur 4 principes :

  • L’approche dĂ©clarative des applications et/ou des infrastructures dans le repository Git,
  • L’unique source de vĂ©ritĂ© (single source of truth) reprĂ©sentĂ©e par le projet Git,
  • L’opĂ©rateur en charge de scruter les modifications apportĂ©es au projet (repository d’images et repository code) et de redĂ©ployer automatiquement ces mises Ă  jour dans le cluster,
  • L’observabilitĂ© permettant de s’assurer que l’Ă©tat effectif du cluster est conforme avec l’Ă©tat dĂ©sirĂ©.

Dans ce chapitre, nous allons lĂ©gĂšrement modifier le pipeline CI/CD mis en place prĂ©cĂ©demment afin d’attribuer la partie CD de la chaĂźne d’intĂ©gration, Ă  une approche GitOps de type « pull ». Effectivement, nous allons supprimer le stage « deployment » du fichier de pipeline. La partie dĂ©ploiement ne sera plus gĂ©rĂ©e par GitLab CI mais par un opĂ©rateur. Dans ce tutoriel, nous avons choisi de travailler avec l’opĂ©rateur Flux appartenant au projet FluxCD.

a – Installation du binaire fluxctl

Le binaire fluxctl permet de dialoguer avec Flux, de manager les workloads ainsi qu’automatiser et faire machine arriĂšre sur les dĂ©ploiements. Vous trouverez davantage d’informations sur le site officiel officiel Ă  l’adresse suivante : https://docs.fluxcd.io/en/1.20.0/references/fluxctl.html

Dans la stack CloudFormation que je vous fournis pour dĂ©ployer l’infrastructure, fluxctl est dĂ©jĂ  installĂ©. Mais pour informations, voici les commandes pour installer l’utilitaire sur une distribution Linux Debian 9 :

sudo apt-get update
sudo apt-get -y install snapd
sudo snap install core
sudo snap install fluxctl --classic
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin

b – Configuration des ressources pour l’opĂ©rateur Flux

Un opérateur est un deamon (sous forme de pod) dans le cluster Kubernetes, qui scrute en temps réel les modifications apportées à la registry et au projet GitLab. Lorsque des modifications sont détectées, il est en charge de redéployer automatiquement les ressources mises à jour dans le cluster Kubernetes.

Il est possible de dĂ©ployer l’opĂ©rateur Flux manuellement Ă  l’aide de manifestes Kubernetes directement dans le cluster ou d’utiliser les Charts Helm. Dans ce tutoriel, nous utiliserons la mĂ©thode manuelle. Pour dĂ©ployer Flux il existe un projet officiel sur GitHub Ă  l’adresse suivante : https://github.com/fluxcd/flux

Cependant, nous utiliserons une configuration assez spĂ©cifique. En effet, nous disposons d’un hĂŽte privĂ© pour hĂ©berger notre application GitLab (nous n’utilisons pas GitLab.com). Ainsi, afin de faciliter la comprĂ©hension, j’ai dĂ©cidĂ© de forker le projet et de l’Ă©purer pour vous fournir uniquement les manifestes dont nous aurons besoins. Danse ce chapitre, nous reviendrons en dĂ©tail sur chaque composant.

Un certain nombre de ressources Kubernetes doivent ĂȘtre créées avant de dĂ©ployer l’opĂ©rateur Flux. Toutes les ressources seront dĂ©ployĂ©es dans le namespace « flux ».

Information L’ensemble des commandes de cette section seront Ă  effectuer depuis le nƓud master de notre cluster Kubernetes .

Récupération du projet

Le projet customisĂ© se trouve sur mon GitHub Ă  l’adresse suivante : https://github.com/samiamoura/gitops-training

Logguez-vous en tant que super administrateur Ă  l’aide de la commande suivante :

sudo su -

RĂ©cupĂ©rez le projet Ă  l’aide de la commande suivante :

git clone https://github.com/samiamoura/gitops-training.git
Création du namespace « flux »

CrĂ©ez le namespace « flux » Ă  l’aide de la commande suivante :

kubectl create namespace flux
namespace/flux cretated 
Génération des clés et création du Secret « flux-git-deploy »

Le pod flux aura besoin d’avoir accĂšs au projet GitLab afin de pouvoir interagir avec celui-ci. La mĂ©thode privilĂ©giĂ©e est la connexion de type SSH. Il est donc essentiel qu’il puisse avoir les crendentials nĂ©cessaires. Pour ce faire, nous allons gĂ©nĂ©rer une paire de clĂ©s privĂ©e/publique sur le serveur kubernetes master et partager la clĂ© privĂ©e avec le pod flux. Comme il s’agit d’une donnĂ©e sensible nous utiliserons un objet Kubernetes de type Secret .

GĂ©nĂ©ration d’une paire de clĂ©s privĂ©e/publique

GĂ©nĂ©rez une paire de clĂ©s privĂ©e/publique Ă  l’aide de la commande suivante :

ssh-keygen -t rsa 

RĂ©cupĂ©rez la clĂ© publique Ă  l’aide de la commande suivante :

cat $HOME/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCkhB7EC7gVZfm1bO4SLCU7F20tQSRnU2TWsss6uqzMCjdCEt55UKn1hNgmvn/qd/JL8StJrb8oEFMI+8M2J165Y1XsHJyOcQJoD/SM6z0perdQqN8wLcDMpDuOjEG4nNoiaUpvFxOcUEMc4fIJZkTSxjPBLIb2UYrogrHubDpHtvdU0iNAHJOZvjmXU0D/IkpRNxpQSheoj0+GTrBOrwYH/2AVsejHmY756VCIl3CsDSYtdnLCCl7Y+Y2obzj8at9lWx0Dg4H/sMiF9GUQdO/0dpqe1DXSYb+y0gujdeM39i1vVbdI4kLh5afZBt02AO/wL8CPqcp0Y7EEa1Kb9nq/ root@master

DĂ©ployez la clĂ© publique rĂ©cupĂ©rĂ©e prĂ©cĂ©demment, sur l’application GitLab via l’interface web de la mĂȘme façon que nous l’avons fait dans la partie #3-c de cet article.

Création du Secret « flux-git-deploy »

CrĂ©ez le secret « flux-git-deploy » Ă  partir de la clĂ© privĂ©e « $HOME/.ssh/id_rsa » dans le namespace « flux » Ă  l’aide de la commande suivante :

kubectl create secret generic flux-git-deploy --from-file=identity=$HOME/.ssh/id_rsa -n flux
secret/flux-git-deploy created
Ajout à la liste des hÎtes connus et création du ConfigMap « flux-ssh-config »

Le pod flux aura besoin d’ajouter l’application GitLab Ă  la liste des hĂŽtes connus afin de pouvoir interagir avec notre projet GitLab. Pour ce faire, nous allons ajouter l’application GitLab Ă  la liste des hĂŽtes connus du serveur kubernetes master et partager ce fichier de configuration avec le pod Ă  l’aide d’un objet Kubernetes de type « ConfigMap ».

Ajout Ă  la liste des hĂŽtes connus

Ajoutez l’application GitLab Ă  la liste des hĂŽtes connus du serveur kubernetes master Ă  l’aide des commandes suivantes :
Information : Editez la variable GITLAB_PUBLICDNS avec le nom du DNS publique du serveur GitLab.

GITLAB_PUBLICDNS=ec2-35-170-208-112.compute-1.amazonaws.com

ssh-keyscan -H -p 2222 $GITLAB_PUBLICDNS >> $HOME/.ssh/known_hosts

Attention : Parfois cette mĂ©thode n’est pas suffisante, il est alors nĂ©cessaire de cloner le projet « shark-application » directement depuis le serveur kubernetes master afin de forcer l’ajout de l’application GitLab Ă  la liste des hĂŽtes connus.

Clonez le projet « shark-application » Ă  l’aide des commandes suivantes :
Information : Editez la variable GIT_URL avec l’URL de votre projet GitLab « shark-application ».

GIT_URL=ssh://git@ec2-35-170-208-112.compute-1.amazonaws.com:2222/samiamoura/shark-application.git

git clone $GIT_URL
Création de la ConfigMap « flux-ssh-config »

CrĂ©ez la ConfigMap « flux-ssh-config » Ă  partir du fichier des hĂŽtes connus « $HOME/.ssh/known_hosts » dans le namespace « flux » Ă  l’aide de la commande suivante :

kubectl create configmap flux-ssh-config --from-file=$HOME/.ssh/known_hosts -n flux
configmap/flux-ssh-config created

c – Configuration et dĂ©ploiement de Flux

L’installation de l’opĂ©rateur Flux dans le cluster Kubernetes se fait en dĂ©ployant un certain nombre de ressources Kubernetes Ă  l’aide de plusieurs manifestes. Nous nous intĂ©resserons notamment Ă  la ressource de type Deployment, flux-gitops/flux-deployment.yaml permettant de dĂ©ployer un pod flux avec des spĂ©cifications particuliĂšres. C’est la configuration de cette ressource qui sera responsable de la communication entre l’opĂ©rateur et le projet GitLab.

Nous allons dans un premier temps, dĂ©crire les paramĂštres du manifeste flux-gitops/flux-deployment.yaml puis nous l’Ă©diterons avec les informations nĂ©cessaires.

Description du déploiement flux

Dans la section « template.spec.volumes » du manifeste flux-gitops/flux-deployment.yaml, nous retrouvons les volumes qui seront associés au pod :

template:
...
  spec:
  ...
    volumes:
    - name: certs
      hostPath:
        path: /etc/docker/certs.d/ec2-35-170-208-112.compute-1.amazonaws.com
    - name: certs2
      hostPath:
        path: /etc/docker/certs.d/ec2-35-170-208-112.compute-1.amazonaws.com
    - name: ssh-config
      configMap:
        name: flux-ssh-config
    - name: git-key
      secret:
        secretName: flux-git-deploy
        defaultMode: 0400
  • Les volumes « certs » et « certs2 » de type hostPath, permettent de monter dans le pod le certificat de la registry GitLab,
  • Le volume « ssh-config » de type configMap, permet de monter dans le pod, le ConfigMap « flux-ssh-config » contenant le fichier des hĂŽtes connus,
  • Le volume « git-key » de type Secret, permet de monter dans le pod, le Secret « flux-git-deploy » contenant la clĂ© privĂ©e, avec les permissions en read-only.

Dans la section « template.spec.containers.volumeMounts » du manifeste flux-gitops/flux-deployment.yaml, nous retrouvons à quels emplacement dans le pod, seront montés les volumes précédemment définis :

template:
...
  spec:
  ...
    containers:
    ...
      volumeMounts:
      - name: certs
        mountPath: /usr/local/share/ca-certificates/
      - name: certs2
        mountPath: /etc/ssl/certs/
      - name: ssh-config
        mountPath: /root/.ssh
      - name: git-key
        mountPath: /etc/fluxd/ssh
        readOnly: true

Dans la section « template.spec.containers.args » du manifeste flux-gitops/flux-deployment.yaml, nous retrouvons la configuration Flux pour intégrer le projet GitLab :

template:
...
  spec:
  ...
    containers:
    ...
      args:
      - --git-url=ssh://git@ec2-35-170-208-112.compute-1.amazonaws.com:2222/samiamoura/shark-application.git
      - --git-branch=master
      - --git-path=kubernetes
      - --git-ci-skip
      ...
  • –git-url : cette instruction permet de dĂ©finir l’URL du repository git Ă  scruter,
  • –git-branch : cette instruction permet de dĂ©finir la branche Ă  surveiller,
  • –git-path : cette instruction permet de dĂ©finir le dossier dans lequel seront hĂ©bergĂ©s les manifestes,
  • –git-ci-skip : cette instruction permet d’Ă©viter de dĂ©clencher un nouveau pipeline lorsque Flux met Ă  jour le projet GitLab. Avec cette instruction on Ă©vite de dĂ©clencher des pipelines en boucle infinie.
Configuration du manifeste flux

Dans cette section, nous allons configurer le manifeste flux-gitops/flux-deployment.yaml avec les informations liées à notre projet :

Ajoutez le rĂ©pertoire oĂč se situe le certificat de la Registy GitLab, dans le manifeste flux-gitops/flux-deployment.yaml Ă  l’aide des commandes suivantes :

GITLAB_PUBLICDNS=$(/usr/local/bin/aws ec2 describe-instances \
  --query "Reservations[*].Instances[*].[PublicDnsName]" \
  --filters Name=tag:Name,Values=GitLabServer Name=instance-state-name,Values=running \
  --output text)

sed -i "s|/etc/docker/certs.d/|/etc/docker/certs.d/$GITLAB_PUBLICDNS|g" \
  $HOME/gitops-training/flux-gitops/flux-deployment.yaml

Ajoutez les informations concernant votre projet GitLab Ă  l’aide des commandes suivantes :
Information : Éditez les variables GIT_URL et GIT_PATH avec vos informations.

GIT_URL=ssh://git@ec2-35-170-208-112.compute-1.amazonaws.com:2222/samiamoura/shark-application.git

GIT_PATH=kubernetes

sed -i "s|--git-url=YOUR_REPOS_URL|--git-url=$GIT_URL|g" \
  $HOME/gitops-training/flux-gitops/flux-deployment.yaml

sed -i "s|--git-path=YOUR_K8S_GIT_PATH|--git-path=$GIT_PATH|g" \
  $HOME/gitops-training/flux-gitops/flux-deployment.yaml
DĂ©ploiement de l’opĂ©rateur Flux

À prĂ©sent l’ensemble de nos ressources Ă©tant configurĂ©es, nous pouvons dĂ©ployer l’opĂ©rateur Flux dans le cluster Kubernetes.

DĂ©ployez le l’opĂ©rateur Flux et toutes ses ressources Ă  l’aide de la commande suivante :

kubectl apply -f $HOME/gitops-training/flux-gitops
serviceaccount/flux created
clusterrole.rbac.authorization.k8s.io/flux created
clusterrolebinding.rbac.authorization.k8s.io/flux created
deployment.apps/flux created
deployment.apps/memcached created
service/memcached created

Comme expliquĂ© prĂ©cĂ©demment, plusieurs ressources sont dĂ©ployĂ©es pour que l’opĂ©rateur Flux puisse exĂ©cuter ses fonctions. Voici une brĂšve description des ressources que nous avons dĂ©ployĂ©es :

  • Un ServiceAccount, un ClusterRole et un ClusterRoleBinding permettant de fournir les authentifications et les autorisations nĂ©cessaires au fonctionnement de Flux,
  • Un Deployment permettant de dĂ©ployer l’opĂ©rateur Flux,
  • Un Service et un Deployment pour « memcached » qui est utilisĂ© par Flux pour garder en cache les metadatas des images.

L’opĂ©rateur Flux est Ă  prĂ©sent dĂ©ployĂ© dans le cluster Kubernetes.

Important : Il est important de regarder rĂ©guliĂšrement les logs du pod Flux afin de pouvoir dĂ©panner les Ă©ventuels problĂšmes. Dans certains cas, un message d’erreur Ă  propos du certificat de la registry peut parfois remonter. Il n’empĂȘche pas l’opĂ©rateur Flux de fonctionner. GĂ©nĂ©ralement, vous pouvez supprimer le message en supprimant le pod Flux.

err="Get https://index.docker.io/v2/: x509: certificate signed by unknown authority"

RĂ©cupĂ©rez le nom du pod Flux et afficher les logs Ă  l’aide des commandes suivantes :

PODFLUXNAME=$(kubectl get all -n flux | grep -i flux | grep -i pod \
  | awk '{print $1}' | awk -F "/" '{print $2}')

kubectl -n flux logs $PODFLUXNAME

Supprimez le pod Flux Ă  l’aide de la commande suivante :

kubectl -n flux delete pod $PODFLUXNAME

d – Modification du pipeline

Modification du fichier de pipeline .gitlab-ci.yml

Comme mentionnĂ© en introduction de ce chapitre, c’est maintenant l’opĂ©rateur Flux qui sera chargĂ© de redĂ©ployer dans le cluster, les changements effectuĂ©s sur le projet et non plus l’outil de CI. Nous allons donc modifier lĂ©gĂšrement le pipeline rĂ©alisĂ© prĂ©cĂ©demment en supprimant le stage « deployment » du fichier .gitlab-ci.yml. Tout le reste du fichier restera identique.

Dans la nouvelle version du fichier.gitlab-ci.yml et du nouveau pipeline, il n’y a plus de commande kubectl pour interagir avec l’API Server du cluster Kubernetes.

Information : L’ensemble des commandes de cette section seront Ă  effectuer depuis le serveur GitLab.

Depuis le serveur GitLab, supprimez le stage « deployment » du fichier .gitlab-ci.yml Ă  l’aide de la commande suivante :

cat <<< 'stages:
  - build
  - test
  - push

build:
  image: docker:stable
  stage: build
  services:
    - docker:dind
  script:
    - docker build -t $CI_REGISTRY_IMAGE:tmp .
    - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
    - docker push $CI_REGISTRY_IMAGE:tmp
  only:
  - master

test:
  image: docker:stable
  stage: test
  services:
    - docker:dind
  script:
    - docker run -d --name shark-app -p 8080:8080 $CI_REGISTRY_IMAGE:tmp
    - sleep 10s
    - TEST=$(docker run --link shark-app samiamoura/curl -s http://shark-app:8080 | grep -i "Are you ready to learn about sharks?")
    - if [ $? -eq 0 ]; then  echo \"TEST OK\"; docker rm -f shark-app ; exit 0; else echo \"TEST KO\"; docker rm -f shark-app ; exit 1; fi;
  only:
  - master

push:
  image: docker:stable
  stage: push
  services:
    - docker:dind
  script:
    - docker image pull $CI_REGISTRY_IMAGE:tmp
    - docker image tag $CI_REGISTRY_IMAGE:tmp $CI_REGISTRY_IMAGE:$CI_BUILD_REF
    - docker image tag $CI_REGISTRY_IMAGE:tmp $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
    - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
    - docker push $CI_REGISTRY_IMAGE:$CI_BUILD_REF
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
  only:
  - master' > $HOME/shark-application/.gitlab-ci.yml
Modification des manifestes Kubernetes

Le fichier de pipeline mis Ă  jour, Ă  prĂ©sent, il nous reste Ă  configurer les manifestes Kubernetes pour qu’ils soient configurĂ©s avec Flux.

Nous n’utiliserons plus le template de dĂ©ploiement shark-application/kubernetes/deployment.tpl nous pouvons donc le supprimer. À la place nous allons crĂ©er un nouveau manifeste Kubernetes shark-application/kubernetes/deployment.yml de type Deployment. Ce manifeste, qui sera mis Ă  jour Ă  chaque fois qu’une image avec un nouveau tag sera dĂ©tectĂ©e grĂące Ă  l’intĂ©gration de Flux, permettra de redĂ©ployer automatiquement l’application dans le cluster Kubernetes. Voici les caractĂ©ristiques du nouveau manifeste :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: shark-app
  annotations:
    flux.weave.works/automated: "true"
    flux.weave.works/tag.shark-app: regexp:^((?!tmp).)*$
  labels:
    app: shark-app
spec:
  selector:
    matchLabels:
      app: shark-app
  template:
    metadata:
      labels:
        app: shark-app
    spec:
      containers:
      - name: shark-app
        image: ec2-35-170-208-112.compute-1.amazonaws.com/samiamoura/shark-application:master

Ce manifeste possĂšde les mĂȘmes spĂ©cifications que celui gĂ©nĂ©rĂ© lors du pipeline avec l’approche de type « push » , sauf que la configuration pour intĂ©grer Flux a Ă©tĂ© ajoutĂ©e. Celle-ci est assurĂ©e par les attributs de type annotations . Ci-dessous, la description des annotations :

  • flux.weave.works/automated: « true » : cette instruction permet d’activer le redĂ©ploiement automatique pour cette ressource,
  • flux.weave.works/tag.shark-app: regexp:^((?!tmp).)*$ : cette instruction permet de s’assurer que l’image avec le tag tmp ne sera pas prise en compte dans le redĂ©ploiement de la ressource.

Supprimez le template de dĂ©ploiement shark-application/kubernetes/deployment.tpl Ă  l’aide de la commande suivante :

rm -f $HOME/shark-application/kubernetes/deployment.tpl

CrĂ©ez le manifeste shark-application/kubernetes/deployment.yml Ă  l’aide des commandes suivantes :
 Information : Editez la variable REGISTRY_URL avec l’adresse de votre Registry.

REGISTRY_URL=ec2-35-170-208-112.compute-1.amazonaws.com/samiamoura/shark-application

cat <<< 'apiVersion: apps/v1
kind: Deployment
metadata:
  name: shark-app
  annotations:
    flux.weave.works/automated: "true"
    flux.weave.works/tag.shark-app: regexp:^((?!tmp).)*$
  labels:
    app: shark-app
spec:
  selector:
    matchLabels:
      app: shark-app
  template:
    metadata:
      labels:
        app: shark-app
    spec:
      containers:
      - name: shark-app
        image: '$REGISTRY_URL':master' > $HOME/shark-application/kubernetes/deployment.yml
Mise Ă  jour du code source de l’application

Pour tester l’approche GitOps de type « pull », nous allons une nouvelle fois modifier lĂ©gĂšrement le code source de l’application. Nous remplacerons le message « This app is powered by GitLab and Kubernetes » par « This app is now powered by Flux and GitOps » sur la page principale de l’application.

Modifiez le message sur la page principale de l’application à l’aide de la commande suivante :

sed -i "s|<p>This app is powered by GitLab and Kubernetes</p>|<p>This app is  now powered by Flux and GitOps</p>|g" \
  $HOME/shark-application/app/views/index.html

Notre nouveau pipeline a Ă©tĂ© configurĂ©. Nous allons pouvoir l’exĂ©cuter dans le prochain chapitre.

8 – ExĂ©cution du pipeline CI/CD de type « pull »

a – DĂ©ploiement de l’application

Nous avons dĂ©ployĂ© l’opĂ©rateur Flux dans le cluster Kubernetes. Puis, nous avons mis Ă  jour notre projet « shark-application » avec : la modification du fichier .gitlab-ci.yml, l’ajout d’un manifeste Kubernetes configurĂ© avec Flux et enfin la modification du code source de l’application. Nous devons Ă  prĂ©sent pousser toutes ces modifications sur le SCM GitLab. Cette action dĂ©clenchera l’exĂ©cution d’un nouveau pipeline CI/CD.

Information : L’ensemble des commandes de cette section seront Ă  effectuer depuis le serveur GitLab.

À la racine du rĂ©pertoire « shark-application » ajoutez tous les fichiers, commitez les changements et poussez les mises Ă  jour sur le projet GitLab :

cd $HOME/shark-application
git add .
git commit -m "Pipeline CI/CD with Flux and GitOps"
git push -u origin master

Depuis l’interface GitLab, dans le menu latĂ©ral Ă  gauche du projet, se rendre dans CI/CD > Pipelines , nous pouvons constater que 3 pipelines ont Ă©tĂ© dĂ©clenchĂ©s Ă  la suite push :

Trois pipelines GitOps
  • Un premier pipeline a Ă©tĂ© dĂ©clenchĂ© Ă  la suite du push des mises Ă  jour du projet, sur le SCM GitLab,
  • Les deux autres pipelines ont Ă©tĂ© dĂ©clenchĂ©s par Flux, lorsque celui-ci Ă  mis Ă  jour le manifeste de dĂ©ploiement shark-application/kubernetes/deployment.yml sur le SCM GitLab; Un pipeline a Ă©tĂ© dĂ©clenchĂ© sur la branche master et le deuxiĂšme sur la branche flux-sync créée par Flux.
  • Les pipelines dĂ©clenchĂ©s par Flux sont dans l’Ă©tat « skipped » et n’ont pas Ă©tĂ© rĂ©alisĂ©s. Ceci, grĂące Ă  l’instruction –git-ci-skip renseignĂ©e dans la configuration de Flux. Cela nous permet d’Ă©viter que des pipelines ne soient exĂ©cutĂ©s en boucle lors de la mise Ă  jour du projet par Flux.

Nous pouvons aussi constater que ce nouveau pipeline possĂšde bien les 3 stages dĂ©finis dans le fichier .gitlab-ci.yml et qu’il n’y a plus de stage « deployment » :

3 stages : build, test, push

b – Test de l’application

Le nouveau pipeline s’étant exĂ©cutĂ© avec succĂšs, nous pouvons tester que l’application a bien Ă©tĂ© mise Ă  jour et redĂ©ployĂ©e dans le cluster Kubernetes. Pour rappel, l’application est exposĂ©e sur le port 30000 des workers Kubernetes. Pour tester l’application, entrez dans un navigateur web l’adresse IP publique de chaque worker Kuberntes ainsi que le port 30000.

http://Adresse_IP_Publique_Worker_Node:30000
  • Test sur le kubernetes worker 1

L’adresse IP Publique du worker 1 est : 35.173.110.79. Entrez l’adresse http://35.173.110.79:30000 dans un navigateur.

Le rĂ©sultat doit ĂȘtre similaire Ă  :

Application dĂ©ployĂ©e avec GitOps – worker1
  • Test sur le kubernetes worker 2

L’adresse IP Publique du worker 1 est : 54.209.65.74. Entrez l’adresse http://54.209.65.74:30000 dans un navigateur.

Le rĂ©sultat doit ĂȘtre similaire Ă  :

Application dĂ©ployĂ©e avec GitOps – worker2

L’application a Ă©tĂ© mise Ă  jour et redĂ©ployĂ©e dans le cluster Kubernetes avec succĂšs.

Le pipeline CI/CD GitOps avec l’approche de type « pull » est fonctionnel. Bien entendu, lui aussi pourrait ĂȘtre optimisĂ© avec notamment le nommage des tags avec semver, ou l’ajouts de stages supplĂ©mentaires et beaucoup d’autres choses.

9 – Bilan

Méthode « push » vs « pull »

Finalement dans cet article, nous avons avons pu voir que les deux approches, s’apparentent Ă  du GitOps. Effectivement, dans les deux mĂ©thodes « push » et « pull », nous disposons, dans un unique projet Git, les manifestes permettant la configuration de notre application. Cependant, avec l’approche du type « pull », nous avons la prĂ©sence d’un opĂ©rateur permettant d’ajouter la notion d’observabilitĂ© dans cluster Kubernetes. De plus, avec cette approche, nous n’avons pas besoin de spĂ©cifier des credentials car nous opĂ©rons Ă  l’intĂ©rieur du cluster. À l’inverse pour la mĂ©thode « push », nous avons du fournir les authentifications nĂ©cessaires pour interagir avec l’API Server et exĂ©cuter les commandes kubectl.

Si vous souhaitez en savoir davantage sur l’approche GitOps dans le monde de l’entreprise, je vous redirige vers un article et une vidĂ©o trĂšs intĂ©ressante sur le sujet. Voici le lien : https://www.sokube.ch/post/gitops-and-the-millefeuille-dilemma.

Environnement

Version des applications

[table id=gitops-version-application /]

Références

Techniques

Personnelles

Sami AMOURA
DevOps Enthusiast  | Docker Certified | Kubernetes Certified CKA & CKAD | AWS Certified