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 tarafından yapılamayan önemli kısımlarını otomatikleştirmek için kullanılır. Jenkins'i Google Cloud'daki Kubernetes'e dağıtarak ve GKE eklentisini kullanarak, ihtiyaç duyulduğunda derleme yürütücülerini hızlı ve otomatik olarak ölçeklendirebiliyoruz. Cloud Storage ile birlikte, minimum çabayla uygulama oluşturabilir ve test edebiliriz.

Yapacaklarınız

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

Gerekenler

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

2. Hazırlanma

Bu kod laboratuvarı, yerel kurulum veya yapılandırma olmadan tamamen Google Cloud Platform'da çalışabilir.

Cloud Shell

Bu kod laboratuvarında, Cloud Shell üzerinden komut satırını kullanarak farklı bulut kaynaklarını ve hizmetlerini hazırlayacak ve yöneteceğiz.

API'leri etkinleştirme

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

  • Compute Engine API: Sanal makine 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 yayınlama 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ı için meta veriler 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 paketine ihtiyacımız var. Benzersizliği sağlamak için adında proje kimliğimizi kullanarak 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, işçi düğümü olarak dağıtılacak kapsüller de 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ırlık 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ğrula

Kümeler oluşturulduktan sonra gcloud container clusters list ile çalıştıklarını onaylayabiliriz.

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

Helm'i yükleme

Jenkins'i kümemize yüklemek için Kubernetes için bir uygulama paket yöneticisi olan Helm'i kullanacağız. Başlamak için Jenkins'i dağıtmak üzere kullanacağımız Kubernetes manifest'lerini 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}

Ardından Helm ikili programını Cloud Console'unuza indirin:

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

Dosyayı açın ve içindeki 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

Ardından, 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 deposu güncelleyebiliriz:

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

28b45298e1e82748.png Doğrulama

Helm'in ./helm version ile çalışabileceğini onaylayın. Bu işlem, istemci ve sunucunun sürüm numaralarını döndürür:

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üklendikten sonra 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ğrula

Kapsülleri kontrol edelim:

kubectl get pods

Çıkışta, Jenkins kapsülümüz RUNNING durumunda gösterilir:

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

Jenkins hizmetinin doğru şekilde oluşturulduğunu doğrulayın:

kubectl get svc

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

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 kurulumu, derleyici aracıları oluşturmak için Kubernetes eklentisini kullanır. Bunlar, Jenkins ana makinesi tarafından gerektiğinde otomatik olarak başlatılır. İşleri bittiğinde otomatik olarak sonlandırılır 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 ayarlarını yapalı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 bu bilgileri alalım:

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

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

1d614c831a621cff.png

Jenkins için bir giriş ekranı göreceğiz. Bu ekranda, kullanıcı adı için admin ve önceki adımda döndürülen şifreyi girebiliriz:

9cba23e856cbc84f.png

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

9261f3e914829137.png

5. GKE eklentisini yükleme ve yapılandırma

Google Kubernetes Engine eklentisi, Jenkins'te oluşturulan dağıtımları GKE'de çalışan Kubernetes kümelerimize yayınlamamıza olanak tanır. Projenizde IAM izinleriyle yapılması gereken bazı yapılandırmalar var. Bu yapılandırmayı Terraform'u 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 klonladığımız GKE projesinin rbac dizini olarak değiştirin:

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

gcp-sa-setup.tf, kısıtlanmış izinlere sahip özel bir GCP IAM rolü ve bu rolü atamak için bir GCP hizmet hesabı 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 açıklayarak 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, bir 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 alanı 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ı vardı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ısını 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/

Ardından, 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şturmamız ve bunu Kubernetes gizlisi 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 dosyayı kullanarak Kubernetes gizli anahtar deposunda bir gizli anahtar oluşturacağız:

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

Cloud Shell'ın 3 nokta menüsünden Dosya İndir'e 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 dönün. Sol bölmede Kimlik bilgileri'ni ve ardından Sistem'i tıklayın.

6c140f7e6bb82f8.png

3b874912cdc8019b.png

Sayfanın Sistem başlıklı bölümünde,genel kimlik bilgilerini ve ardından soldaki kimlik bilgilerini ekle'yi tıklayın:

4350c0e68561119b.png

3d3526551cdae8b.png

Tür açılır menüsünde Özel anahtardan Google hizmet hesabı'nı seçin. Ad olarak "kaniko-role" yazın, 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ı ardışık düzen oluşturmadan önce Jenkins'i tanımlamamız gereken bazı ortam değişkenleri vardır. Bunları şöyle sıralayabiliriz:

  • JENK_INT_IT_ZONE: Kubernetes kümesinin bölgesi. Bizim durumumuzda us-east1-d
  • JENK_INT_IT_PROJECT_ID: Bu Jenkins örneğini barındıran GCP proje kimliğini belirtir.
  • JENK_INT_IT_STAGING: "Hazırlık" küme adımız. Demo amaçlı olarak staging olarak ayarlanmıştır.
  • JENK_INT_IT_PROD: "prod" küme adımız. Demo amaçlı olarak 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, verdiğimiz adla (kaniko-role) eşleşmelidir.

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

d54f279190a07878.png

Ardından Sistemi Yapılandır:

ce79d218b2799640.png

Küresel özellikler adlı bir bölüm göreceksiniz. 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 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 "Yeni Öğe"yi tıklayın:

8d1270ce4d7b6a8a.png

Ad olarak "jenkins-integration-sample" yazın, proje türü olarak "Çok Dallı Hat"ı seçin ve Tamam'ı tıklayın:

eb071ecfbb4d775b.png

Akış yapılandırması sayfasına yönlendiriliriz. Kol Kaynakları bölümünde Proje Deposu olarak https://github.com/GoogleCloudPlatform/jenkins-integration-samples.git adresini girin. Derleme Yapılandırması bölümünde, Komut Dosyası Yolu olarak "gke/Jenkinsfile" yazın.

5135bd6b0374508c.png

Bu ayarları uygulamak için Kaydet'i tıklayın. Kayıttan sonra Jenkins, deponun taranmasını ve her dal için bir derleme işlemini başlatır. Derleme işlemi devam ederken Kubernetes İş Yükleri sayfasında kapsüllerin oluşturulduğunu, çalıştırıldığını ve silindiğini görürsünüz.

Derlemeler tamamlandığında Kubernetes İş Yükleri sayfasında, her biri üretim veya test grubuna karşılık gelen jenkins-integration-samples-gke adlı iki öğe görürsünüz. Durum "Tamam" olarak görünür:

bdec6b1753d1ba07.png

Aşağıdaki gcloud komutunu kullanarak, ardışık düzenimize karşılık gelen bir kapsayıcı görüntüsünü Google Container Registry'ye yüklediğimizi göreceğiz:

gcloud container images list

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

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

Kabuğunuzun 8081 numaralı bağlantı noktasından iş yükünüzün 8080 numaralı bağlantı noktasına bağlantı noktası yönlendirme ayarlamak için aşağıdakileri ç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ındaki Web Önizlemesi simgesini tıklayın ve "8081 bağlantı noktasında önizle"yi seçin.

1b19b5b56f1bae7.png

e80e995e71763bb2.png

8. Temizleme

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

Projeyi silme

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

Proje listesinde, üzerinde çalıştığımız projeyi seçin ve Sil'i tıklayın. Proje kimliğini girmeniz istenir. Şifrenizi girip Kapat'ı tıklayın.

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

gcloud projects delete $GOOGLE_CLOUD_PROJECT

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

Kubernetes Kümesi

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

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

Depolama Alanları

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

Görüntü özetlerini kullanarak Google Container Registry görüntülerini sileriz. Ö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'de dağıtmayı ve işleri Kubernetes kümelerine dağıtmayı öğrendiniz.

İşlediğimiz konular

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