blue body of water during daytime — Kubernetes nedir Container Orchestration'ı kullanmaya başlayın

Şırnak merkezli, banka yan kuruluşu olarak POS + ödeme + esnaf finansman uygulamaları geliştiren bir fintech, 28 microservice’ini eski VM tabanlı deployment’tan AKS’e taşıdı. 8 aylık programın sahadaki teknik notları aşağıda.

Kubernetes Nedir? Neden?

Konu Docker standalone Kubernetes (K8s)
Multi-host orchestration Yok (Swarm sınırlı) Var (cluster)
Self-healing Manuel Otomatik (pod restart, reschedule)
Scaling Manuel HPA + cluster autoscaler
Service discovery Manuel Built-in (DNS + Service)
Rollout / rollback Manuel Built-in (Deployment)
Karmaşıklık Düşük Yüksek (öğrenme eğrisi)

AKS vs Self-Hosted K8s

Self-hosted (kubeadm, RKE2) tam kontrol verir ama operasyon yükü yüksek (control plane backup, etcd, API server upgrade). AKS managed control plane, Azure-native entegrasyon (Entra ID, Key Vault, ACR, Defender for Containers). Şirket AKS Standard tier seçti ($73/ay control plane SLA).

Cluster Topology

AKS Cluster: aks-prod-tr
Region: Northeurope (TR'ye yakın, ExpressRoute)
Kubernetes versiyon: 1.30 (auto upgrade enabled, channel: stable)

Networking:
  - Network plugin: Azure CNI Overlay
  - Network policy: Cilium (BPF-based, advanced)
  - Service CIDR: 10.0.0.0/16
  - Pod CIDR: 10.244.0.0/16 (overlay, VNet IP yemiyor)

API Server: Private (no public)
Ingress: Application Gateway Ingress Controller (AGIC) + WAF

Node Pool Tasarımı

Pool SKU Sayı Workload
system D4s_v5 3 (zone-spread) kube-system, ingress, monitoring
app-default D8s_v5 4-15 (autoscale) Standart microservice
app-memory E16s_v5 (memory-opt) 2-6 In-memory cache, ML inference
spot-batch D8s_v5 Spot 0-10 (autoscale) Non-critical batch, ETL

Pod Resource Management

apiVersion: apps/v1
kind: Deployment
metadata:
  name: payment-api
  namespace: payment
spec:
  replicas: 3
  selector:
    matchLabels: { app: payment-api }
  template:
    metadata:
      labels: { app: payment-api }
    spec:
      nodeSelector:
        agentpool: app-default
      containers:
      - name: api
        image: acrprod.azurecr.io/payment-api:1.4.2
        ports: [{ containerPort: 8080 }]
        resources:
          requests: { cpu: "200m", memory: "256Mi" }
          limits:   { cpu: "1000m", memory: "1Gi" }
        readinessProbe:
          httpGet: { path: /health/ready, port: 8080 }
          initialDelaySeconds: 5
          periodSeconds: 5
        livenessProbe:
          httpGet: { path: /health/live, port: 8080 }
          initialDelaySeconds: 30
          periodSeconds: 10
        env:
        - name: ConnectionStrings__Db
          valueFrom:
            secretKeyRef: { name: payment-secrets, key: db-conn }

Horizontal Pod Autoscaler

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: payment-api-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: payment-api
  minReplicas: 3
  maxReplicas: 30
  metrics:
  - type: Resource
    resource:
      name: cpu
      target: { type: Utilization, averageUtilization: 70 }
  - type: Resource
    resource:
      name: memory
      target: { type: Utilization, averageUtilization: 80 }
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 50
        periodSeconds: 60

Ingress (AGIC + WAF)

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: payment-ingress
  annotations:
    kubernetes.io/ingress.class: azure/application-gateway
    appgw.ingress.kubernetes.io/ssl-redirect: "true"
    appgw.ingress.kubernetes.io/waf-policy-for-path: "/subscriptions/.../wafPolicy"
    appgw.ingress.kubernetes.io/health-probe-path: "/health/live"
spec:
  tls:
  - hosts: [api.fintech.com.tr]
    secretName: tls-api
  rules:
  - host: api.fintech.com.tr
    http:
      paths:
      - path: /payment
        pathType: Prefix
        backend:
          service:
            name: payment-api
            port: { number: 80 }

Secret Management (Key Vault CSI)

apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: payment-kv
spec:
  provider: azure
  parameters:
    usePodIdentity: "false"
    useVMManagedIdentity: "true"
    userAssignedIdentityID: ""
    keyvaultName: "kv-prod-fintech"
    objects: |
      array:
        - |
          objectName: db-connection-string
          objectType: secret
        - |
          objectName: payment-api-key
          objectType: secret
    tenantId: ""
  secretObjects:
  - secretName: payment-secrets
    type: Opaque
    data:
    - objectName: db-connection-string
      key: db-conn
    - objectName: payment-api-key
      key: api-key

Avantaj: K8s Secret olarak direkt yazmaktan daha güvenli. Key Vault’tan canlı çekiliyor, döndürmeler otomatik.

RBAC + Entra ID

AKS Entra ID integration:
  - Cluster admin: Entra group "aks-cluster-admin" (3 kişi)
  - Namespace admin (payment): Entra group "team-payment"
  - Read-only (auditor): Entra group "aks-readonly"

kubectl auth check:
  kubectl get pods -n payment  # team-payment user → izin var
  kubectl delete deploy/x -n trading  # team-payment user → izin yok

Observability

Metric / log Araç
Container log Container Insights → Log Analytics
Metric (Prometheus) Azure Managed Prometheus + Grafana
Tracing OpenTelemetry → App Insights
Alert Azure Monitor alert + Teams webhook

Security: Defender for Containers

  • Image scan (CVE) on push to ACR
  • Runtime threat detection (suspicious pod, lateral movement)
  • Compliance benchmark (CIS, PCI DSS)
  • Network policy gap analizi

Sonuçlar (8 Ay)

Metrik Önce (VM) Sonra (AKS)
Deployment frequency ~~haftada 1 ~~günde 4-6
Mean Time to Recovery ~~45 dk ~~3 dk (rollback)
Resource utilization (avg CPU) ~~%18 ~~%52 (bin packing)
VM sayısı ~~28 ~~12 (node pool)
Aylık compute maliyet ~~$8.500 ~~$5.200
Black Friday peak handling Manuel scale 2 saat Auto-scale 3 dk

Sahada Düşülen Üç Tuzak

  1. Resource request/limit eksik bırakmak: Pod’lar çakışır, OOMKill olur, scheduler kötü kararlar verir. Her container’a request + limit zorunlu.
  2. Probe (readiness/liveness) eklememek: Pod up sanılır ama trafik kabul etmiyor, ya da app dead ama K8s restart etmiyor. Probe’lar Day 1.
  3. Tek cluster’a her şeyi sıkıştırmak: Dev + test + prod aynı cluster’da, namespace ile ayrım yetmez. Cluster ayrımı (en az prod ayrı) güvenlik + blast radius.

CloudSpark olarak AKS cluster tasarımı, node pool stratejisi, Azure CNI Overlay + Cilium, ingress + WAF, Key Vault CSI integration, RBAC ve observability stack için danışmanlık veriyoruz.

🇹🇷 Türkçe🇬🇧 English🇩🇪 Deutsch🇫🇷 Français🇸🇦 العربية🇷🇺 Русский🇪🇸 Español