Ömer Burak Demirpolat
6 min readJun 8, 2021

Baştan sona Kubernetes Deploy ve Continuous Delivery

Bu yazı Go ile yazılmış bir web uygulamasını Kubernetes ortamına dağıtmak ve ArgoCD ile Continuous Delivery sürecini gerçekleştirmek üzerine olacak.

Şunu bildirmeliyim ki ben bir DevOps veya bu işte uzman birisi değilim. Yazdığım uygulamayı deploy ettim ve neler yaptığımı yazmak istedim, bu doğrultuda hatalar veya yanlış öğrendiğim/aktardığım şeyler olabilir. Hata var ise çözün :D

Yazı şu aşamaları içerecek;

  • Web uygulaması oluşturmak.
  • Uygulamayı dockerize etmek ve Docker Hub’a iletmek.
  • kubectl ve minikube kurulumu.
  • Uygulamamızın Kubernetes manifest dosyalarını oluşturmak.
  • ArgoCD entegrasyonu.

Basit bir web uygulaması oluşturalım.

mkdir $GOPATH/kubetest && touch $GOPATH/kubetest/main.go

Uygulamamı yazdım şimdi uygulamamı bir image haline getiriyorum. Bunun için bir Dockerfile yazalım.

FROM golang:1.16
WORKDIR /go/src/app
COPY main.go .
RUN go build main.go
CMD ["./main"]

Image build edelim. Ben yaratacağım image Docker Hub üzerinde barındıracağım. Bu işlem için hub.docker.com adresinde bir hesap yaratmalısınız.

Şimdi Docker Hub için login işlemini gerçekleştirelim.

docker login -u burak -p YOUR-PASSWORD

Şimdi bir image

docker build . -t burak/kubetest

Son olarak yarattığım image Docker Hub’a push ediyorum.

docker push burak/kubetest

Daha sonra Kubernetes ortamında çalışacak uygulamalar bu image kullanacak.

Şimdi kubectl kuralım. Cluster’ımızı yönetirken bunu bu CLI’ın komutları ile gerçekleştireceğiz.

brew install kubectl

Şimdi minikube kuralım.

minikube Kubernetes’i lokal olarak çalıştırmamızı sağlayan bir araç. Bunun için Docker cihazınızda kurulu olmalı. Podlar docker veya bazı diğer sanallaştırma araçları ile yönetiliyor.

brew install minikubeminikube start

Bu komut girildiğinde Docker çalışıyor olmalı.

Eğer daha önce kubectl kurduysanız ve aktif bir context’iniz var ise context olarak minikube’e geçiş yapmamız gerekecek.

Önce geçerli context’imizi öğrenelim.

kubectl config current-context

Örneğin benim geçerli context’im çalıştığım şirketin clusteri şeklindeydi.

Şimdi minikube’u geçerli context olarak atayalım.

kubectl config current-context minikube

Tip : var olan context’leri listelemek için

kubectl config get-contexts -o name

Şimdi Kubernetes manifest’lerini oluşturalım.

3 farklı manifest’e ihtiyacım var. Service, deployment ve ConfigMap

service.yaml

deployment.yaml

configMap.yaml

Oluşturduğum dosyaları ./kubetest/argocd klasörü altına taşıyorum. Bunun nedenini daha sonra ArgoCD kurulumunda aktaracağım.

Service

Service cluster içerisinde çalışan uygulamamızı dışarıya servis etmemizi sağlayan mekanizma.

apiVersion: v1
kind: Service
metadata:
name: kubetest-svc
spec:
selector:
app: myapp
ports:
- port: 3001
targetPort: 3001
type: LoadBalancer

Buradaki en önemli 3 spec’i açıklayayım.

app = myapp manifest’lerin birbiri ile ilişki kurmasını sağlayan ayrıştırıcı.

Örneğin benim uygulamam çalışmak için service, deployment ve configMap nesnelerine ihtiyaç duyuyor fakat bu cluster’da başka uygulamalar da bulunabilir. Hangi manifest dosyasının hangi app ile bağlanacağı bu selector ile belirleniyor.

port, bu servisin hangi port üzerinden ulaşabilir olduğunu, hizmet vereceğini belirliyor.

targetPort, pod içerisinde hangi porta bind edileceğini belirliyor.

Deployment

Deployment uygulamamızın hangi image ile oluşturulacağını, kaç replikadan oluşacağını, uygulamanın replikalar içerisinde hangi porttan hizmet vereceğini tanımladığımız nesne.

apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
labels:
app: myapp
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: burak/kubetest
ports:
- containerPort: 3001
envFrom:
- configMapRef:
name: myappconfig

Daha önce yarattığımız image buraya container altında belirtiyoruz. Yaratılan her bir replica/pod bu image kullanacak.

Service dosyasında kullandığımız ayrıştırıcı aslında burada yaratılmış “labels”. Bu “app: myapp” selectoru ile yaratılan nesneler bu deployment dosyasında oluşturulacak podlar ile bağlanacak.

Görüldüğü üzere burada oluşturulacak container’ların hangi image ile yaratılacağı, portu belirtilmiş.

Burada önemli durumlardan bir tanesi de “envFrom” anahtarı.

Bu key son yaratacağımız nesne olan configMap’in referansını belirttiğimiz bölüm. Bu deployment nesnesi ile yaratılan podlar’da “myappconfig” adındaki configMap nesnesinde tanımlı ortam değişkenleri atanacak.

ConfigMap

Bu uygulama için oluşturacağımız son nesne.

apiVersion: v1
kind: ConfigMap
metadata:
name: myappconfig
namespace: default
data:
HOST: ":3001"

configMap nesneleri oluşturulan podlara ortam değişkenlerini atamak için veya config dosyası olarak kullanılabiliyor. Ben podların ortam değişkenlerimi atamak için kullandım.

ArgoCD dökümanı oldukça açıklayıcı.

kubectl create namespace argocd && kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

Bu komut “argocd” adı ile bir namespace oluşturuyor. ArgoCD servisleri ve uygulaması bu namespace altında olacak.

ArgoCD’yi komut satırından yönetmek için ArgoCD CLI kuralım.

brew install argocd

ArgoCD server’ı expose etmek için servis tipi LoadBalancer atanıyor.

Kubernetes servis tiplerini incelemek için : https://www.vmware.com/topics/glossary/content/kubernetes-services

Halen ArgoCD dökümanından ilerliyorum.

kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'

Artık ArgoCD’ye 80 portundan erişmemiz gerekiyor fakat son bir aşama daha var. ArgoCD default olarak “admin” kullanıcı ile geliyor ve bu kullanıcının şifresi ArgoCD Server’ın pod name’i olarak atanıyor.

“admin” kullanıcısının şifresini şöyle öğrenebiliriz.

kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-server -o name | cut -d'/' -f 2

Şu an ArgoCD hazır ve 80 portu üzerinde ve minikube içerisinde çalışıyor, şu an sadece cluster içerisinden erişim sağlanabilir durumda.

minikube ile çalışırken expose olan servislere external ip verilmesi için ağ geçidi verilmesi gerekiyor. Bunun için :

minikube tunnel

Şimdi localhost:80 adresinde çalışan ArgoCD’ye erişebiliriz.

Yazdığımız web uygulaması 3001 portunda çalışacak fakat web uygulamamız henüz Kubernetes ortamına dahil olmadı. Henüz uygulamaya erişemeyiz.

Eğer şifreyi güncellemek isterseniz öncelikle cli üzerinden login olmanız gerekecek.

argocd login 127.0.0.1

Ardından

argocd account update-password

Şimdi ArgoCD arayüzüne gidelim ve bir uygulama oluşturalım ardından oluşturulan uygulamayı git repomuz ile bağlayalım.

Uygulamam https://github.com/bdemirpolat/kubetest reposunda ve ilk olarak git repomu ArgoCD’ye bağlamam gerek.

Bunun için https://localhost/settings adresine gidiyorum ve seçtiğim bir seçenek ile repomu bağlıyorum SSH veya HTTPS.

New App kısmından açılan sayfada uygulama adını giriyorum.

Project: default

Sync Policy: Automatic

Repository URL : https://github.com/bdemirpolat/kubetest

Siz burada kendi reponuzu kullanmalısınız.

Path: argocd

Daha önce Kubernetes manifestlerini projemin içerisindeki “argocd” klasörüne taşıdığımı söylemiştim. Bunun sebebi ArgoCD bizden manifestler için bir klasör istiyor ve bu klasördeki manifest dosyaları ile çalışıyor.

Cluster URL seçelim, farklı cluster eklemediyseniz zaten bir tane gözükecektir.

Namespace olarak eğer daha önce farklı bir namespace eklemediyseniz veya uygulamanızı farklı namespace üzerinde çalıştırmadıysanız “default” girmelisiniz.

Uygulamayı kaydediyorum.

Uygulamayı kaydettiğim anda auto sync çalışıyor ve ArgoCD minikube üzerindeki cluster’a manifestleri apply etmeye başlıyor.

Görüntüm şöyle.

Ayrıca üzerine tıkladığımda 1 tane pod’un çalıştığını görüyorum.

Artık bu git reposuna yeni bir commit geldiğinde manifest dosyalarındaki değişiklikleri ArgoCD Kubernetes üzerinde uygulayacak. Bu değişiklikler configMap için olabilir örneğin yeni bir ortam değişkeni atamanız gerekebilir veya replica/pod sayısı artabilir/azalabilir, repomuzun “argocd” klasöründeki tüm manifest dosyalarındaki değişikler ArgoCD tarafından yakalanacak ve uygulanacak.

Bir eksik nokta var ki bence en önemlisi. Yazdığımız web server uygulamasında bir değişiklik yapıldığında podlarda çalışan image’in güncellenmesi. ArgoCD’nin image değişikliğini de anlaması lazım.

Varsayalım ki biz Kubernetes manifest dosyalarında deployment dosyasını değiştirdik replica sayısını 1'den 2'ye çıkarttık ve aynı zamanda uygulamamıza yeni bir feature ekledik fakat deployment dosyasındaki image hala eski image.

ArgoCD manifest dosyasındaki değişikliği algıladı fakat image için bir değişiklik yok. Bu nedenle yeni eklediğimiz feature podlara uygulanmadı. Bunun için ArgoCD’yi her zaman latest imajı tekrar çekmesini sağlayabiliriz fakat Docker Hub üzerindeki imajımızı versiyonlasak bu işi daha temiz yönetebiliriz.

Yani amacımız yeni bir feature eklendiğinde tekrar image build edilsin ve build edilen yeni image farklı bir versiyon numarası ile taglensin.

Versiyonlama işini bumpversion adlı araç ile yapacağım, bunun için.

brew install bumpversion

Ardından projemin bulunduğu dizinde bumpversion config dosyasını yaratıyorum.

touch .bumpversion.cfg

Config dosyasına şunları yazıyorum.

[bumpversion]
current_version = 0.0.0
commit = True
tag = True

Bu konfigürasyon doğrultusunda her bir yeni versiyon alındığında bumpversion versiyon değişikliğini commit edecek ve bu versiyonda bir tag oluşturacak.

bumpversion’un kullanımına ilişkin detayları buradan inceleyebilirsiniz.

Uygulamamızın ilk versiyonunu oluşturalım.

bumpversion patch

Uygulamamın versiyonu 0.0.1 oldu ve .bumpversion.cfg dosyası artık şöyle gözüküyor.

[bumpversion]
current_version = 0.0.1
commit = True
tag = True

Şimdi basit bir shell script yazacağız ve bu shell script;

  • Uygulamamızın güncel versiyonunu .bumpversion.cfg adlı dosyadan okuyacak.
  • Elde ettiği güncel versiyon ile yeni bir Docker image’i yaratacak ve bu yarattığı Docker image güncel uygulama versiyonu ile taglenecek. (0.0.1 versiyonu için yaratılan image “burak/kubetest:0.0.1” şeklinde oluşturulacak.)
  • Yeni oluşturulan image Docker Hub’a push edilecek.
  • Deployment dosyamızdaki eski versiyon olan “burak/kubetest” ifadesini yeni versiyonumuz olan “burak/kubetest:0.0.1” olarak değiştirecek.

Shell dosyamızı yaratalım.

touch build.sh

Scripti yazalım.

#!/bin/bash
version=$(awk 'NR == 2' .bumpversion.cfg | sed 's/current_version = //g')
docker
build . -t "burak/kubetest:$version"
docker push "burak/kubetest:$version"
sed "s/kubetest.*/kubetest:$version/g" ./argo/deployment.yaml | tee ./argo/deployment.yaml

Sonuç olarak uygulamamıza yeni bir güncelleme ekledik ve Kubernetes ortamına bu güncellemeyi iletmek istiyoruz. Her şey hazır.

Yapılan değişiklikleri repomuza pushladığımızda ArgoCD yeni image’i tüm podlara uygulayacak.

Buraya kadar okuduysanız vallahi bravo.

Desteği için Sertaç Bayır’a teşekkürler.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

No responses yet

Write a response