Kaynak İzolasyonu: Kubernetes Namespace ile Ortam Ayrımı

Kubernetes cluster’ı yönetirken en sık karşılaşılan sorunlardan biri, farklı ekiplerin veya farklı ortamların aynı cluster üzerinde çakışmadan çalışmasını sağlamaktır. Geliştirme ortamından production’a uzanan süreçte, bir ekibin yanlışlıkla başka bir ekibin servisini silmesi ya da kaynak limitlerini aşarak diğerlerinin performansını düşürmesi ciddi operasyonel sorunlara yol açar. İşte tam bu noktada Kubernetes Namespace kavramı devreye giriyor ve hayatımızı ciddi ölçüde kolaylaştırıyor.

Namespace Nedir ve Neden Gereklidir?

Kubernetes Namespace’leri, tek bir fiziksel cluster içinde birden fazla sanal cluster oluşturmanın yoludur. Bunu şöyle düşünebilirsin: büyük bir açık ofis düşün, herkes aynı binada çalışıyor ama farklı departmanlar kendi bölmelerinde, kendi kurallarıyla faaliyet gösteriyor.

Namespace olmadan yaşanan tipik sorunlar şunlardır:

  • İsim çakışmaları: İki farklı ekip aynı isimde deployment oluşturmak istediğinde conflict yaşanır
  • Kaynak kargaşası: Hangi pod hangi ekibe ait, kim ne kadar CPU/memory kullanıyor takip edilemez
  • Güvenlik açıkları: Her ekip her şeyi görebilir, izin yönetimi imkansız hale gelir
  • Kaza riski: Bir geliştirici yanlış ortamda kubectl delete komutunu çalıştırır ve production servislerini siler

Namespace, bu sorunların tamamına pratik bir çözüm sunar. Aynı cluster kaynaklarını paylaşırken mantıksal izolasyon sağlar.

Varsayılan Namespace’ler

Kubernetes kurulumunda birkaç namespace hazır gelir. Bunları iyi tanımak önemlidir.

kubectl get namespaces

Çıktıda göreceğin varsayılan namespace’ler:

  • default: Herhangi bir namespace belirtilmeden oluşturulan kaynaklar buraya düşer. Production için kullanmak tavsiye edilmez.
  • kube-system: Kubernetes’in kendi bileşenleri burada çalışır. DNS, kube-proxy, metric-server gibi sistem servisleri burada bulunur. Dokunma.
  • kube-public: Tüm kullanıcılara açık, genellikle cluster bilgilerinin tutulduğu namespace. Nadiren kullanılır.
  • kube-node-lease: Node heartbeat mekanizması için kullanılır. Sistem tarafından yönetilir.

kube-system namespace’ine müdahale etmek ciddi cluster sorunlarına yol açabilir. Bu namespace’i salt okunur kabul et.

Namespace Oluşturma ve Temel Yönetim

Gerçek bir senaryoyu ele alalım: Bir şirkette backend ekibi, frontend ekibi ve bir de data engineering ekibi var. Hepsi aynı cluster’ı kullanıyor. Her birinin development, staging ve production ortamları mevcut.

# Ekip bazlı namespace oluşturma
kubectl create namespace backend-dev
kubectl create namespace backend-staging
kubectl create namespace backend-prod

kubectl create namespace frontend-dev
kubectl create namespace frontend-staging
kubectl create namespace frontend-prod

kubectl create namespace data-dev
kubectl create namespace data-prod

Alternatif olarak YAML ile namespace tanımlamak daha temiz bir yaklaşımdır çünkü bu tanımları Git’e commit edebilirsin:

# namespace-definitions.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: backend-prod
  labels:
    team: backend
    environment: production
    cost-center: "eng-001"
---
apiVersion: v1
kind: Namespace
metadata:
  name: frontend-prod
  labels:
    team: frontend
    environment: production
    cost-center: "eng-002"
kubectl apply -f namespace-definitions.yaml

Label kullanımı çok önemlidir. Daha sonra namespace’leri label’a göre filtreleyebilir, monitoring araçlarına maliyet takibi yaptırabilirsin.

Namespace İçinde Kaynak Oluşturma

Bir namespace içinde kaynak oluşturmanın iki yolu var: komut satırında -n parametresi kullanmak ya da manifest dosyasında namespace belirtmek.

# Belirli bir namespace içinde deployment oluşturma
kubectl create deployment nginx --image=nginx:1.25 -n backend-dev

# Namespace içindeki kaynakları listeleme
kubectl get pods -n backend-dev
kubectl get all -n backend-dev

# Tüm namespace'lerdeki pod'ları görmek
kubectl get pods --all-namespaces
# ya da kısa haliyle
kubectl get pods -A

Manifest içinde namespace belirtmek daha güvenlidir çünkü yanlış namespace’e deploy riski ortadan kalkar:

# backend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-server
  namespace: backend-prod
  labels:
    app: api-server
    team: backend
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api-server
  template:
    metadata:
      labels:
        app: api-server
    spec:
      containers:
      - name: api
        image: company/api-server:v2.1.0
        ports:
        - containerPort: 8080
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"

ResourceQuota ile Kaynak Sınırlandırma

Namespace izolasyonunun en kritik parçası kaynak kotalarıdır. Bir ekibin tüm cluster CPU’sunu tüketmesi diğer ekipleri etkiler. ResourceQuota ile her namespace’e kaynak sınırı koyabilirsin.

# backend-prod-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: backend-prod-quota
  namespace: backend-prod
spec:
  hard:
    # Compute kaynakları
    requests.cpu: "10"
    requests.memory: 20Gi
    limits.cpu: "20"
    limits.memory: 40Gi
    # Object sayıları
    pods: "50"
    services: "20"
    persistentvolumeclaims: "10"
    configmaps: "30"
    secrets: "30"
    deployments.apps: "15"
kubectl apply -f backend-prod-quota.yaml

# Quota durumunu kontrol etme
kubectl describe resourcequota backend-prod-quota -n backend-prod

Çıktı şöyle görünür:

Name:                   backend-prod-quota
Namespace:              backend-prod
Resource                Used    Hard
--------                ----    ----
limits.cpu              2       20
limits.memory           4Gi     40Gi
pods                    8       50
requests.cpu            1       10
requests.memory         2Gi     20Gi

Gerçek dünya deneyimimden paylaşayım: Bir müşteride data ekibinin Spark job’ları gece yarısı tüm cluster kaynaklarını tüketiyor, sabah geldiğinde production servisler cevap veremez hale geliyordu. ResourceQuota ile data namespace’ine sınır koyduktan sonra bu sorun tamamen ortadan kalktı.

LimitRange ile Pod Bazlı Sınırlar

ResourceQuota namespace’in toplamını sınırlar ama LimitRange, tek bir pod veya container için minimum ve maksimum sınırlar koyar. Ayrıca resource request/limit belirtmeden oluşturulan pod’lara otomatik default değer atar.

# backend-limitrange.yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: backend-limitrange
  namespace: backend-dev
spec:
  limits:
  - type: Container
    default:
      cpu: "500m"
      memory: "256Mi"
    defaultRequest:
      cpu: "100m"
      memory: "128Mi"
    max:
      cpu: "2"
      memory: "2Gi"
    min:
      cpu: "50m"
      memory: "64Mi"
  - type: Pod
    max:
      cpu: "4"
      memory: "4Gi"
  - type: PersistentVolumeClaim
    max:
      storage: "50Gi"
    min:
      storage: "1Gi"
kubectl apply -f backend-limitrange.yaml
kubectl describe limitrange backend-limitrange -n backend-dev

LimitRange’in güzel yanı şu: Yeni geliştiriciler resource limit belirtmeyi unutsa bile sistemin çökmesini engeller. Default değerler otomatik uygulanır.

RBAC ile Namespace Erişim Kontrolü

Namespace izolasyonunu tamamlamanın yolu RBAC (Role-Based Access Control) kullanmaktır. Namespace oluşturdun ama herkes hala her namespace’e erişebiliyorsa izolasyon yarım kalmış demektir.

# backend-team-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: backend-developer
  namespace: backend-dev
rules:
- apiGroups: ["", "apps", "batch"]
  resources: ["pods", "deployments", "services", "configmaps", "jobs"]
  verbs: ["get", "list", "watch", "create", "update", "patch"]
- apiGroups: [""]
  resources: ["pods/log", "pods/exec"]
  verbs: ["get", "list", "create"]
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# backend-team-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: backend-developer-binding
  namespace: backend-dev
subjects:
- kind: User
  name: ahmet.yilmaz
  apiGroup: rbac.authorization.k8s.io
- kind: User
  name: fatma.kaya
  apiGroup: rbac.authorization.k8s.io
- kind: Group
  name: backend-team
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  apiRef: backend-developer
  apiGroup: rbac.authorization.k8s.io
kubectl apply -f backend-team-role.yaml
kubectl apply -f backend-team-rolebinding.yaml

# Bir kullanıcının namespace üzerindeki yetkilerini test etme
kubectl auth can-i create pods -n backend-dev --as ahmet.yilmaz
kubectl auth can-i delete deployments -n backend-prod --as ahmet.yilmaz

Bu yapıda backend geliştiricileri kendi dev namespace’lerinde özgürce çalışabilir ama production namespace’ine erişimleri kısıtlıdır. Production’a deploy yetkisi sadece senior engineer ve DevOps ekibinde olur.

NetworkPolicy ile Ağ İzolasyonu

Namespace izolasyonu yalnızca RBAC ile tamamlanmaz. Varsayılan olarak farklı namespace’lerdeki pod’lar birbirleriyle serbestçe iletişim kurabilir. NetworkPolicy ile bu trafiği kontrol altına alabilirsin.

# backend-network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: backend-prod-isolation
  namespace: backend-prod
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
  ingress:
  # Sadece aynı namespace'den gelen trafiğe izin ver
  - from:
    - namespaceSelector:
        matchLabels:
          name: backend-prod
  # Frontend namespace'inden gelen trafiğe izin ver
  - from:
    - namespaceSelector:
        matchLabels:
          environment: production
          team: frontend
    ports:
    - protocol: TCP
      port: 8080
  egress:
  # DNS trafiğine izin ver
  - ports:
    - protocol: UDP
      port: 53
  # Database namespace'ine çıkışa izin ver
  - to:
    - namespaceSelector:
        matchLabels:
          team: database
          environment: production
    ports:
    - protocol: TCP
      port: 5432

NetworkPolicy’nin çalışması için cluster’ında CNI eklentisinin bunu desteklemesi gerekir. Calico, Cilium ve Weave Net bu politikaları uygular. Flannel ise varsayılan olarak desteklemez.

kubectl Context ile Verimli Çalışma

Her komuta -n namespace-adi eklemek yorucu olabilir. Context ayarlarıyla varsayılan namespace değiştirebilirsin:

# Mevcut context'i göster
kubectl config current-context

# Context için varsayılan namespace ayarla
kubectl config set-context --current --namespace=backend-dev

# Artık -n belirtmeden backend-dev namespace'inde çalışırsın
kubectl get pods

# Farklı cluster/namespace kombinasyonları için ayrı context oluşturma
kubectl config set-context backend-prod-ctx 
  --cluster=production-cluster 
  --user=backend-admin 
  --namespace=backend-prod

kubectl config use-context backend-prod-ctx

Bunun yanı sıra kubens aracını kullanmak namespace geçişlerini çok daha hızlı yapar:

# kubectx ve kubens kurulumu
brew install kubectx  # macOS
# ya da
sudo apt install kubectx  # Ubuntu/Debian

# Hızlı namespace geçişi
kubens backend-dev
kubens backend-prod
kubens -  # bir önceki namespace'e geri dön

Ekibine bunu anlattığında biri mutlaka “hocam bu araç olmadan nasıl yaşıyordunuz” diyecektir. Haklı da.

Gerçek Dünya Senaryosu: Multi-Tenant Cluster Yapısı

Bir SaaS şirketinde çalıştığını düşün. Müşterilerin her biri aynı cluster’da izole ortam istiyor. İşte pratik bir namespace stratejisi:

# Müşteri bazlı namespace oluşturma scripti
#!/bin/bash

CUSTOMER=$1
ENVIRONMENT=${2:-dev}
NAMESPACE="${CUSTOMER}-${ENVIRONMENT}"

# Namespace oluştur
kubectl create namespace $NAMESPACE

# Label ekle
kubectl label namespace $NAMESPACE 
  customer=$CUSTOMER 
  environment=$ENVIRONMENT 
  managed-by=platform-team

# ResourceQuota uygula
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ResourceQuota
metadata:
  name: ${NAMESPACE}-quota
  namespace: ${NAMESPACE}
spec:
  hard:
    requests.cpu: "4"
    requests.memory: 8Gi
    limits.cpu: "8"
    limits.memory: 16Gi
    pods: "20"
    services: "10"
EOF

echo "Namespace $NAMESPACE hazır."

Bu şekilde her yeni müşteri için tekrarlanabilir, standart bir ortam oluşturabilirsin. Platform ekiplerinin hayatını kolaylaştıran bu tür scriptler git repo’nda yaşamalıdır.

Namespace’ler Arası Servis İletişimi

Aynı namespace içindeki servisler birbirini direkt servis adıyla bulur. Farklı namespace’lerdeki servislere erişmek için tam DNS adını kullanman gerekir.

Kubernetes DNS formatı:
<servis-adi>.<namespace>.svc.cluster.local

Örneğin backend-prod namespace’indeki bir servisin frontend-prod namespace’inden çağrılması:

# Aynı namespace içinde
http://api-service:8080

# Farklı namespace'den
http://api-service.backend-prod.svc.cluster.local:8080

ConfigMap’te bu adresleri tutmak deployment’ları taşınabilir kılar:

apiVersion: v1
kind: ConfigMap
metadata:
  name: service-endpoints
  namespace: frontend-prod
data:
  API_URL: "http://api-service.backend-prod.svc.cluster.local:8080"
  AUTH_URL: "http://auth-service.backend-prod.svc.cluster.local:9090"

Namespace Temizleme ve Lifecycle Yönetimi

Namespace silmek, içindeki tüm kaynakları da siler. Bu güçlü ama tehlikeli bir özelliktir.

# Namespace ve tüm içeriğini silme (DİKKATLİ OL!)
kubectl delete namespace backend-dev

# Silme işleminin durumunu takip etme
kubectl get namespace backend-dev -w

# Bazen namespace "Terminating" durumunda takılır
# Bu durumda finalizer'ları temizlemek gerekebilir
kubectl get namespace backend-dev -o json | 
  jq '.spec.finalizers = []' | 
  kubectl replace --raw /api/v1/namespaces/backend-dev/finalize -f -

Geçici ortamlar için otomatik temizleme mekanizması kurabilirsin. Örneğin bir CI/CD pipeline’ında PR namespace’leri şöyle silinebilir:

# PR kapatıldığında namespace temizleme
NAMESPACE="pr-${PR_NUMBER}"
kubectl delete namespace $NAMESPACE --ignore-not-found=true
echo "PR namespace $NAMESPACE silindi."

Namespace Stratejileri: Ne Zaman Ne Kullanmalı?

Yaygın kullanılan namespace stratejilerini madde madde değerlendirmek gerekirse:

  • Ortam bazlı (dev/staging/prod): Küçük ekipler için basit, anlaşılır. Ekipler arası izolasyon zayıf.
  • Ekip bazlı: Her ekip kendi namespace’ini yönetir. Özerklik yüksek, koordinasyon ihtiyacı azalır.
  • Uygulama bazlı: Her microservice kendi namespace’inde. Granüler kontrol sağlar ama yönetim karmaşıklaşır.
  • Hibrit (ekip + ortam): Çoğu büyük organizasyon için en uygun yaklaşım. backend-prod, frontend-staging gibi kombinasyonlar.

Küçük bir startup için basit dev/staging/prod yeterlidir. 50+ kişilik mühendislik ekibi için hibrit strateji kaçınılmazdır.

Monitoring ve Observability

Namespace bazlı izleme, maliyet takibi ve problem tespiti için kritiktir.

# Namespace bazlı kaynak kullanımını görüntüleme
kubectl top pods --all-namespaces --sort-by=memory

# Belirli namespace'in kaynak tüketimi
kubectl top pods -n backend-prod --sort-by=cpu

# Namespace'e ait tüm event'leri takip etme
kubectl get events -n backend-prod --sort-by='.lastTimestamp'

# Namespace içindeki tüm kaynakları özet görüntüleme
kubectl get all -n backend-prod

Prometheus ve Grafana kullanıyorsan, namespace label’ına göre dashboard oluşturabilirsin. Böylece her ekibin kendi kaynak kullanımını görmesi, maliyet geri dönüşlerinin (chargeback) yapılması mümkün olur.

Yaygın Hatalar ve Kaçınılması Gerekenler

Deneyimlerimden derlediğim kritik hatalar:

  • default namespace’ini production için kullanmak: İzolasyon yoktur, kaza riski çok yüksektir.
  • ResourceQuota koymadan production’a çıkmak: İlk büyük yük testinde tüm cluster çökebilir.
  • Namespace adlarında tutarsızlık: backend-prod, BackendProd, backend_prod karışıklığı Helm chart’larını ve scriptleri kırar. Küçük harf ve tire kullan.
  • Çok fazla namespace açmak: Her şey için ayrı namespace açmak yönetimi imkansız kılar. Mantıklı grupla.
  • RBAC’sız namespace: Namespace var ama herkes her namespace’e erişebiliyorsa izolasyon kağıt üzerinde kalır.
  • NetworkPolicy’yi unutmak: Pod bazlı network trafiği kısıtlanmadan namespace izolasyonu eksik kalır.

Sonuç

Kubernetes Namespace’leri, karmaşık çok ekipli ve çok ortamlı yapıları yönetilebilir hale getiren temel araçtır. Sadece kaynak izolasyonu değil, RBAC ile yetki yönetimi, ResourceQuota ile maliyet kontrolü, NetworkPolicy ile güvenlik ve LimitRange ile istikrar sağlar.

Namespace stratejin ne olursa olsun, şu üç prensibi her zaman uygula: her namespace’e ResourceQuota koy, RBAC ile minimum yetki prensibini uygula ve namespace tanımlarını mutlaka Git’te tut. Bu temeller üzerine kurulan bir cluster, ekibinin büyüklüğü ne olursa olsun ölçeklenebilir ve güvenli kalır.

Namespace yönetimini otomatize etmek için Helm chart’ları ya da Crossplane gibi araçlar bir sonraki adımdır. Ama önce temeli sağlam kur: manual namespace yönetimini anlayan biri, otomasyon araçlarını çok daha etkin kullanır. Sysadmin’in en değerli yetkinliği araçları değil, temel prensipleri kavramaktır.

Yorum yapın