Kubernetes LAB04 10/20

Merhaba arkadaşlar bu yazımda cluster’ımızın control plane’ine erişme yollarını keşfetmeye devam edeceğiz. Güvenlik konusunu işleyeceğimiz zaman Bearer Token kullanımı ile birçok işlem yapacağız. Daha sonra Kubernetes API’sine uygulama düzeyinde erişim için yerel bir proxy sunucusu dağıtacağız.

RESTful API Erişimi

Cluster’a güvensiz bir şekilde API çağrısında bulunmak için curl komutunu kullanacağız. IP adresini ve portunu öğrendikten sonra cluster verilerini RESTful bir şekilde alabiliriz. Varsayılan olarak bilgilerin çoğu sınırlıdır, ancak kimlik doğrulama politikasında yapılan değişiklikler daha fazla erişime izin verebilir.

Öcelikle API sunucusunun bir kopyasını çalıştıran bir node’un API ve portunu bilmemiz gerekir. Genel cluster yapılandırmasını almak için kubectl config view komutunu kullanacağız ve sunucu bilgilerini bulacağız. Burda hem IP’yi hem port’u verecektir.

$ kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.142.0.14:6443
  name: kubernetes
....

IP ve port’umuzu aldıktan sonra bearer token‘ı bulmamız gerekecek. Önce cluster’a sonra da default namespace’de bulunan token’lara bakacağız. Cluster controller’larının her biri için bir secret olacaktır.

$ kubectl get secrets --all-namespaces
NAMESPACE         NAME                                             TYPE                                  DATA   AGE
default           default-token-nbczn                              kubernetes.io/service-account-token   3      7d12h
kaynak-limiti     default-token-6rt8h                              kubernetes.io/service-account-token   3      5d3h
kube-node-lease   default-token-rls54                              kubernetes.io/service-account-token   3      7d12h
....

$ kubectl get secrets
NAME                  TYPE                                  DATA   AGE
default-token-nbczn   kubernetes.io/service-account-token   3      7d12h

$ kubectl describe secret default-token-nbczn
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9
....

Listelediğimiz secret’in detaylarına baktığımız zaman token değerini burada görebiliriz. token değerimizi kopyalayalım, dosyaya kayıt edelim veya linux komutları ile değişkene atayalım. Değişkene atamak isteyenler için linux komutunu aşağıda yazalım.

$ export token=$(kubectl describe secret default-token-nbczn | grep ^token | cut -f7 -d ' ')

Cluster içerisinden temel API bilgilerini alıp alamadığımızı test edelim. Sunucu adını ve port’unu, token’ımızı ve sertifika kullanmamak için -k parametresini unutmayalım.

$ curl https://10.142.0.14:6443/apis --header "Authorization: Bearer $token" -k
{
  "kind": "APIGroupList",
  "apiVersion": "v1",
  "groups": [
    {
      "name": "apiregistration.k8s.io",
      "versions": [
        {
          "groupVersion": "apiregistration.k8s.io/v1",
          "version": "v1"
        },
....

Aynı komutu bu sever v1’deki API’lara bakmak için kullanalım.

$ curl https://10.142.0.14:6443/api/v1 --header "Authorization: Bearer $token" -k
{
  "kind": "APIResourceList",
  "groupVersion": "v1",
  "resources": [
    {
      "name": "bindings",
      "singularName": "",
      "namespaced": true,
      "kind": "Binding",
      "verbs": [
        "create"
      ]
    },
....

Bu seferde namespaces lsitesini almak için kullanalım. Ama bu noktada bir hata ile karşılaşacağız. Bunun sebebi RBAC’ın yetkisine sahip olunmadığı için cluster içerisindeki namespace’lerin listelenmemesidir.

$ curl https://10.142.0.14:6443/api/v1/namespaces --header "Authorization: Bearer $token" -k
....
"message": "namespaces is forbidden: User \"system:serviceaccount:default:default\" cannot list resource \"namespaces\" in API group \"\" at the c
....

Proxy Kullanarak API Erişimi

API ile etkileşime geçmenin bir başka yolu da proxy kullanmaktır. Proxy bir node’dan veya bir pod içerisinde bir yan araç kullanımı yoluyla çalıştırılabilir. Aşağıdaki adımlarda bir proxy dağıtımı yapacağız. API sunucusuna erişmek için curl kullanacağız.

Öncelikle proxy’i başlatalım. Varsayılan olarak ön planda başlayacaktır. Burdan geçebileceğimiz birkaç seçenek var. Yardım çıktısını gözden geçirerek başlayalım.

$ kubectl proxy -h
Yardım çıktıları yüklenir...

Yardım çıktılarında belirtilen API prefix ayarı ile arka planda proxy’i çalıştıralım. Enter’a basarak komut istemcisine geri dönebilirsiniz.

$ kubectl proxy --api-prefix=/ &
[1] 3849
Starting to serve on 127.0.0.1:8001

Şimdi curl komutunu kullanarak belirtilen noktadaki proxy IP ve portunu kullanabiliriz.

$ curl http://127.0.0.1:8001/api/v1/namespaces
{
  "kind": "NamespaceList",
  "apiVersion": "v1",
  "metadata": {
    "selfLink": "/api/v1/namespaces",
    "resourceVersion": "860608"
  },
  "items": [
    {
      "metadata": {
        "name": "default",
....

Job’lar ile Çalışalım

Çoğu API nesnesi kullanılabilir olmaya devam edecek şekilde dağıtılmış olsada, Job adı verilen nesneler belirli süreleri ayrı ayrı çalıştırmak için, CronJob adı verilen nesneler ise düzenli olarak çalıştırmak için kullanılır.

Beş saniye’lik sleep fonksiyonunda duran bir container oluşturup durduracak bir job oluşturalım.

$ vim ilkjob.yaml
apiVersion: batch/v1
kind: Job
metadata:
   name: uykucu
spec:
   template:
      spec:
         containers:
         - name: uykucucontainer
           image: busybox
           command: ["/bin/sleep"]
           args: ["5"]
         restartPolicy: Never

$ kubectl create -f ilkjob.yaml
job.batch/uykucu created

$ kubectl get job
NAME     COMPLETIONS   DURATION   AGE
uykucu   1/1           8s         16s

$ kubectl describe jobs.batch uykucu
Name:           uykucu
Namespace:      default
Selector:       controller-uid=8739c3f5-5f0c-11e9-bd37-42010a8e000e
Labels:         controller-uid=8739c3f5-5f0c-11e9-bd37-42010a8e000e
                job-name=uykucu
Annotations:    <none>
Parallelism:    1
Completions:    1
Start Time:     Sun, 14 Apr 2019 23:25:02 +0000
Completed At:   Sun, 14 Apr 2019 23:25:10 +0000
Duration:       8s
Pods Statuses:  0 Running / 1 Succeeded / 0 Failed
....

Job’un yapılandırma bilgilerini görüntüleyelim. Job’ın nasıl çalıştığını etkilemek için kullanacağınız üç parametre vardır. Bu parametreleri görmek için job’ı yaml formatında çıktısını alalım ( -o yaml). BackoffLimit, completions ve parallelism değerlerini görebilirsiniz. Daha sonra bu parametreleri ekleyelim.

$ kubectl get jobs.batch uykucu -o yaml
....
spec:
  backoffLimit: 6
  completions: 1
  parallelism: 1
....

$ kubectl delete jobs.batch uykucu
job.batch "uykucu" deleted

Oluşturduğumuz YAML dosyasına completions parametresini ekleyip 3 değerini verelim.

$ vim ilkjob.yaml
....
  name: uykucu
spec:
   completions: 3
   template:
      spec:
         containers:
....

$ kubectl create -f ilkjob.yaml
job.batch/uykucu created

$ kubectl get jobs
NAME     COMPLETIONS   DURATION   AGE
uykucu   3/3           21s        29s

$ kubectl get pods
NAME           READY   STATUS      RESTARTS   AGE
uykucu-hlk49   1/1     Running     0          2s
uykucu-p2jh9   0/1     Completed   0          17s
uykucu-wnh78   0/1     Completed   0          9s

YAML dosyasına eklediğimiz parametre ile birlikte artık 3 tane pod’umuz oluşmaktadır. Yalnız biz 5 saniye sonra pod’u durdurduğumuz için 5’sn pod çalışır ve ardından kendini durdurur ve diğer pod’u oluşturur. Bu işlem completions değerine kadar devam eder. Örnek çıktıları aşağıda listeliyorum.

kubernetes_VM@k8s-vm:~$ kubectl get pods
NAME           READY   STATUS    RESTARTS   AGE
uykucu-p2jh9   1/1     Running   0          4s

kubernetes_VM@k8s-vm:~$ kubectl get pods
NAME           READY   STATUS              RESTARTS   AGE
uykucu-p2jh9   0/1     Completed           0          8s
uykucu-wnh78   0/1     ContainerCreating   0          0s

kubernetes_VM@k8s-vm:~$ kubectl get pods
NAME           READY   STATUS      RESTARTS   AGE
uykucu-p2jh9   0/1     Completed   0          10s
uykucu-wnh78   1/1     Running     0          2s

kubernetes_VM@k8s-vm:~$ kubectl get pods
NAME           READY   STATUS              RESTARTS   AGE
uykucu-hlk49   0/1     ContainerCreating   0          1s
uykucu-p2jh9   0/1     Completed           0          16s
uykucu-wnh78   0/1     Completed           0          8s

kubernetes_VM@k8s-vm:~$ kubectl get pods
NAME           READY   STATUS      RESTARTS   AGE
uykucu-hlk49   1/1     Running     0          2s
uykucu-p2jh9   0/1     Completed   0          17s
uykucu-wnh78   0/1     Completed   0          9s

kubernetes_VM@k8s-vm:~$ kubectl get pods
NAME           READY   STATUS      RESTARTS   AGE
uykucu-hlk49   0/1     Completed   0          10s
uykucu-p2jh9   0/1     Completed   0          25s
uykucu-wnh78   0/1     Completed   0          17s

Şimdi bu job’ımızı silelim ve YAML dosyamıza bu sefer parallelism parametresini 2 değeri olarak ekleyelim, completions değerini de 5 olarak güncelleyelim ve job’ı dağıtalım.

$ kubectl delete jobs.batch uykucu
job.batch "uykucu" deleted

$ vim ilkjob.yaml
....
  name: uykucu
spec:
   completions: 5
   parallelism: 2
   template:
      spec:
         containers:
....

$ kubectl create -f ilkjob.yaml
job.batch/uykucu created

Parallelism parametresi bize eş zamanlı olarak completions tamamlanana kadar pod çalıştırmamızı sağlıyor. Örnek çıktıları aşağıda görebilirsiniz.

kubernetes_VM@k8s-vm:~$ kubectl get pods
NAME           READY   STATUS              RESTARTS   AGE
uykucu-68bhl   0/1     ContainerCreating   0          1s
uykucu-kgp5p   0/1     ContainerCreating   0          1s

NAME           READY   STATUS    RESTARTS   AGE
uykucu-68bhl   1/1     Running   0          4s
uykucu-kgp5p   1/1     Running   0          4s

kubernetes_VM@k8s-vm:~$ kubectl get pods
NAME           READY   STATUS              RESTARTS   AGE
uykucu-4wqnb   0/1     Completed           0          9s
uykucu-j6wbz   0/1     ContainerCreating   0          2s
uykucu-l78sp   0/1     ContainerCreating   0          2s
uykucu-nd76p   0/1     Completed           0          9s

kubernetes_VM@k8s-vm:~$ kubectl get pods
uykucu-68bhl   0/1     Completed           0          15s
uykucu-7x6rg   0/1     Completed           0          8s
uykucu-kgp5p   0/1     Completed           0          15s
uykucu-t98pr   0/1     Completed           0          8s
uykucu-tkqlv   0/1     ContainerCreating   0          1s

kubernetes_VM@k8s-vm:~$ kubectl get pods
NAME           READY   STATUS      RESTARTS   AGE
uykucu-68bhl   0/1     Completed   0          17s
uykucu-7x6rg   0/1     Completed   0          10s
uykucu-kgp5p   0/1     Completed   0          17s
uykucu-t98pr   0/1     Completed   0          10s
uykucu-tkqlv   1/1     Running     0          3s

kubernetes_VM@k8s-vm:~$ kubectl get pods
NAME           READY   STATUS      RESTARTS   AGE
uykucu-68bhl   0/1     Completed   0          20s
uykucu-7x6rg   0/1     Completed   0          13s
uykucu-kgp5p   0/1     Completed   0          20s
uykucu-t98pr   0/1     Completed   0          13s
uykucu-tkqlv   0/1     Completed   0          6s

Belirli bir süre sonra işi durduracak bir parametre ekleyelim. activeDeadlineSeconds değerini 15 olarak YAML dosyasımıza ekleyelim. Job ve tüm pod’lar 15 saniye çalıştıktan sonra tamamlanacaktır.

$ vim ilkjob.yaml
....
  name: uykucu
spec:
   completions: 5
   parallelism: 2
   activeDeadlineSeconds: 15
   template:
      spec:
         containers:
....

$ kubectl delete jobs.batch uykucu
job.batch "uykucu" deleted

$ kubectl create -f ilkjob.yaml
job.batch/uykucu created

$ kubectl get jobs
NAME     COMPLETIONS   DURATION   AGE
uykucu   0/5           1s         1s

$ kubectl get jobs
NAME     COMPLETIONS   DURATION   AGE
uykucu   2/5           13s        13s

$ kubectl get jobs
NAME     COMPLETIONS   DURATION   AGE
uykucu   3/5           36s        36s

$ kubectl get pods
NAME           READY   STATUS      RESTARTS   AGE
uykucu-9lqmv   0/1     Completed   0          3m48s
uykucu-fbszj   0/1     Completed   0          3m41s
uykucu-kn9q7   0/1     Completed   0          3m48s

$ kubectl get job uykucu -o YAML
....
 conditions:
  - lastProbeTime: "2019-04-14T23:55:24Z"
    lastTransitionTime: "2019-04-14T23:55:24Z"
    message: Job was active longer than specified deadline
    reason: DeadlineExceeded
    status: "True"
    type: Failed
  startTime: "2019-04-14T23:55:09Z"
....
$ kubectl delete jobs.batch uykucu
job.batch "uykucu" deleted

Gördüğünüz gibi 5 tane pod oluşturmaya çalışmadı. Her pod 5 saniye çalışıyordu. İlk 2 pod parallelism’den oluştu sonra 15. saniyeyi dolduracak şekilde 3. pod oluştu ve işlemi tamamladı.

CronJob Oluşturalım

Bir CronJob zaman doğru olduğu sürece sizin adınıza toplu job yaratacak bir zaman döngüsü oluşturur. Mevcutta oluşturduğumuz ilkjob.yaml dosyasını bu örnek üzerinden devam ettireceğiz.

$ cp ilkjob.yaml ilkcronjob.yaml

$ vim ilkcronjob.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
   name: uykucu
spec:
   schedule: "*/2 * * * *"
   jobTemplate:
      spec:
         template:
            spec:    
               containers:
               - name: uykucucontainer
                 image: busybox
                 command: ["/bin/sleep"]
                 args: ["5"]
               restartPolicy: Never

$ kubectl create -f ilkcronjob.yaml
cronjob.batch/uykucu created

$ kubectl get cronjobs.batch
NAME     SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
uykucu   */2 * * * *   False     0        <none>          32s

$ kubectl get jobs.batch
No resources found.

$ kubectl get cronjobs.batch
NAME     SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
uykucu   */2 * * * *   False     0        100s            3m31s

$ kbuectl get jobs.batch
NAME                COMPLETIONS   DURATION   AGE
uykucu-1555287000   1/1           8s         2m6s

$ kbuectl get jobs.batch
NAME                COMPLETIONS   DURATION   AGE
uykucu-1555287000   1/1           8s         2m40s
uykucu-1555287120   1/1           7s         39s

schedule: “*/2 * * * *” => bu kısımda linux stili CronJob syntax’ı belirledik. ( 2 dakikada 1). 2 dakika dolduktan sonra oluşturduğumuz CronJob bizim için bir Job oluşturdu. Bu işlem her iki dakikada bir devam edecektir.

$ kubectl get jobs.batch
NAME                COMPLETIONS   DURATION   AGE
uykucu-1555287000   1/1           8s         4m4s
uykucu-1555287120   1/1           7s         2m3s
uykucu-1555287240   0/1           3s         3s

Şimdi şöyle bir örnek yapalım. activeDeadlineSeconds parametresini 10 saniyelik bir şekilde ilkcronjob.yaml dosyamıza ekleyelim. Bu sayede işlem 10 saniyeden fazla devam ederse sonlanacak.

$ vim ilkcronjob.yaml
....
  jobTemplate:
      spec:
         template:
            spec:    
               activeDeadlineSeconds: 10
               containers:
....

$ kubectl delete cronjobs.batch uykucu
cronjob.batch "uykucu" deleted

$ kubectl create -f ilkcronjob.yaml
cronjob.batch/uykucu created

$ kubectl get jobs
NAME                COMPLETIONS   DURATION   AGE
uykucu-1555287600   1/1           7s         2m46s
uykucu-1555287720   1/1           8s         46s

$ kubectl get pods
NAME                      READY   STATUS      RESTARTS   AGE
uykucu-1555287600-slhdr   0/1     Completed   0          2m58s
uykucu-1555287720-kxspl   0/1     Completed   0          58s

$ kubectl get cronjobs.batch
NAME     SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
uykucu   */2 * * * *   False     0        73s             3m56s

Ortamımızı temiz bir şekilde bırakmak için cronjob’ımızı silelim.

$ kubectl delete cronjobs.batch uykucu
cronjob.batch "uykucu" deleted

Laboratuvarımızın burda sonuna gelmiş bulunmaktayız. Umarım yapılanları iyi bir şekilde anlamışsınızdır, görüşmek üzere !

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 !!!!

Leave a Reply

Your email address will not be published. Required fields are marked *