Konteynerleştirme, bir uygulamayı bağımlılıkları ve çalışma ortamıyla birlikte taşınabilir tek bir pakete koymaktır. “Benim makinemde çalışıyordu” sorunu biter: geliştirmede, testte ve üretimde aynı imaj çalışır. Bu yazı Docker ile imaj hazırlamayı ve Kubernetes ile o imajları ölçekte yönetmeyi anlatıyor.
Neden konteyner
Sanal makineler her biri tam bir işletim sistemi taşır; konteynerler ise ana makinenin çekirdeğini paylaşır. Bu yüzden saniyeler içinde açılır, daha az kaynak harcar ve aynı sunucuda daha fazla iş çalıştırır. Asıl kazanç ise tutarlılıktır: imaj bir kez derlenir, her ortamda aynı biçimde çalışır.
Docker ile başlangıç
Uygulamanın ortamı bir Dockerfile ile tanımlanır. Node.js uygulaması için üretime uygun bir örnek:
FROM node:22-alpine
WORKDIR /app
ENV NODE_ENV=production
# Önce yalnız bağımlılık dosyaları: kod değişince bu katman önbellekten gelir
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
USER node # kök kullanıcıyla çalıştırma
EXPOSE 3000
CMD ["node", "server.js"]
Bu dosya:
- Hafif bir Alpine tabanlı Node.js imajıyla başlar
- Bağımlılıkları kilit dosyasına göre (
npm ci) ve yalnız üretim için kurar - Bağımlılık katmanını koddan önce koyarak derlemeyi hızlandırır
- Uygulamayı ayrıcalıksız
nodekullanıcısıyla çalıştırır
Derleyip çalıştırmak için:
docker build -t my-app:1.0 .
docker run -p 3000:3000 my-app:1.0
Bir de .dockerignore dosyası ekleyin; node_modules, .git ve .env gibi dosyalar imaja girmemeli.
Kubernetes ne yapar
Docker konteyneri hazırlar, Kubernetes çok sayıda konteyneri bir küme üzerinde yönetir:
- Otomatik ölçekleme: yüke göre kopya sayısını artırıp azaltır
- Kendini onarma: çöken konteyneri yeniden başlatır
- Kesintisiz güncelleme: yeni sürümü kopyaları sırayla değiştirerek yayınlar
- Servis keşfi: konteynerler arası ağı ve DNS’i yönetir
- Depolama: kalıcı diskleri konteynerlere bağlar
Temel kavramlar
Pod: Kubernetes’in en küçük dağıtım birimi; genellikle tek bir konteyner taşır.
Deployment: pod’ların istenen durumunu (imaj, kopya sayısı) tanımlar; Kubernetes bu durumu sürekli korur.
Service: pod’lara sabit bir adres ve DNS adı verir.
ConfigMap ve Secret: yapılandırmayı ve gizli bilgileri koddan ayırır. Secret’lar yalnız base64 ile kodlanır, şifrelenmez; gerçek sırlar için bir sır yöneticisi (Vault, Sealed Secrets, bulut KMS) kullanın.
Örnek dağıtım
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 3
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
securityContext:
runAsNonRoot: true
containers:
- name: web-app
image: registry.example.com/web-app:1.0.3 # "latest" değil, sabit sürüm
ports:
- containerPort: 3000
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
readinessProbe:
httpGet: { path: /ready, port: 3000 }
periodSeconds: 5
livenessProbe:
httpGet: { path: /health, port: 3000 }
initialDelaySeconds: 15
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: web-app
spec:
selector:
app: web-app
ports:
- port: 80
targetPort: 3000
Bu yapılandırma üç kopyayla erişilebilirliği sağlar, kaynak isteklerini tanımlar ve iki ayrı sağlık kontrolü ekler. Hazırlık kontrolü (readiness) başarısız olan pod trafikten çıkarılır; canlılık kontrolü (liveness) başarısız olan pod yeniden başlatılır. Canlılık kontrolünü veritabanı gibi dış bağımlılıklara bağlamayın; aksi hâlde veritabanı yavaşladığında tüm pod’lar art arda yeniden başlar.
İyi uygulamalar
Küçük imaj: Alpine ya da distroless gibi küçük taban imajları ve çok aşamalı (multi-stage) derleme; küçük imaj daha hızlı dağıtılır ve daha az zafiyet taşır.
Güvenlik: imajları zafiyet taramasından geçirin, kök kullanıcıyla çalıştırmayın, sırları asla Dockerfile’a yazmayın.
Kaynak yönetimi: her konteynere bellek isteği ve sınırı tanımlayın. İşlemci sınırı yük altında yavaşlamaya yol açabileceği için çoğu durumda yalnız istek tanımlamak yeter.
Sabit sürüm etiketleri: üretimde latest kullanmayın; hangi sürümün çalıştığını bilmek ve geri almak için sabit etiket ya da imaj özeti (digest) kullanın.
Kayıt ve izleme: uygulama kaydını standart çıktıya yazın, Prometheus ve merkezi kayıt sistemiyle toplayın.
Nereden başlamalı
Küme yönetimini devretmek istiyorsanız Amazon EKS, Google GKE ya da Azure AKS gibi yönetilen bir Kubernetes servisiyle başlayın. Öğrenmek için yerelde kind, Minikube ya da Docker Desktop’ın Kubernetes desteği yeterlidir. Kubernetes küçük ekipler için ağır olabilir; tek bir uygulama çalıştırıyorsanız yönetilen bir konteyner servisi daha basit bir başlangıçtır.
Sonuç
Docker konteyner standardını, Kubernetes ise ölçekte işletmeyi sağlar. Birlikte daha güvenilir dağıtım, daha hızlı ölçekleme ve daha az elle iş demektir. Konteynerleştirmeyle küçük başlayın, Kubernetes’i ihtiyaç doğdukça benimseyin.
Konteyner ve Kubernetes geçişinizi birlikte planlamak isterseniz bize yazın.
ByteGurus
Yazar