Kubernetes Deployment Nedir?

Kubernetes Deployment, uygulamaların hızlı ve güvenli bir şekilde dağıtılmasını, güncellenmesini ve yönetilmesini sağlayan bir Kubernetes nesnesidir.

Deployment, uygulamanın Pod'larını oluşturur ve izler. Otomatik olarak yeni Pod'lar oluşturur ve çökmeler durumunda otomatik olarak yeniden başlatır. Ayrıca güncelleme ve geri alma işlemlerini kolaylaştırır, uygulamanın kesintisiz olarak güncellenmesine veya eski sürüme geri dönülmesine olanak tanır. Ölçeklendirme için de esneklik sağlar, isteğe bağlı olarak daha fazla veya daha az Pod çalıştırılmasını sağlar. Deployment'lar, Kubernetes üzerinde uygulama dağıtımı ve yönetimi için güçlü bir araçtır.

Bir önceki yazımızda Kubernetes deployment stratejilerini incelemiştik. Yazıdan hatırlayacağınız üzere deployment'ları manual yapmak zahmetli ve kubectl rolling-update komutuyla yapmakta güvenilmez ve tercih edilmeyen yöntemdi. Bu yazımızda Kubernetes deployment işlemlerini Deployments nesnesi ile nasıl daha güvenilir ve efektif bir şekilde yapacağınızı göstereceğiz.

Kubernetes Rolling Update ve Blue-Green Deployment Nedir?
Kubernetes Rolling Update ve Blue-Green Deployment, uygulamaların güncellenmesi ve dağıtımı için kullanılan stratejilerdir.

1. Deployment Nesnesi Oluşturmak

Bir Deployment nesnesi oluşturduğunuzda otomatik olarak bir de ReplicaSet nesnesi oluşturulur. ReplicaSet, ReplicationController'un yerini alan yeni nesil bir Kubernetes nesnesidir.

Kubernetes ReplicaSet Nedir?
Kubernetes ReplicaSet, belirli bir pod sayısını yönetmek ve high availability sağlamak için kullanılan bir Kubernetes nesnesidir.

Kubernetes Deployment nesnesini kullanıdığınızda, aslında pod'lar Bu oluşturulan ReplicaSet tarafından oluşturulur ve yönetilir.

Bir Deployment nesnesi oluşturmak, ReplicationController veya ReplicaSet oluşturmaktan farklı değildir. Deployment nesnesi oluşturmak için aşağıdaki manifesti örnek alabilirsiniz.

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

Manifest dosyası hazır olduktan sonra kubectl create veya kubectl apply komutlarından birisi ile Deployment'ı oluşturabilirsiniz.

 kubectl create -f file-deployment.yaml --record
💡
Deployment oluştururken --record parametresi, yapılan değişiklikleri Deployment kayıtlarına eklemek için kullanılır. Bu parametre, Deployment nesnesinin revision (düzeltme) tarihçesini tutar ve yapılan değişiklikleri kaydeder.

Ardından kubectl get deployment komutu ile oluşturduğunuz Deployment nesnesini görebilirsiniz. Ayrıca kubectl rollout status deployment komutuyla da Deployment durumunu görebilirsiniz.

$ kubectl rollout status deployment nginx-deployment
deployment nginx-deployment successfully rolled out

Deployment nesnesinin oluşturduğu ReplicaSet nesnesi de rollout  yani deployment işlemi sonucu belirtilen replica sayısı kadar Pod oluşturur.

$ kubectl get pod
NAME                   READY  STATUS   RESTARTS  AGE
web-1506449474-otnnh   1/1    Running  0         14s
web-1506449474-vmn7s   1/1    Running  0         14s
web-1506449474-xis6m   1/1    Running  0         14s
💡
Pod isimlerinde ortada yer alan sayı, pod template'in hash değeridir. Deployment tarafından oluşturulan ReplicaSet'te aynı hash değerini isminde barındırır. Böylece Deployment her versiyon için hangi ReplicaSet'i yöneteceğini bilir.

2. Deployment İle Kullanılabilecek Stratejiler

Deployment, varsayılan olarak Rolling Update stratejisini kullanır. Rolling update ile mevcut pod'larınız sonlandırılırken eş zamanlı olarak yeni pod'lar oluşturulur.

Diğer bir strateji ise Recreate'dir. Eğer uygulamanız multi-version çalışmayı desteklemiyorsa önce mevcut tüm pod'ların aynı anda silinip ardından yenilerinin oluşturulmasını sağlayan Recreate stratejisini kullanabilirsiniz.

3. Deployment Rolling Update ile Güncelleme Başlatmak

Bir deployment başlatabilmek için temel kural ReplicaSet'in template'inin veya replica saysının değişiyor olmasıdır. Yani bir deployment'ın manifestinde spec altındaki replicas veya template alanlarını değiştirdiğinizde Deployment tetiklenir.

💡
Deployment app/v1 versiyonunda Deployment'ın label selector alanı değiştirilemezdir. Bu nedenle Deployment'ı tetikleyemez.

Bir Deployment nesnesini tetikleyerek güncelleme başlatmanın en yaygın senaryosu, Pod içindeki container'ların versiyonunu değiştirmektir. Bunu kubectl set image komutuyla kolaylıkla yapabilirsiniz.

$ kubectl set image deployment nginx-deployment nginx=nginx:1.2
deployment "nginx-deployment" image updated
💡
kubectl set image komutu ayrıca ReplicationController ve ReplicaSet nesnelerinin de image'lerinin değiştirilmesine olanak sağlar.

Deployment template değişikliği ile tetiklenip güncellemeyi başlattığında rolling update işlemi gerçekleştirilir ve eski ReplicaSet yeni ReplicaSet ile değiştirilir.

Yeni ReplicaSet ismi, yeni template'in hash değerini içerir. Eski ReplicaSet ise birazdan göreceğimiz rolling back işlemleri için silinmeden muhafaza edilir.

ReplicaSet'leri listelediğinizde eski ve yeni RS'yi listede görebilirsiniz.

$ kubectl get rs
NAME                         DESIRED  CURRENT  AGE
nginx-deployment-1506449474  0        0        24m
nginx-deployment-1581357123  3        3        23m

4. Deployment Güncelleme Geçmişini Listelemek

Deployment, rolling back işlemini mümkün kılmak için yaptığınız güncellemelerin tarihçesini saklar. Bu tarihçeyi kubectl rollout history deployment komutu ile görebilirsiniz.

$ kubectl rollout history deployment nginx-deployment
deployments "nginx-deployment":
REVISION  CHANGE-CAUSE
2         kubectl set image deployment nginx-deployment nginx=nginx:1.2
3         kubectl set image deployment nginx-deployment nginx=nginx:1.3

--record komutunu kullandığımız için CHANGE-CAUSE sütununda Deployment güncellemesini tetikleyen komutu görebiliyoruz.

Varsayılan olarak saklanan güncelleme geçmişi sayısı 10'dur. Fakat Deployment nesnesinin revisionHistoryLimit parametresini değiştirerek bu sayıyı istediğiniz gibi ayarlayabilirsiniz.

5. Deployment Rolling Back ile Güncellemeyi Geri Almak

Bir Deployment güncelleme işlemi sonrası eğer işler yolunda gitmezse ve yaptığınız güncellemeyi geri almak isterseniz kubectl rollout undo deployment komutunu kullanabilirsiniz.

Direkt ReplicationController veya ReplicaSet kullanmak yerine bir Deployment nesnesi kullanmanın en önemli avantajı güncellemeleri geri alabilmenizdir.

Bir önceki başlıkta yaptığımız güncelleme işlemini geri alalım.

$ kubectl rollout undo deployment nginx-deployment
deployment "nginx-deployment" rolled back
💡
undo komutu, güncellemeniz halen devam ediyorken bile kullanılabilir. Bu, önce güncellemeyi durdurur ve o ana kadar oluşturulmuş yeni pod'ları silerek eski versiyonun pod'larını tekrar oluşturur.

Eğer bir önceki yerine tarihçedeki belirli bir ana geri dönmek istiyorsanız, history komutunun çıktısındaki REVISION numaralarını --to-revision parametresiyle kullanabilirsiniz.

kubectl rollout undo deployment nginx-deployment --to-revision=1

6. Deployment Güncellemeyi Duraklatmak

Bazı durumlarda güncellemeyi tek seferde tamamlamak yerine belirli bir noktada durdurarak yeni versiyonu test etmek isteyebilirsiniz. Deployment, pause komutu ile bunu mümkün kılar. Buna canary release adı da verillir.

Canary release, bir yazılımın yeni bir sürümünü kullanıcılara aşamalı ve kontrollü bir şekilde sunmayı sağlayan bir dağıtım stratejisidir. Bu strateji, yeni bir sürümün tamamını kullanıcılara hemen sunmak yerine, yeni sürümün bir alt kümesini küçük bir kullanıcı grubuna veya trafik akışına yönlendirerek performansını ve istikrarını değerlendirmeyi amaçlar.

Bir güncellemeyi başlattıktan sonra kubectl rollout pause deployment komutu ile güncellemeyi devam ederken durdurabilirsiniz.

$ kubectl rollout pause deployment nginx-deployment
deployment "nginx-deployment" paused
🔴
Bir güncelleme duraklatıldığında undo işlevi geçersiz kalır. Güncellemeyi geri alabilmek için önce duraklatılmış güncelleme devam ettirilmelidir.

7. Deployment Duraklatılan Güncellemeyi Devam Ettirmek

Güncellemenizi durdurup yeni pod'ları test ettikten ve bir sorun yoksa devam ettirebilmek için resume koutunu kullanabilirsiniz.

$ kubectl rollout resume deployment nginx-deployment
deployment "nginx-deployment" paused

Böylece güncelleme kaldığı yerden devam edecektir.

8. Deployment Güncelleme Limitlerini Kontrol Etmek

Bir Deployment rollout işlemi başlatıp status komutu ile işlemi izlediğinizde tüm pod'ların birer birer silinip oluşturulduğunu görürsünüz. Tek tek yapmak yerine Deployment maxSurge ve maxUnavailable değerlerini değiştirerek güncellemeyi hızlandırabilir veya yavaşlatabilirsiniz.

Kubernetes Deployment nesnesinin spec.strategy.rollingUpdate bölümünde bulunan maxSurge ve maxUnavailable parametreleri, rolling update işlemini yönetmek için kullanılır. Bu parametreler, Kubernetes'e güncelleme sırasında kaç yeni Pod'un başlatılacağını ve aynı anda kaç Pod'un kullanılamaz olabileceğini belirtmek için kullanılır.

  • maxSurge: güncelleme sırasında izin verilen en fazla yeni Pod sayısını belirtir. Örneğin, maxSurge: 25% değeri verildiyse, mevcut Pod sayısının %25'inden fazla yeni Pod başlatılabilir. Varsayılan değeri %25'dir. Bu, toplam Pod sayısını geçici olarak artırabilir ve yük dengesini sağlamak için kullanılabilir.
  • maxUnavailable: güncelleme sırasında izin verilen en fazla kullanılamayan (hizmet dışı) Pod sayısını belirtir. Örneğin, maxUnavailable: 1 değeri verildiyse, güncelleme sırasında en fazla 1 Pod hizmet dışı kalabilir. Varsayılan değeri %25'dir. Bu, yüksek kullanılabilirlik sağlamak için kullanılan Pod'ların sayısını kontrol etmeye yardımcı olur.

Bu iki parametre, güncelleme işlemini daha kontrollü hale getirir ve ağır bir etki veya kullanıcı kesintisi olmadan yeni sürüme geçişi sağlar. Örneğin, maxSurge ve maxUnavailable değerlerini dikkatli bir şekilde ayarlayarak, kullanıcı trafiği üzerinde minimal etkiyle sürdürülebilir bir güncelleme süreci sağlanabilir.

Örnek bir senaryoya bakalım:

spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0

Replica sayısının 3 olduğu bir Deployment'ta,  her daim çalışan 3 pod olacak ve aynı anda ortamda en fazla 4 pod bulunacak şekilde güncelleme devam etti.

Şimdi başka bir senaryoya bakalım:

spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1

Replica sayısının 3 olduğu bir Deployment'ta,  her daim çalışan 2 pod (repica sayısı - maxUnavailable) olacak ve aynı anda ortamda en fazla 4 pod bulunacak şekilde güncelleme devam etti. Ve farkettiğiniz gibi ilk senaryodan daha kısa sürede güncelleme tamamlandı.

Bu iki değeri kendi senaryonuza göre güncelleyerek rollout işlemlerinizin stratejisini değiştirebilirsiniz.

9. Deployment Sorunlu Güncellemeleri Engellemek

Başlattığımız bir rollout işlemindeki versiyon eğer sorunluysa, komple çalışmayan bir versiyona geçiş yapmamak için ekstra bir güvenlik katmanı ekleyebiliriz. Deployment nesnesi, minReadySeconds parametresi ile sorunlu güncellemeleri engellememizi sağlar.

minReadySeconds parametresi, sıradaki Pod'u oluşturmaya başlamadan önce son oluşturulan Pod'un Ready durumunda ne kadar süre çalışması gerektiğini belirtir.

minReadySeconds parametresi, saniye cinsinden bir değer alır. Örneğin, minReadySeconds: 30 değeri verildiyse, yeni başlatılan bir Pod'un en az 30 saniye boyunca Ready halde olması beklenir.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-app-container
          image: my-app-image:latest
          ports:
            - containerPort: 8080
          readinessProbe:
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 10
            periodSeconds: 5
          # minReadySeconds parametresi burada tanımlanır
          minReadySeconds: 30
💡
minReadySeconds kullanmadan yalnızca readiness probe tanımlarsanız, readiness probe ilk kez çalışıp başarılı olduğunda yeni bölmeler hemen kullanılabilir olarak kabul edilir ve sıradaki Pod'lar oluşturulmaya devam edilir. Fakat readiness probe kısa bir süre sonra başarısız olmaya başlarsa, hatalı sürüm tüm Pod'lara dağıtılmış olur. Bu nedenle, minReadySeconds'u uygun şekilde ayarlamalısınız.

Eğer bir pod minReadySeconds süresi kadar Ready kalamazsa güncelleme devam edemeyecektir. Çünkü sıradaki Pod'lar oluşturulmayacaktır. Böyle bir durumda kubectl rollout undo deployment komutu ile güncellemeyi rollback edebilirsiniz.

Son olarak ise rollout işlemi bu ve benzeri sorunlar sebebiyle eğer askıda kalırsa, ProgressDeadlineExceeded (.spec.progressDeadlineSeconds) parametresi ile belirli bir süre sonra Failed durumuna geçmesi sağlanabilir. Varsayılan değeri ise 600sn yani 10dk dır.

$ kubectl describe deploy nginx-deployment
Name: nginx-deployment
...
Conditions:
 Type Status Reason
 ---- ------ ------
 Available True MinimumReplicasAvailable
 Progressing False ProgressDeadlineExceeded

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

Kubernetes StatefulSet Nedir?
Kubernetes StatefulSet, Pod’ların benzersiz isimlendirme ve ağ kimlikleriyle durumlarını korur.