GKE'de Jenkins Çok Dallı Ardışık Düzen

1. Genel Bakış

Jenkins, mevcut en popüler sürekli entegrasyon çözümlerinden biridir. Yazılım geliştirme sürecinin insan dışı temel kısımlarını otomatikleştirmek için kullanılır. Jenkins'i Google Cloud'da Kubernetes'e dağıtıp GKE eklentisinden yararlanarak, gerektiğinde derleme yürütücülerini hızlı ve otomatik olarak ölçeklendirebiliyoruz. Cloud Storage ile birlikte, minimum çabayla bir uygulama oluşturup test edebiliyoruz.

Yapacaklarınız

  • Jenkins'i Kubernetes kümesine dağıtma
  • Jenkins'in yürütücü düğümleri olarak kapsüller oluşturup yok etmesini sağlamak için Jenkins GKE eklentisini dağıtın ve yapılandırın.
  • Örnek SpringBoot uygulaması oluşturma ve test etme
  • Google Container Registry'de kapsayıcı oluşturma ve yayınlama
  • Örnek uygulamayı bir hazırlama ve üretim GKE ortamına dağıtma

Gerekenler

  • Faturalandırmanın ayarlandığı bir Google Cloud projesi. Hesabınız yoksa oluşturmanız gerekir.

2. Hazırlanma

Bu codelab, yerel kurulum veya yapılandırma olmadan tamamen Google Cloud Platform'da çalıştırılabilir.

Cloud Shell

Bu codelab boyunca, Cloud Shell üzerinden komut satırını kullanarak farklı bulut kaynaklarını ve hizmetlerini sağlayıp yöneteceğiz.

.

API'leri etkinleştirme

Projemizde etkinleştirmemiz gereken API'ler şunlardır:

  • Compute Engine API: Sanal makineler oluşturur ve çalıştırır.
  • Kubernetes Engine API: Container tabanlı uygulamalar oluşturur ve yönetir.
  • Cloud Build API: Google Cloud'un sürekli entegrasyon ve sürekli teslim platformu
  • Service Management API: Hizmet üreticilerin Google Cloud Platform'da hizmet yayınlamasına olanak tanır.
  • Cloud Resource Manager API: Google Cloud kaynak kapsayıcılarının meta verilerini oluşturur, okur ve günceller.

Aşağıdaki gcloud komutuyla gerekli API'leri etkinleştirin:

gcloud services enable compute.googleapis.com \
container.googleapis.com \
cloudbuild.googleapis.com \
servicemanagement.googleapis.com \
cloudresourcemanager.googleapis.com \
--project ${GOOGLE_CLOUD_PROJECT}

GCS paketi oluşturma

Test çalışmamızı yüklemek için bir GCS paketi gerekir. Benzersizliği sağlamak için adında proje kimliğimizin yer aldığı bir paket oluşturalım:

gsutil mb gs://${GOOGLE_CLOUD_PROJECT}-jenkins-test-bucket/ 

3. Kubernetes kümeleri oluşturma

Küme oluşturma

Ardından, çalışan düğümleri olarak gönderilecek pod'lar da dahil olmak üzere Jenkins sistemimizi barındıracak bir GKE kümesi oluşturacağız. --scopes işaretiyle belirtilen ek kapsam, Jenkins'in Cloud Source Repositories ve Container Registry'ye erişmesine olanak tanır. Cloud Console'da aşağıdakileri çalıştırın:

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

Ayrıca örnek uygulamamızın hazırlama ve üretim derlemelerini barındırmak için 2 küme dağıtalım:

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

28b45298e1e82748.png Doğrulayın

Kümeler oluşturulduktan sonra gcloud container clusters list ile çalışıp çalışmadıklarını doğrulayabiliriz.

Çıkışın STATUS sütununda RUNNING olmalıdır:

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. Helm ile Jenkins'i dağıtma

Helm'i yükleme

Kümemize Jenkins'i yüklemek için Kubernetes'e yönelik bir uygulama paketi yöneticisi olan Helm'i kullanacağız. Başlamak için Jenkins'i dağıtmak üzere kullanacağımız Kubernetes manifestlerini içeren projeyi indirin:

git clone https://github.com/GoogleCloudPlatform/continuous-deployment-on-kubernetes.git ~/continuous-deployment-on-kubernetes

Mevcut çalışma dizininizi proje dizini olarak değiştirin:

cd ~/continuous-deployment-on-kubernetes/

Kendinize küme yöneticisi rolü izinleri vermek için bir küme rolü bağlaması oluşturun:

kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=$(gcloud config get-value account)

Kimlik bilgilerini alarak Jenkins kümenize bağlanın:

gcloud container clusters get-credentials jenkins-cd --zone us-east1-d --project ${GOOGLE_CLOUD_PROJECT}

Ayrıca Helm ikili dosyasını Cloud Console'unuza indirin:

wget https://storage.googleapis.com/kubernetes-helm/helm-v2.14.1-linux-amd64.tar.gz

Dosyanın sıkıştırmasını açın ve içerdiği helm dosyasını mevcut çalışma dizininize kopyalayın:

tar zxfv helm-v2.14.1-linux-amd64.tar.gz && \
cp linux-amd64/helm .

Tiller, Kubernetes kümesinde çalışan Helm'in sunucu tarafıdır. tiller adlı bir hizmet hesabı oluşturalım:

kubectl create serviceaccount tiller \
--namespace kube-system

Ayrıca, değişiklik yapabilmesi için cluster-admin küme rolüne bağlayın:

kubectl create clusterrolebinding tiller-admin-binding \
--clusterrole=cluster-admin \
--serviceaccount=kube-system:tiller

Artık Helm'i başlatabilir ve depoyu güncelleyebiliriz:

./helm init --service-account=tiller && \
./helm repo update

28b45298e1e82748.png Doğrula

Helm'in ./helm version ile çalışmaya hazır olduğunu onaylayın. Bu komut, istemcinin ve sunucunun sürüm numaralarını döndürmelidir:

Client: &version.Version{SemVer:"v2.14.1", GitCommit:"5270352a09c7e8b6e8c9593002a73535276507c0", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.14.1", GitCommit:"5270352a09c7e8b6e8c9593002a73535276507c0", GitTreeState:"clean"}

Jenkins'i yükleme

Helm, kümemize yüklendiğine göre artık Jenkins'i yüklemeye hazırız:

./helm install stable/jenkins -n cd \
-f jenkins/values.yaml \
--version 1.2.2 --wait

28b45298e1e82748.png Doğrulayın

Pod'ları kontrol edelim:

kubectl get pods

Çıkışta, Jenkins pod'umuzun RUNNING (ÇALIŞIYOR) durumunda olduğu gösterilmelidir:

NAME                          READY     STATUS    RESTARTS   AGE
cd-jenkins-7c786475dd-vbhg4   1/1       Running   0          1m

Jenkins hizmetinin düzgün şekilde oluşturulduğunu onaylayın:

kubectl get svc

Çıkış şu şekilde görünmelidir:

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

Jenkins yüklemesinde, oluşturucu aracıları oluşturmak için Kubernetes eklentisi kullanılacaktır. Bu işlemler, gerektiğinde Jenkins ana sunucusu tarafından otomatik olarak başlatılır. İşleri bittiğinde otomatik olarak sonlandırılırlar ve kaynakları kümenin kaynak havuzuna geri eklenir.

Jenkins'e bağlanma

Jenkins, kümemizde çalışıyor ancak kullanıcı arayüzüne erişmek için Cloud Shell'den bağlantı noktası yönlendirme ayarlayalım:

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 &

Yükleme sırasında bir yönetici şifresi oluşturuldu. Şimdi de geri alalım:

printf $(kubectl get secret cd-jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo

Cloud Shell'in üst kısmında Web Önizlemesi simgesini 7ddf5a65fd556dd6.png tıklayın ve "8080 numaralı bağlantı noktasında önizle"yi seçin.

1d614c831a621cff.png

Kullanıcı adı için admin ve önceki adımda döndürülen şifreyi girebileceğimiz bir Jenkins oturum açma ekranı görmemiz gerekir:

9cba23e856cbc84f.png

Oturum aç'ı tıkladığımızda Jenkins'in ana sayfasına yönlendirilmemiz gerekir.

9261f3e914829137.png

5. GKE eklentisini yükleyip yapılandırma

Google Kubernetes Engine eklentisi, Jenkins'te oluşturulan dağıtımları GKE'de çalışan Kubernetes kümelerimizde yayınlamamıza olanak tanır. Projenizde IAM izinleriyle ilgili yapılması gereken bazı yapılandırmalar var. Bu yapılandırmayı Terraform kullanarak dağıtacağız.

İlk olarak GKE eklenti projesini indirin:

git clone https://github.com/jenkinsci/google-kubernetes-engine-plugin.git ~/google-kubernetes-engine-plugin

Otomatik IAM İzinleri Yapılandırması

Mevcut çalışma dizininizi, daha önce kopyaladığımız GKE projesinin rbac dizini olarak değiştirin:

cd ~/google-kubernetes-engine-plugin/docs/rbac/

gcp-sa-setup.tf, bu rolü vermek için bir GCP hizmet hesabının yanı sıra sınırlı izinlere sahip özel bir GCP IAM rolü oluşturacak bir Terraform yapılandırma dosyasıdır. Dosyada proje, bölge ve hizmet hesabı adı değişkenleri için değerler gerekir. Bu değerleri, önce aşağıdaki ortam değişkenlerini tanımlayarak sağlarız:

export TF_VAR_project=${GOOGLE_CLOUD_PROJECT}
export TF_VAR_region=us-east1-d
export TF_VAR_sa_name=kaniko-role

Terraform'u başlatın, plan oluşturun ve uygulayın:

terraform init
terraform plan -out /tmp/tf.plan
terraform apply /tmp/tf.plan && rm /tmp/tf.plan

Hizmet hesabının, Cloud Storage paketimize kaydetmek için depolama yöneticisi izinlerine sahip olması gerekir:

gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
--member serviceAccount:kaniko-role@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com \
--role 'roles/storage.admin'

Ayrıca, ardışık düzenimizin dağıtım aşamaları için kapsayıcı izinlerine de ihtiyacı olacaktır:

gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} --member \
serviceAccount:kaniko-role@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com --role 'roles/container.developer'

Artık gke robot dağıtıcıyı kullanarak GKE eklentisi için küme izinlerini ayarlamak üzere Helm'i kullanabiliriz. Çalışma dizininizi GKE projesinin Helm dizini olarak değiştirin:

cd ~/google-kubernetes-engine-plugin/docs/helm/

Ve sağlanan Helm grafiğini kullanarak yükleyin:

export TARGET_NAMESPACE=kube-system && \
envsubst < gke-robot-deployer/values.yaml | helm install ./gke-robot-deployer --name gke-robot-deployer -f -

6. Jenkins'i yapılandırma

Hizmet Hesabı Anahtarları

Hizmet hesabının düzgün çalışması için bir özel anahtar dosyası oluşturup bunu Kubernetes sırrı olarak eklememiz gerekir. Öncelikle aşağıdaki gcloud komutuyla dosyayı oluşturun:

gcloud iam service-accounts keys create /tmp/kaniko-secret.json --iam-account kaniko-role@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com

Bu dosyayla Kubernetes gizli anahtar deposunda bir gizli anahtar oluştururuz:

kubectl create secret generic jenkins-int-samples-kaniko-secret --from-file=/tmp/kaniko-secret.json 

Cloud Shell'in 3 nokta menüsünden Dosya İndir öğesine erişerek JSON dosyasını yerel diskinize indirin:

c40378e72013b843.png

Dosya yolunu girin /tmp/kaniko-secret.json ve İndir'i tıklayın.

Jenkins sayfasına geri dönün ve sol taraftaki bölmede Credentials (Kimlik Bilgileri), ardından System'i (Sistem) tıklayın.

6c140f7e6bb82f8.png3b874912cdc8019b.png

Sayfanın Sistem başlıklı bölümünde,sol tarafta Global kimlik bilgileri'ni ve ardından Kimlik bilgileri ekle'yi tıklayın:

4350c0e68561119b.png3d3526551cdae8b.png

Tür açılır listesinde Özel anahtardan Google hizmet hesabı'nı seçin. Ad olarak "kaniko-role" girin, ardından önceki adımlarda oluşturulan JSON anahtarınızı yükleyin ve Tamam'ı tıklayın.

b0502213408e730e.png

Ortam değişkenleri

Çok dallı işlem hattını oluşturmadan önce Jenkins'te tanımlamamız gereken bazı ortam değişkenleri vardır. Bunları şöyle sıralayabiliriz:

  • JENK_INT_IT_ZONE: Kubernetes kümesinin bölgesi. Örneğimizde us-east1-d
  • JENK_INT_IT_PROJECT_ID: Bu Jenkins örneğine barındıran GCP proje kimliğini ifade eder.
  • JENK_INT_IT_STAGING: "Hazırlama" kümemizin adı. Gösterim amacıyla staging olarak ayarlanmıştır.
  • JENK_INT_IT_PROD: "prod" kümemizin adı. Bu demoda prod
  • JENK_INT_IT_BUCKET: Önceki adımda oluşturulan Google Cloud Storage paketi
  • JENK_INT_IT_CRED_ID: Önceki adımda JSON kullanılarak oluşturulan kimlik bilgilerini ifade eder. Değer, kaniko-role olarak verdiğimiz adla eşleşmelidir.

Bunları eklemek için Manage Jenkins'e (Jenkins'i Yönet) gidin:

d54f279190a07878.png

Ardından Sistemi Yapılandır'ı tıklayın:

ce79d218b2799640.png

Global properties (Genel özellikler) adlı bir bölüm bulunur. Environment variables (Ortam değişkenleri) kutusunu işaretlediğimizde, yukarıdaki değişkenleri anahtar/değer çiftleri olarak eklemek için tıklayacağımız bir Add (Ekle) düğmesi gösterilir:

81aa222a2b17b2cc.png

Değişiklikleri uygulamak için sayfanın alt kısmındaki Kaydet düğmesini tıklayın.

7. Ardışık düzen oluşturma

Jenkins'te "New Item"ı (Yeni Öğe) tıklayın:

8d1270ce4d7b6a8a.png

Ad için "jenkins-integration-sample" girin, proje türü olarak "Multibranch Pipeline"ı (Çok dallı işlem hattı) seçin ve Tamam'ı tıklayın:

eb071ecfbb4d775b.png

Ardışık düzen yapılandırma sayfasına yönlendiriliriz. Branch Sources (Dal Kaynakları) bölümünde Project Repository (Proje Deposu) olarak https://github.com/GoogleCloudPlatform/jenkins-integration-samples.git adresini girin. Build Configuration (Derleme Yapılandırması) bölümünde, Script Path (Komut Dosyası Yolu) olarak "gke/Jenkinsfile"ı girin.

5135bd6b0374508c.png

Bu ayarları uygulamak için Kaydet'i tıklayın. Kaydettikten sonra Jenkins, deponun taranmasını ve her dal için sonraki derlemeyi başlatır. İşlem ilerledikçe Kubernetes İş Yükleri sayfasında derlemeler ilerlerken kapsüllerin oluşturulduğunu, çalıştırıldığını ve yok edildiğini görürsünüz.

Derlemeler tamamlandığında Kubernetes Workloads (Kubernetes İş Yükleri) sayfasında jenkins-integration-samples-gke adlı iki öğe görürsünüz. Bu öğelerin her biri prod veya test kümesine karşılık gelir. Durum "Tamam" olarak gösterilir:

bdec6b1753d1ba07.png

Aşağıdaki gcloud komutunu kullanarak, Google Container Registry'ye işlem hattımıza karşılık gelen bir kapsayıcı resmi yüklediğimizi görebiliriz:

gcloud container images list

İş yükünü tarayıcınızda görmek için üretim kümesinin kimlik bilgilerini alın:

gcloud container clusters get-credentials prod --zone us-east1-d --project ${GOOGLE_CLOUD_PROJECT}

Ayrıca, kabuğunuzun bağlantı noktası 8081'den iş yükünüzün bağlantı noktası 8080'e bağlantı noktası yönlendirme ayarlamak için aşağıdaki komutu çalıştırın:

export POD_NAME=$(kubectl get pods -o jsonpath="{.items[0].metadata.name}") &&
kubectl port-forward $POD_NAME 8081:8080 >> /dev/null &

Cloud Shell'in üst kısmında Web Önizlemesi simgesini tıklayın ve "8081 numaralı bağlantı noktasında önizle"yi seçin.

1b19b5b56f1bae7.pnge80e995e71763bb2.png

8. Temizleme

Kubernetes'e Jenkins ve örnek bir çok dallı ardışık düzenin nasıl dağıtılacağını inceledik. Şimdi de projemizi oluşturduğumuz kaynaklardan temizleme zamanı.

Projeyi silme

İsterseniz projenin tamamını silebilirsiniz. GCP Console'da Cloud Resource Manager sayfasına gidin:

Proje listesinde, üzerinde çalıştığımız projeyi seçip Sil'i tıklayın. Proje kimliğini girmeniz istenir. Girip Kapat'ı tıklayın.

Alternatif olarak, projenin tamamını doğrudan Cloud Shell'den gcloud ile silebilirsiniz:

gcloud projects delete $GOOGLE_CLOUD_PROJECT

Farklı faturalandırılabilir bileşenleri tek tek silmeyi tercih ediyorsanız bir sonraki bölüme geçin.

Kubernetes Kümesi

gcloud ile Kubernetes kümesinin tamamını silin:

gcloud container clusters delete jenkins-cd --zone=us-east1-d

Depolama paketleri

Yüklenen tüm dosyaları kaldırın ve gsutil ile paketimizi silin:

gsutil rm -r gs://${GOOGLE_CLOUD_PROJECT}-jenkins-test-bucket

Google Container Registry Görüntüleri

Google Container Registry görüntüleri, görüntü özetleri kullanılarak silinir. Öncelikle aşağıdaki komutla özetleri alın:

gcloud container images list-tags gcr.io/${GOOGLE_CLOUD_PROJECT}/jenkins-integration-samples-gke --format="value(digest)"

Ardından, döndürülen her özet için:

gcloud container images delete gcr.io/${GOOGLE_CLOUD_PROJECT}/jenkins-integration-samples-gke@sha256:<DIGEST>

9. Tebrikler!

Mükemmel! Başardınız. Jenkins'i GKE'ye dağıtmayı ve işleri Kubernetes kümelerine göndermeyi öğrendiniz.

İşlediğimiz konular

  • Kubernetes kümesi dağıtıp Jenkins'i yüklemek için Helm'i kullandık.
  • Jenkins'in derleme yapılarını Kubernetes kümelerine dağıtmasını sağlamak için GKE eklentisini yükleyip yapılandırdık.
  • Jenkins'i, işi GKE kümelerine gönderen çok dallı bir ardışık düzen oluşturacak şekilde yapılandırdık.