1. Przegląd
Jenkins to jedno z najpopularniejszych dostępnych rozwiązań do ciągłej integracji. Służy do automatyzacji najważniejszych elementów procesu tworzenia oprogramowania, które nie wymagają udziału człowieka. Dzięki wdrożeniu Jenkinsa w Kubernetes w Google Cloud i wykorzystaniu wtyczki GKE możemy szybko i automatycznie skalować wykonawców kompilacji w miarę potrzeb. W połączeniu z Cloud Storage możemy tworzyć i testować aplikacje przy minimalnym wysiłku.
Co musisz zrobić
- Wdrażanie usługi Jenkins w klastrze Kubernetes
- Wdrażanie i konfigurowanie wtyczki Jenkins GKE, aby umożliwić Jenkinsowi tworzenie i niszczenie podów jako węzłów wykonawczych
- Kompilowanie i testowanie przykładowej aplikacji SpringBoot
- Tworzenie i publikowanie kontenera w Google Container Registry
- Wdrażanie przykładowej aplikacji w środowiskach GKE typu staging i produkcyjnym
Czego potrzebujesz
- projekt Google Cloud ze skonfigurowanymi rozliczeniami; Jeśli nie masz konta, musisz je utworzyć.
2. Przygotowania
Ten przewodnik można w całości uruchomić na Google Cloud Platform bez konieczności instalowania ani konfigurowania czegokolwiek lokalnie.
Cloud Shell
W tym module praktycznym będziemy udostępniać różne zasoby i usługi w chmurze oraz nimi zarządzać za pomocą wiersza poleceń w Cloud Shell.
Włączanie interfejsów API
Oto interfejsy API, które musimy włączyć w naszym projekcie:
- Compute Engine API – tworzy i uruchamia maszyny wirtualne.
- Kubernetes Engine API – tworzy aplikacje oparte na kontenerach i zarządza nimi.
- Cloud Build API – platforma Google Cloud do ciągłej integracji i ciągłego dostarczania.
- Service Management API – umożliwia producentom usług publikowanie usług na platformie Google Cloud Platform.
- Cloud Resource Manager API – tworzy, odczytuje i aktualizuje metadane kontenerów zasobów Google Cloud.
Włącz wymagane interfejsy API za pomocą tego polecenia gcloud:
gcloud services enable compute.googleapis.com \
container.googleapis.com \
cloudbuild.googleapis.com \
servicemanagement.googleapis.com \
cloudresourcemanager.googleapis.com \
--project ${GOOGLE_CLOUD_PROJECT}
Utwórz zasobnik GCS
Aby przesłać testową pracę, potrzebujemy zasobnika GCS. Utwórzmy zasobnik, używając w nazwie identyfikatora projektu, aby zapewnić jej unikalność:
gsutil mb gs://${GOOGLE_CLOUD_PROJECT}-jenkins-test-bucket/
3. Tworzenie klastrów Kubernetes
Tworzenie klastra
Następnie utworzymy klaster GKE, który będzie hostować nasz system Jenkins, w tym pody, które będą wysyłane jako węzły robocze. Dodatkowy zakres wskazany przez flagę --scopes umożliwi Jenkinsowi dostęp do Cloud Source Repositories i Container Registry. W Cloud Console wykonaj te czynności:
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
Wdrożymy też 2 klastry, w których będziemy hostować wersje testowe i produkcyjne naszej przykładowej aplikacji:
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
Zweryfikuj
Po utworzeniu klastrów możemy potwierdzić, że działają one z gcloud container clusters list.
Dane wyjściowe powinny zawierać RUNNING w kolumnie 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. Wdrażanie Jenkinsa za pomocą narzędzia Helm
Instalowanie Helma
Do zainstalowania Jenkinsa w klastrze użyjemy Helma, czyli menedżera pakietów aplikacji dla Kubernetes. Na początek pobierz projekt zawierający pliki manifestu Kubernetes, których użyjemy do wdrożenia Jenkinsa:
git clone https://github.com/GoogleCloudPlatform/continuous-deployment-on-kubernetes.git ~/continuous-deployment-on-kubernetes
Zmień aktualny katalog roboczy na katalog projektu:
cd ~/continuous-deployment-on-kubernetes/
Utwórz powiązanie roli klastra, aby przyznać sobie uprawnienia roli administratora klastra:
kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=$(gcloud config get-value account)
Połącz się z klastrem Jenkins, uzyskując jego dane logowania:
gcloud container clusters get-credentials jenkins-cd --zone us-east1-d --project ${GOOGLE_CLOUD_PROJECT}
Pobierz plik binarny Helm do konsoli Cloud:
wget https://storage.googleapis.com/kubernetes-helm/helm-v2.14.1-linux-amd64.tar.gz
Rozpakuj plik i skopiuj zawarty w nim plik Helm do bieżącego katalogu roboczego:
tar zxfv helm-v2.14.1-linux-amd64.tar.gz && \ cp linux-amd64/helm .
Tiller to serwerowa część Helm, która działa w klastrze Kubernetes. Utwórz konto usługi o nazwie tiller:
kubectl create serviceaccount tiller \ --namespace kube-system
Powiąż go z rolą klastra cluster-admin, aby mógł wprowadzać zmiany:
kubectl create clusterrolebinding tiller-admin-binding \ --clusterrole=cluster-admin \ --serviceaccount=kube-system:tiller
Teraz możemy zainicjować Helm i zaktualizować repozytorium:
./helm init --service-account=tiller && \ ./helm repo update
Zweryfikuj
Sprawdź, czy Helm jest gotowy do użycia – w tym celu wpisz ./helm version. Powinny się wyświetlić numery wersji klienta i serwera:
Client: &version.Version{SemVer:"v2.14.1", GitCommit:"5270352a09c7e8b6e8c9593002a73535276507c0", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.14.1", GitCommit:"5270352a09c7e8b6e8c9593002a73535276507c0", GitTreeState:"clean"}
Instalowanie Jenkinsa
Po zainstalowaniu Helm w klastrze możemy zainstalować Jenkins:
./helm install stable/jenkins -n cd \ -f jenkins/values.yaml \ --version 1.2.2 --wait
Zweryfikuj
Sprawdźmy pody:
kubectl get pods
Dane wyjściowe powinny zawierać nasz pod Jenkinsa ze stanem RUNNING:
NAME READY STATUS RESTARTS AGE cd-jenkins-7c786475dd-vbhg4 1/1 Running 0 1m
Sprawdź, czy usługa Jenkins została utworzona prawidłowo:
kubectl get svc
Dane wyjściowe powinny wyglądać mniej więcej tak:
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
Instalacja Jenkinsa będzie używać wtyczki Kubernetes do tworzenia agentów kompilacji. W razie potrzeby będą one automatycznie uruchamiane przez serwer główny Jenkinsa. Po zakończeniu pracy są one automatycznie zamykane, a ich zasoby są ponownie dodawane do puli zasobów klastra.
Łączenie z Jenkinsem
Jenkins działa w naszym klastrze, ale aby uzyskać dostęp do interfejsu, skonfigurujmy przekierowanie portów z 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 &
Podczas instalacji wygenerowano hasło administratora. Odzyskajmy go:
printf $(kubectl get secret cd-jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo
U góry Cloud Shell kliknij ikonę podglądu w przeglądarce
i wybierz „Podejrzyj na porcie 8080”.

Powinien pojawić się ekran logowania do Jenkinsa, na którym możesz wpisać admin jako nazwę użytkownika i hasło zwrócone w poprzednim kroku:

Po kliknięciu Zaloguj się powinniśmy zostać przekierowani na stronę główną Jenkinsa.

5. Instalowanie i konfigurowanie wtyczki GKE
Wtyczka Google Kubernetes Engine umożliwia publikowanie wdrożeń utworzonych w Jenkinsie w klastrach Kubernetes działających w GKE. W projekcie trzeba skonfigurować uprawnienia. Wdrożymy tę konfigurację za pomocą Terraform.
Najpierw pobierz projekt wtyczki GKE:
git clone https://github.com/jenkinsci/google-kubernetes-engine-plugin.git ~/google-kubernetes-engine-plugin
Automatyczna konfiguracja uprawnień
Zmień bieżący katalog roboczy na katalog rbac projektu GKE, który został wcześniej sklonowany:
cd ~/google-kubernetes-engine-plugin/docs/rbac/
gcp-sa-setup.tf to plik konfiguracji Terraform, który utworzy niestandardową rolę uprawnień GCP z ograniczonymi uprawnieniami oraz konto usługi GCP, do którego zostanie przypisana ta rola. Plik wymaga wartości zmiennych projektu, regionu i nazwy konta usługi. Podajemy te wartości, deklarując najpierw te zmienne środowiskowe:
export TF_VAR_project=${GOOGLE_CLOUD_PROJECT}
export TF_VAR_region=us-east1-d
export TF_VAR_sa_name=kaniko-role
Zainicjuj Terraform, wygeneruj plan i zastosuj go:
terraform init terraform plan -out /tmp/tf.plan terraform apply /tmp/tf.plan && rm /tmp/tf.plan
Konto usługi będzie potrzebować uprawnień administratora miejsca na dane, aby zapisywać dane w naszym zasobniku 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'
Będzie też potrzebować uprawnień do kontenera na etapach wdrażania potoku:
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} --member \
serviceAccount:kaniko-role@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com --role 'roles/container.developer'
Teraz możemy użyć Helm, aby skonfigurować uprawnienia klastra dla wtyczki GKE za pomocą narzędzia do wdrażania robotów GKE. Zmień katalog roboczy na katalog helm projektu GKE:
cd ~/google-kubernetes-engine-plugin/docs/helm/
Zainstaluj za pomocą podanej karty Helm:
export TARGET_NAMESPACE=kube-system && \ envsubst < gke-robot-deployer/values.yaml | helm install ./gke-robot-deployer --name gke-robot-deployer -f -
6. Konfigurowanie Jenkinsa
Klucze kont usługi
Aby konto usługi działało prawidłowo, musimy wygenerować plik klucza prywatnego i dodać go jako wpis tajny Kubernetes. Najpierw wygeneruj plik za pomocą tego polecenia gcloud:
gcloud iam service-accounts keys create /tmp/kaniko-secret.json --iam-account kaniko-role@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com
Utworzymy klucz tajny w magazynie obiektów tajnych Kubernetes za pomocą tego pliku:
kubectl create secret generic jenkins-int-samples-kaniko-secret --from-file=/tmp/kaniko-secret.json
Pobierz plik JSON na dysk lokalny, klikając opcję Pobierz plik w menu z 3 kropkami w Cloud Shell:

Wpisz ścieżkę do pliku /tmp/kaniko-secret.json i kliknij Pobierz.
Wróć na stronę Jenkinsa i w panelu po lewej stronie kliknij kolejno Dane logowania i System.


W sekcji strony System kliknij po lewej stronie kolejno Globalne dane logowania i Dodaj dane logowania:


W menu Rodzaj wybierz Konto usługi Google z klucza prywatnego. Wpisz „kaniko-role” jako nazwę, a następnie prześlij klucz JSON utworzony w poprzednich krokach i kliknij OK.

Zmienne środowiskowe
Zanim utworzymy potok wielogałęziowy, musimy zdefiniować w Jenkinsie kilka zmiennych środowiskowych. Są to:
- JENK_INT_IT_ZONE – strefa klastra Kubernetes. W naszym przypadku
us-east1-d - JENK_INT_IT_PROJECT_ID – identyfikator projektu GCP, w którym znajduje się ta instancja Jenkinsa.
- JENK_INT_IT_STAGING – nazwa naszego klastra „staging”, na potrzeby demonstracji jest to
staging - JENK_INT_IT_PROD – nazwa naszego klastra „prod”. W celach demonstracyjnych jest to
prod - JENK_INT_IT_BUCKET – zasobnik Cloud Storage utworzony w poprzednim kroku.
- JENK_INT_IT_CRED_ID – odnosi się do danych logowania utworzonych przy użyciu pliku JSON w poprzednim kroku. Wartość powinna być zgodna z nadaną przez nas nazwą,
kaniko-role
Aby je dodać, otwórz Zarządzaj Jenkinsem:

Następnie kliknij Skonfiguruj system:

Znajduje się tam sekcja Właściwości globalne. Gdy zaznaczymy pole Zmienne środowiskowe, pojawi się przycisk Dodaj, który klikniemy, aby dodać powyższe zmienne jako pary klucz-wartość:

Aby zastosować zmiany, kliknij przycisk Zapisz u dołu strony.
7. Konfigurowanie potoku
W Jenkinsie kliknij „New Item” (Nowy element):

Wpisz „jenkins-integration-sample” jako nazwę i wybierz „Multibranch Pipeline” jako typ projektu, a potem kliknij OK:

Nastąpi przekierowanie na stronę konfiguracji potoku. W sekcji Źródła gałęzi wpisz https://github.com/GoogleCloudPlatform/jenkins-integration-samples.git jako Repozytorium projektu. W sekcji Konfiguracja kompilacji wpisz „gke/Jenkinsfile” jako Ścieżkę skryptu.

Kliknij Zapisz, aby zastosować te ustawienia. Po zapisaniu Jenkins rozpocznie skanowanie repozytorium i kolejną kompilację dla każdej gałęzi. W miarę postępu procesu na stronie Zadania Kubernetes będą tworzone, uruchamiane i usuwane pody.
Po zakończeniu kompilacji na stronie Zadania Kubernetes znajdziesz 2 elementy o nazwie jenkins-integration-samples-gke, z których każdy odpowiada klastrowi produkcyjnemu lub testowemu. Stan będzie OK:

Za pomocą tego polecenia gcloud sprawdzimy, czy obraz kontenera odpowiadający naszemu potokowi został przesłany do Google Container Registry:
gcloud container images list
Aby wyświetlić zadanie w przeglądarce, uzyskaj dane logowania do klastra produkcyjnego:
gcloud container clusters get-credentials prod --zone us-east1-d --project ${GOOGLE_CLOUD_PROJECT}
Uruchom to polecenie, aby skonfigurować przekierowanie portu 8081 z powłoki do portu 8080 obciążenia:
export POD_NAME=$(kubectl get pods -o jsonpath="{.items[0].metadata.name}") &&
kubectl port-forward $POD_NAME 8081:8080 >> /dev/null &
U góry Cloud Shell kliknij ikonę podglądu w przeglądarce i wybierz „Podejrzyj na porcie 8081”.


8. Czyszczenie
Omówiliśmy już, jak wdrożyć Jenkinsa i przykładowy potok wielogałęziowy w Kubernetes. Teraz musimy usunąć z projektu wszystkie utworzone zasoby.
Usuwanie projektu
Jeśli wolisz, możesz usunąć cały projekt. W konsoli GCP otwórz stronę Cloud Resource Manager:
Na liście projektów wybierz projekt, nad którym pracowaliśmy, i kliknij Usuń. Pojawi się prośba o wpisanie identyfikatora projektu. Wpisz go i kliknij Wyłącz.
Możesz też usunąć cały projekt bezpośrednio z Cloud Shell za pomocą gcloud:
gcloud projects delete $GOOGLE_CLOUD_PROJECT
Jeśli wolisz usuwać poszczególne komponenty podlegające opłacie, przejdź do następnej sekcji.
Klaster Kubernetes
Usuń cały klaster Kubernetes za pomocą gcloud:
gcloud container clusters delete jenkins-cd --zone=us-east1-d
Zasobniki Cloud Storage
Usuń wszystkie przesłane pliki i usuń nasz zasobnik za pomocą narzędzia gsutil:
gsutil rm -r gs://${GOOGLE_CLOUD_PROJECT}-jenkins-test-bucket
Obrazy w Google Container Registry
Usuniemy obrazy Google Container Registry za pomocą skrótów obrazów. Najpierw pobierz skróty za pomocą tego polecenia:
gcloud container images list-tags gcr.io/${GOOGLE_CLOUD_PROJECT}/jenkins-integration-samples-gke --format="value(digest)"
Następnie w przypadku każdego zwróconego podsumowania:
gcloud container images delete gcr.io/${GOOGLE_CLOUD_PROJECT}/jenkins-integration-samples-gke@sha256:<DIGEST>
9. Gratulacje!
Super! Udało się. Wiesz już, jak wdrożyć Jenkinsa w GKE i wysyłać zadania do klastrów Kubernetes.
Omówione zagadnienia
- Wdrożyliśmy klaster Kubernetes i użyliśmy Helma do zainstalowania Jenkinsa.
- Zainstalowaliśmy i skonfigurowaliśmy wtyczkę GKE, aby umożliwić Jenkinsowi wdrażanie artefaktów kompilacji w klastrach Kubernetes.
- Skonfigurowaliśmy Jenkinsa tak, aby skonfigurować potok wielogałęziowy, który rozdziela pracę między klastry GKE.