İçerik
Bu yazıda Jenkins CI/CD süreçlerinin tamamını bulabilirsiniz. Gelecek yazımda SonarQube entegrasyonuna da değineceğim. Ayrıca Kubernetes deployment stratejilerine de daha sonraki yazımda değineceğim.
Harbor, Jenkins, Gitlab ve Kubernetes – Rancher kurulumlarına bağlantılara tıklayarak ulaşabilirsiniz.
NOT: Bu işlemler için Jenkins yazımda olan alternatif kurulumu yapmanız gerekir.
Ek olarak ilgili toolların resmi web siteleri aşağıdaki gibidir.
Jenkins: https://www.jenkins.io/
Gitlab: https://about.gitlab.com/install/
Rancher: https://rancher.com/
Harbor: https://goharbor.io/
Gitlab Repository Yapılandırması
Jenkins CI/CD İçin Proje Dosyalarının Yüklenmesi
Gitlab üzerinde test ci/cd projemizi yapılandıralım. Root altında test adlı repository oluşturdum. Oluşturulan repository’nin Project Visibility ayarını Gitlab üzerinden “Internal” olarak ayarladım. Bu şekilde Jenkins, Gitlab’a username password ile giriş yapıp, projeyi görebilecek. Aşağıdaki registry ve gitlab adreslerini kendinize göre yapılandırın.
Dockerfile Dosyasının Yapılandırılması
Dockerfile adlı dosyamıza aşağıdaki komutları yazalım.
FROM httpd:2.4
COPY ./index.html /usr/local/apache2/htdocs/
Jenkinsfile Dosyasının Yapılandırılması
Jenkinsfile adlı dosyamıza aşağıdaki komutları yazalım.
pipeline {
environment {
registry = "harbor.sezer.test:443/library"
dockerImage = ""
projectName = "test-image"
}
agent any
stages {
stage('Checkout Gitlab Source') {
steps {
git url:'https://gitlab.sezer.test/root/test.git', branch:'main', credentialsId:'deneme-test-123-deneme-2345'
}
}
stage('Build Image') {
steps{
script {
docker.withServer('tcp://127.0.0.1:2376') {
dockerImage = docker.build registry + "/" + projectName + ":$BUILD_NUMBER"
}
}
}
}
stage('Version Image Push') {
steps{
script {
docker.withServer('tcp://127.0.0.1:2376') {
withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'harbor-registry', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) {
sh "echo ${PASSWORD} | docker -H tcp://127.0.0.1:2376 --config /bitnami/jenkins/home/.docker login harbor.sezer.test:443 -u ${USERNAME} --password-stdin"
}
sh "docker -H tcp://127.0.0.1:2376 --config /bitnami/jenkins/home/.docker push ${registry}/${projectName}:${BUILD_NUMBER}"
}
}
}
}
stage('Retag Image') {
steps{
script {
docker.withServer('tcp://127.0.0.1:2376') {
withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'harbor-registry', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) {
sh "echo ${PASSWORD} | docker -H tcp://127.0.0.1:2376 --config /bitnami/jenkins/home/.docker login harbor.sezer.test:443 -u ${USERNAME} --password-stdin"
}
sh "docker -H tcp://127.0.0.1:2376 --config /bitnami/jenkins/home/.docker tag ${registry}/${projectName}:${BUILD_NUMBER} ${registry}/${projectName}:latest"
}
}
}
}
stage('Latest Image Push') {
steps{
script {
docker.withServer('tcp://127.0.0.1:2376') {
withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'harbor-registry', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) {
sh "echo ${PASSWORD} | docker -H tcp://127.0.0.1:2376 --config /bitnami/jenkins/home/.docker login harbor.sezer.test:443 -u ${USERNAME} --password-stdin"
}
sh "docker -H tcp://127.0.0.1:2376 --config /bitnami/jenkins/home/.docker push ${registry}/${projectName}:latest"
}
}
}
}
stage('Remove All Image') {
steps{
script {
docker.withServer('tcp://127.0.0.1:2376') {
sh 'docker -H tcp://127.0.0.1:2376 rmi $(docker -H tcp://127.0.0.1:2376 images -a -q) -f'
}
}
}
}
stage('Deploy App on K8S') {
steps {
script {
withKubeConfig([credentialsId: 'rancherconfig']) {
sh 'sed -ie "s/THIS_STRING_IS_REPLACED_DURING_BUILD/$(date)/g" myweb.yaml'
sh 'kubectl apply -f myweb.yaml'
}
}
}
}
}
}
Web Dosyasının Yapılandırılması
index.html dosyamıza aşağıdaki komutları yazalım.
<center>
<h1>Sezer.test</h1>
<h1>v1.0</h1>
<br><hr>
<p>Harbor Registry - Gitlab - Jenkins CI/CD - Kubernetes Deployment</p>
</center>
Deployment Dosyasının Yapılandırılması
myweb.yaml dosyamıza aşağıdaki kubernetes komutlarını yazalım
apiVersion: v1
kind: Namespace
metadata:
name: myweb
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: myweb
name: myweb
namespace: myweb
spec:
replicas: 3
selector:
matchLabels:
app: myweb
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
template:
metadata:
labels:
app: myweb
spec:
containers:
- image: harbor.sezer.test:443/library/test-image:latest
imagePullPolicy: Always
name: myweb
env:
- name: BUILD_DATE
value: 'THIS_STRING_IS_REPLACED_DURING_BUILD'
---
apiVersion: v1
kind: Service
metadata:
labels:
app: myweb
name: myweb
namespace: myweb
spec:
ports:
- nodePort: 32223
port: 80
protocol: TCP
targetPort: 80
selector:
app: myweb
type: NodePort
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myweb
namespace: myweb
spec:
ingressClassName: nginx
rules:
-
host: myweb.test
http:
paths:
-
backend:
service:
name: myweb
port:
number: 80
path: /
pathType: Prefix
Jenkins Ayarları
Jenkis admin arayüzüne giriş yapalım. Ardından Jenkins’i Yönet menüsüne girelim.
Kullanılabilir menüsü altında arama yapıp daha sonra aşağıdaki 5 eklentiyi tek tek yüklüyoruz.
1- Kubernetes CLI Plugin
2- Kubernetes
3- Docker Pipeline
4- GitLab Plugin
5- Generic Webhook Trigger Plugin
NOT: Yükleme yaparken without restart butonundan yapın. Tüm eklentileri yükledikten sonra Jenkins’i yeniden başlat kutusunu seçin.
Yükleme yaptıktan sonra Jenkins’i yeniden başlatın butonuna tıklayarak arayüzden yeniden başlatma işlemini gerçekleştirin.
Tekrar Jenkins admin arayüzüne giriş yaptıktan sonra “Jenkins’i Yönet > Sistem Konfigürasyonunu Değiştir” adımlarını takip edelim.
Sayfanın en altına inip Cloud menüsündeki “a separate configuration page.” bağlantısına tıklıyoruz.
Kubernetes’i seçiyoruz.
Kubernetes Cloud details butonuna tıklıyoruz
Credentials kısmında Add’e tıklayıp “Jenkins” seçeneğine tıklıyoruz
Açılan pencerede Kind kısmından Secretfile seçeneğini seçiyoruz
Rancher arayüzünden Cluster config‘i indiriyorum.
İlgili kısımları Jenkins üzerinden dolduruyorum ardından “Add” butonuna basıyorum. Buradaki ID ana repodaki Jenkinsfile dosyasına bağlı.
withKubeConfig([credentialsId: 'rancherconfig'])
Credentials kısmından eklediğim Credential’ı seçip “Test Connection” butonuna basıyorum.
Test sonucu başarılı ise size aşağıdaki gibi sonuç göstermeli.
Connected to Kubernetes v1.21.8
Ardından Jenkins ayarlarını kendi Jenkins sunucunuza göre düzenleyin.
Pod templates butonuna tıklayarak devam edin
Ardından “Add Pod Template” butonuna tıklayın.
Name kısmına “kube” yazın ve ardından “Pod template details” butonuna basın
Labels kısmına “kubepod” yazın. Ardından Containers başlığı altında “Add Container” butonuna basarak “Container Template‘i” seçin.
Ayarları aşağıdaki gibi düzenleyin ve kaydedin
Name => inbound-agent
Docker image => jenkins/inbound-agent:latest
Working directory => /bitnami/jenkins/home (Bitnami reposu ile kurduysanız)
Command to run => /bin/sh -c
Arguments to pass to the command => cat
Allocate pseudo-TTY => ✓
Jenkins üzerinde yeni bir iş oluşturuyoruz
Projeye bir isim verip, Pipeline seçip Ok butonuna basın
Advanced Project Options sekmesine tıklayıp, Pipeline > Defination kısmını “Pipeline script from SCM” olarak seçin.
SCM > Git – Repository URL: Gitlab URL adresi olarak ayarlayıp Credential kısmındaki add butonuna basıp “Jenkins‘i” seçin.
Açılan kısımda bilgileri kendi Gitlab bilgileriniz ile doldurun. ID kısmını da Jenkinsfile‘a eklediğimiz CridentialsID ile değiştirin. Bizimki test için aşağıdaki gibiydi
steps {
git url:'https://gitlab.sezer.test/root/test.git', branch:'test-deploy-stage', credentialsId:'deneme-test-123-deneme-2345'
}
Buradaki “deneme-test-123-deneme-2345” değeri tırnaklar olmadan ID kısmına yazın.
Ardından Cretandial seçin, Branch Specifier kısmına da branch adınızı yazıp kaydedin.”main” olabilir veya benimki gibi farklı olabilir. “test-deploy-stage“
Ana sayfadan Jenkins’i Yönet > Manage Nodes and Clouds kısmına tıklayalım.
Configure seçeneğine tıklayalım
Etiketler kısmına “kubepod” ekleyelim. Bu pipeline dosyamızda belirttiğimiz alan.
agent { label 'kubepod' }
Oluşturduğumuz test-pipeline’a girelim ve “Şimdi yapılandır” butonuna basarak yapılandırmayı bir test edelim.
Build işlemi başladı. Tıklayıp canlı izleyebilirsiniz.
Sonuç aşağıdaki gibi
kubectl get pods -n myweb
NAME READY STATUS RESTARTS AGE
myweb-6b849784f5-j9xks 1/1 Running 0 57s
Gitlab Webhook Yapılandırması
Şimdi Github push veya commit yapıldığında auto build işlemini sağlayacağız.
Oluşturduğumuz test-pipeline projemize Jenkins üzerinden girelim
Konfigürasyonu düzenle kısmına tıklayalım
Build trigger sekmesine tıklayıp ayarları aşağıdaki gibi yapalım ardından Gelişmiş butonuna basalım
Sayfanın aşağı kısmında Generate Token butonuna basalım çıkan token’i kopyalayalım ve ardından projeyi tekrardan kaydedelim.
Gitlab projemize girip Settings > Webhooks menüsüne tıklayalım
Ayarları aşağıdaki gibi kendinize göre düzenleyip Add Webhook butonuna basarak kaydedin.
Test > Push Event ‘e basarak konfigürasyonun doğru çalışıp çalışmadığını kontrol edebilirsiniz.
Başarılı ise 200 kodu dönecektir
Şimdi gitlab kısmında index.html’i değiştirelim ve bakalım push yapacak mı?
Bingooo. Artık oto build yapıyor
Buraya kadar okuyup uyguladıysanız bir alkışı hak ettiniz CLAP CLAP