1. Panoramica
Jenkins è una delle soluzioni di integrazione continua più diffuse disponibili. Viene utilizzato per automatizzare le parti essenziali non umane del processo di sviluppo del software. Eseguendo il deployment di Jenkins su Kubernetes su Google Cloud e utilizzando il plug-in GKE, possiamo scalare rapidamente e automaticamente gli esecutori di build in base alle esigenze. In combinazione con Cloud Storage, possiamo creare e testare un'applicazione con il minimo sforzo.
Attività previste
- Esegui il deployment di Jenkins in un cluster Kubernetes
- Esegui il deployment e configura il plug-in Jenkins GKE per consentire a Jenkins di creare ed eliminare i pod come nodi esecutori
- Crea e testa un'applicazione SpringBoot di esempio
- Crea e pubblica un container in Google Container Registry
- Esegui il deployment dell'applicazione di esempio in un ambiente GKE di gestione temporanea e produzione
Che cosa ti serve
- Un progetto Google Cloud con la fatturazione configurata. Se non ne hai uno, dovrai crearne uno.
2. Preparazione
Questo codelab può essere eseguito completamente su Google Cloud Platform senza alcuna installazione o configurazione locale.
Cloud Shell
In questo codelab, eseguiremo il provisioning e la gestione di diversi servizi e risorse cloud utilizzando la riga di comando tramite Cloud Shell.
Abilita API
Ecco le API che dovremo abilitare nel nostro progetto:
- API Compute Engine: crea ed esegue macchine virtuali
- API Kubernetes Engine: crea e gestisce applicazioni basate su container
- API Cloud Build: la piattaforma di integrazione continua e distribuzione continua di Google Cloud
- API Service Management: consente ai produttori di servizi di pubblicare servizi su Google Cloud
- API Resource Manager: crea, legge e aggiorna i metadati per i contenitori di risorse Google Cloud
Abilita le API richieste con il seguente comando gcloud:
gcloud services enable compute.googleapis.com \
container.googleapis.com \
cloudbuild.googleapis.com \
servicemanagement.googleapis.com \
cloudresourcemanager.googleapis.com \
--project ${GOOGLE_CLOUD_PROJECT}
Crea un bucket GCS
Avremo bisogno di un bucket GCS per caricare il nostro lavoro di test. Creiamo un bucket utilizzando l'ID progetto nel nome per garantire l'unicità:
gsutil mb gs://${GOOGLE_CLOUD_PROJECT}-jenkins-test-bucket/
3. Creazione di cluster Kubernetes
Crea il cluster
Successivamente, creeremo un cluster GKE che ospiterà il nostro sistema Jenkins, inclusi i pod che verranno inviati come nodi worker. L'ambito aggiuntivo indicato dal flag --scopes consentirà a Jenkins di accedere a Cloud Source Repositories e Container Registry. In Cloud Console, esegui questo comando:
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
Eseguiamo anche il deployment di due cluster per ospitare le build di gestione temporanea e produzione della nostra applicazione di esempio:
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
Verifica
Una volta creati i cluster, possiamo confermare che vengono eseguiti con gcloud container clusters list
L'output dovrebbe contenere RUNNING nella colonna 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. Esegui il deployment di Jenkins con Helm
Installare Helm
Utilizzeremo Helm, un gestore di pacchetti di applicazioni per Kubernetes, per installare Jenkins sul nostro cluster. Per iniziare, scarica il progetto che include i manifest Kubernetes che utilizzeremo per eseguire il deployment di Jenkins:
git clone https://github.com/GoogleCloudPlatform/continuous-deployment-on-kubernetes.git ~/continuous-deployment-on-kubernetes
Cambia la directory di lavoro attuale con la directory del progetto:
cd ~/continuous-deployment-on-kubernetes/
Crea un cluster role binding per concederti le autorizzazioni del ruolo cluster-admin:
kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=$(gcloud config get-value account)
Connettiti al tuo cluster Jenkins recuperando le relative credenziali:
gcloud container clusters get-credentials jenkins-cd --zone us-east1-d --project ${GOOGLE_CLOUD_PROJECT}
e scarica il file binario Helm nella console Cloud:
wget https://storage.googleapis.com/kubernetes-helm/helm-v2.14.1-linux-amd64.tar.gz
Decomprimi il file e copia il file Helm incluso nella directory di lavoro attuale:
tar zxfv helm-v2.14.1-linux-amd64.tar.gz && \ cp linux-amd64/helm .
Tiller è il lato server di Helm che viene eseguito sul cluster Kubernetes. Creiamo un service account denominato tiller:
kubectl create serviceaccount tiller \ --namespace kube-system
e associa il ruolo al ruolo del cluster cluster-admin in modo che possa apportare modifiche:
kubectl create clusterrolebinding tiller-admin-binding \ --clusterrole=cluster-admin \ --serviceaccount=kube-system:tiller
Ora possiamo inizializzare Helm e aggiornare il repository:
./helm init --service-account=tiller && \ ./helm repo update
Verifica
Verifica che Helm sia pronto per l'uso con ./helm version. Dovrebbero essere restituiti i numeri di versione del client e del server:
Client: &version.Version{SemVer:"v2.14.1", GitCommit:"5270352a09c7e8b6e8c9593002a73535276507c0", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.14.1", GitCommit:"5270352a09c7e8b6e8c9593002a73535276507c0", GitTreeState:"clean"}
Installa Jenkins
Ora che Helm è installato sul nostro cluster, possiamo procedere con l'installazione di Jenkins:
./helm install stable/jenkins -n cd \ -f jenkins/values.yaml \ --version 1.2.2 --wait
Verifica
Controlliamo i pod:
kubectl get pods
L'output dovrebbe mostrare il pod Jenkins con lo stato RUNNING:
NAME READY STATUS RESTARTS AGE cd-jenkins-7c786475dd-vbhg4 1/1 Running 0 1m
Verifica che il servizio Jenkins sia stato creato correttamente:
kubectl get svc
L'output dovrebbe essere simile al seguente:
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'installazione di Jenkins utilizzerà il plug-in Kubernetes per creare agenti di build. Verranno avviati automaticamente dal master Jenkins in base alle esigenze. Al termine del loro lavoro, vengono automaticamente terminati e le loro risorse vengono aggiunte di nuovo al pool di risorse del cluster.
Connettiti a Jenkins
Jenkins è in esecuzione sul nostro cluster, ma per accedere alla UI, configuriamo il port forwarding da 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 &
Durante l'installazione è stata generata una password amministratore. Recuperiamolo:
printf $(kubectl get secret cd-jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo
Nella parte superiore di Cloud Shell, fai clic sull'icona Anteprima web
e seleziona "Anteprima sulla porta 8080".

Dovremmo visualizzare una schermata di accesso per Jenkins in cui possiamo inserire admin per il nome utente e la password restituita nel passaggio precedente:

Quando facciamo clic su Accedi, dovremmo essere indirizzati alla pagina principale di Jenkins.

5. Installa e configura il plug-in GKE
Il plug-in Google Kubernetes Engine ci consente di pubblicare i deployment creati in Jenkins nei nostri cluster Kubernetes in esecuzione in GKE. È necessario eseguire alcune configurazioni con le autorizzazioni IAM sul progetto. Eseguiremo il deployment di questa configurazione utilizzando Terraform.
Innanzitutto, scarica il progetto del plug-in GKE:
git clone https://github.com/jenkinsci/google-kubernetes-engine-plugin.git ~/google-kubernetes-engine-plugin
Configurazione automatica delle autorizzazioni IAM
Cambia la directory di lavoro attuale con la directory rbac del progetto GKE che abbiamo clonato in precedenza:
cd ~/google-kubernetes-engine-plugin/docs/rbac/
gcp-sa-setup.tf è un file di configurazione Terraform che creerà un ruolo IAM GCP personalizzato con autorizzazioni limitate insieme a un service account GCP a cui concedere il ruolo. Il file richiede valori per le variabili del progetto, della regione e del nome del service account. Forniamo questi valori dichiarando prima le seguenti variabili di ambiente:
export TF_VAR_project=${GOOGLE_CLOUD_PROJECT}
export TF_VAR_region=us-east1-d
export TF_VAR_sa_name=kaniko-role
Inizializza Terraform, genera un piano e applicalo:
terraform init terraform plan -out /tmp/tf.plan terraform apply /tmp/tf.plan && rm /tmp/tf.plan
Il service account avrà bisogno delle autorizzazioni di amministratore di archiviazione per salvare nel nostro 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'
Avrà anche bisogno delle autorizzazioni del contenitore per le fasi di deployment della pipeline:
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} --member \
serviceAccount:kaniko-role@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com --role 'roles/container.developer'
Ora possiamo utilizzare Helm per configurare le autorizzazioni del cluster per il plug-in GKE utilizzando il robot di deployment GKE. Cambia la directory di lavoro in quella di Helm del progetto GKE:
cd ~/google-kubernetes-engine-plugin/docs/helm/
e installa utilizzando il grafico Helm fornito:
export TARGET_NAMESPACE=kube-system && \ envsubst < gke-robot-deployer/values.yaml | helm install ./gke-robot-deployer --name gke-robot-deployer -f -
6. Configura Jenkins
Chiavi service account
Affinché il service account funzioni correttamente, dobbiamo generare un file della chiave privata e aggiungerlo come secret di Kubernetes. Innanzitutto, genera il file con il seguente comando gcloud:
gcloud iam service-accounts keys create /tmp/kaniko-secret.json --iam-account kaniko-role@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com
Creeremo una chiave segreta nell'archivio dei secret di Kubernetes con questo file:
kubectl create secret generic jenkins-int-samples-kaniko-secret --from-file=/tmp/kaniko-secret.json
Scarica il file JSON sul disco locale accedendo all'elemento Scarica file dal menu con tre puntini di Cloud Shell:

Inserisci il percorso del file /tmp/kaniko-secret.json e fai clic su Scarica.
Nella pagina Jenkins, nel riquadro a sinistra, fai clic su Credenziali,quindi su Sistema.


Nella sezione della pagina intitolata Sistema,fai clic su Credenziali globali e poi su Aggiungi credenziali a sinistra:


Nel menu a discesa Tipo, seleziona Service account Google da chiave privata. Inserisci "kaniko-role" come nome, quindi carica la chiave JSON creata nei passaggi precedenti e fai clic su OK.

Variabili di ambiente
Prima di creare la pipeline multibranch, dobbiamo definire alcune variabili di ambiente per Jenkins. Sono:
- JENK_INT_IT_ZONE: la zona del cluster Kubernetes. Nel nostro caso
us-east1-d - JENK_INT_IT_PROJECT_ID: fa riferimento all'ID progetto GCP che ospita questa istanza di Jenkins
- JENK_INT_IT_STAGING: il nome del nostro cluster di "staging", a scopo dimostrativo è
staging - JENK_INT_IT_PROD: il nome del nostro cluster "prod". A scopo dimostrativo, è
prod - JENK_INT_IT_BUCKET: il bucket Cloud Storage creato nel passaggio precedente
- JENK_INT_IT_CRED_ID: si riferisce alle credenziali create utilizzando il file JSON nel passaggio precedente. Il valore deve corrispondere al nome che gli abbiamo assegnato,
kaniko-role
Per aggiungerli, vai a Manage Jenkins (Gestisci Jenkins):

Poi Configura sistema:

Verrà visualizzata una sezione denominata Proprietà globali e, quando selezioniamo la casella Variabili di ambiente, viene visualizzato un pulsante Aggiungi su cui fare clic per aggiungere le variabili precedenti come coppie chiave-valore:

Fai clic sul pulsante Salva in fondo alla pagina per applicare le modifiche.
7. Configurare una pipeline
In Jenkins, fai clic su "New Item" (Nuovo elemento):

Inserisci "jenkins-integration-sample" come nome, seleziona "Pipeline multi-branch" come tipo di progetto e fai clic su OK:

Verrà visualizzata la pagina di configurazione della pipeline. In Branch Sources (Origini dei rami), inserisci https://github.com/GoogleCloudPlatform/jenkins-integration-samples.git come Project Repository (Repository progetto). In Configurazione build, inserisci "gke/Jenkinsfile" come percorso dello script.

Fai clic su Salva per applicare queste impostazioni. Al salvataggio, Jenkins avvierà una scansione del repository e una build successiva per ogni ramo. Man mano che avanza, vedrai i pod creati, eseguiti ed eliminati man mano che le build avanzano nella pagina Workload Kubernetes.
Al termine delle build, nella pagina Workload Kubernetes troverai due elementi denominati jenkins-integration-samples-gke, ognuno corrispondente al cluster di produzione o di test. Lo stato sarà OK:

Utilizzando il seguente comando gcloud vedremo che abbiamo caricato un'immagine container in Google Container Registry corrispondente alla nostra pipeline:
gcloud container images list
Per visualizzare il workload nel browser, recupera le credenziali per il cluster di produzione:
gcloud container clusters get-credentials prod --zone us-east1-d --project ${GOOGLE_CLOUD_PROJECT}
Esegui questo comando per configurare un port forwarding dalla porta 8081 della shell alla porta 8080 del tuo workload:
export POD_NAME=$(kubectl get pods -o jsonpath="{.items[0].metadata.name}") &&
kubectl port-forward $POD_NAME 8081:8080 >> /dev/null &
Nella parte superiore di Cloud Shell, fai clic sull'icona Anteprima web e seleziona "Anteprima sulla porta 8081".


8. Esegui la pulizia
Abbiamo esaminato come eseguire il deployment di Jenkins e di una pipeline multibranch di esempio su Kubernetes. Ora è il momento di liberare spazio nel nostro progetto da tutte le risorse che abbiamo creato.
Eliminare il progetto
Se preferisci, puoi eliminare l'intero progetto. Nella console di GCP, vai alla pagina Cloud Resource Manager:
Nell'elenco dei progetti, seleziona il progetto su cui abbiamo lavorato e fai clic su Elimina. Ti verrà chiesto di digitare l'ID progetto. Inseriscilo e fai clic su Chiudi.
In alternativa, puoi eliminare l'intero progetto direttamente da Cloud Shell con gcloud:
gcloud projects delete $GOOGLE_CLOUD_PROJECT
Se preferisci eliminare i diversi componenti fatturabili uno alla volta, vai alla sezione successiva.
Cluster Kubernetes
Elimina l'intero cluster Kubernetes con gcloud:
gcloud container clusters delete jenkins-cd --zone=us-east1-d
Bucket di archiviazione
Rimuovi tutti i file caricati ed elimina il nostro bucket con gsutil:
gsutil rm -r gs://${GOOGLE_CLOUD_PROJECT}-jenkins-test-bucket
Immagini di Google Container Registry
Elimineremo le immagini di Google Container Registry utilizzando i digest delle immagini. Innanzitutto, recupera i digest con il seguente comando:
gcloud container images list-tags gcr.io/${GOOGLE_CLOUD_PROJECT}/jenkins-integration-samples-gke --format="value(digest)"
Poi, per ogni riepilogo restituito:
gcloud container images delete gcr.io/${GOOGLE_CLOUD_PROJECT}/jenkins-integration-samples-gke@sha256:<DIGEST>
9. Complimenti!
Evvai! Ce l'hai fatta! Hai imparato a eseguire il deployment di Jenkins su GKE e a distribuire i job ai cluster Kubernetes.
Argomenti trattati
- Abbiamo eseguito il deployment di un cluster Kubernetes e utilizzato Helm per installare Jenkins
- Abbiamo installato e configurato il plug-in GKE per consentire a Jenkins di eseguire il deployment degli artefatti di build nei cluster Kubernetes
- Abbiamo configurato Jenkins per impostare una pipeline multibranch che distribuisce il lavoro ai cluster GKE