1. Présentation
Jenkins est l'une des solutions d'intégration continue les plus populaires. Elle permet d'automatiser les parties non humaines essentielles du processus de développement logiciel. En déployant Jenkins sur Kubernetes dans Google Cloud et en utilisant le plug-in GKE, nous pouvons mettre à l'échelle rapidement et automatiquement les exécuteurs de compilation en cas de besoin. Combiné à Cloud Storage, nous pouvons créer et tester une application avec un minimum d'efforts.
Objectifs de l'atelier
- Déployer Jenkins sur un cluster Kubernetes
- Déployer et configurer le plug-in GKE Jenkins 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 SpringBoot
- 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 facturation configurée. Si vous n'en avez pas, vous devrez en créer un.
2. Configuration
Cet atelier de programmation peut s'exécuter entièrement sur Google Cloud Platform sans aucune installation ni configuration locale.
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ée et gère des applications basées sur des conteneurs
- API Cloud Build : plate-forme d'intégration et de livraison continues de Google Cloud
- API Service Management : permet aux producteurs de services de publier des services sur Google Cloud Platform
- API Cloud Resource Manager : crée, lit et met à 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 aurons besoin d'un bucket GCS pour importer notre travail de test. 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 travail. Le champ d'application supplémentaire indiqué par l'option --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 compilations 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 afficher 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 paquets d'applications pour Kubernetes, afin d'installer Jenkins sur notre cluster. Pour commencer, téléchargez le projet qui inclut les fichiers manifestes Kubernetes que nous allons utiliser pour déployer Jenkins :
git clone https://github.com/GoogleCloudPlatform/continuous-deployment-on-kubernetes.git ~/continuous-deployment-on-kubernetes
Remplacez votre répertoire de travail actuel par le répertoire du projet :
cd ~/continuous-deployment-on-kubernetes/
Créez une liaison de rôle de cluster pour vous accorder les autorisations de rôle d'administrateur de cluster :
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 afin 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 à fonctionner avec ./helm version. Cette commande doit renvoyer les numéros de version du client et du serveur :
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 sommes prêts à 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 :
NAME READY STATUS RESTARTS AGE cd-jenkins-7c786475dd-vbhg4 1/1 Running 0 1m
Vérifiez que le service Jenkins a été créé correctement :
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 nécessite l'utilisation du plug-in Kubernetes pour que des agents de compilation soient créés. Ils seront automatiquement lancés par le maître Jenkins selon les besoins. 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 "Preview on port 8080" (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 vous cliquez sur Sign in (Se connecter), vous devriez être redirigé vers la page principale de Jenkins.

5. Installer et configurer le plug-in GKE
Le plug-in Google Kubernetes Engine nous permet de publier des déploiements créés dans Jenkins sur nos clusters Kubernetes exécutés dans GKE. Vous devez effectuer une configuration avec les autorisations IAM de 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 accorder ce rôle. Le fichier nécessite des valeurs pour les variables de projet, de région et de nom de 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 de stockage 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 à l'aide de 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 magasin de secrets 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 "Download File" (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 "Download" (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 de la page intitulée System (Système), cliquez sur "Global credentials" (Identifiants globaux), puis sur "Add credentials" (Ajouter des identifiants) à gauche :


Dans le menu déroulant "Kind" (Type), sélectionnez Google Service Account from private key (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 devons définir certaines variables d'environnement Jenkins avant de créer le pipeline multibranche. Les voici :
- JENK_INT_IT_ZONE : zone du cluster Kubernetes. Dans notre cas,
us-east1-d - JENK_INT_IT_PROJECT_ID : fait référence à l'ID du projet GCP hébergeant cette instance de 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 donné,
kaniko-role
Pour les ajouter, accédez à Manage Jenkins (Gérer Jenkins) :

Puis Configure System (Configurer le système) :

Une section nommée Global properties (Propriétés globales) s'affiche. Lorsque nous cochons la case Environment variables (Variables d'environnement), un bouton Add (Ajouter) s'affiche. Cliquez dessus pour ajouter les variables ci-dessus en tant que paires clé-valeur :

Cliquez sur le bouton Save (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 Branch Sources (Sources de branche), saisissez https://github.com/GoogleCloudPlatform/jenkins-integration-samples.git comme Project Repository (Dépôt de projet). Sous Build Configuration (Configuration de compilation), saisissez "gke/Jenkinsfile" comme Script Path (Chemin d'accès au script).

Cliquez sur Save (Enregistrer) pour appliquer ces paramètres. Une fois l'enregistrement effectué, Jenkins lance une analyse du dépôt, puis 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 "Kubernetes Workloads" (Charges de travail Kubernetes).
Une fois les compilations terminées, vous trouverez deux éléments sur la page "Kubernetes Workloads" (Charges de travail Kubernetes) nommés jenkins-integration-samples-gke, chacun correspondant au cluster de production ou de test. L'état sera "OK" :

À l'aide de la commande gcloud suivante, nous verrons 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 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 "Preview on port 8081" (Prévisualiser sur le port 8081).


8. Nettoyage
Nous avons vu comment déployer Jenkins et un exemple de pipeline multibranche 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 préférez, 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 condensés d'image. Commencez par récupérer les condensés à l'aide de la commande suivante :
gcloud container images list-tags gcr.io/${GOOGLE_CLOUD_PROJECT}/jenkins-integration-samples-gke --format="value(digest)"
Ensuite, pour chaque condensé renvoyé :
gcloud container images delete gcr.io/${GOOGLE_CLOUD_PROJECT}/jenkins-integration-samples-gke@sha256:<DIGEST>
9. Félicitations !
Bravo ! Vous avez réussi. Vous avez appris à déployer Jenkins sur GKE et à distribuer des tâches 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 créer un pipeline multibranche qui distribue le travail aux clusters GKE.