Kubectl Apply Komutunun Perde Arkası: Kaynak Yönetimi ve Senkronizasyon
Kubernetes dünyasında kaynakları yönetmek, deklaratif (declarative) yaklaşımla mümkündür ve kubectl apply komutu bu yaklaşımın kalbinde yer alır. Ancak bu basit görünen komutun perde arkasında neler döndüğünü hiç merak ettiniz mi? Bu makalede, kubectl apply‘ın nasıl çalıştığını, istemci taraflı (client-side) ve sunucu taraflı (server-side) uygulama mekanizmalarını, karmaşık senaryolardaki davranışlarını ve en iyi uygulama yöntemlerini derinlemesine inceleyeceğiz. Amacımız, bu komutun sadece bir dosya göndermekten çok daha fazlası olduğunu, Kubernetes ortamınızda istikrarlı ve öngörülebilir bir durum yaratmak için kritik bir rol oynadığını göstermektir.
Kubernetes Kaynak Yönetimi Neden Bu Kadar Önemli?
Modern uygulama geliştirme ve dağıtım süreçlerinde, sistemlerin karmaşıklığı her geçen gün artmaktadır. Mikroservis mimarileri, bulut yerel (cloud-native) uygulamalar ve sürekli entegrasyon/sürekli dağıtım (CI/CD) boru hatları, altyapı yönetiminin de aynı hızda evrilmesini gerektirmektedir. İşte bu noktada Kubernetes gibi konteyner orkestrasyon platformları devreye girer. Kubernetes, uygulamalarınızı ölçeklenebilir, hataya dayanıklı ve yönetilebilir bir şekilde çalıştırmanıza olanak tanır. Ancak bu güç, doğru kaynak yönetimi stratejileriyle birleştiğinde gerçek potansiyeline ulaşır.
Geleneksel sunucu yönetimi yöntemlerinde, bir sunucuya SSH ile bağlanıp komutlar çalıştırmak veya yapılandırma dosyalarını manuel olarak düzenlemek yaygın bir yaklaşımdı. Ancak binlerce konteynerin ve yüzlerce mikroservisin çalıştığı dinamik bir ortamda bu yöntemler sürdürülemez hale gelir. Her bir değişikliğin manuel olarak yapılması, insan hatasına açık kapı bırakır, tutarsız yapılandırmalara yol açar ve felaket kurtarma senaryolarını kabusa çevirir. Bu nedenle, Kubernetes gibi platformlar, altyapıyı kod olarak (Infrastructure as Code – IaC) yönetme felsefesini benimser. Kaynaklarınızı YAML veya JSON formatında tanımlarsınız ve Kubernetes’e bu tanımları uygulamasını söylersiniz.
Peki, bu deklaratif yönetim yaklaşımı neden bu kadar kritik? Çünkü bu sayede sisteminizin “istenen durumunu” (desired state) açıkça belirtirsiniz. Örneğin, bir uygulamanın her zaman üç kopyasının (replica) çalışmasını, belirli bir miktarda CPU ve belleğe sahip olmasını veya belirli ağ kurallarına uymasını isteyebilirsiniz. Kubernetes, sizin belirttiğiniz bu durumu sürekli olarak gözlemler ve mevcut durum (current state) ile istenen durum arasında bir tutarsızlık olduğunda otomatik olarak düzeltici aksiyonlar alır. Bu, sisteminizin kendi kendini iyileştirmesini ve belirtilen yapılandırmaya her zaman uygun kalmasını sağlar. İşte kubectl apply komutu, bu deklaratif felsefenin Kubernetes API’sine ulaşan ana kapısıdır. Bu komut, kaynak tanımlarınızı API sunucusuna göndererek sistemin istenen duruma geçmesini tetikler ve bu süreç, düşündüğünüzden çok daha karmaşıktır.
Deklaratif Yönetim ve İstenen Durum Kavramı
kubectl apply komutunun derinliklerine inmeden önce, Kubernetes’in temelini oluşturan iki önemli kavramı anlamak şarttır: deklaratif (declarative) yönetim ve istenen durum (desired state). Bu kavramlar, Kubernetes’in “kendi kendini iyileştiren” ve “otonom” yapısının temelini oluşturur ve kubectl apply‘ın çalışma prensibini doğrudan etkiler.
Deklaratif Yönetim Nedir?
Deklaratif yönetim, bir sistemin “nasıl” bir duruma getirileceğini değil, “hangi” durumda olması gerektiğini tanımladığımız bir yaklaşımdır. Geleneksel olarak, sistemleri yönetirken imperatif (imperative) bir yaklaşım benimseriz. Örneğin, bir sunucuya bağlanır, bir paketi kurmak için apt install my-package komutunu çalıştırır, bir servisi başlatmak için systemctl start my-service yazarız. Bu, adım adım talimatlar vererek bir sonuca ulaşmaya çalışmaktır. Imperatif yaklaşımlar, küçük ve basit sistemlerde iyi çalışsa da, büyük ve karmaşık dağıtık sistemlerde hızla yönetilemez hale gelir.
Deklaratif yönetimde ise, sistemin son durumunu (örneğin, “bir web uygulamasından 3 adet çalışsın”, “bu uygulama 80 portundan erişilebilir olsun”) bir yapılandırma dosyası (genellikle YAML veya JSON) aracılığıyla belirtiriz. Kubernetes gibi bir sistem, bu yapılandırma dosyasını okur ve bu istenen duruma ulaşmak için gerekli tüm adımları kendi başına atar. Bu yaklaşım, insan hatasını en aza indirir, tekrarlanabilirliği artırır ve sistemin öngörülebilirliğini sağlar. kubectl apply, işte bu deklaratif yapılandırma dosyalarını Kubernetes kümesine iletmek için kullanılan birincil araçtır.
İstenen Durum (Desired State) Nedir?
İstenen durum, Kubernetes’e sağladığınız YAML veya JSON manifest dosyalarında tanımladığınız, kümedeki kaynakların (Pod’lar, Deployment’lar, Service’ler vb.) ideal yapılandırmasıdır. Örneğin, aşağıdaki basit bir Deployment manifestosu, bir Nginx uygulamasının istenen durumunu tanımlar:
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
resources:
limits:
cpu: "100m"
memory: "128Mi"
requests:
cpu: "50m"
memory: "64Mi"
Bu manifestoda, Kubernetes’e şunları söylüyoruz:
nginx-deploymentadında bir Deployment kaynağı oluştur.- Bu Deployment’ın 3 adet kopyası (
replicas: 3) her zaman çalışır durumda olsun. - Her bir kopya (Pod),
nginx:1.14.2imajını kullanan bir Nginx konteyneri içersin. - Konteynerin 80 portunu aç.
- Her Pod’a belirli CPU ve bellek kaynakları tahsis et.
Siz bu manifestoyu kubectl apply -f nginx-deployment.yaml ile uyguladığınızda, Kubernetes API Sunucusu bu istenen durumu alır. Ardından, Kubernetes kontrol düzlemi (control plane) içindeki denetleyiciler (controllers), kümenin mevcut durumunu sürekli olarak bu istenen durumla karşılaştırır. Eğer mevcut durumda 3 Nginx Pod’u çalışmıyorsa (örneğin, biri çökmüşse veya hiç oluşturulmamışsa), denetleyici yeni Pod’lar oluşturarak veya mevcutları düzelterek istenen duruma ulaşmayı hedefler. Bu sürekli senkronizasyon ve kendi kendini düzeltme mekanizması, Kubernetes’i modern altyapı yönetiminde vazgeçilmez kılar. kubectl apply‘ın görevi, bu istenen durumu Kubernetes’e doğru ve güvenli bir şekilde bildirmektir.
kubectl apply Nasıl Çalışır? İstemci Taraflı Uygulama (Client-Side Apply)
kubectl apply komutunun temel çalışma prensibi, bir YAML veya JSON dosyasında tanımlanan istenen durumu Kubernetes kümesine iletmektir. Ancak bu süreç, basit bir dosya kopyalamadan çok daha karmaşıktır. Özellikle Kubernetes’in ilk zamanlarından beri kullanılan istemci taraflı uygulama (Client-Side Apply) mekanizması, kaynakların güncellenmesi sırasında üç yönlü bir birleştirme (three-way merge) stratejisi kullanır. Bu strateji, birden fazla kullanıcının veya sürecin aynı kaynağı eş zamanlı olarak güncellemeye çalışması durumunda ortaya çıkabilecek sorunları yönetmek için geliştirilmiştir.
Üç Yönlü Birleştirme (Three-Way Merge) Mekanizması
İstemci taraflı uygulama, bir kaynağı güncellerken üç farklı bilgi parçasını dikkate alır:
- Canlı Durum (Live State): Kubernetes kümesinde o anki kaynağın mevcut durumu. Bu, API sunucusundan sorgulanarak elde edilir.
- Son Uygulanan Yapılandırma (Last-Applied-Configuration): Bir önceki
kubectl applyişlemi sırasında kullanılan yapılandırma. Bu bilgi, kaynağınmetadata.annotationsalanındakubectl.kubernetes.io/last-applied-configurationanahtarı altında saklanır. Bu,kubectl apply‘ın hangi alanları daha önce yönettiğini hatırlamasını sağlar. - Yeni Yapılandırma (New Configuration): Sizin
kubectl apply -f my-resource.yamlkomutuyla sağlamış olduğunuz YAML veya JSON dosyası. Bu, kaynağın ulaşmasını istediğiniz en güncel durumdur.
kubectl apply komutu çalıştırıldığında, aşağıdaki adımlar izlenir:
- Manifest Dosyasını Oku:
kubectlistemcisi, belirttiğiniz YAML/JSON dosyasını okur ve yeni yapılandırmayı belleğine alır. - Canlı Durumu Al:
kubectl, Kubernetes API sunucusuna bir GET isteği göndererek güncellenmek istenen kaynağın mevcut durumunu (canlı durumu) alır. - Son Uygulanan Yapılandırmayı Al:
kubectl, canlı durumdanmetadata.annotations["kubectl.kubernetes.io/last-applied-configuration"]alanındaki değeri çıkarır. Bu, daha öncekubectl applytarafından uygulanan yapılandırmadır. Eğer bu annotation yoksa, kaynak ilk kez uygulanıyor demektir. - Farkı Hesapla ve Birleştir: İşte sihirli kısım burada gerçekleşir.
kubectlistemcisi, yeni yapılandırma, canlı durum ve son uygulanan yapılandırma arasındaki farkı (diff) hesaplar. Bu üç bilgiyi kullanarak, bir “birleştirme yaması” (merge patch) oluşturur. Bu yama, canlı durumun nasıl güncellenmesi gerektiğini belirtir. Örneğin, eğer yeni yapılandırmada bir alan eklenmişse ve bu alan son uygulanan yapılandırmada yoksa, yama bu alanı ekler. Eğer bir alan son uygulanan yapılandırmada olup yeni yapılandırmada yoksa, yama bu alanı canlı durumdan kaldırır. Eğer bir alan hem son uygulanan hem de yeni yapılandırmada varsa ve değeri değişmişse, yama yeni değeri uygular. - PATCH İsteğini Gönder: Oluşturulan birleştirme yaması, Kubernetes API sunucusuna bir HTTP PATCH isteği olarak gönderilir. Bu istek, kaynağın sadece değişen alanlarını günceller.
- Güncelle ve Annotation Ekle: API sunucusu, PATCH isteğini işler ve kaynağı günceller. Ayrıca, güncellenen kaynağın
metadata.annotationsalanına, o anki yeni yapılandırmanın bir kopyasınıkubectl.kubernetes.io/last-applied-configurationolarak ekler. Bu, bir sonrakikubectl applyişlemi için referans noktası olacaktır.
Örnek Senaryo ve Sorunlar
Diyelim ki bir Deployment kaynağınız var. İlk olarak, bir geliştirici aşağıdaki YAML dosyasını uygular:
# deploy-v1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
template:
spec:
containers:
- name: my-container
image: my-image:v1
resources:
limits:
cpu: "100m"
kubectl apply -f deploy-v1.yaml komutu çalıştırılır. Kaynak oluşturulur ve last-applied-configuration annotation’ı eklenir.
Şimdi, bir operasyon mühendisi, bu Deployment’ın CPU limitini artırmak ister ve aynı anda Pod’ların kaynaklarını da günceller. Ancak, deploy-v1.yaml dosyasında sadece CPU limiti vardır. Operasyon mühendisi, kubectl edit deployment my-app komutunu kullanarak doğrudan kümedeki canlı kaynağı düzenler ve bellek limitini de ekler:
# Canlı durumdaki değişiklik (kubectl edit ile yapıldı)
# ...
resources:
limits:
cpu: "200m"
memory: "256Mi" # Yeni eklenen alan
# ...
Daha sonra, geliştirici, kendi deploy-v1.yaml dosyasını (içinde sadece CPU limiti olanı) tekrar kubectl apply -f deploy-v1.yaml ile uygulamak ister. Bu durumda:
- Yeni Yapılandırma:
deploy-v1.yaml(CPU: 100m) - Canlı Durum: (CPU: 200m, Memory: 256Mi)
- Son Uygulanan Yapılandırma: (CPU: 100m)
kubectl apply, üç yönlü birleştirmeyi yaparak, CPU limitini tekrar 100m’ye çekecek, çünkü bu, geliştiricinin dosyasında belirtilen ve daha önce kendisi tarafından uygulanan değerdir. Ancak, operasyon mühendisinin eklediği memory: 256Mi alanı, geliştiricinin manifest dosyasında hiç geçmediği ve last-applied-configuration içinde de olmadığı için, kubectl apply bu alanı dokunmadan bırakır. Bu durum, istemci taraflı uygulamanın “sahip olmadığı” alanlara dokunmama prensibinden kaynaklanır.
Bu mekanizma, basit senaryolarda işe yarasa da, özellikle birden fazla ekibin aynı kaynağın farklı alanlarını yönettiği veya otomasyon araçlarının devreye girdiği karmaşık ortamlarda sorunlara yol açabilir. Örneğin, bir kullanıcının manuel olarak yaptığı bir değişikliğin, başka bir kubectl apply işlemi tarafından beklenmedik bir şekilde silinmesi veya çakışmaların fark edilmemesi gibi durumlar ortaya çıkabilir. İşte bu tür sorunları çözmek için Server-Side Apply (Sunucu Taraflı Uygulama) geliştirilmiştir.
Server-Side Apply (SSA): Yeni Nesil Yaklaşım ve Alan Sahipliği
İstemci taraflı uygulamanın (Client-Side Apply) getirdiği karmaşıklıklar ve özellikle eş zamanlı güncellemelerde ortaya çıkan sorunlar, Kubernetes topluluğunu daha sağlam ve öngörülebilir bir mekanizma aramaya itti. Bu arayışın sonucunda ortaya çıkan Server-Side Apply (SSA), kubectl apply komutunun çalışma şeklini kökten değiştiren ve Kubernetes kaynak yönetiminde yeni bir dönemi başlatan bir yaklaşımdır. SSA, özellikle çok kullanıcılı ve çok araçlı ortamlarda kaynak yönetimini basitleştirmeyi ve çakışmaları daha etkin bir şekilde ele almayı hedefler.
Neden Server-Side Apply?
Client-Side Apply’ın temel zorlukları şunlardı:
last-applied-configurationAnnotation’ının Yükü: Her kaynakta bu annotation’ın tutulması, kaynağın boyutunu artırır ve API sunucusunda ek yük oluşturur. Ayrıca, bu annotation’ın manuel olarak silinmesi veya bozulması durumunda beklenmedik davranışlar ortaya çıkabilir.- Çakışma Yönetimi: Client-Side Apply, çakışmaları tam olarak çözmez, sadece birleştirme yapar. İki farklı istemci aynı alan üzerinde farklı değerler belirtirse, son uygulayan kazanır veya karmaşık durumlarda beklenmedik sonuçlar doğabilir.
- Alan Sahipliği Eksikliği: Hangi kullanıcının veya aracın kaynağın hangi alanından sorumlu olduğunu takip etmek zordur. Bu durum, bir ekip tarafından yapılan değişikliğin diğer bir ekip tarafından farkında olmadan üzerine yazılmasına neden olabilir.
Server-Side Apply, bu sorunlara çözüm getirmek için geliştirilmiştir. Temel fikri, birleştirme mantığını istemciden (kubectl) alıp doğrudan Kubernetes API sunucusuna taşımaktır. Bu sayede, API sunucusu, kaynakların güncellenmesi sırasında daha akıllı kararlar alabilir ve alan sahipliğini (field ownership) takip edebilir.
Server-Side Apply Nasıl Çalışır?
SSA’nın anahtar kavramı “alan sahipliği”dir. Her kaynak alanı (örneğin, spec.replicas, spec.template.spec.containers[0].image), onu en son güncelleyen “yönetici” (field manager) tarafından sahip olunur. Bir yönetici, bir alanın değerini değiştirdiğinde, o alanın sahibi olur. Eğer başka bir yönetici aynı alanın değerini değiştirmeye çalışırsa, bir çakışma (conflict) oluşur ve API sunucusu bu durumu bildirir.
SSA’nın çalışma adımları şunlardır:
- Manifest Dosyasını Gönder:
kubectl apply --server-side -f my-resource.yamlkomutuyla, istemci manifest dosyasını doğrudan Kubernetes API sunucusuna gönderir. İstemci, bu noktada canlı durumu veya son uygulanan yapılandırmayı çekmez. - API Sunucusu İşler: API sunucusu, gelen manifesti alır ve aşağıdaki adımları uygular:
- Alan Sahipliğini Belirle: API sunucusu, manifestte belirtilen her alan için, bu alanın mevcut sahibini (eğer varsa) ve yeni sahibini (
--field-managerparametresiyle belirtilen veya varsayılan olarakkubectlolan) kontrol eder. - Birleştirme ve Çakışma Tespiti: API sunucusu, yeni yapılandırmayı canlı durumla birleştirmeye çalışır. Eğer bir alanın yeni değeri, canlı durumdaki değerden farklıysa ve bu alanın sahibi başka bir yönetici ise, bir çakışma oluşur.
- Çakışma Yönetimi:
- Eğer çakışan alanın sahibi siz değilseniz ve
--force-conflicts(kısaca-f) bayrağını kullanmadıysanız, API sunucusu bir hata döndürür ve işlemi reddeder. Bu, yanlışlıkla başkasının yaptığı değişikliklerin üzerine yazılmasını engeller. - Eğer
--force-conflictsbayrağını kullanırsanız, API sunucusu çakışan alanın sahipliğini sizden yana değiştirir ve değeri günceller. Bu, “ben bu alanı yönetmek istiyorum, diğerlerinin değişikliklerini geçersiz sayıyorum” demektir. - Eğer çakışan alanın sahibi sizseniz veya alanın hiç sahibi yoksa, güncelleme sorunsuz bir şekilde gerçekleşir ve o alanın sahibi siz olursunuz.
- Eğer çakışan alanın sahibi siz değilseniz ve
- Alan Sahipliğini Belirle: API sunucusu, manifestte belirtilen her alan için, bu alanın mevcut sahibini (eğer varsa) ve yeni sahibini (
- Kaynak Durumunu Güncelle: Başarılı bir birleştirmenin ardından, API sunucusu kaynağı günceller ve her alan için hangi yöneticinin (field manager) ona sahip olduğunu kaydeden özel bir yapılandırma (
managedFields) ekler. Bu,last-applied-configurationannotation’ının yerini alır.
ManagedFields Örneği
Bir kaynağın managedFields bölümü, kimin hangi alanları yönettiğini gösterir. Örneğin, bir Deployment’ın managedFields çıktısı şöyle görünebilir:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
managedFields:
- apiVersion: apps/v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:labels:
f:app: {}
f:spec:
f:replicas: {}
f:selector: {}
f:template:
f:metadata:
f:labels:
f:app: {}
f:spec:
f:containers:
k:{"name":"my-container"}:
f:image: {}
f:name: {}
f:resources:
f:limits:
f:cpu: {}
manager: kubectl
operation: Apply
time: "2023-10-26T10:00:00Z"
- apiVersion: apps/v1
fieldsType: FieldsV1
fieldsV1:
f:spec:
f:template:
f:spec:
f:containers:
k:{"name":"my-container"}:
f:resources:
f:limits:
f:memory: {}
manager: my-ops-tool
operation: Apply
time: "2023-10-26T10:05:00Z"
Yukarıdaki örnekte, kubectl yöneticisi spec.replicas ve spec.template.spec.containers[0].image gibi alanlara sahipken, my-ops-tool adlı başka bir yönetici spec.template.spec.containers[0].resources.limits.memory alanına sahiptir. Bu, farklı araçların veya ekiplerin aynı kaynağın farklı yönlerini güvenli bir şekilde yönetebilmesini sağlar.
Server-Side Apply, özellikle GitOps yaklaşımlarında ve birden fazla otomasyon aracının (Helm, Argo CD, Flux CD vb.) aynı kümeyi yönettiği senaryolarda çok daha sağlam ve tercih edilen bir yöntem haline gelmiştir. Çakışmaların API sunucusu tarafında yönetilmesi, tutarlılığı artırır ve beklenmedik davranışları en aza indirir.
Vaka Analizi: Çoklu Ekip Ortamında Kaynak Yönetimi Sorunları ve Çözümleri
Kubernetes’in benimsenmesiyle birlikte, büyük kuruluşlar genellikle birden fazla geliştirme ekibinin, operasyon ekibinin ve güvenlik ekibinin aynı Kubernetes kümesi üzerinde çalıştığı senaryolarla karşılaşır. Bu durum, kaynak yönetimini karmaşıklaştırır ve özellikle istemci taraflı uygulama (Client-Side Apply) kullanıldığında çeşitli sorunlara yol açabilir. Bu vaka analizinde, bu sorunları ve Server-Side Apply (SSA) ile nasıl çözülebileceklerini inceleyeceğiz.
Senaryo: “Uygulama A” Deployment’ının Karmaşık Yönetimi
Bir e-ticaret şirketi olan “HızlıTeslimat A.Ş.”de, “Uygulama A” adında kritik bir mikroservis bulunmaktadır. Bu uygulamanın Kubernetes Deployment’ı üç farklı ekip tarafından yönetilmektedir:
- Geliştirme Ekibi (DevTeam): Uygulamanın Docker imaj sürümünü ve Pod’ların genel yapılandırmasını (çevre değişkenleri gibi) yönetir.
- Operasyon Ekibi (OpsTeam): Pod’ların replika sayısını (ölçeklendirme), kaynak limitlerini (CPU/Bellek) ve Pod dağıtım stratejilerini (nodeSelector gibi) yönetir.
- Güvenlik Ekibi (SecTeam): Uygulamanın güvenlik bağlamını (SecurityContext) ve ağ politikalarını (NetworkPolicy) yönetir.
Client-Side Apply ile Ortaya Çıkan Sorunlar
Her ekip, kendi YAML dosyalarını kubectl apply ile uyguladığında aşağıdaki sorunlar ortaya çıkmıştır:
- Beklenmedik Üzerine Yazmalar:
DevTeam,
nginx:1.20imajınınginx:1.21olarak güncellemek için kendideployment.yamldosyasını uygular. Bir süre sonra, OpsTeam, uygulamanın yoğunluğunu azaltmak için replika sayısını 3’ten 5’e çıkarmak amacıyla kendideployment.yamldosyasını uygular. Ancak, OpsTeam’in dosyası eski bir imaj sürümünü (nginx:1.20) içerebilir, çünkü DevTeam’in yaptığı değişiklikten habersizdir. Sonuç olarak, OpsTeam’inkubectl applyişlemi, replika sayısını güncellerken, imaj sürümünü tekrar eski haline (nginx:1.20) döndürebilir. Bu durum, DevTeam’in yaptığı değişikliğin üzerine yazılmasına ve uygulamanın beklenmedik bir şekilde eski bir sürüme dönmesine neden olur. last-applied-configurationÇakışmaları ve Bozulmalar:DevTeam, kendi
deployment.yamldosyasını uyguladığında, kaynağınlast-applied-configurationannotation’ı DevTeam’in dosyasının içeriğiyle güncellenir. OpsTeam aynı kaynağa kendideployment.yamldosyasını uyguladığında, bu annotation OpsTeam’in dosyasının içeriğiyle güncellenir. Bu, herkubectl applyişlemiyle annotation’ın sürekli değişmesi anlamına gelir. Eğer bir ekip,kubectl editile manuel bir değişiklik yaparsa,last-applied-configurationannotation’ı güncellenmez ve sonrakikubectl applyişlemi sırasında bu manuel değişiklikler beklenmedik bir şekilde silinebilir.- Manuel Müdahalelerin Kaybolması:
SecTeam, acil bir güvenlik açığını kapatmak için bir Deployment’a
securityContexteklemek üzerekubectl edit deployment my-appkomutunu kullanır. Bu değişiklik doğrudan kümede yapılır. Birkaç gün sonra, DevTeam veya OpsTeam, kendi versiyonlarındakideployment.yamldosyasınıkubectl applyile uyguladığında, bu dosyalarsecurityContextalanını içermediği için, üç yönlü birleştirme sırasında bu alanlast-applied-configuration‘da da yer almadığından, canlı durumdan silinebilir. Bu durum, güvenlik açığının tekrar ortaya çıkmasına neden olur.
Server-Side Apply (SSA) ile Çözümler
HızlıTeslimat A.Ş., bu sorunları aşmak için Server-Side Apply’a geçmeye karar verir. Her ekip, kendi kubectl apply --server-side --field-manager= komutunu kullanır.
- Alan Sahipliği ile Çakışma Önleme:
- DevTeam, imaj sürümünü güncellerken
--field-manager=DevTeamkullanır. Böylecespec.template.spec.containers[0].imagealanının sahibi DevTeam olur. - OpsTeam, replika sayısını güncellerken
--field-manager=OpsTeamkullanır. Böylecespec.replicasalanının sahibi OpsTeam olur. - SecTeam,
securityContexteklerken--field-manager=SecTeamkullanır. Böylecespec.template.spec.securityContextalanının sahibi SecTeam olur.
Şimdi, eğer OpsTeam yanlışlıkla kendi
deployment.yamldosyasında eski bir imaj sürümü belirtirse ve--field-manager=OpsTeamile uygulamaya çalışırsa, API sunucusu bir çakışma tespit eder. Çünküspec.template.spec.containers[0].imagealanının sahibi DevTeam’dir. API sunucusu, OpsTeam’e bir hata mesajı döndürür ve işlemi reddeder. OpsTeam, bu hatayı görerek DevTeam ile iletişime geçebilir veya--force-conflictsbayrağını kullanarak DevTeam’in sahipliğini zorla alabilir (bu genellikle dikkatli kullanılması gereken bir seçenektir). - DevTeam, imaj sürümünü güncellerken
- Temiz ve Güvenilir Yönetim:
last-applied-configurationannotation’ının artık kullanılmasına gerek kalmaz. Her alanın sahibimanagedFieldsbölümünde açıkça belirtildiği için, hangi ekibin hangi alandan sorumlu olduğu kolayca anlaşılır. Bu, hata ayıklamayı ve sorumluluk takibini basitleştirir. - Manuel Değişikliklerin Korunması (İstenirse):
Eğer SecTeam, acil bir durumda
kubectl editile bir değişiklik yaparsa, bu değişiklik varsayılan olarakkubectl-editadında bir yönetici tarafından yapılmış gibi kaydedilir. Diğer ekiplerkubectl apply --server-sidekullandığında, SecTeam’in yaptığı değişiklikler, eğer diğer ekiplerin manifest dosyalarında bu alanlar belirtilmemişse, üzerine yazılmaz. Eğer diğer ekipler bu alanları kendi manifestolarına ekler ve--force-conflictskullanmazsa, API sunucusu çakışma hatası verir ve SecTeam’in yaptığı değişikliği korur. Bu, manuel müdahalelerin yanlışlıkla kaybolmasını büyük ölçüde engeller.
Sonuç olarak, Server-Side Apply, HızlıTeslimat A.Ş.’nin çoklu ekip ortamında Kubernetes kaynaklarını daha güvenli, tutarlı ve öngörülebilir bir şekilde yönetmesini sağlamıştır. Ekipler arasındaki çakışmalar azalmış, hata ayıklama kolaylaşmış ve operasyonel verimlilik artmıştır.
Yaygın Hatalar ve Çözümleri
kubectl apply komutu güçlü olsa da, yanlış kullanıldığında veya beklenmedik durumlarla karşılaşıldığında çeşitli hatalara yol açabilir. Bu bölümde, sık karşılaşılan bazı hataları ve bunların olası çözümlerini inceleyeceğiz.
-
Hata: “The request is invalid: patch: Invalid value: “null”: field is immutable”
Açıklama: Bazı Kubernetes kaynak alanları, bir kere ayarlandıktan sonra değiştirilemez (immutable) özelliktedir. Örneğin, bir Pod’un konteyner adı veya bir Service’in tipi (ClusterIP, NodePort, LoadBalancer) bazen değiştirilemez olabilir. Bu hatayı genellikle, mevcut bir kaynağın immutable bir alanını değiştirmeye çalıştığınızda alırsınız.
Çözüm: Immutable alanları değiştirmek için genellikle kaynağı silip yeniden oluşturmanız gerekir. Ancak bu, uygulamanızda kesintiye yol açabilir. Kesintisiz bir güncelleme için, yeni yapılandırmayı farklı bir isimle oluşturup, trafiği yavaş yavaş yeni kaynağa yönlendirebilirsiniz (mavi/yeşil dağıtım veya canary dağıtım stratejileri). Eğer Pod’un konteyner adını değiştirmeye çalışıyorsanız, Deployment’ı silip yeniden oluşturmanız gerekecektir. Bir Service’in tipini değiştirmek istiyorsanız, Service’i silip yeni tip ile tekrar oluşturmanız gerekebilir.
-
Hata: “Error from server (Conflict): conflicts with other field managers” (Server-Side Apply kullanırken)
Açıklama: Server-Side Apply (SSA) kullanırken, bir alanın sahipliği başka bir yöneticiye (field manager) aitken o alanı değiştirmeye çalıştığınızda bu hatayı alırsınız. SSA, çakışmaları önlemek ve alan sahipliğini korumak için tasarlanmıştır.
Çözüm:
--force-conflictsKullanımı: Eğer bu alanı gerçekten siz yönetmek istiyorsanız ve diğer yöneticinin değişikliklerini geçersiz kılmaya hazırsanız,kubectl apply --server-side --force-conflicts -f my-resource.yamlkomutunu kullanabilirsiniz. Ancak bu, dikkatli kullanılması gereken bir seçenektir, çünkü başkasının değişikliklerini zorla üzerine yazarsınız.- İletişim Kurma: En iyi çözüm, çakışan alanı yöneten ekiple iletişime geçmektir. Belki de onların yapılandırmalarını kendi manifest dosyanıza dahil etmeniz veya sorumlulukları netleştirmeniz gerekiyordur.
--field-managerBelirtme: Her ekibin veya aracın kendi--field-manageradını belirtmesi, çakışmaları daha şeffaf hale getirir ve kimin hangi alandan sorumlu olduğunu kolayca görmeyi sağlar.
-
Hata: “Error from server (NotFound): deployments.apps “my-app” not found”
Açıklama: Belirtilen isimde ve türde bir kaynağın Kubernetes kümesinde bulunamadığını gösterir. Bu genellikle yanlış kaynak adı, yanlış ad alanı (namespace) veya kaynağın henüz oluşturulmamış olması nedeniyle oluşur.
Çözüm:
- Kaynak Adını Kontrol Edin: Manifest dosyanızdaki
metadata.nameilekubectlkomutunda kullandığınız adın eşleştiğinden emin olun. - Ad Alanını Kontrol Edin: Kaynağın doğru ad alanında (namespace) olduğunu doğrulayın. Eğer kaynak farklı bir ad alanındaysa,
-n <namespace_adı>bayrağını kullanmanız gerekir. Örneğin:kubectl apply -f my-resource.yaml -n production. - Kaynak Türünü Kontrol Edin:
kindalanının doğru yazıldığından emin olun (örneğin,DeploymentyerineDeploymentsyazmak gibi yazım hataları).
- Kaynak Adını Kontrol Edin: Manifest dosyanızdaki
-
Hata: “Error from server (Forbidden): deployments.apps “my-app” is forbidden: User “…” cannot patch resource “deployments” in API group “apps” in the namespace “…”
Açıklama: Bu hata, Kubernetes Role-Based Access Control (RBAC) kuralları nedeniyle kullanıcının veya hizmet hesabının (service account) belirtilen işlemi (bu durumda “patch” yani güncelleme) yapmaya yetkisinin olmadığını gösterir.
Çözüm:
- RBAC İzinlerini Kontrol Edin: Kullanıcının veya hizmet hesabının ilgili ad alanında ve kaynak türünde “patch” (veya “update”) iznine sahip olduğundan emin olun. Gerekirse, bir ClusterRole veya Role tanımlayarak ve bunu bir ClusterRoleBinding veya RoleBinding ile kullanıcıya/hizmet hesabına bağlayarak izinleri genişletmeniz gerekebilir.
- Doğru Kimlik Bilgilerini Kullanın: Doğru Kubernetes bağlamını (context) ve kimlik bilgilerini kullandığınızdan emin olun.
kubectl config current-contextkomutuyla mevcut bağlamı kontrol edebilirsiniz.
-
Hata: “The Deployment “my-app” is invalid: spec.selector: Required value:
selectoris immutable after creation”Açıklama: Bir Deployment’ın
spec.selectoralanı, Deployment oluşturulduktan sonra değiştirilemez. Bu alan, Deployment’ın hangi Pod’ları yöneteceğini belirler ve değiştirilmesi tutarsızlıklara yol açabilir.Çözüm: Eğer
spec.selector‘ı değiştirmeniz gerekiyorsa, mevcut Deployment’ı silmeniz ve yeniselectordeğeriyle yeniden oluşturmanız gerekir. Bu da yukarıda bahsedildiği gibi kesintiye neden olabilir ve dikkatli bir planlama gerektirir.
Bu hataları anlamak ve doğru çözümleri uygulamak, Kubernetes ortamınızda sorunsuz bir kaynak yönetimi deneyimi için kritik öneme sahiptir. Genellikle, hata mesajları sorunun kökeni hakkında değerli ipuçları sağlar ve bunları dikkatlice okumak, çözüm yolunu bulmada size yardımcı olacaktır.
İleri Düzey İpuçları ve En İyi Uygulamalar
kubectl apply komutunu daha verimli ve güvenli kullanmak için bazı ileri düzey ipuçları ve en iyi uygulamalar mevcuttur. Bu yöntemler, özellikle büyük ve karmaşık Kubernetes ortamlarında kaynak yönetimini kolaylaştırır ve hata potansiyelini azaltır.
1. Idempotency (Tekrar Edilebilirlik) Prensibi
kubectl apply‘ın en temel ve önemli özelliklerinden biri idempotency’dir. Bir işlemi birden fazla kez tekrarladığınızda, sistemin durumu her zaman aynı sonuca ulaşmalıdır. Yani, aynı YAML dosyasını kubectl apply ile defalarca uygulasanız bile, kaynaklar zaten istenen durumdaysa herhangi bir değişiklik yapılmamalıdır. Bu, CI/CD boru hatlarında ve otomasyon senaryolarında kritik öneme sahiptir. Kaynaklarınızı tasarlarken bu prensibi göz önünde bulundurun; yani her kubectl apply işlemi, kaynağı her zaman belirttiğiniz duruma getirebilmelidir.
2. Kustomize veya Helm ile Kullanım
Tek bir kubectl apply komutu basit senaryolar için yeterli olsa da, gerçek dünya uygulamaları genellikle birden fazla YAML dosyasını ve çevreye özgü (dev, test, prod) yapılandırmaları içerir. Bu noktada Kustomize veya Helm gibi araçlar devreye girer:
- Kustomize: Kubernetes’e özgü, şablonlama (templating) yerine “yama” (patch) tabanlı bir yapılandırma yönetimi aracıdır. Temel YAML dosyalarınızı tanımlar ve farklı ortamlar için üzerine yamalar uygulayarak değişiklikler yapmanızı sağlar. Kustomize, sonunda yine standart Kubernetes YAML çıktıları üretir ve bunları
kubectl apply -k <kustomize_dizini>komutuyla uygulayabilirsiniz. Bu,kubectl apply‘ın gücünü korurken, yapılandırma çeşitliliğini yönetmenizi sağlar. - Helm: Kubernetes için bir paket yöneticisidir. Uygulamaları “chart” adı verilen önceden paketlenmiş ve yapılandırılabilir şablonlar aracılığıyla dağıtmanızı sağlar. Helm, değerleri (values) kullanarak chart’ları özelleştirmenize olanak tanır ve temelde Kubernetes manifest dosyaları üretip bunları API sunucusuna gönderir. Helm’in kendi
helm upgradekomutu, arka plandakubectl applybenzeri mekanizmalar kullanır ve Server-Side Apply ile de entegre çalışabilir.
3. GitOps Prensip ve Uygulamaları
GitOps, Kubernetes kaynak yönetiminde modern bir yaklaşımdır. Temel olarak, tüm uygulama ve altyapı yapılandırmalarınızı bir Git deposunda (repository) tutmayı ve bu depoyu sisteminizin “tek doğruluk kaynağı” (single source of truth) olarak kullanmayı savunur. Değişiklikler Git’e commit edildiğinde, otomasyon araçları (Flux CD, Argo CD gibi) bu değişiklikleri algılar ve otomatik olarak Kubernetes kümenize uygular. Bu yaklaşım, kubectl apply‘ın deklaratif doğasını en üst düzeyde kullanır ve aşağıdaki faydaları sağlar:
- Versiyon Kontrolü: Tüm değişikliklerin geçmişi Git’te tutulur.
- Denetlenebilirlik: Kimin ne zaman hangi değişikliği yaptığını kolayca takip edebilirsiniz.
- Geri Alma Kolaylığı: Hatalı bir dağıtım durumunda, Git’teki önceki bir commit’e geri dönmek, kümenin durumunu da o commit’teki yapılandırmaya döndürür.
- Otomasyon: Manuel müdahaleler azalır, CI/CD boru hatları ile entegrasyon kolaylaşır.
GitOps araçları, arka planda genellikle Server-Side Apply kullanarak kaynakları günceller ve böylece çakışma yönetimini daha etkin hale getirir.
4. Dry-Run Modu ile Değişiklikleri Önizleme
Bir değişikliği uygulamadan önce ne gibi etkileri olacağını görmek, olası hataları önlemek için çok önemlidir. kubectl apply komutu, bu amaçla --dry-run bayrağını sunar:
kubectl apply --dry-run=client -f my-resource.yaml: Bu komut, istemci tarafında birleştirme işlemini yapar ve API sunucusuna herhangi bir istek göndermeden uygulanacak yamayı gösterir. Bu, syntax hatalarını veya basit mantık hatalarını yakalamak için kullanışlıdır.kubectl apply --dry-run=server -f my-resource.yaml: Bu komut, API sunucusuna bir istek gönderir ancak sunucu değişikliği kalıcı olarak kaydetmez. Sunucu, değişikliğin geçerli olup olmadığını, çakışma olup olmadığını kontrol eder ve sonucu geri döndürür. Bu, Server-Side Apply mekanizmasını test etmek ve potansiyel çakışmaları önceden görmek için daha kapsamlı bir yoldur.
5. kubectl diff Kullanımı
Bir YAML dosyasını uygulamadan önce, bu dosyanın kümedeki mevcut kaynakla arasındaki farkları görmek, beklenmedik değişiklikleri önlemek için harika bir yoldur. kubectl diff -f my-resource.yaml komutu, yerel dosyanız ile kümedeki canlı durum arasındaki tüm değişiklikleri gösterir. Bu, özellikle büyük ve karmaşık manifest dosyalarında çok değerlidir.
Bu ileri düzey ipuçları ve en iyi uygulamalar, kubectl apply komutunu sadece bir “uygulama” aracı olmaktan çıkarıp, Kubernetes ortamınızda güvenli, verimli ve ölçeklenebilir bir kaynak yönetim stratejisinin temel taşı haline getirmenize yardımcı olacaktır.
Sonuç
kubectl apply komutu, Kubernetes kaynak yönetiminin temel taşıdır ve basit bir komut olmanın ötesinde, karmaşık bir deklaratif yönetim felsefesini ve gelişmiş senkronizasyon mekanizmalarını barındırır. İstemci taraflı uygulamanın (Client-Side Apply) üç yönlü birleştirme (three-way merge) stratejisi ve last-applied-configuration annotation’ı ile nasıl çalıştığını, aynı zamanda bu yaklaşımın çoklu ekip ortamlarında yol açabileceği potansiyel sorunları detaylıca inceledik. Bu sorunlara çözüm olarak geliştirilen Server-Side Apply (SSA) ile tanıştık; alan sahipliği (field ownership) ve API sunucusu tabanlı çakışma yönetimi sayesinde kaynak yönetiminin nasıl daha güvenli, şeffaf ve öngörülebilir hale geldiğini gördük.
Gerçek dünya senaryolarında, özellikle birden fazla ekibin aynı küme üzerinde çalıştığı durumlarda, SSA’nın sunduğu avantajlar yadsınamaz. Kaynaklarınızı Kustomize veya Helm gibi araçlarla yönetmek, GitOps prensiplerini benimsemek ve --dry-run veya kubectl diff gibi komutlarla değişiklikleri önceden kontrol etmek, operasyonel verimliliği ve sistem istikrarını önemli ölçüde artıracaktır. Unutmayın ki, Kubernetes’in gücü, sadece kaynakları dağıtmakta değil, aynı zamanda onları tutarlı ve güvenli bir şekilde yönetebilmektedir. kubectl apply‘ın derinliklerini anlamak, bu gücü tam anlamıyla kullanmanın anahtarıdır.
Sıkça Sorulan Sorular
-
kubectl applyilekubectl createveyakubectl replacearasındaki fark nedir?kubectl create, bir kaynağı yalnızca ilk kez oluşturmak için kullanılır ve kaynak zaten varsa hata verir.kubectl replace, mevcut bir kaynağı tamamen yeni bir tanımla değiştirir; bu da kaynakta tanımlanmayan tüm alanların silinmesine neden olur ve kaynağı sıfırdan oluşturmaya benzer.kubectl applyise deklaratif bir yaklaşımdır; bir kaynağı oluşturur veya günceller, ancak yalnızca belirtilen alanları değiştirir ve mevcut olmayan alanları korur. Bu,kubectl apply‘ı sürekli entegrasyon/dağıtım (CI/CD) boru hatları için daha uygun hale getirir. -
Server-Side Apply (SSA) kullanmak neden Client-Side Apply’dan daha iyidir?
SSA, özellikle çok kullanıcılı ve çok araçlı ortamlarda daha iyi bir deneyim sunar. Alan sahipliği (field ownership) kavramı sayesinde, hangi kullanıcının veya aracın kaynağın hangi alanından sorumlu olduğunu takip eder ve çakışmaları API sunucusu tarafında yönetir. Bu, yanlışlıkla üzerine yazmaları önler, hata ayıklamayı kolaylaştırır ve
last-applied-configurationannotation’ının getirdiği karmaşıklığı ortadan kaldırır. Daha tutarlı ve öngörülebilir bir kaynak yönetimi sağlar. -
--force-conflictsbayrağını ne zaman kullanmalıyım?--force-conflictsbayrağını yalnızca, bir alanın sahipliğini başka bir yöneticiden (field manager) zorla almak istediğinizden eminseniz kullanmalısınız. Bu, genellikle başka bir ekibin veya otomasyon aracının yaptığı bir değişikliği bilerek geçersiz kılmak istediğiniz durumlarda kullanılır. Ancak bu, potansiyel olarak diğer ekiplerin iş akışlarını bozabileceği için çok dikkatli ve genellikle ekip içi mutabakatla kullanılmalıdır. -
kubectl applyile yapılan değişiklikleri nasıl geri alabilirim?kubectl applyile yapılan değişiklikleri geri almanın en iyi yolu, GitOps prensiplerini takip etmektir. Eğer kaynak tanımlarınız Git’te versiyonlanıyorsa, hatalı commit’i geri alabilir (revert) ve GitOps aracınızın (Argo CD, Flux CD vb.) bu değişikliği kümenize uygulamasını sağlayabilirsiniz. Manuel olarak geri almak isterseniz, önceki bir yapılandırma dosyasınıkubectl applyile tekrar uygulayabilir veyakubectl rollout undogibi komutlarla Deployment’ların önceki revizyonlarına dönebilirsiniz. -
Server-Side Apply, tüm Kubernetes kaynak türlerini destekliyor mu?
Evet, Server-Side Apply (SSA) Kubernetes’in 1.16 sürümünden itibaren beta olarak tanıtılmış ve 1.22 sürümünden itibaren genel olarak kullanılabilir (GA) hale gelmiştir. Temel olarak tüm yerleşik (built-in) Kubernetes kaynak türleri ve çoğu özel kaynak tanımı (Custom Resource Definitions – CRD’ler) için SSA desteği bulunmaktadır. Ancak, bazı eski veya çok özel CRD’lerde tam uyumluluk için ek yapılandırmalar gerekebilir.
#Kubernetes #kubectl #DevOps #GitOps #CloudNative #ServerSideApply #KaynakYönetimi #Teknoloji