1. Présentation
Jenkins est l'une des solutions d'intégration continue les plus populaires. Il est utilisé pour automatiser les parties non humaines essentielles du processus de développement logiciel. En déployant Jenkins sur Kubernetes sur Google Cloud et en utilisant le plug-in GKE, nous pouvons mettre à l'échelle rapidement et automatiquement les exécuteurs de compilation selon les besoins. Combiné à Cloud Storage, il nous permet de créer et de tester une application avec un minimum d'efforts.
Objectifs de l'atelier
- Déployer Jenkins sur un cluster Kubernetes
- Déployez et configurez le plug-in Jenkins GKE pour permettre à Jenkins de créer et de détruire des pods en tant que nœuds d'exécution.
- Créer et tester un exemple d'application Spring Boot
- Créer et publier un conteneur dans Google Container Registry
- Déployer l'exemple d'application dans un environnement GKE de préproduction et de production
Prérequis
- Un projet Google Cloud avec la facturation configurée. Si vous n'en avez pas, vous devrez en créer un.
2. Configuration
Cet atelier de programmation peut être exécuté entièrement sur Google Cloud Platform, sans installation ni configuration locales.
Cloud Shell
Tout au long de cet atelier de programmation, nous allons provisionner et gérer différentes ressources et différents services cloud à l'aide de la ligne de commande via Cloud Shell.
Activer les API
Voici les API que nous devrons activer dans notre projet :
- API Compute Engine : crée et exécute des machines virtuelles
- API Kubernetes Engine : créez et gérez des applications basées sur des conteneurs.
- API Cloud Build : plate-forme d'intégration et de déploiement continus de Google Cloud
- API Service Management : permet aux producteurs de services de publier des services sur Google Cloud Platform.
- API Cloud Resource Manager : permet de créer, lire et mettre à jour les métadonnées des conteneurs de ressources Google Cloud.
Activez les API requises à l'aide de la commande gcloud suivante :
gcloud services enable compute.googleapis.com \
container.googleapis.com \
cloudbuild.googleapis.com \
servicemanagement.googleapis.com \
cloudresourcemanager.googleapis.com \
--project ${GOOGLE_CLOUD_PROJECT}
Créer un bucket GCS
Nous allons avoir besoin d'un bucket GCS pour importer nos tests. Créons un bucket en utilisant l'ID de notre projet dans le nom pour garantir son unicité :
gsutil mb gs://${GOOGLE_CLOUD_PROJECT}-jenkins-test-bucket/
3. Créer des clusters Kubernetes
Créer le cluster
Nous allons ensuite créer un cluster GKE qui hébergera notre système Jenkins, y compris les pods qui seront distribués en tant que nœuds de calcul. Le champ d'application supplémentaire indiqué par l'indicateur --scopes permettra à Jenkins d'accéder à Cloud Source Repositories et à Container Registry. Dans la console Cloud, exécutez la commande suivante :
gcloud container clusters create jenkins-cd \ --machine-type n1-standard-2 --num-nodes 1 \ --zone us-east1-d \ --scopes "https://www.googleapis.com/auth/source.read_write,cloud-platform" \ --cluster-version latest
Déployons également deux clusters pour héberger nos versions de préproduction et de production de notre exemple d'application :
gcloud container clusters create staging \ --machine-type n1-standard-2 --num-nodes 1 \ --zone us-east1-d \ --cluster-version latest
gcloud container clusters create prod \ --machine-type n1-standard-2 --num-nodes 2 \ --zone us-east1-d \ --cluster-version latest
Valider
Une fois les clusters créés, nous pouvons vérifier qu'ils sont en cours d'exécution avec gcloud container clusters list.
Le résultat doit contenir RUNNING dans la colonne STATUS :
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS jenkins-cd us-east1-d 1.15.9-gke.9 34.74.77.124 n1-standard-2 1.15.9-gke.9 2 RUNNING prod us-east1-d 1.15.9-gke.9 35.229.98.12 n1-standard-2 1.15.9-gke.9 2 RUNNING staging us-east1-d 1.15.9-gke.9 34.73.92.228 n1-standard-2 1.15.9-gke.9 2 RUNNING
4. Déployer Jenkins avec Helm
Installer Helm
Nous allons utiliser Helm, un gestionnaire de packages d'application pour Kubernetes, afin d'installer Jenkins sur notre cluster. Pour commencer, téléchargez le projet qui inclut les fichiers manifestes Kubernetes que nous utiliserons pour déployer Jenkins :
git clone https://github.com/GoogleCloudPlatform/continuous-deployment-on-kubernetes.git ~/continuous-deployment-on-kubernetes
Passez de votre répertoire de travail actuel au répertoire du projet :
cd ~/continuous-deployment-on-kubernetes/
Créez une liaison de rôle de cluster pour vous attribuer les autorisations du rôle cluster-admin :
kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=$(gcloud config get-value account)
Connectez-vous à votre cluster Jenkins en obtenant ses identifiants :
gcloud container clusters get-credentials jenkins-cd --zone us-east1-d --project ${GOOGLE_CLOUD_PROJECT}
Téléchargez le binaire Helm dans votre console Cloud :
wget https://storage.googleapis.com/kubernetes-helm/helm-v2.14.1-linux-amd64.tar.gz
Décompressez le fichier et copiez le fichier Helm inclus dans votre répertoire de travail actuel :
tar zxfv helm-v2.14.1-linux-amd64.tar.gz && \ cp linux-amd64/helm .
Tiller est le côté serveur de Helm qui s'exécute sur le cluster Kubernetes. Créons un compte de service nommé tiller :
kubectl create serviceaccount tiller \ --namespace kube-system
Associez-le au rôle de cluster cluster-admin pour qu'il puisse apporter des modifications :
kubectl create clusterrolebinding tiller-admin-binding \ --clusterrole=cluster-admin \ --serviceaccount=kube-system:tiller
Nous pouvons maintenant initialiser Helm et mettre à jour le dépôt :
./helm init --service-account=tiller && \ ./helm repo update
Valider
Vérifiez que Helm est prêt à l'emploi avec ./helm version. Les numéros de version du client et du serveur doivent s'afficher :
Client: &version.Version{SemVer:"v2.14.1", GitCommit:"5270352a09c7e8b6e8c9593002a73535276507c0", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.14.1", GitCommit:"5270352a09c7e8b6e8c9593002a73535276507c0", GitTreeState:"clean"}
Installer Jenkins
Maintenant que Helm est installé sur notre cluster, nous pouvons installer Jenkins :
./helm install stable/jenkins -n cd \ -f jenkins/values.yaml \ --version 1.2.2 --wait
Valider
Vérifions les pods :
kubectl get pods
Le résultat doit afficher notre pod Jenkins avec l'état "RUNNING" (EN COURS D'EXÉCUTION) :
NAME READY STATUS RESTARTS AGE cd-jenkins-7c786475dd-vbhg4 1/1 Running 0 1m
Vérifiez que le service Jenkins a bien été créé :
kubectl get svc
Le résultat devrait ressembler à ceci :
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE cd-jenkins ClusterIP 10.35.241.170 <none> 8080/TCP 2m27s cd-jenkins-agent ClusterIP 10.35.250.57 <none> 50000/TCP 2m27s kubernetes ClusterIP 10.35.240.1 <none> 443/TCP 75m
L'installation de Jenkins utilisera le plug-in Kubernetes pour créer des agents de compilation. Ils seront automatiquement lancés par le maître Jenkins en cas de besoin. Une fois leur travail terminé, ils sont automatiquement arrêtés et leurs ressources sont ajoutées au pool de ressources du cluster.
Se connecter à Jenkins
Jenkins s'exécute sur notre cluster, mais pour accéder à l'interface utilisateur, configurons le transfert de port à partir de Cloud Shell :
export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/component=jenkins-master" -l "app.kubernetes.io/instance=cd" -o jsonpath="{.items[0].metadata.name}") &&
kubectl port-forward $POD_NAME 8080:8080 >> /dev/null &
Un mot de passe administrateur a été généré lors de l'installation. Récupérons-le :
printf $(kubectl get secret cd-jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo
En haut de Cloud Shell, cliquez sur l'icône Aperçu Web
, puis sélectionnez "Prévisualiser sur le port 8080".

Un écran de connexion Jenkins devrait s'afficher. Vous pouvez y saisir admin comme nom d'utilisateur et le mot de passe renvoyé à l'étape précédente :

Lorsque nous cliquons sur Sign in (Se connecter), nous devrions être redirigés vers la page principale de Jenkins.

5. Installer et configurer le plug-in GKE
Le plug-in Google Kubernetes Engine nous permet de publier les déploiements créés dans Jenkins sur nos clusters Kubernetes exécutés dans GKE. Vous devez effectuer une configuration avec les autorisations IAM sur votre projet. Nous allons déployer cette configuration à l'aide de Terraform.
Commencez par télécharger le projet de plug-in GKE :
git clone https://github.com/jenkinsci/google-kubernetes-engine-plugin.git ~/google-kubernetes-engine-plugin
Configuration automatisée des autorisations IAM
Remplacez votre répertoire de travail actuel par le répertoire "rbac" du projet GKE que nous avons cloné précédemment :
cd ~/google-kubernetes-engine-plugin/docs/rbac/
gcp-sa-setup.tf est un fichier de configuration Terraform qui crée un rôle IAM GCP personnalisé avec des autorisations limitées, ainsi qu'un compte de service GCP auquel attribuer ce rôle. Le fichier nécessite des valeurs pour les variables du projet, de la région et du nom du compte de service. Nous fournissons ces valeurs en déclarant d'abord les variables d'environnement suivantes :
export TF_VAR_project=${GOOGLE_CLOUD_PROJECT}
export TF_VAR_region=us-east1-d
export TF_VAR_sa_name=kaniko-role
Initialisez Terraform, générez un plan et appliquez-le :
terraform init terraform plan -out /tmp/tf.plan terraform apply /tmp/tf.plan && rm /tmp/tf.plan
Le compte de service aura besoin des autorisations d'administrateur Storage pour enregistrer des données dans notre bucket Cloud Storage :
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
--member serviceAccount:kaniko-role@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com \
--role 'roles/storage.admin'
Il aura également besoin d'autorisations de conteneur pour les étapes de déploiement de notre pipeline :
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} --member \
serviceAccount:kaniko-role@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com --role 'roles/container.developer'
Nous pouvons maintenant utiliser Helm pour configurer les autorisations de cluster pour le plug-in GKE à l'aide du déploiement de robot GKE. Remplacez votre répertoire de travail par le répertoire Helm du projet GKE :
cd ~/google-kubernetes-engine-plugin/docs/helm/
Installez-le à l'aide du chart Helm fourni :
export TARGET_NAMESPACE=kube-system && \ envsubst < gke-robot-deployer/values.yaml | helm install ./gke-robot-deployer --name gke-robot-deployer -f -
6. Configurer Jenkins
Clés de compte de service
Pour que le compte de service fonctionne correctement, nous devons générer un fichier de clé privée et l'ajouter en tant que secret Kubernetes. Commencez par générer le fichier avec la commande gcloud suivante :
gcloud iam service-accounts keys create /tmp/kaniko-secret.json --iam-account kaniko-role@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com
Nous allons créer une clé secrète dans le secret store Kubernetes avec ce fichier :
kubectl create secret generic jenkins-int-samples-kaniko-secret --from-file=/tmp/kaniko-secret.json
Téléchargez le fichier JSON sur votre disque local en accédant à l'élément "Télécharger le fichier" dans le menu à trois points de Cloud Shell :

Saisissez le chemin d'accès au fichier /tmp/kaniko-secret.json, puis cliquez sur "Télécharger".
De retour sur la page Jenkins, dans le volet de gauche, cliquez sur Credentials (Identifiants), puis sur System (Système).


Dans la section Système de la page, cliquez sur "Identifiants globaux", puis sur "Ajouter des identifiants" à gauche :


Dans le menu déroulant "Type", sélectionnez Compte de service Google à partir d'une clé privée. Saisissez "kaniko-role" comme nom, puis importez la clé JSON que vous avez créée lors des étapes précédentes et cliquez sur OK.

Variables d'environnement
Nous devrons définir certaines variables d'environnement Jenkins avant de créer le pipeline multibranches. Les voici :
- JENK_INT_IT_ZONE : zone du cluster Kubernetes. Dans notre cas,
us-east1-d - JENK_INT_IT_PROJECT_ID : ID du projet GCP hébergeant cette instance Jenkins
- JENK_INT_IT_STAGING : nom de notre cluster de préproduction. À des fins de démonstration, il s'agit de
staging. - JENK_INT_IT_PROD : nom de notre cluster de production. À des fins de démonstration, il s'agit de
prod. - JENK_INT_IT_BUCKET : bucket Google Cloud Storage créé à l'étape précédente
- JENK_INT_IT_CRED_ID : fait référence aux identifiants créés à l'aide du fichier JSON de l'étape précédente. La valeur doit correspondre au nom que nous lui avons attribué,
kaniko-role.
Pour les ajouter, accédez à Gérer Jenkins :

Ensuite, Configure System (Configurer le système) :

Une section nommée Propriétés globales s'affiche. Lorsque nous cochons la case Variables d'environnement, un bouton Ajouter s'affiche. Nous cliquons dessus pour ajouter les variables ci-dessus sous forme de paires clé/valeur :

Cliquez sur le bouton Enregistrer en bas de la page pour appliquer les modifications.
7. Configurer un pipeline
Dans Jenkins, cliquez sur "New Item" (Nouvel élément) :

Saisissez "jenkins-integration-sample" comme nom, sélectionnez "Multibranch Pipeline" (Pipeline multibranche) comme type de projet, puis cliquez sur OK :

Vous serez redirigé vers la page de configuration du pipeline. Sous Sources de branche, saisissez https://github.com/GoogleCloudPlatform/jenkins-integration-samples.git comme dépôt du projet. Sous Configuration de compilation, saisissez "gke/Jenkinsfile" comme chemin d'accès au script.

Cliquez sur Enregistrer pour appliquer ces paramètres. Une fois l'enregistrement effectué, Jenkins lance une analyse du dépôt et une compilation pour chaque branche. Au fur et à mesure de la progression, vous verrez des pods être créés, exécutés et détruits sur la page "Charges de travail Kubernetes".
Une fois les compilations terminées, vous trouverez deux éléments sur la page "Charges de travail Kubernetes" nommés "jenkins-integration-samples-gke", chacun correspondant au cluster de production ou de test. L'état est défini sur "OK" :

La commande gcloud suivante nous montre que nous avons importé une image de conteneur dans Google Container Registry correspondant à notre pipeline :
gcloud container images list
Pour afficher la charge de travail dans votre navigateur, obtenez les identifiants du cluster de production :
gcloud container clusters get-credentials prod --zone us-east1-d --project ${GOOGLE_CLOUD_PROJECT}
Exécutez ensuite la commande suivante pour configurer un transfert de port du port 8081 de votre shell vers le port 8080 de votre charge de travail :
export POD_NAME=$(kubectl get pods -o jsonpath="{.items[0].metadata.name}") &&
kubectl port-forward $POD_NAME 8081:8080 >> /dev/null &
En haut de Cloud Shell, cliquez sur l'icône Aperçu Web, puis sélectionnez "Prévisualiser sur le port 8081".


8. Nettoyage
Nous avons vu comment déployer un pipeline Jenkins et un exemple de pipeline multibranches sur Kubernetes. Il est maintenant temps de nettoyer notre projet de toutes les ressources que nous avons créées.
Supprimer le projet
Si vous le souhaitez, vous pouvez supprimer l'intégralité du projet. Dans la console GCP, accédez à la page Cloud Resource Manager :
Dans la liste des projets, sélectionnez celui dans lequel vous avez travaillé, puis cliquez sur Supprimer. Vous serez alors invité à saisir l'ID du projet. Saisissez-le, puis cliquez sur Arrêter.
Vous pouvez également supprimer le projet dans son intégralité directement dans Cloud Shell avec gcloud :
gcloud projects delete $GOOGLE_CLOUD_PROJECT
Si vous préférez supprimer les différents composants facturables un par un, passez à la section suivante.
Cluster Kubernetes
Supprimez l'intégralité du cluster Kubernetes avec gcloud :
gcloud container clusters delete jenkins-cd --zone=us-east1-d
Buckets de stockage
Supprimez tous les fichiers importés et notre bucket avec gsutil :
gsutil rm -r gs://${GOOGLE_CLOUD_PROJECT}-jenkins-test-bucket
Images Google Container Registry
Nous allons supprimer les images Google Container Registry à l'aide des résumés d'image. Tout d'abord, récupérez les résumés avec la commande suivante :
gcloud container images list-tags gcr.io/${GOOGLE_CLOUD_PROJECT}/jenkins-integration-samples-gke --format="value(digest)"
Ensuite, pour chaque récapitulatif renvoyé :
gcloud container images delete gcr.io/${GOOGLE_CLOUD_PROJECT}/jenkins-integration-samples-gke@sha256:<DIGEST>
9. Félicitations !
Bravo ! Bravo ! Vous avez appris à déployer Jenkins sur GKE et à distribuer des jobs aux clusters Kubernetes.
Points abordés
- Nous avons déployé un cluster Kubernetes et utilisé Helm pour installer Jenkins.
- Nous avons installé et configuré le plug-in GKE pour permettre à Jenkins de déployer des artefacts de compilation sur des clusters Kubernetes.
- Nous avons configuré Jenkins pour configurer un pipeline multibranche qui distribue le travail aux clusters GKE.