1. Présentation
Jenkins est l'une des solutions d'intégration continue les plus populaires du marché. Elle permet d'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 faire évoluer rapidement et automatiquement les exécuteurs de compilation en fonction des besoins. Combiné à Cloud Storage, nous pouvons créer et tester une application avec un minimum d'efforts.
Objectifs de l'atelier
- Déployer Jenkins dans 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'application exemple 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 devez 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 services cloud à l'aide de la ligne de commande via Cloud Shell.
Activer les API
Voici les API que nous devrons activer pour 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 continue 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 notre ID de projet comme nom pour garantir son caractère unique:
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'indicateur --scopes
permet à 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 les builds de préproduction et de production de notre application exemple:
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 s'exécutent avec gcloud container clusters list
.
La colonne STATUS
doit contenir RUNNING
:
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, pour 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
Définissez votre répertoire de travail actuel sur le 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 la 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
et l'associer 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 devraient 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 devrait 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 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 si nécessaire. 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'UI, nous allons configurer 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-la:
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 sur le Web , puis sélectionnez "Preview on port 8080" (Prévisualiser sur le port 8080).
Un écran de connexion à Jenkins devrait s'afficher, dans lequel vous pouvez saisir le admin
pour le nom d'utilisateur et le mot de passe renvoyés à l'étape précédente:
Lorsque nous cliquons sur Connexion, 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 du plug-in GKE:
git clone https://github.com/jenkinsci/google-kubernetes-engine-plugin.git ~/google-kubernetes-engine-plugin
Configuration automatique des autorisations IAM
Définissez votre répertoire de travail actuel sur 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 de nom du projet, de région et 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 l'appliquez:
terraform init terraform plan -out /tmp/tf.plan terraform apply /tmp/tf.plan && rm /tmp/tf.plan
Le compte de service aura besoin d'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éployeur 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 un 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".
Sur la page Jenkins, dans le volet de gauche, cliquez sur Credentials (Identifiants), puis sur System (Système).
Dans la section 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 créée aux étapes précédentes et cliquez sur OK.
Variables d'environnement
Nous devons définir certaines variables d'environnement pour Jenkins avant de créer le pipeline à plusieurs branches. 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 de projet GCP hébergeant cette instance de Jenkins
- JENK_INT_IT_STAGING : nom de notre cluster de préproduction. Pour des raisons 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 à l'étape précédente. La valeur doit correspondre au nom que nous lui avons attribué,
kaniko-role
.
Pour les ajouter, accédez à Manage Jenkins (Gérer Jenkins) :
Ensuite, accédez à Configure System (Configurer le système) :
Une section intitulée Propriétés globales s'affiche. Lorsque nous cochons la case Variables d'environnement, un bouton Ajouter s'affiche. Nous pouvons cliquer dessus pour ajouter les variables ci-dessus en tant que 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 êtes 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 Build Configuration (Configuration de compilation), saisissez "gke/Jenkinsfile" comme Script Path (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 ultérieure pour chaque branche. Au fur et à mesure de la compilation, des pods sont créés, exécutés et détruits sur la page "Charges de travail Kubernetes".
Une fois les builds terminés, deux éléments nommés jenkins-integration-samples-gke s'affichent sur la page "Charges de travail Kubernetes", chacun correspondant au cluster de production ou de test. L'état indique "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, récupérez 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 sur le Web", puis sélectionnez "Preview on port 8081" (Prévisualiser sur le port 8081).
8. Nettoyage
Nous avons vu comment déployer un Jenkins et un exemple de pipeline multibranche sur Kubernetes. Il est maintenant temps de supprimer toutes les ressources que nous avons créées de notre projet.
Supprimer le projet
Si vous 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 supprimerons les images Google Container Registry à l'aide des récapitulatifs d'images. Commencez par récupérer les récapitulatifs à 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 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 tâches à des 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 dans des clusters Kubernetes.
- Nous avons configuré Jenkins pour configurer un pipeline multibranche qui distribue le travail aux clusters GKE.