Helm ile Kubernetes Uygulama Paketi Yönetimi

Kubernetes üzerinde uygulama dağıtımı yaparken bir noktadan sonra onlarca YAML dosyasıyla boğuştuğunuzu fark edersiniz. Deployment, Service, ConfigMap, Secret, Ingress… Bunların hepsini tek tek yönetmek hem zaman alıcı hem de hata yapmaya açık bir süreç. İşte tam burada Helm devreye giriyor ve hayatınızı ciddi ölçüde kolaylaştırıyor.

Helm Nedir ve Neden Kullanmalıyız?

Helm, Kubernetes için geliştirilmiş bir paket yöneticisidir. Nasıl ki Linux’ta apt ya da yum ile uygulama kuruyorsanız, Kubernetes’te de Helm ile kompleks uygulamaları tek komutla kurabilir, güncelleyebilir ve kaldırabilirsiniz.

Helm’in temel bileşenleri şunlardır:

  • Chart: Bir uygulamanın tüm Kubernetes kaynaklarını tanımlayan şablon dosyaları koleksiyonu
  • Release: Bir chart’ın Kubernetes cluster’ına kurulmuş hali
  • Repository: Chart’ların depolandığı ve paylaşıldığı merkezi yer
  • Values: Chart şablonlarını özelleştirmek için kullanılan konfigürasyon değerleri

Gerçek dünya senaryosunu düşünelim: Şirketinizde test, staging ve production ortamları var. Her ortam için farklı resource limit’leri, replica sayıları ve konfigürasyonlar gerekiyor. Helm olmadan her ortam için ayrı YAML setleri tutmanız gerekir. Helm ile sadece tek bir chart yazıp farklı values.yaml dosyalarıyla her ortamı yönetebilirsiniz.

Helm Kurulumu

Helm kurulumu oldukça basit. Linux sistemlerde şu yöntemle kurabilirsiniz:

# Script ile kurulum
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

# Paket yöneticisi ile (Ubuntu/Debian)
curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt update && sudo apt install helm

# Kurulumu doğrulama
helm version

Helm 3 ile birlikte Tiller bileşeni ortadan kalktı, bu yüzden cluster tarafında ekstra bir şey kurmanıza gerek yok. Helm direkt olarak kubectl credential’larınızı kullanarak cluster ile iletişim kurar.

Repository Yönetimi

Helm chart’larını bulabileceğiniz birçok repository var. En yaygın kullanılanları ekleyelim:

# Artifact Hub üzerinden popüler repo'ları ekleme
helm repo add stable https://charts.helm.sh/stable
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo add cert-manager https://charts.jetstack.io

# Tüm repo'ları güncelleme
helm repo update

# Mevcut repo'ları listeleme
helm repo list

# Belirli bir chart'ı arama
helm search repo nginx
helm search repo bitnami/wordpress

# Artifact Hub'da arama (internet üzerinden)
helm search hub prometheus

Repo ekledikten sonra helm search repo komutu ile istediğiniz uygulamayı arayabilirsiniz. Ben genellikle Bitnami repo’sunu tercih ediyorum çünkü chart’ları düzenli olarak güncelleniyor ve güvenlik yamaları hızlıca uygulanıyor.

İlk Chart Kurulumu

Teoriden pratiğe geçelim. Bir Nginx kurulumu yapalım ve Helm’in gücünü görelim:

# Namespace oluşturma
kubectl create namespace web-apps

# Chart hakkında bilgi alma
helm show values bitnami/nginx

# Basit kurulum
helm install my-nginx bitnami/nginx --namespace web-apps

# Kurulumu doğrulama
helm list --namespace web-apps
kubectl get pods --namespace web-apps

# Release detaylarını görme
helm status my-nginx --namespace web-apps

helm install komutunun yapısı şu şekildedir: helm install [RELEASE_ADI] [CHART_ADI] [PARAMETRELER]

Kurulum sırasında önemli parametreler:

  • –namespace: Hangi namespace’e kurulacağı
  • –create-namespace: Namespace yoksa otomatik oluştur
  • –values / -f: Özel values dosyası kullan
  • –set: Komut satırından değer geç
  • –dry-run: Gerçekten kurmadan test et
  • –debug: Detaylı çıktı göster
  • –wait: Pod’lar hazır olana kadar bekle
  • –timeout: Bekleme süresi limiti

Kendi Chart’ınızı Oluşturma

İşte Helm’in asıl gücü burada ortaya çıkıyor. Kendi uygulamanız için chart oluşturabilirsiniz:

# Yeni chart oluşturma
helm create my-webapp

# Oluşturulan yapı
tree my-webapp/
# my-webapp/
# ├── Chart.yaml          # Chart metadata
# ├── values.yaml         # Default değerler
# ├── charts/             # Bağımlı chart'lar
# └── templates/          # Kubernetes manifest şablonları
#     ├── deployment.yaml
#     ├── service.yaml
#     ├── ingress.yaml
#     ├── _helpers.tpl
#     └── NOTES.txt

Basit bir web uygulaması için values.yaml dosyasını düzenleyelim:

# values.yaml
replicaCount: 2

image:
  repository: nginx
  tag: "1.25"
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: true
  className: nginx
  hosts:
    - host: myapp.example.com
      paths:
        - path: /
          pathType: Prefix

resources:
  limits:
    cpu: 500m
    memory: 128Mi
  requests:
    cpu: 250m
    memory: 64Mi

autoscaling:
  enabled: false
  minReplicas: 2
  maxReplicas: 10
  targetCPUUtilizationPercentage: 80

env:
  APP_ENV: production
  LOG_LEVEL: info

configMap:
  enabled: true
  data:
    nginx.conf: |
      server {
        listen 80;
        location /health {
          return 200 'healthy';
        }
      }

Şimdi deployment şablonunu inceleyelim:

# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "my-webapp.fullname" . }}
  labels:
    {{- include "my-webapp.labels" . | nindent 4 }}
spec:
  {{- if not .Values.autoscaling.enabled }}
  replicas: {{ .Values.replicaCount }}
  {{- end }}
  selector:
    matchLabels:
      {{- include "my-webapp.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "my-webapp.selectorLabels" . | nindent 8 }}
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - containerPort: 80
          resources:
            {{- toYaml .Values.resources | nindent 12 }}
          env:
            {{- range $key, $value := .Values.env }}
            - name: {{ $key }}
              value: {{ $value | quote }}
            {{- end }}

Chart’ı test etmeden önce her zaman lint ve dry-run yapın:

# Chart syntax kontrolü
helm lint my-webapp/

# Oluşturulacak manifest'leri görme (kurulum yapmadan)
helm template my-webapp my-webapp/ --values my-webapp/values.yaml

# Dry run ile test
helm install my-webapp-test my-webapp/ --dry-run --debug --namespace test

Çoklu Ortam Yönetimi

En sık karşılaşılan gerçek dünya senaryolarından biri çoklu ortam yönetimidir. Tek chart, birden fazla ortam:

# Ortam bazlı values dosyaları oluşturma
# values-dev.yaml, values-staging.yaml, values-prod.yaml

# Development ortamı kurulumu
helm install my-webapp-dev my-webapp/ 
  --namespace development 
  --create-namespace 
  -f my-webapp/values.yaml 
  -f environments/values-dev.yaml

# Production ortamı kurulumu
helm install my-webapp-prod my-webapp/ 
  --namespace production 
  --create-namespace 
  -f my-webapp/values.yaml 
  -f environments/values-prod.yaml 
  --set image.tag=v2.1.0 
  --wait 
  --timeout 5m

values-prod.yaml örneği:

# environments/values-prod.yaml
replicaCount: 5

image:
  tag: "v2.1.0"

resources:
  limits:
    cpu: 2000m
    memory: 512Mi
  requests:
    cpu: 500m
    memory: 256Mi

autoscaling:
  enabled: true
  minReplicas: 5
  maxReplicas: 20
  targetCPUUtilizationPercentage: 70

ingress:
  enabled: true
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
  hosts:
    - host: myapp.company.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: myapp-tls
      hosts:
        - myapp.company.com

env:
  APP_ENV: production
  LOG_LEVEL: warn

Güncelleme ve Rollback

Helm’in en değerli özelliklerinden biri versiyonlama ve rollback yeteneğidir:

# Mevcut release'leri listeleme
helm list --all-namespaces

# Release güncelleme
helm upgrade my-webapp-prod my-webapp/ 
  --namespace production 
  -f my-webapp/values.yaml 
  -f environments/values-prod.yaml 
  --set image.tag=v2.2.0 
  --wait

# Release geçmişini görme
helm history my-webapp-prod --namespace production

# Önceki versiyona rollback
helm rollback my-webapp-prod 1 --namespace production

# Belirli bir versiyona rollback
helm rollback my-webapp-prod 3 --namespace production

# Upgrade + otomatik rollback (başarısız olursa)
helm upgrade my-webapp-prod my-webapp/ 
  --namespace production 
  --atomic 
  --cleanup-on-fail 
  --set image.tag=v2.3.0

--atomic parametresi özellikle önemli: Eğer upgrade başarısız olursa Helm otomatik olarak önceki versiyona döner. Production ortamında bu parametreyi mutlaka kullanın.

Helm Secrets ve Hassas Veri Yönetimi

Gerçek dünyada en kritik konulardan biri hassas verilerin yönetimidir. Helm values dosyalarını git’e commit ettiğinizde şifrelerin açıkta kalmaması gerekiyor. Bunun için helm-secrets plugin’i kullanabilirsiniz:

# helm-secrets plugin kurulumu
helm plugin install https://github.com/jkroepke/helm-secrets

# SOPS ile şifreleme (AWS KMS, GCP KMS veya GPG key kullanabilirsiniz)
# GPG key oluşturma
gpg --gen-key

# Secrets dosyası oluşturma
cat > secrets.yaml << EOF
database:
  password: super-secret-password
  connectionString: postgresql://user:pass@db:5432/mydb
redis:
  password: redis-secret-pass
EOF

# Dosyayı şifreleme
sops --encrypt --pgp YOUR_GPG_KEY_ID secrets.yaml > secrets.enc.yaml

# Şifreli dosya ile deployment
helm secrets upgrade my-webapp-prod my-webapp/ 
  --namespace production 
  -f environments/values-prod.yaml 
  -f secrets.enc.yaml

Alternatif olarak Kubernetes Secret’larını direkt referans etmek de yaygın bir pratiktir:

# Secret'ı Kubernetes'te manuel oluştur, Helm sadece referans etsin
kubectl create secret generic db-credentials 
  --from-literal=password=supersecret 
  --namespace production

# values.yaml'da external secret referansı
# existingSecret: db-credentials

Chart Bağımlılıkları

Gerçek uygulamalar genellikle veritabanı, cache gibi bileşenlere ihtiyaç duyar. Helm’in bağımlılık yönetimi bu durumu çözer:

# Chart.yaml
apiVersion: v2
name: my-fullstack-app
description: Full stack uygulama chart'ı
type: application
version: 1.0.0
appVersion: "2.1.0"

dependencies:
  - name: postgresql
    version: "12.x.x"
    repository: https://charts.bitnami.com/bitnami
    condition: postgresql.enabled
  - name: redis
    version: "17.x.x"
    repository: https://charts.bitnami.com/bitnami
    condition: redis.enabled
# Bağımlılıkları indirme
helm dependency update my-fullstack-app/

# Bağımlılıkları listeleme
helm dependency list my-fullstack-app/

# Bağımlılıklar dahil kurulum
helm install my-app my-fullstack-app/ 
  --namespace production 
  --set postgresql.enabled=true 
  --set postgresql.auth.password=dbpassword 
  --set redis.enabled=true

Helm Hooks

Hooks, belirli lifecycle event’lerinde özel işlemler yapmanıza olanak tanır. Örneğin kurulum öncesi database migration çalıştırabilirsiniz:

# templates/pre-install-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: {{ include "my-webapp.fullname" . }}-migrations
  annotations:
    "helm.sh/hook": pre-upgrade,pre-install
    "helm.sh/hook-weight": "-5"
    "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
spec:
  template:
    spec:
      containers:
        - name: migrations
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          command: ["python", "manage.py", "migrate"]
          env:
            - name: DATABASE_URL
              valueFrom:
                secretKeyRef:
                  name: db-credentials
                  key: url
      restartPolicy: Never

Hook tipleri:

  • pre-install: Kurulumdan önce çalışır
  • post-install: Kurulumdan sonra çalışır
  • pre-upgrade: Güncellemeden önce çalışır
  • post-upgrade: Güncellemeden sonra çalışır
  • pre-rollback: Rollback öncesi çalışır
  • pre-delete: Silme işlemi öncesi çalışır

OCI Registry ile Chart Yönetimi

Modern Helm workflow’larında chart’ları OCI registry’lerde saklamak giderek yaygınlaşıyor:

# OCI registry login (Docker Hub örneği)
helm registry login registry-1.docker.io

# Chart'ı OCI formatında push etme
helm package my-webapp/
helm push my-webapp-1.0.0.tgz oci://registry-1.docker.io/mycompany

# OCI registry'den kurulum
helm install my-webapp 
  oci://registry-1.docker.io/mycompany/my-webapp 
  --version 1.0.0 
  --namespace production

# AWS ECR için
aws ecr get-login-password --region us-east-1 | 
  helm registry login --username AWS --password-stdin 
  123456789.dkr.ecr.us-east-1.amazonaws.com

helm push my-webapp-1.0.0.tgz 
  oci://123456789.dkr.ecr.us-east-1.amazonaws.com/helm-charts

GitOps ile Helm Entegrasyonu

Argocd veya Flux kullananlar için Helm chart’larını GitOps pipeline’ına entegre etmek çok yaygın:

# ArgoCD Application manifest örneği
# Bu YAML'ı git repo'nuzda saklayın, ArgoCD otomatik senkronize eder

cat > argocd-app.yaml << 'EOF'
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-webapp-prod
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/mycompany/helm-charts
    targetRevision: HEAD
    path: my-webapp
    helm:
      valueFiles:
        - values.yaml
        - environments/values-prod.yaml
      parameters:
        - name: image.tag
          value: v2.1.0
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
EOF

kubectl apply -f argocd-app.yaml

Faydalı Helm Komutları

Günlük operasyonlarda sık kullandığım komutlar:

# Tüm namespace'lerdeki release'leri listeleme
helm list --all-namespaces

# Başarısız release'leri bulma
helm list --all-namespaces --failed

# Release'in manifest'lerini görme
helm get manifest my-webapp-prod --namespace production

# Kullanılan values'ları görme
helm get values my-webapp-prod --namespace production

# Tüm values'ları görme (default + custom)
helm get values my-webapp-prod --namespace production --all

# Release'i silme (PV'ler dahil tüm kaynaklar)
helm uninstall my-webapp-prod --namespace production

# Eski release geçmişini temizleme
helm history my-webapp-prod --namespace production --max 10

# Chart'ın tüm notlarını görme
helm get notes my-webapp-prod --namespace production

Yaygın Sorunlar ve Çözümleri

Release pending durumunda kalıyorsa:

# Pending release'leri temizleme
helm list --all-namespaces --pending
helm rollback my-webapp-prod --namespace production
# veya
helm uninstall my-webapp-prod --namespace production
kubectl delete secret -l owner=helm,name=my-webapp-prod --namespace production

Values override çalışmıyorsa dikkat edilecekler:

  • --set komutları her zaman -f dosyalarını override eder
  • Nested değerler için --set parent.child=value kullanın
  • Nokta içeren key’ler için --set "annotations.kubernetes.io/ingress-class=nginx" escape kullanın
  • Array değerler için --set "hosts[0]=example.com,hosts[1]=www.example.com" formatını kullanın

Sonuç

Helm, Kubernetes ekosisteminin vazgeçilmez bir parçası haline gelmiş durumda. Küçük bir side project’ten büyük kurumsal uygulamalara kadar her ölçekte işe yarıyor. Özellikle şu noktalarda değer katıyor:

  • Tekrarlayan YAML yazma derdinden kurtarıyor
  • Ortam yönetimini standardize ediyor
  • Rollback mekanizmasıyla riskleri azaltıyor
  • Ekip içinde uygulama paketleme standartları oluşturuyor

Başlangıçta community chart’larını kullanarak Helm’e alışın, sonra kendi chart’larınızı yazmaya başlayın. Chart yazarken helm lint, helm template ve --dry-run üçlüsünü asla atlamamanızı öneririm, bu üç komut production’da sizi çok kez kurtaracak.

GitOps tarafına geçtiğinizde ArgoCD veya Flux ile Helm’i birleştirmek, gerçek anlamda “uygulama git’te tanımlanır, cluster kendisi sync olur” yaklaşımını hayata geçirmenizi sağlıyor. Bu noktaya geldiğinizde Kubernetes yönetimi bambaşka bir boyut kazanıyor.

Yorum yapın