Kubernetes Pod Nedir?

Pod, içinde bir veya birden fazla container'ın çalıştığı en küçük Kubernetes birimidir. Bir Pod, birbirleriyle yakından ilişkili olan ve aynı Node üzerinde çalışması gereken container'lar için bir gruplama mekanizması sağlar.

Her Pod, kendine tahsis edilmiş bir internal IP adresine sahiptir. Bir Kubernetes cluster içindeki tüm pod'lar aynı network-address space'i kullandıkları için, bir pod, başka bir pod'un IP adresine kolaylıkla ve doğrudan erişebilir.

Bir pod içinde, bir veya birden fazla container çalışabilir. Asıl container'ın yanında ek olarak çalışan diğer container'lara sidecar container'da denir.

Pod'larla ilgili en önemli şey, bir pod birden çok container içerdiğinde, hepsinin her zaman tek bir node üzerinde çalıştırılmasıdır. Bir pod'un container'ları asla birden çok node üzerine yayılmaz.

Aynı pod içinde çalışan container'lar , aynı network ve linux namespace'i kullanırlar. Bu sebeple aynı pod'un içindeki container'lar;

  • Aynı hostname ve network interface'leri paylaşırlar. Örneğin, bir Pod'un adı "my-pod" ise, Pod içindeki ilk container'ın hostname'i "my-pod-0", ikinci container'ın hostname'i "my-pod-1" olur ve böyle devam eder.
  • Aynı network namespace'i kullandıkları için aynı IP ve port aralığını kullanmış olurlar. Bu nedenle aynı pod içindeki container'larda port çakışmasına dikkat edilmelidir.
  • Aynı loopback network interface'ı paylaştıkları için birbirleriyle localhost üzerinden direkt iletişime geçebilirler.
  • Aynı volume'u aynı pod içindeki tüm container'lar mount edebilir.

1. Pod Nasıl Oluşturulur?

Tüm Kubernetes objeleri gibi Pod'ları da iki yöntemle oluşturabiliriz:

  1. Kubernetes REST API endpoint'e bir JSON veya YAML manifest dosyası göndermek.
  2. kubectl aracını kullanarak CLI üzerinden komutlarla oluşturmak.
💡
kubectl aracı ile CLI komutlarını kullanmak genellikle sınırlı sayıda özellik yapılandırmanıza izin verir. Fakat, Kubernetes objelerini YAML veya JSON dosyalarından tanımlamanız, bir sürüm kontrol sisteminde (github vs.) bu manifestlerin depolanmasını mümkün kılmak gibi bir avantaj sağlar.

1.1. Manifest Dosyasının Hazırlanması

Kubernetes Pod oluşturmak için bir YAML manifest dosyası kullanabilirsiniz. Bu dosya, Pod'un nasıl oluşturulacağına dair bilgileri içerir. Aşağıdaki örnek, bir YAML manifest dosyasıdır ve "my-pod" adında bir Pod oluşturur:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container-1
    image: nginx:latest
  - name: my-container-2
    image: busybox:latest
    command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']
  restartPolicy: OnFailure

Bu YAML dosyasında, Pod'un oluşturulması için gerekli olan 4 ana parametre vardır:

  • apiVersion: Kullanılan Kubernetes API sürümünü belirtir. Pod objesi için v1 kullanılır.
  • kind: Oluşturulacak objenin türünü belirtir. Bu örnekte, bir Pod oluşturulacağı için Pod olarak ayarlanır.
  • metadata: Pod'un metadata bilgilerini içerir. Örneğin Pod'un adını name parametresi ile belirleyebiliriz.
  • spec: Pod'un özelliklerini belirtir. Bu örnekte, Pod içindeki cantainer'ların listesi yer alır.
💡
apiVersion parametresinin hangi değerini öğrenmek için http://kubernetes.io/docs/api adresini ziyaret edebilir veya kubectl explain pod komutunu kullanabilirsiniz. Örnek çıktı aşağıdaki gibidir:

Bu dört ana parametreden herhangi birisi hakkında detaylı bilgi almak için kubectl explain komutunu kullanabilirsiniz. Örneğin kubectl explain pod.spec komutunun çıktısı şu şekildedir:


Biz yinede bazı parametreleri kendimiz de açıklayalım.

➡ Dört ana parametreden olan spec şu alt parametreleri içerebilir:

  • containers: Pod içindeki container'ların belirtildiği alandır.
  • volumes: Pod içinde kullanılacak volume'ların belirtildiği alandır.
  • restartPolicy: Container'ların çökmesi durumunda ne yapılacağını belirtir. Örneğin, Always olarak ayarlanırsa, container'ların çökmesi durumunda otomatik olarak yeniden başlatılır.
  • imagePullSecrets: Container'ların Docker imajlarını çekerken kullanılacak kimlik doğrulama bilgilerini belirtir.
  • hostAliases: Pod'lar için özel host isimleri tanımlamak için kullanılır.
  • nodeSelector: Pod'un hangi node'larda çalışacağını belirtir.
  • tolerations: Pod'un çalışabileceği belirli bir durumda tolerans sağlar.
  • affinity: Pod'un başka kaynaklara bağımlılıklarını belirtir.

Örneğin tüm bu parametreleri içeren örnek bir YAML dosyası örneği şu şekildedir:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  labels:
    app: my-app
spec:
  hostAliases:
    - ip: "127.0.0.1"
      hostnames:
        - "localhost"
    - ip: "10.240.0.1"
      hostnames:
        - "kube-master"
  containers:
    - name: my-container
      image: nginx:latest      
      volumeMounts:
        - name: my-volume
          mountPath: /usr/share/nginx/html
  volumes:
    - name: my-volume
      emptyDir: {}
  restartPolicy: Always
  terminationGracePeriodSeconds: 30
  dnsPolicy: ClusterFirst
  nodeSelector:
    disktype: ssd
  serviceAccountName: default
  automountServiceAccountToken: true
  imagePullSecrets:
    - name: my-registry-key
  schedulerName: default-scheduler
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
    seLinuxOptions:
      user: "system_u"
      role: "system_r"
      type: "svirt_sandbox_file_t"
      level: "s0:c123,c456"
  priorityClassName: high
  priority: 1000
  dnsConfig:
    nameservers:
      - "1.1.1.1"
      - "8.8.8.8"
    searches:
      - "my-domain.local"

➡ Diğer bir parametre olan metadata şu alt parametreleri içerebilir:

  • name: Pod'un adıdır.
  • labels: Pod'a etiketler ekler. Etiketler, kaynakları gruplamak, aramak veya filtrelemek için kullanılabilir. Örnek olarak:
metadata:
  name: my-pod
  labels:
    env: production
    app: my-app
  • annotations: Pod hakkında ek bilgi sağlar. Bu bilgiler, açıklama veya notlar gibi metin bilgileri olabilir. Örnek olarak:
metadata:
  name: my-pod
  annotations:
    description: This is my production pod.
    version: 1.0.0
  • namespace: Pod'un ait olduğu namespace'i belirtir. Namespace'ler, Kubernetes cluster'ındaki farklı ortamları veya uygulamaları ayırmak için kullanılabilir. Örnek olarak:
metadata:
  name: my-pod
  namespace: production
  • ownerReferences: Pod'un sahibi olan objeyi belirtir. Bu parametre, Pod'un silinmesi durumunda sahibi olan objenin de silinmesini sağlar. Örnek olarak:
metadata:
  name: my-pod
  ownerReferences:
    - apiVersion: apps/v1
      kind: Deployment
      name: my-deployment

spec parametresi altında yer alan ve önemli bir parametre olan containers ise şu alt parametreleri içerebilir:

  • name: Container'ın adıdır. Bu parametre zorunludur.
  • image: Container'ın kullanacağı Docker image'ı belirtir.
  • command: Container'ın  başlarken çalıştıracağı komutu belirtir.
  • args: Container'ın başlarken kullanacağı komut argümanlarını belirtir.
  • env: Container'ın kullanacağı ortam değişkenlerini belirtir.
  • ports: Container'ın kullanacağı portları belirtir.
  • volumeMounts: Container'ın kullandığı volume'leri belirtir.
  • resources: Container'ın kullanabileceği kaynakları (CPU, RAM vb.) sınırlar.
  • lifecycle: Container'ın  başlatma ve sonlandırma işlemlerini belirtir.

Örnek bir YAML dosyası olarak ise aşağıdaki örneği verebiliriz:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  labels:
    app: my-app
spec:
  hostAliases:
    - ip: "127.0.0.1"
      hostnames:
        - "localhost"
    - ip: "10.240.0.1"
      hostnames:
        - "kube-master"
  containers:
    - name: my-container
      image: nginx:latest
      command: ["nginx"]
      args: ["-g", "daemon off;"]
      env:
        - name: MY_ENV_VAR
          value: "my-value"
      envFrom:
        - configMapRef:
            name: my-configmap
        - secretRef:
            name: my-secret
      ports:
        - name: http
          containerPort: 80
        - name: https
          containerPort: 443
      livenessProbe:
        httpGet:
          path: /healthz
          port: http
        initialDelaySeconds: 30
        periodSeconds: 10
        timeoutSeconds: 5
      readinessProbe:
        httpGet:
          path: /readiness
          port: http
        initialDelaySeconds: 10
        periodSeconds: 5
        timeoutSeconds: 2
      volumeMounts:
        - name: my-volume
          mountPath: /usr/share/nginx/html
  volumes:
    - name: my-volume
      emptyDir: {}
💡
Pod manifest dosyasında ports parametresinin belirtilmesi tamamen bilgilendirme amaçlıdır. ports parametresini eklememenin, istemcilerin bağlanıp bağlanamayacağı üzerinde hiçbir etkisi yoktur. Eğer bir pod, 0.0.0.0 adresine bağlı bir port üzerinden bağlantıları kabul ediyorsa, ports parametresinde açıkça belirtilmemiş olsa bile diğer podlar her zaman ona bağlanabilir. Ancak, cluster'ınızı kullanan herkesin her pod'un hangi portu expose ettiğini hızlı bir şekilde görebilmesi için ports parametresi tanımlamak mantıklıdır.

1.2. Hazırlanan Manifest Dosyasının Çalıştırılması

Pod manifest dosyasını hazırladıktan sonra ilgili pod'ları oluşturabilmek için kubectl create veya kubectl apply komutlarını kullanabilirsiniz.

kubectl create -f <pod-definition-file>.yaml
👁️
YAML dosyasında tanımladığınız pod daha önceden oluşturulmuşsa kubectl create komutu sonraki çalıştırmalarınızda hata verir. Manifest dosyasında düzenleme yaptıktan sonra podu güncellemek için kubectl create yerine kubectl apply komutunu kullanmalısınız.
💡
Podları belirli bir namespace altında oluşturmak istiyorsanız create komutuna -n parametresi ile ilgili namespace'in adını ekleyebilirsiniz. kubectl create -f <pod-definition-file>.yaml -n custom-namespace

1.3. CLI Aracılığıyla Pod Oluşturmak

Pod oluşturmak için YAML veya JSON dosyası kullanmak istemiyorsanız, aşağıdaki adımları izleyerek doğrudan terminalden pod oluşturabilirsiniz:

  1. Terminali açın: Pod'u oluşturmak için kullanacağınız komutları çalıştırmak için bir terminal açın.
  2. Pod'u oluşturun: Aşağıdaki komutu kullanarak pod'u oluşturun:
kubectl run <pod-name> --image=<image-name> --port=<port-number>

Bu komut, "pod-name" adlı bir pod oluşturur, "image-name" adlı bir Docker imajı kullanır ve "port-number" adlı bir portu açar.

Örneğin, aşağıdaki komutla "my-pod" adlı bir pod oluşturabilirsiniz:

kubectl run my-pod --image=nginx --port=80 --restart=Never

1.4. Pod'ları Belirli Bir Node Üzerinde Oluşturmak

Yukarıdaki başlıklarda yer alan aşamaları uygulayarak bir pod oluşturduğunuzda, oluşan pod cluster üzerinde yer alan ve varsa cpu,  memory gibi koşulları sağlayan rastgele bir node üzerinde oluşturulur. Fakat pod'un oluşturulacağı node'u seçmekte mümkündür.

Örneğin Kubernetes cluster'ımızdaki machine-1 ve machine-2 isimli nodelar CPU, machine-3 ve machine-4 isimli nodelar GPU içersin. İlk olarak tüm nodları type label'ı ile etiketleyelim.

kubectl label node machine-1 type=cpu
kubectl label node machine-2 type=cpu
kubectl label node machine-3 type=gpu
kubectl label node machine-4 type=gpu

Ardından pod oluştururken eğer oluşturulacak pod'un gpu içeren makinelerden birinde oluşturulmasını istiyorsak, pod manifest dosyasındaki spec bölümü altında yer alan nodeSelector parametresini type=gpu olarak ayarlamalıyız.

apiVersion: v1
kind: Pod
metadata:
 name: image-processor
spec:
 nodeSelector:
 	type: gpu
 containers:
 - image: nvidia/cuda
 	name: cuda

Artık bu manifest dosyasını kubectl create veya kubectl apply komutuyla çalıştırdığınızda pod'unuz gpu içeren node'lardan birinde çalıştırılacaktır.

2. Oluşturulan Pod'ların İncelenmesi ve Listelenmesi

  • Cluster'da yer alan pod'ları listelemek için kubectl get pods komutunu kullanabilirsiniz.
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
my-pod 1/1 Running 0 32s
  • Belirli label'lara ait podları listelemek için -l parametresini kullanabilirsiniz.
kubectl get pods -l environment
kubectl get pods -l environment=production,type=gpu
  • Bir pod'un loglarını görmek için kubectl logs <pod-name> komutunu kullanabilirsiniz.
kubectl logs my-pod
  • Bir pod içinde yer alan belirli bir container'ın loglarını görmek için -c parametresi ile birlikte kubectl logs <pod-name> -c <container-name> komutunu  kullanabilirsiniz.
kubectl logs my-pod -c my-container
💡
Container logları, her gün ve log dosyasının boyutu 10 MB'a her ulaştığında otomatik olarak rotate edilir. kubectl logs komutu yalnızca son rotate'deki log çıktılarını gösterir.
  • Pod'un detaylarını görüntülemek için kubectl describe pod <pod-name> komutunu kullanabilirsiniz:
$ kubectl describe pod web
Name:             web
Namespace:        default
Priority:         0
Service Account:  default
Node:             minikube/192.168.49.2
Start Time:       Fri, 28 Apr 2023 16:45:40 +0300
Labels:           name=WebApp
***
***

Bu komut, pod'un adını belirttiğinizde pod hakkında ayrıntılı bilgi sağlar. Pod'un etiketleri, durumu, oluşturma zamanı ve diğer özellikleri gibi bilgileri içerir.

3. Pod'ların Silinmesi

Kubernetes'te bir podu silmek için aşağıdaki adımları takip edebilirsiniz.

Bir podu silmek istediğinizde ilgili pod içindeki tüm containerlarda çalışan process'lere önce SIGTERM sinyali gönderilir. Eğer processler 30 saniye içinde sonlandırılmazsa bu sefer SIGKILL sinyali gönderilerek zorla sonladırılır.

Bir podu silmek için önce silmek istediğiniz podun adını bulmalısınız.

kubectl get pods

Daha sonra, aşağıdaki komutu kullanarak podu silebilirsiniz:

kubectl delete pod <pod-adı>

Tek bir pod yerine geçerli namespace altındaki tüm podları silmek istiyorsanız --all parametresini kullanabilirsiniz.

kubectl delete pod --all

Belirli bir label'a sahip tüm podları silmek isterseniz ise -l parametresi ile ilgili label'ı yazarak kullanabilirsiniz.

kubectl delete pod -l app=be

4. Pod'lara Annotation Eklemek ve Silmek

Pod Annotation, bir pod'unun üzerine belirli bir anahtar-değer çiftini eklemek veya mevcut bir anahtarın değerini güncellemek için kullanılır.

Bu işlem, bir pod'un metaverilerine ek açıklama eklemek veya mevcut açıklamaları güncellemek için kullanılabilir. Örneğin, bir pod'un ne amaçla oluşturulduğunu, kim tarafından oluşturulduğunu, hangi sürümün kullanıldığını ve diğer benzer bilgileri açıklamak için kullanılabilir.

Aşağıdaki örnek, "my-pod" adlı bir pod'un üzerine "app-version" anahtarını eklemek için kullanılan bir "pod annotate" komutunu göstermektedir:

kubectl annotate pod my-pod app-version=1.0.0

Pod'lara eklenen annonation'ları silmek için ilgili annotation'ın sonuna - koyarak komutu çalıştırmanız yeterlidir.

kubectl annotate pod my-pod app-version-

Ayrıca, tüm annotation'ları silmek istiyorsanız, --all parametresini kullanabilirsiniz:

kubectl annotate pod my-pod --all

5. Pod'lara Label Eklemek ve Silmek

Pod label'ları, Kubernetes'te pod'ları gruplamak ve filtrelemek için kullanılan etiketlerdir. Pod'ların özelliklerini veya işlevlerini belirlemek için kullanılabilirler. Etiketler, pod'ların Kubernetes'te ölçeklendirilmesi, izlenmesi, güncellenmesi ve yönetilmesi için önemlidir.

💡
Pod label konusunu bir sonraki başlıkta oldukça detaylı işleyeceğiz. Şimdilik sadece bir pod'a nasıl label eklenip çıkarılabildiğini hızlıca göstereceğiz.

Aşağıdaki komut, kubectl label kullanarak my-pod adlı bir pod'a environment=production label'ı eklemek için bir örnek göstermektedir:

kubectl label pod my-pod environment=production

Bu komut, my-pod adlı pod'a environment=production etiketini ekler. -l veya --selector parametresini kullanarak birden fazla pod'u seçebilirsiniz. Örneğin, aşağıdaki komut, app=my-app ve tier=backend etiketlerine sahip tüm pod'ları seçer ve environment=production etiketi ekler:

kubectl label pods -l app=my-app,tier=backend environment=production

kubectl label komutunu kullanarak pod'lardan etiketleri de kaldırabilirsiniz. Aşağıdaki komut, my-pod adlı pod'dan environment etiketini kaldırır:

kubectl label pod my-pod environment-

Bu komut, my-pod adlı pod'dan environment etiketini kaldırır. Etiketi silmek için anahtar adının sonuna - eklemeniz yeterlidir.

6. Pod'lara IP Adresi ve Port ile Erişmek

Oluşturduğumuz pod şu anda çalışıyor ve kubectl get veya kubectl logs komutlarıyla görüntüleyebiliyoruz. Fakat bu pod içinde çalışan uygulamamıza nasıl erişeceğiz?

Pod'lara atanan IP adresleri internal IP adresleridir ve cluster dışından direkt bu IP adreslerine erişemezsiniz. Cluster dışından pod'larınıza erişim elde etmek için önce kubectl port-forward <exernal-port>:<internal-port> komutu ile ilgili pod'a port yönlendirmesi yapmamız gerekir.

Bu örnekte local makinenin 8888 portunu Pod içindeki 80 portuna yönlendirmiş olduk.

Artık 127.0.0.1:80 adresine gittiğinizde uygulamanızı görmüş olacaksınız.

💡
Pod'lara cluster dışından erişmek için Service'leri de tercih edebilirsiniz. Fakat bu konuyu ilerleyen başlıklarda inceleyeceğiz.
💡
Eğer sildiğiniz bir pod tekrardan ayağa kalkıyorsa ReplicationController mevcut olabilir. Bu podu silebilmek için ilgili ReplicationController altından çıkarınız veya önce ReplicationController'ı siliniz.

Sıradaki yazı ile eğitim serisine devam edebilirsiniz.

Kubernetes Label Nedir?
Kubernetes label, Kubernetes nesnelerinizi sınıflandırmak, tanımlamak, filtrelemek için kullanılan key-value çiftleridir.