Helm 3'ten Helm 4'e: Ne Değişti, Neyi Bozar ve Helm 3 EOL Takvimi
Helm 4, Helm 3 chart'larını ve release'lerini değiştirmeden yönetir; kırılan şeyler script'ler, plugin'ler ve post-renderer'lardır, Helm 3'ün security desteği ise 10 Şubat 2027'de biter. Helm 3.22 ile Helm 4.3'ü yan yana çalıştırıp server-side apply latching'ini, iki sürüm karışınca SSA'nın nasıl geri alındığını, flag ve log değişikliklerini, post-renderer'ın plugin'e dönüşmesini, deneysel Chart v3'ü ve Helm 2 dönemi bir chart'ı gerçek çıktılarla görüyor, bir geçiş checklist'i çıkarıyoruz.
Sürüm notu: Bu yazıdaki örnekler Helm 4.3.2 ve Helm 3.22.1, kind 0.33 ile Kubernetes 1.37 ve kubectl 1.37 ile denenmiştir.
Önce Tahmin Et
Bir release'i Helm 3 ile kurdun. CI'ın Helm sürümünü 4'e yükseltiyorsun ve aynı release'i upgrade ediyorsun. Helm 4 yeni release'leri server-side apply ile kuruyor; bu eski release'i de server-side apply ile mi günceller? Ekipten biri hâlâ kendi bilgisayarındaki Helm 3 ile aynı release'e bir upgrade yaparsa, bir sonraki Helm 4 upgrade'i hangi yöntemi kullanır? Cevap server-side apply bölümünde; release Secret'ının içinden okunmuş gerçek değerlerle.
Takvim: Helm 3'ün Sonu
Helm 4.0.0, 12 Kasım 2025'te çıktı. Helm ekibi başlangıçta Helm 3 için bug fix'lerin Temmuz 2026'da, security fix'lerin Kasım 2026'da biteceğini duyurmuştu. Haziran 2026'daki EOL (End of Life; bir sürümün destek alamaz hâle gelmesi) duyurusuyla takvim uzatıldı:
| Tarih | Olay |
|---|---|
| 12 Kasım 2025 | Helm 4.0.0 yayımlandı |
| 9 Eylül 2026 | Helm 3'ün son, sınırlı feature release'i olarak planlandı (GitHub'da 3.22.0, 10 Eylül tarihli); aynı hafta Helm 4.3.0 çıktı |
| 9 Eylül 2026'ya kadar | Helm 3'e bug fix |
| 15 Ekim 2026 | 3.22.1 patch sürümü (aynı gün 4.3.1) |
| 10 Şubat 2027 | Helm 3'e security fix'lerin sonu; bu tarihten sonra Helm 3 için hiçbir sürüm çıkmayacak |
3.22, yeni Kubernetes sürümleri için client kütüphanesi güncellemesinden ibaret; Helm 3'e yeni özellik gelmiyor. Şubat 2027'den sonra Helm 3, yeni çıkan Kubernetes sürümlerine karşı test edilmeyecek ve bir güvenlik açığı bulunsa da düzeltilmeyecek. Bu yazının yazıldığı gün güncel Helm 4 sürümü 4.3.2 (13 Kasım 2026).
Neler Değişti
Helm ekibinin hedefi, Helm 3 ile kurulabilen chart'ların Helm 4 ile de kurulabilmesi ve Helm 3 release'lerinin geçiş adımı olmadan Helm 4 ile yönetilebilmesiydi; bu serideki denemelerde de chart'lar değişmeden çalıştı. Kırılan şeyler çoğunlukla chart'ların etrafında: CI script'leri, plugin'ler, SDK kullanan araçlar. Kısa liste:
- Server-side apply: yeni release'ler için varsayılan, mevcut release'ler önceki yöntemde kalır.
- kstatus ile bekleme:
--waitbir strateji alıyor (watcher,hookOnly,legacy), bayrak yoksa yalnızca hook'lar bekleniyor. - Yeni plugin sistemi:
plugin.yaml'daapiVersion,typeveruntimealanları, WASM (WebAssembly; tarayıcı dışında da çalışan taşınabilir bytecode formatı) tabanlı opsiyonel runtime, post-renderer'ların plugin olması. - Flag değişiklikleri:
--atomicyerine--rollback-on-failure,--forceyerine--force-replace;helm list --allkaldırıldı, liste varsayılan olarak bütün durumları gösteriyor;helm statusresource'ları varsayılan olarak gösteriyor. helm registry loginyalnızca registry adresi kabul ediyor; OCI (Open Container Initiative; container image'ları için açık standart) chart'larında digest ile kurulum.- Values: multi-document values dosyaları ve
--set-jsonile bütün bir JSON object'i. - Loglama Go'nun slog paketine geçti; SDK'nın import yolu
helm.sh/helm/v4ve paketler sürümlü (pkg/chart/v2,pkg/release/v1). - Deneysel Chart v3 (
HELM_EXPERIMENTAL_CHART_V3), tekrarlanabilir chart paketleri ve içerik tabanlı cache.
Bunların bir kısmını serinin önceki yazılarında gördük: kstatus ve --rollback-on-failure beşinci yazıda, registry login ve digest altıncı yazıda, multi-document values dördüncü yazıda. Bu yazıda geri kalanları iki Helm sürümünü yan yana çalıştırarak deniyoruz. Helm 3.22.1'i ayrı bir klasöre kurup helm3 adıyla çağırdık:
helm3 version --short
helm version --short
v3.22.1+gd6c1a0e
v4.3.2+g8346aaa
Server-Side Apply ve Latching
Bookstore'un (sitedeki serilerin ortak örnek uygulaması, bir online kitapçı) chart'ını Helm 3 ile kurduk ve iki yardımcı fonksiyonla release Secret'ındaki apply_method alanını ve Deployment'taki helm manager'ının işlem tipini okuduk:
helm3 install bookstore charts/bookstore -n bookstore-legacy -f deploy/values-dev.yaml --wait
# Release Secret'ındaki apply_method alanı ve Deployment'ta helm'e ait managedFields kaydı
release() {
kubectl -n bookstore-legacy get secret "sh.helm.release.v1.bookstore.v$1" -o jsonpath='{.data.release}' \
| base64 -d | base64 -d | gunzip | jq -c '{version, apply_method: (.apply_method // "(none)")}'
}
owner() {
kubectl -n bookstore-legacy get deploy bookstore-api -o json --show-managed-fields \
| jq -r '.metadata.managedFields[] | select(.manager=="helm") | "\(.manager)\t\(.operation)"'
}
release 1; owner
{"version":1,"apply_method":"(none)"}
helm Update
Helm 3 bu alanı hiç yazmıyor ve değişiklikleri CSA (client-side apply; farkı Helm'in hesaplayıp patch olarak gönderdiği yöntem) ile yapıyor; managedFields'taki Update bunu gösteriyor. Şimdi aynı release'i Helm 4 ile upgrade ettik, önce bayraksız, sonra --server-side=true ile:
helm upgrade bookstore charts/bookstore -n bookstore-legacy -f deploy/values-dev.yaml --wait
release 2; owner
helm upgrade bookstore charts/bookstore -n bookstore-legacy -f deploy/values-dev.yaml --server-side=true --wait
release 3; owner
{"version":2,"apply_method":"csa"}
helm Update
{"version":3,"apply_method":"ssa"}
helm Apply
Helm 4 bayraksız upgrade'de release'in önceki yöntemine "kilitlendi" (latching) ve CSA ile devam etti; bunu da kayda csa olarak yazdı. --server-side=true ile SSA'ya (server-side apply; nesneyi API server'ın birleştirdiği ve her alanın sahibini kaydettiği yöntem) geçti, managedFields'ta Apply göründü ve bundan sonraki bayraksız upgrade'ler SSA ile devam edecek. Önce Tahmin Et'in ikinci yarısı:
helm3 upgrade bookstore charts/bookstore -n bookstore-legacy -f deploy/values-dev.yaml --wait
release 4
helm upgrade bookstore charts/bookstore -n bookstore-legacy -f deploy/values-dev.yaml
release 5
{"version":4,"apply_method":"(none)"}
{"version":5,"apply_method":"csa"}
Helm 3'ün yaptığı upgrade, apply_method alanını bilmediği için kayıttan düşürdü; ardından gelen Helm 4 upgrade'i alanı bulamayınca release'i yeniden CSA'ya bağladı. Yani aynı release'e iki Helm sürümüyle dokunmak, SSA'ya geçişi sessizce geri alıyor. Geçişte bütün ekibin ve bütün pipeline'ların aynı anda Helm 4'e geçmesi bu yüzden önemli. SSA'ya geçiş, beşinci yazıda gördüğümüz field ownership çakışmalarını da beraberinde getiriyor: kubectl ile elle değiştirilmiş alanlar artık sessizce ezilmiyor, upgrade bir çakışma hatasıyla duruyor. Geçişi, böyle elle değişikliklerin olmadığı bir anda ve önce staging'de yapmak gerekiyor.
Flag'ler, Komutlar ve Loglar
helm upgrade bookstore charts/bookstore -n bookstore-legacy -f deploy/values-dev.yaml --force
helm list --all -n bookstore-legacy
Flag --force has been deprecated, use --force-replace instead
Release "bookstore" has been upgraded. Happy Helming!
Error: unknown flag: --all
Yeniden adlandırılan flag'ler (--atomic, --force) uyarıyla çalışmaya devam ediyor, CI loglarında bu satırları aramak geçişin ilk adımı. Kaldırılan flag'ler ise script'i kırıyor: helm list --all Helm 4'te bilinmeyen bir flag, çünkü helm list artık bütün durumları varsayılan olarak gösteriyor. Helm 3'te çalışan helm registry login registry.example.com/charts gibi yollu adresler de altıncı yazıda gördüğümüz gibi hata veriyor. Loglar da değişti: Helm 4, Go'nun yapılandırılmış log paketi slog'u kullanıyor ve uyarılar ile debug satırları level=... msg=... biçiminde geliyor. Bu satırları ayrıştıran bir log toplama kuralın varsa güncellemen gerekiyor:
helm upgrade bookstore charts/bookstore -n bookstore-legacy -f deploy/values-dev.yaml --debug 2>&1 | grep "^level=" | head -4
level=DEBUG msg="preparing upgrade" name=bookstore
level=DEBUG msg="getting last revision" name=bookstore
level=DEBUG msg="getting release history" name=bookstore
level=DEBUG msg="chart name" chart-name=bookstore
Bir de davranış değişikliği var: --wait verilmeden yapılan bir upgrade Helm 4'te de Deployment'ların hazır olmasını beklemiyor ve varsayılan hookOnly stratejisi yalnızca hook'ları bekliyor. Helm 3'te --wait kullanan script'ler Helm 4'te watcher stratejisine geçiyor ve bekleme mantığı kstatus'a dayanıyor; zaman aşımı mesajları da farklı.
Plugin Sistemi ve Post-Renderer'lar
Post-renderer, Helm'in render ettiği manifest'leri cluster'a göndermeden önce bir programdan geçirmesi. Helm 3'te bu program doğrudan bir executable olabiliyordu. Bütün resource'lara bir team label'ı ekleyen küçük bir script ile:
#!/usr/bin/env sh
# Post-renderer: render edilmiş manifest'leri stdin'den okur, team label'ı ekleyip stdout'a yazar.
sed 's/^ labels:$/ labels:\n example.com\/team: bookstore/'
helm3 template bookstore charts/bookstore -f deploy/values-dev.yaml \
--post-renderer ./add-team-label.sh --show-only templates/service.yaml | grep -A2 "labels:"
helm template bookstore charts/bookstore -f deploy/values-dev.yaml --post-renderer ./add-team-label.sh
labels:
example.com/team: bookstore
app.kubernetes.io/name: bookstore
Error: invalid argument "./add-team-label.sh" for "--post-renderer" flag: plugin: {Name:./add-team-label.sh Type:postrenderer/v1} not found
Helm 3 script'i çalıştırdı, Helm 4 ise ./add-team-label.sh'ı bir plugin adı sanıp bulamadı. Helm 4'te post-renderer bir plugin tipi; script'i bir plugin.yaml ile sarmak gerekiyor:
apiVersion: v1
type: postrenderer/v1
name: team-label
version: 0.1.0
runtime: subprocess
runtimeConfig:
platformCommand:
- command: ${HELM_PLUGIN_DIR}/add-team-label.sh
helm plugin install ./plugins/team-label
helm plugin list
helm template bookstore charts/bookstore -f deploy/values-dev.yaml --post-renderer team-label \
--show-only templates/service.yaml | grep -A2 "labels:"
Installing plugin from local directory (development mode)
Installed plugin: team-label
NAME VERSION TYPE APIVERSION PROVENANCE SOURCE
team-label 0.1.0 postrenderer/v1 v1 local dev unknown
labels:
example.com/team: bookstore
app.kubernetes.io/name: bookstore
Lokal bir klasörden kurulan plugin "development mode"da, provenance kontrolü olmadan kuruluyor. Helm 4'te uzak kaynaklardan kurulan plugin'ler için imza ve doğrulama da plugin sisteminin parçası oldu. Yeni sistemin bir yan etkisini de Helm 3'te gördük: iki sürüm aynı plugin klasörünü paylaşınca Helm 3 yeni biçimdeki plugin.yaml'ı okuyamıyor ve her komutta uyarı basıyor:
helm3 template x v3demo
failed to load plugins: failed to load plugin at "<HELM_DATA_HOME>/plugins/team-label/plugin.yaml": error unmarshaling JSON: while decoding JSON: json: unknown field "apiVersion"
Mevcut Helm 3 plugin'leri Helm 4'te çalışmaya devam ediyor; bu serideki chart'larda bir sorun görmedik, ama kendi yazdığın ya da kullandığın plugin'leri Helm 4 ile ayrıca denemelisin. Plugin bakımcıları için Helm dokümanında eski alanların yeni karşılıklarını listeleyen bir geçiş rehberi var. WASM runtime'ı (runtime: extism/v1) plugin'i bir sandbox'ta, izin verilen host'lar ve bellek sınırıyla çalıştırıyor; bu runtime'ı bu yazı için denemedim.
Chart Formatı: v1, v2 ve Deneysel v3
Helm 4 yeni bir chart formatı için zemin hazırlıyor. Chart v3 deneysel bir bayrak arkasında:
helm create --chart-api-version=v3 v3demo
HELM_EXPERIMENTAL_CHART_V3=1 helm create --chart-api-version=v3 v3demo
head -2 v3demo/Chart.yaml
HELM_EXPERIMENTAL_CHART_V3=1 helm lint v3demo
HELM_EXPERIMENTAL_CHART_V3=1 helm install x v3demo --dry-run=client
Error: this feature has been marked as experimental and is not enabled by default. Please set HELM_EXPERIMENTAL_CHART_V3=1 in your environment to use this feature
Creating v3demo
apiVersion: v3
name: v3demo
==> Linting v3demo
[ERROR] Chart.yaml: apiVersion 'v3' is not valid. The value must be either "v1" or "v2"
[INFO] Chart.yaml: icon is recommended
Error: INSTALLATION FAILED: invalid chart apiVersion
4.3.2'de v3 bir chart iskeleti oluşturulabiliyor ve helm show chart ile okunabiliyor, ama lint ve install henüz kabul etmiyor. Bugün yazdığın chart'lar apiVersion: v2 ile kalmalı; v2 chart'lar Helm 4'te değişmeden çalışıyor.
Öbür uçta Helm 2 dönemi chart'lar var. Helm 2'nin cluster'da Tiller adlı bir sunucu bileşeni vardı ve desteği Kasım 2020'de bitti; ama o dönemin chart'ları hâlâ eski repo'larda, şirket içi depolarda karşına çıkıyor. Tanıma işaretleri: apiVersion: v1, dependency'ler için ayrı bir requirements.yaml ve çoğu zaman artık var olmayan Kubernetes API'leri. Böyle bir chart'ı Helm 4 ile denedik:
# Chart.yaml (Helm 2 dönemi)
apiVersion: v1
name: bookstore-legacy
version: 0.9.0
appVersion: "0.9"
description: A Helm 2 era chart (apiVersion v1)
---
# requirements.yaml: v1 chart'larda dependency'ler burada
dependencies:
- name: valkey
version: "1.0.x"
repository: https://valkey.io/valkey-helm/
condition: valkey.enabled
---
# templates/deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: {{ .Release.Name }}-api
spec:
replicas: 1
template:
metadata:
labels:
app: {{ .Release.Name }}-api
spec:
containers:
- name: api
image: {{ .Values.image }}
helm dependency list legacy-chart
helm lint legacy-chart
NAME VERSION REPOSITORY STATUS
valkey 1.0.x https://valkey.io/valkey-helm/ missing
==> Linting legacy-chart
[INFO] Chart.yaml: icon is recommended
[WARNING] templates/deployment.yaml: extensions/v1beta1 Deployment is deprecated in v1.8+, unavailable in v1.16+; use apps/v1 Deployment
[ERROR] templates/deployment.yaml: a Deployment must contain matchLabels or matchExpressions, and "test-release-api" does not
[WARNING] legacy-chart: chart directory is missing these dependencies: valkey
Error: 1 chart(s) linted, 1 chart(s) failed
Helm 4 v1 formatını hâlâ okuyor: requirements.yaml'daki dependency'yi tanıdı ve helm dependency update ile Chart.lock yerine requirements.lock yazdı. Lint, kaldırılmış API'yi uyarı olarak, selector'ı olmayan Deployment'ı hata olarak gösterdi. Install ise API server'dan döndü:
helm dependency update legacy-chart
ls legacy-chart
helm install old legacy-chart -n bookstore-old
...
Deleting outdated charts
Chart.yaml
charts
requirements.lock
requirements.yaml
templates
values.yaml
Error: INSTALLATION FAILED: unable to build kubernetes objects from release manifest: resource mapping not found for name: "old-api" namespace: "" from "": no matches for kind "Deployment" in version "extensions/v1beta1"
ensure CRDs are installed first
extensions/v1beta1 Deployment'ları Kubernetes 1.16'da kaldırıldı; bu ve benzeri API'lerin listesi Kubernetes serisinin 18. yazısında. Böyle bir chart'ı taşımak için önce apiVersion: v2'ye geçip dependency'leri Chart.yaml'a almak, sonra template'lerdeki API sürümlerini güncellemek gerekiyor. Cluster'da kaldırılmış bir API ile kaydedilmiş bir release varsa (release Secret'ındaki manifest eski API'yi gösteriyorsa) upgrade bile yapılamaz; bunun için Helm topluluğunun helm-mapkubeapis plugin'i release kaydındaki API'leri yeniden yazıyor. Bu plugin'i bu yazı için çalıştırmadım.
Geçiş Checklist'i
- CI imajlarında ve geliştirici makinelerinde Helm sürümünü aynı anda 4.x'e yükselt; aynı release'e iki sürümle dokunmak SSA'ya geçişi geri alıyor.
- Script'lerde
--atomic,--force,helm list --all, yolluhelm registry loginve doğrudan executable veren--post-rendererkullanımlarını ara. --waitkullanmayan deploy adımlarına bilinçli bir strateji ekle; Helm 4'ün varsayılanı yalnızca hook'ları bekliyor.- Post-renderer'ları
postrenderer/v1plugin'ine, kendi plugin'lerini yeniplugin.yamlbiçimine taşı ve Helm 4 ile dene. - Release'leri SSA'ya bilinçli olarak geçir (
--server-side=true), önce staging'de; elle değiştirilmiş alanların çakışma çıkaracağını bekle. - Helm SDK kullanan iç araçları
helm.sh/helm/v4'e taşı, slog tabanlı log ayrıştırma kurallarını güncelle. - Eski chart'larda kaldırılmış Kubernetes API'lerini
helm lintve kubeconform ile ara;apiVersion: v1chart'ları v2'ye taşı.
Üretimde Dikkat
Helm 4'e geçiş bir binary değişikliği gibi görünse de aslında bir deploy yönteminin değişmesi; geçişi bir release penceresine koy ve ilk upgrade'leri yakından izle. SSA'ya geçmenin faydası, birden fazla aracın aynı resource'a dokunduğu cluster'larda daha belirgin: Argo CD, operator'ler, HPA (yüke göre pod sayısını ayarlayan autoscaler) ve Helm aynı Deployment'ın farklı alanlarını yönetiyorsa çakışmalar sessizce ezilmek yerine görünür hâle geliyor. Helm 3'ün security desteği 10 Şubat 2027'de bitiyor; ondan sonra bulunan bir güvenlik açığı Helm 3'te kalacak. CI'da Helm sürümünü sabitle (bu serideki workflow'da v4.3.2) ve yükseltmeleri bir pull request ile, chart testleri koşarak yap.
Sık Düşülen Tuzaklar
Helm 4'e geçince bütün release'lerin kendiliğinden SSA'ya geçeceğini sanmak. Ekipte biri Helm 3 kullanmaya devam ederken release'leri SSA'ya taşımak. Deprecation uyarılarını görmezden gelip flag'lerin bir sonraki major sürümde kaldırılmasını beklemek. Post-renderer script'inin Helm 4'te de çalışacağını varsaymak. Helm 3 ve Helm 4'ü aynı plugin klasörüyle kullanıp sürekli plugin uyarısı almak. Chart v3'ü production chart'ları için kullanmaya çalışmak. Helm 2 dönemi bir chart'ı, kaldırılmış API'lerine bakmadan yeni bir cluster'a kurmaya çalışmak.
Küçük Bir Deneme
★☆☆ Kendi CI script'lerinde ve Makefile'larında --atomic, --force, list --all ve registry login kullanımlarını ara ve Helm 4 karşılıklarıyla değiştir.
★★☆ Helm 3 ile bir release kur, birkaç alanı kubectl edit ile değiştir ve Helm 4 ile önce bayraksız, sonra --server-side=true ile upgrade et. Hangi adımda çakışma hatası aldığını ve apply_method'ın nasıl değiştiğini not et.
★★★ Post-renderer plugin'ini Kustomize ile çalışacak şekilde yeniden yaz: plugin, stdin'den gelen manifest'leri bir dosyaya yazsın ve kustomize build ile bir patch uygulasın. Kubernetes serisinin 14. yazısındaki overlay mantığını Helm chart'ının üzerine bu yolla taşı.
Bu yazıyla Helm serisi tamamlandı. Serinin sonunda elinde Bookstore için sürümlü, şeması olan, migration'ı hook ile yapan, OCI registry'de yayımlanan ve CI'da test edilen bir chart var. Bu chart'ı Git'ten sürekli senkronize etmek, yani deploy'u bir pipeline'dan cluster içindeki bir agent'a devretmek GitOps ve Argo CD serisinin konusu.