Kubernetes LAB07 16/20

Selamlar arkadaşlar, bu yazımda Kubernetes Volumes konusunun örneklerini yapacağız.

Container dosyaları geçici dosyalardır. Bir container’ın yıkılması veya yeniden başlatılması durumunda kaybolacaktırlar. Ek olarak bir pod içerisindeki container’lar arasında dosyaları paylaştırmak için birtakım yöntemlere ihtiyacımız olacaktır.

Volume, bir pod’daki container’lar tarafından erişilebilen bir dizindir. Mevcut Docker volume’lerinin aksine, bir Kubernetes volume’ü pod’ların yaşam döngüsüne sahiptir, container’ların değil. Aynı pod içerisinde farklı volume’lere sahip dizinler kullanılabilir ancak volume’ler içe içe geçmezler. Her birinin kendi bağlantı noktası olması gerekir. Volume’leri spec.volumes ve spec.containers.volumeMounts parametreleri ile bildiririz.

ConfigMap Kullanımı

Temel olaark bir key-value (anahtar- değer) çiftlerine sahip ConfigMap örnekleri yapacağız. Bu özelliklele verileri hazır duruma getirip pod’lara ortam değişkeni veya configürasyon verileri olarak okutabiliriz. Bir ConfigMap, Secret‘ın küçük halidir. Fark olarak base64 olarak şifrelenmemektedir. String formatında depolanırlar.

Bir ConfigMap’in veri alabilmesi için farklı üç yöntem vardır: Literal, Individual ve File. Bunları inceleyelim.

Şehirleri içeren bir ConfigMap oluşturacağız. ConfigMap’e tanımlanacak bir dizi dosya yaratacağız. İlk önce bir dizi oluşturup bunun içerisine dört tane şehir dosyası ve yaşadığımız şehiri belirten dosyalar oluşturacağız. Bu örnek üzerinden ConfigMap’i anlamaya çalışacağım.

$ mkdir sehirler
$ echo 34 > sehirler/istanbul
$ echo 61 > sehirler/trabzon
$ echo 55 > sehirler/samsun
$ echo 55 > sehirler/ankara
$ echo "baskent" >> sehirler/ankara
$ echo yalova > yasanilanSehir

Şimdi bir ConfigMap oluşturup bu dosyaları ekleyelim.

$ kubectl create configmap sehirler --from-literal=text=ankara --from-file=./sehirler --from-file=./yasanilanSehir
configmap/sehirler created

ConfigMap’imizi listeleyelim, bakalım nasıl bir sonuç elde edeceğiz.

$ kubectl get configmap sehirler
NAME       DATA   AGE
sehirler   6      44s

$ kubectl get configmap sehirler -o yaml
apiVersion: v1
data:
  ankara: |
    06
    baskent
  istanbul: |
    34
  samsun: |
    55
  text: ankara
  trabzon: |
    61
  yasanilanSehir: |
    yalova
kind: ConfigMap
....

Artık oluşturduğumuz ConfigMap’i kullanmak için bir pod oluşturup deneyebiliriz.

$ vim config-ornek.yaml
apiVersion: v1
kind: Pod
metadata:
   name: config-ornek
spec:
   containers:
   - name: nginx
     image: nginx
     env:
     - name: ortam
       valueFrom:
          configMapKeyRef:
             name: sehirler
             key: yasanilanSehir

$ kubectl create -f config-ornek.yaml
pod/config-ornek created

$ kubectl exec -it config-ornek -- /bin/bash -c 'echo $ortam'
yalova

$ kubectl delete po config-ornek
pod "config-ornek" deleted

Evet arkadaşlar burda oluşturduğumuz pod içerisinde ortam değişkeni belirledik. Bunuda env anahtarı ile gerçekleştirdik. Ardından bu ortam değişkenine ConfigMap’teki yasanilanSehir değerini yerleştirdik. Sonra pod içerisinde komut çalıştırarak ekrana yazdırdık. yalova yazısını gördük. Şimdi daha gelişmiş bir örnek yapalım. YAML dosyamızı açalım ve aşağıdaki kodlarla değiştirelim ve sonuca bakalım.

$ vim config-ornek.yaml
apiVersion: v1
kind: Pod
metadata:
   name: config-ornek
spec:
   containers:
   - name: nginx
     image: nginx
     envFrom:
     - configMapRef:
          name: sehirler

$ kubectl create -f config-ornek.yaml
pod/config-ornek created

$ kubectl exec -it config-ornek -- /bin/bash -c 'env'
HOSTNAME=config-ornek
NJS_VERSION=1.15.12.0.3.1-1~stretch
NGINX_VERSION=1.15.12-1~stretch
samsun=55

KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
text=ankara
KUBERNETES_PORT=tcp://10.96.0.1:443
PWD=/
HOME=/root
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP_PORT=443
ankara=06
baskent

KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
TERM=xterm
yasanilanSehir=yalova

SHLVL=1
KUBERNETES_SERVICE_PORT=443
istanbul=34

trabzon=61

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_SERVICE_HOST=10.96.0.1
_=/usr/bin/env

$ kubectl delete pod config-ornek
pod "config-ornek" deleted

Burda sonuca baktığımzı zaman oluşturulan pod’un tüm ortam değişkenlerini listelediğimzide bizim YAML dosyasında belirttiğimiz ConfigMap’inde bu listede göründüğünü fark ettik. Kısaca ConfigMap’i kısıtlayıp pod’a atayabiliriz veya direk kayıtlı ConfigMap’i atayabiliriz.

Şimdi YAML dosyası üzerinden bir ConfigMap oluşturalım ve listeleyelim. Ardından bir pod oluşturup denemesini gerçekleştirelim.

$ vim telefon-map.yaml
apiVersion: v1
kind: ConfigMap
metadata:
   name: akilli-telefon
   namespace: default
data:
   telefon.marka: Huawei
   telefon.model: P30

$ kubectl create -f telefon-map.yaml
configmap/akilli-telefon created

$ vim config-map.yaml
apiVersion: v1
kind: Pod
metadata:
   name: config-ornek
spec:
   containers:
   - name: nginx
     image: nginx
     volumeMounts:
     - name: telefon-vol
       mountPath: /etc/telefon
   volumes:
   - name: telefon-vol
     configMap:
        name: akilli-telefon

Artık ConfigMap’i bir pod’a mount edilmiş bir volume olarak kullanabilmeyi sağlayacağız.

$ kubectl create -f config-ornek.yaml
pod/config-ornek created

$ kubectl exec -it config-ornek -- /bin/bash -c 'df -ha | grep telefon'
/dev/sda1       9.7G  2.7G  7.0G  28% /etc/telefon

$ kubectl exec -it config-ornek -- /bin/bash -c 'cat /etc/telefon/telefon.marka'
Huawei

Görmüş olduğunuz üzere volume mount ettik ve ardından ConfigMap’i bu birime yerleştirdik. Bu önceki örneğe göre daha standardize olmuş bir örnek oldu. Şimdi bu pod’u silip bir sonraki başlığımıze geçebiliriz.

$ kubectl delete pods config-ornek
pod "config-ornek" deleted

$ kubectl delete configmap akilli-telefon sehirler
configmap "akilli-telefon" deleted
configmap "sehirler" deleted

Kalıcı NFS Volume’ü Oluşturalım (PV)

(Persistent Volume)

İlk önce NFS sunucusu dağtıacağız ve test edeceğiz. Sonra container’ların taleplerine göre onlara NFS volume oluşturacağız.

Bunun için ilk olarak NFS sunucusu kurmak için aşağıdaki yazılımı kurmamız gerekiyor.

$ sudo apt-get update && sudo apt-get install -y nfs-kernel-server

Bir dizin oluşturup içini dolduralım.

$ sudo mkdir /opt/ylv
$ sudo chmod 1777 /opt/ylv
$ sudo bash -c 'echo yalova > /opt/ylv/merhaba.txt'

Yeni oluşturulan dizini paylaşmak için NFS sunucusu dosyasını düzenlememiz lazım. Dizini herkesle paylaşacağız.

$ sudo vim /etc/exports
/opt/ylv/ *(rw,sync,no_root_squash,subtree_check)

Yukarıdaki dizini açtığımzıda örnek ekleme şekillerini görürüz. Hemen altında yazan değeri dosyanın içine ekledik.

Eklediğimiz yazıyı etkinleştirmek için dosyayı tekrardan okutmamız lazım. Okutmak için aşağıdaki kodu çalıştırıyoruz.

$ sudo exportfs -ra

Ortamımızda iki node bulunduğu için kaynağı ikinci node’a mount edip test etmemiz lazım. Şimdi worker-node-1 node’una bağlanalım ve aşağıdaki komutları çalıştıralım.

$ (worker-node-1) sudo apt-get -y install nfs-common
....

$ (worker-node-1) showmount -e master-node-1
Export list for master-node-1:
/opt/ylv *

$ (worker-node-1) sudo mount 10.128.0.2:/opt/ylv /mnt
$ (worker-node-1) ls -l /mnt
total 4
-rw-r--r-- 1 root root 7 Apr 18 14:45 merhaba.txt

worker-node-1’de master-node-1’e kurduğumuz volume’ü mount ettik ardından test işlemini sağladık. Şimdi master-node’umuza dönebiliriz.

Oluşturduğumuz ve kurduğumuz NFS volume’ünü şimdi bir pod aracılığıyla test edelim.

$ vim PVol.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
   name: pvvol
spec:
   capacity:
      storage: 1Gi
   accessModes:
      - ReadWriteMany
   persistentVolumeReclaimPolicy: Retain
   nfs:
      path: /opt/ylv
      server: master-node-1
      readOnly: false

$ kubectl create -f PVol.yaml
persistentvolume/pvvol created

$ kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   
pvvol   1Gi        RWX            Retain           Available                                   ....

Kalıcı Claim Volume Oluşturalım (PVC)

(Persistent Volume Claim)

Pod’ların yeni PV’den yararlanması için PVC oluşturmamız gerekiyor. Hadi başlayalım.

$ kubectl get pvc
No resources found.

$ vim pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
   name: pvc-deneme
spec:
   accessModes:
   - ReadWriteMany
   resources:
      requests:
         storage: 200Mi

Yeni PVC’yi kuralım ve bağlı olduğunu doğrulayalı. 200Mi önermesine rağmen boyutun 1Gi olduğunu unutmayalım. Sadece bir volume bu boyutu kullanabilir.

$ kubectl create -f pvc.yaml
persistentvolumeclaim/pvc-deneme created

$ kubectl get pvc
NAME         STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc-deneme   Bound    pvvol    1Gi        RWX                           2s

$ kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                
pvvol   1Gi        RWX            Retain           Bound    default/pvc-deneme
$ kubectl delete pvc pvc-deneme
$ kubectl delete pv pvvol

PVC Adetini ve Kullanımını Sınırlamak için ResourceQuota Kullanımı

Cloud tabanlı depolamanın esnekliği, genellikle kullanıcılar arasında tüketimin sınırlandırmasını gerektirir. Hem toplam tüketimi hemde kalıcı Volume Claim talep sayısını sınırlandırmak için ResourceQuota nesnesini kullanacağız.

ResourceQuota nesnesi için bir YAML dosyası oluşturalım. Toplam 500Mi kullanımıyla depolama sınırı ve 10 claims ayarlayacağız.

$ vim depolama-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
   name: storage-quota
spec:
   hard:
      persistentvolumeclaims: "10"
      requests.storage: "500Mi"

Bir namespace oluşturacağız. Adını “kucuk” olarak belirleyeceğiz ve sınırlandırma getireceğiz.

$ kubectl create namespace kucuk
namespace/kucuk created

$ kubectl describe ns kucuk
Name:         kucuk
Labels:       <none>
Annotations:  <none>
Status:       Active

No resource quota.

No resource limits.

Oluşturduğumuz namespace içerisinde bir önceki başlıkta oluşturduğumuz YAML dosyalarını dağıtıyoruz.

$ kubectl -n kucuk create -f PVol.yaml
persistentvolume/pvvol created

$ kubectl -n kucuk create -f pvc.yaml
persistentvolumeclaim/pvc-deneme created

ResourceQuota’mızıda bu namespace içerisinde oluşturuyoruz.

$ kubectl -n kucuk create -f depolama-quota.yaml
resourcequota/storage-quota created

$ kubectl describe ns kucuk
Name:         kucuk
Labels:       <none>
Annotations:  <none>
Status:       Active

Resource Quotas
 Name:                   storage-quota
 Resource                Used   Hard
 --------                ---    ---
 persistentvolumeclaims  1      10
 requests.storage        200Mi  500Mi

No resource limits.

Namespace’imizin detaylarını görüntülediğimiz zaman artık ResourceQuota’nın namespace içerisinde aktif olduğunu görebiliriz.

Şimdi bu namespace’de bir deployment çalıştırma vaktimiz geldi. Sizin için önceden hazırladığım bu adresteki YAML dosyasını dağıtacağız. YAML dosyasındaki değerler bu başlık altındaki PV ve PVC’nin adları hedef alınarak düzenlenmiştir. Eğer siz başka isimde oluşturduysanız düzenleyip ardından dağıtımı başlatmalısınız.

$ wget https://tinyurl.com/y3pysh7x -O nfs-vol.yaml
$ kubectl -n kucuk create -f nfs-vol.yaml
deployment.apps/nginx-nfs created

$ kubectl get deploy --namespace=kucuk
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
nginx-nfs   1/1     1            1           20s

Oluşturulan pod’u inceleyelim.

$ kubectl get po -n kucuk
NAME                         READY   STATUS    RESTARTS   AGE
nginx-nfs-7f5f75d6fd-94hq8   1/1     Running   0          65s

$ kubectl -n kucuk describe pod nginx-nfs-7f5f75d6fd-94hq8
....
 Mounts:
      /opt from nfs-vol (rw)
....

$ kubectl describe ns kucuk
Name:         kucuk
Labels:       <none>
Annotations:  <none>
Status:       Active

Resource Quotas
 Name:                   storage-quota
 Resource                Used   Hard
 --------                ---    ---
 persistentvolumeclaims  1      10
 requests.storage        200Mi  500Mi

No resource limits.

Burada nfs-vol içerisinden /opt dizininin mount edildiğini teyit ettik. Şimdi /opt/ylv dizininin içerisinde 300Mi’lık bir dosya oluşturalım ve ResourceQuota’yı tekrardan görüntüleyelim.

$ sudo dd if=/dev/zero of=/opt/ylv/ucyuzlukdosya bs=1M count=300
300+0 records in
300+0 records out
314572800 bytes (315 MB, 300 MiB) copied, 0.278532 s, 1.1 GB/s

$ du -h /opt/
301M    /opt/ylv
101M    /opt/cni/bin
101M    /opt/cni
401M    /opt/

$ kubectl describe ns kucuk
Name:         kucuk
Labels:       <none>
Annotations:  <none>
Status:       Active

Resource Quotas
 Name:                   storage-quota
 Resource                Used   Hard
 --------                ---    ---
 persistentvolumeclaims  1      10
 requests.storage        200Mi  500Mi

No resource limits.

Tekrardan ResourceQuotas bilgilerine baktığımızda 300Mi’lik bir dosya oluşturmamıza rağmen burada kullanılan halen 200Mi olarak gösterilmektedir. Çünkü deployment olarak oluşturulmayan dosyalar bu kotaya dahil değildir.

Şimdide nginx-nfs deployment’ımızı silerek kotamıza bakalım nasıl değişecek.

$ kubectl -n kucuk delete deploy nginx-nfs
deployment.extensions "nginx-nfs" deleted

$ kubectl describe ns kucuk
Name:         kucuk
Labels:       <none>
Annotations:  <none>
Status:       Active

Resource Quotas
 Name:                   storage-quota
 Resource                Used   Hard
 --------                ---    ---
 persistentvolumeclaims  1      10
 requests.storage        200Mi  500Mi

No resource limits.

Deployment’ımızı kaldırmamıza rağmen şunu görüyoruz kotamız hiçbir şekilde değişmedi. Halbuki 200Mi’lik alanı bu dağıtım karşılıyordu. Demekki sadece dağıtımı silmek kotadan yer açmıyor. Bu işlemleri yönetebilmek için policy’ler oluşturmak veya tanımlamak gerekiyor. Şuanki PV’deki policy’miz Retain olarak tanımlı. Bizim burda bileceğimzi üç tane policy ayarı mevcut: Delete, Retain ve Recycle.

Şimdi policy içeren birtakım örnekler yapalım. Öncelikle işe PVC’mizi ve PV’mizi silerek başlayalım.

$ kubectl -n kucuk delete pvc/pvc-deneme
persistentvolumeclaim "pvc-deneme" deleted

$ kubectl -n kucuk delete pv/pvvol
persistentvolume "pvvol" deleted

Burada tekrardan PV’mizi dağıtalım ve çalışır durumdayken Retain durumunu Delete durumuna çekelim.

$ kubectl create -f PVol.yaml
persistentvolume/pvvol created

$ kubectl patch pv pvvol -p '{"spec":{"persistentVolumeReclaimPolicy":"Delete"}}'
persistentvolume/pvvol patched

$ kubectl get pv/pvvol
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM  
pvvol   1Gi        RWX            Delete           Available                  

Şuanki kotamıza bakalım.

$ kubectl describe ns kucuk
Name:         kucuk
Labels:       <none>
Annotations:  <none>
Status:       Active

Resource Quotas
 Name:                   storage-quota
 Resource                Used  Hard
 --------                ---   ---
 persistentvolumeclaims  0     10
 requests.storage        0     500Mi

No resource limits.

PVC’mizi tekrardan kuralım. Çalıştırılmış olan bir pod olmadığı halde yinede kaynak kullanımını kontrol edelim.

$ kubectl -n kucuk create -f pvc.yaml
persistentvolumeclaim/pvc-deneme created

$ kubectl describe ns kucuk
....
 requests.storage        200Mi  500Mi

Herhangi bir pod olmamasına rağmen az önce Retain policy’si aktif olduğu için önceki pod’dan ayrılmış olan alan halen duruyor. Eğer pod’u tekrardan dağıtırsak daha önceden tuttuğu alanı kullanmaya devam edecektir.

Fakat şuanda policy’miz Delete ve şuankinden farklı bir deployment yapar ve silersek bu deployment’ı tutma işlemi yapmayacaktır.

Diğer bir policy olan Recycle adından da anlaşılacağı gibi pod silindiği zaman tutulacak olan alanı bir geri dönüşüm kutusuna koyar ve istersek bu geri dönüşüm kutusundan geri döndürüp pod’a tekrardan kullandırabiliriz.

Labaratuvar yazımız burada sonlandı. Ortamımızda oluşturduğumuz PV, PVC ve namespace’i silelim. Bir sonraki yazımda görüşmek üzere hoşçakalın.

$ kubectl -n kucuk delete deployment nginx-nfs
deployment.extensions "nginx-nfs" deleted

$ kubectl -n kucuk delete pvc/pvc-deneme
persistentvolumeclaim "pvc-deneme" deleted

$ kubectl -n kucuk delete pv/pvvol
persistentvolume "pvvol" deleted

$ kubectl delete ns kucuk
namespace "kucuk" deleted

Umarım bu yazı sizin için bilgilendirici olmuştur. Yazıyla ilgili bir sorunuz, görüşünüz veya isteğiniz varsa alt kısımda bulunan yorumlardan veya mail adresimden iletişime geçebilirsiniz. Bu yazının başkaları içinde bilgilendirici olduğunu düşünüyorsanız sosyal olun ve sosyal medyada paylaşın! Okuduğunuz için teşekkürler !!!!

†

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir