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 deletekomutunu ç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-staginggibi 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_prodkarışı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.