25/11/2021

Kubernetes Örnek -1

Eğitim ve test amaçlı olarak minikube ve docker destop önelikle eğer benim gibi ortamınız windows ise kurulmalıdır.

Yapacağımız örnek ise “TechWorld with Nana” kanalının “Kubernetes Crash Course for Absolute Beginners [NEW]” da anlatılandır.

Örnekte arka planda MongoDB nin oldugu bir NodeJS tabanlı web application kurulumu yapacağız.

4 adet dosya olusturacagiz.

  • Config map : Mongo db endpoint ayarlari
  • Secret : mongobd user ve password
  • Mongodb App icin Deployment ve service ayarlari
  • WebApp icin deployment ve service ayarlari

ConfigMap

Ilk dosyamiz „Mongo-config.yaml“

Surdan ilk kismi kopyaliyoruz

https://kubernetes.io/docs/concepts/configuration/configmap/

apiVersion: v1
kind: ConfigMap
metadata:
  name: game-demo
data:

sonra bunu editliyorruz. Data altinda key:value ciftleri olmalidir

apiVersion: v1
kind: ConfigMap
metadata:
  name: Mongo-config
data:
  mongo-url: mongo-service

Secret

Simdi „Secrets“  mongo-secret.yaml

https://kubernetes.io/docs/concepts/configuration/secret/

yukarida ki linkten örnek kismi aliyoruz.

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  USER_NAME: YWRtaW4=
  PASSWORD: MWYyZDFlMmU2N2Rm

ve editliyoruz.

apiVersion: v1
kind: Secret
metadata:
  name: mongo-secret
type: Opaque
data:
  mongo-user: bW9uZ28tdXNlcg==
  mongo-password: bW9uZ28tcGFzc3dvcmQ=

Secrets dosyasina yazilan username ve password gibi gizli bilgiler base64 olarak kodlanmalidir.

Bunun icin bash te

$ echo -n "mongo-user"|base64
bW9uZ28tdXNlcg==

Olur. Password üde ayni sekilde yapariz. Secrets linkinde cok önemli bilgiler var mutlaka okunmali.

Service ve Deployment

Simdi de mongobd icin deployment ve service konfigürasyonunu olusturalim.

„mongo.yaml“ her bir deployment bir service e ihtiyac duyar bu nedenle ikisi tekbir dosyadadir.

Asagida ki linke gidip yine örnegi kopyaliyoruz.

https://kubernetes.io/docs/concepts/workloads/controllers/deployment/

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

Ve tabii ki yine editliyoruz. Ancak burda bilmemiz gereken template bölümü pod larin sablonu gibidir. Template bölümünün kendi metadatasi ve kendi spec alt bölümü vardir. Bu kısım deployment icinde pod u tanimlar. POD icinde birden cok container olabilir ancak mantık olarak her pod da bir application olmalidir. Template:spec:container icinde bu containerlari tanimliyoruz.

Bu örnekte mongodb kullanacagimiz icin docker hub dan önce mongodb nin tam adını buluyoruz. (örnekte tag olarak versiyon 5 kullanıldı) port bilgiside dockerhub daki dokümandan geldi.


Ayrica metadata altında labeller var. Kubernetes da her componente bir label vermek mümkündür. Labellar key:value ikiklisidir ve resourcelara atanırlar. Labeller kullanışlı teşhis (identification) elemanlarıdır. Örnek

„env“:“dev“

„release“:“Pazar gunu“

Her yeni resource tipi (örnegin POD) olustuğunda bunların unique bir adı olur ancak label hepsinde aynidir. Böylece POD replikalarinin tamamini ayni label ile teshis edebiliriz. Bu nedenle PODlar icin label zorunlu olarak olmak zorundadir. Diger componentlerde label opsiyoneldir ama önerilir.

POD replikalari olustururken Deployment nereden biliyor hangi tip POD olusturacagini? Yani K8s nereden biliyor hangi POD hangi deployment a ait? Iste bu „Spec:selector:matchLabels“ ile saglanir. MatchLabels ile tanimlanmis tüm POD’lar o deploymenta aittir.

En son kac replika POD istedigimizi belirttigimiz POD sayisi mevcut. Biz simdilik basitlik amaciyla tek replika yapacagiz.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mongo-deployment
  labels:
    app: mongo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mongo
  template:
    metadata:
      labels:
        app: mongo
    spec:
      containers:
      - name: mongodb
        image: mongo:5
        ports:
        - containerPort: 27017

YAML da „—„ ile birden cok yaml dosyasini tek bir dosyada toplayabiliriz

Burada da böyle yapacagiz ve service örnegini de bunun altina ekleyecegiz.

Önce örnek config i asagida ki linkten aliyoruz.

https://kubernetes.io/docs/concepts/services-networking/service/

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

simdi de editleyelim

burada metadata:name ile belirledigimiz name mongo-config.yaml da ki service namedir. Yani ikisi ayni olmalidir.

Service configuration icinde „spec:selector:“ vardir bunun ile service hangi POD lara forwarding yapacagini ögrenmektedir. Bu nedenle buraya girdigimiz deger deployment taki POD’larin labellari ile ayni olmalidir.

Ayrica iki adet port tanimi mevcuttur. „Port „ bu servise hangi porttan erisilebilecegidir ve „targetPort“ ise POD’lara hangi porttan forward edecegidir. Bu nedenle Deployment ta belirtilen POD portu ile ayni olmak zorundadir.

apiVersion: v1
kind: Service
metadata:
  name: mongo-service
spec:
  selector:
    app: mongo
  ports:
    - protocol: TCP
      port: 27017
      targetPort: 27017

Buraya kadar MongoDB application i icin gerekli ayarlari yaptik ancak ayrica web applicationimizda var bu mongo db nin erisecegi. Bütün settingleri kopyalayip „webapp.yaml“ dosyasini olusturuyoruz.

Image ise : nanajanashia/k8s-demo-app:v1.0

Bu basit bir nodejs application ve port 3000 de. POD ve Container ve ayrica service portunu ayni yapiyoruz.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp-deployment
  labels:
    app: webapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: webapp
  template:
    metadata:
      labels:
        app: webapp
    spec:
      containers:
      - name: webapp
        image: nanajanashia/k8s-demo-app:v1.0
        ports:
        - containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
  name: webapp -service
spec:
  selector:
    app: webapp
  ports:
    - protocol: TCP
      port: 3000
      targetPort: 3000

Secret ve configMap bağlama

Buraya kadar hemen hemen gerekli her dosayi olusturduk ancak henüz secret ve configMap i baglamadik.

MongoDB basladiginda derhal username ve password u set etmemiz gerekmektedir. Peki nasil?

Docker hub da ki MongoDB sayfasina gidiyoruz ve dökümantasyonu okuyoruz.

https://hub.docker.com/_/mongo

orada environment ayarları var.

environment:

MONGO_INITDB_ROOT_USERNAME: root

MONGO_INITDB_ROOT_PASSWORD: example

Peki bu environment setting i nasıl göndereceğiz?

Deployment config dosyasinda MongoDB Container ayarlarının altına gri bölümden sonra olacak sekilde aşağıyı ekliyoruz.

spec:
      containers:
      - name: mongodb
        image: mongo:5
        ports:
        - containerPort: 27017
        env:
	- name:  MONGO_INITDB_ROOT_USERNAME
	   value: 
	   valueFrom:
		secretKeyRef: 
		   name: mongo-secret
		   key: mongo-user
	 - name:  MONGO_INITDB_ROOT_PASSWORD
	    valueFrom:
		secretKeyRef: 
		   name: mongo-secret
		   key: mongo-password

Istersek normal bir environment degişkenini name ve value olarak direk gönderebiliriz. Ancak bizde secret oldugu için onu refere etmemiz gerekiyor. Bu nedenle „value“ yerine „valueFrom“ kullandık.

secretKeyRef ile dosyanin adını ve key ile de hangi değerin „Value“ sini alacağımızı söyledik. Aynı işlemi hem password için hemde username için yaptık.

Daha sonra webapp başladığında onunda veritabanina erişmesi gerekmekte dolayısıyla ona da bir password ve username iletmemiz gerekiyor ki basladiginda database e erissin. Ayrica hangi database eriseceginide „configMap“ ile belirtiyoruz. Nananin containerinin hangi değişkenleri alacağı yine docker hub daki sayfasinda belirtilmiş.

Tabii bu ayarlarda Webapp Container config inin altına ekleniyor. Mavi kısım MongoDB container env ayarından direk copy paste.

containers:
      - name: webapp
        image: nanajanashia/k8s-demo-app:v1.0
        ports:
        - containerPort: 3000
       env:
	 - name: USER_NAME
	   valueFrom:
		secretKeyRef: 
		   name: mongo-secret
		   key: mongo-user
	 - name: USER_PWD
	   valueFrom:
		secretKeyRef: 
		   name: mongo-secret
		   key: mongo-password
	 - name: DB_URL
	   valueFrom:
		configMapKeyRef: 
		   name: mongo-config
		   key: mongo-url

ConfigMap ten referans yaparken „configMapKeyRef“ kullaniliyor.

Geriye son bir basamak kaldi ve oda bu uygulamanin disardan erisilebilir olmasini saglamaktir.

Buda „external service“ ile olur. Bunun icin service config dosyasini editlememiz gerekmektedir.

apiVersion: v1
kind: Service
metadata:
  name: webapp -service
spec:
  type: ClusterIP
  type: NodePort
  selector:
    app: webapp
  ports:
    - protocol: TCP
      port: 3000
      targetPort: 3000
      nodePort: 30100 

type default olarak °ClusterIP° dir. „NodePort“ external bir servis tipidir. Type: NodePort eklenince Spec:Ports a da nodePort key:value ciftini eklemek gereklidir. NodePort ile her bir node daki IP nin belirli bir Portunu static olarak Application in erisilebilmesi icin acar.

<nodeIP>:<nodePort> ile bu servise erisebilecegiz ve oda arkasinda ki POD’lara erisebilecek.

NodePort sadece 30000 ile 32767 portlari arasinda tanimlanabilir.

UYGULAMA (DEPLOYMENT)

Bu noktaya kadar tüm konfigürasyonlari bitirdik ancak henüz deploy etmedik. Artik kubectl ile deploy edebiliriz.

Ancak deploy etmeden önce „configMap“ ve „Secret hazir olmalidir.

$ kubectl apply –f mongo-config.yaml  --> configMap
$ kubectl apply –f mongo-secret.yaml --> Secret
$ kubectl apply –f mongo.yaml --> DB yi baslatiyoruz önce cünkü webapp ona depend ediyor. DB olmadan webapp crash
$ kubectl apply –f webapp.yaml  --> Webapp deployment

Kontroller

$ kubectl get all

$ kubectl get configmap

$ kubectl get secret

$ kubectl describe service webapp-service –> eger daha cok detay görmek istersek

$ kubectl logs <POD name> –> o POD a ilisken loglari görmek icin

-f ile stream olarak da görebiliriz.

$ kubectl get svc –>scv= service burada

$ minikube ip –> minikube un baglandigi IP yi bulmak icin.

$ kubectl get node –>burdda da node (minikube ) ip si görülür.

$ kubectl get node –o wide 

Leave a Reply