Detailed image of a server rack with glowing lights in a modern data center.

“Geliştirme bitti, prod’a nasıl çıkıyoruz?” sorusunun cevabı 2026’da hâlâ “dev’e SCP, prod’da git pull” olmamalı. Modern CI/CD pipeline, kod değişikliğinin commit’ten production’a güvenli, izlenebilir ve geri alınabilir biçimde geçişini sağlar. Bu yazıda bir SaaS müşterimizde kurduğumuz pipeline’ı tüm bileşenleriyle paylaşıyorum: GitHub Actions, Argo CD, CloudSpark Kubernetes (CSPK), HashiCorp Vault, Prometheus.

Pipeline’ın 7 Aşaması

Aşama Araç Süre (tipik)
1. Code commit + PR GitHub
2. CI: build + unit test + lint GitHub Actions 3-5 dk
3. Container image build + scan GitHub Actions + Trivy 2-4 dk
4. Image push to registry CloudSpark Container Registry 30-60 sn
5. Manifest update (image tag) GitHub Actions (commit to gitops repo) 10 sn
6. CD: GitOps reconciliation Argo CD 30-60 sn
7. Smoke test + alert Synthetic monitoring 1-3 dk

Toplam commit-to-production: ~~10-15 dakika (canary aşaması dahil ~~30 dk).

GitHub Actions Workflow

name: CI/CD
on:
  push:
    branches: [main]
    tags: ['v*']
  pull_request:
    branches: [main]

env:
  REGISTRY: registry.cloudspark.com.tr
  IMAGE: api-service

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - run: npm run lint
      - run: npm test -- --coverage
      - uses: codecov/codecov-action@v4

  build-and-push:
    needs: test
    if: github.event_name == 'push'
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ secrets.REGISTRY_USER }}
          password: ${{ secrets.REGISTRY_PASS }}
      
      - name: Compute tags
        id: tags
        run: |
          if [[ "${{ github.ref }}" == refs/tags/* ]]; then
            echo "tag=${{ github.ref_name }}" >> $GITHUB_OUTPUT
            echo "env=production" >> $GITHUB_OUTPUT
          else
            SHORT_SHA=$(git rev-parse --short HEAD)
            echo "tag=main-${SHORT_SHA}" >> $GITHUB_OUTPUT
            echo "env=staging" >> $GITHUB_OUTPUT
          fi
      
      - uses: docker/build-push-action@v5
        with:
          push: true
          tags: ${{ env.REGISTRY }}/${{ env.IMAGE }}:${{ steps.tags.outputs.tag }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
      
      - name: Trivy scan
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE }}:${{ steps.tags.outputs.tag }}
          severity: 'CRITICAL,HIGH'
          exit-code: '1'
      
      - name: Update gitops manifest
        env:
          GITOPS_TOKEN: ${{ secrets.GITOPS_TOKEN }}
        run: |
          git clone https://x:${GITOPS_TOKEN}@github.com/myorg/gitops.git
          cd gitops
          yq eval -i '.spec.template.spec.containers[0].image = "${{ env.REGISTRY }}/${{ env.IMAGE }}:${{ steps.tags.outputs.tag }}"' apps/api/${{ steps.tags.outputs.env }}/deployment.yaml
          git config user.email "ci@example.com"
          git config user.name "CI Bot"
          git add .
          git commit -m "chore: update api-service image to ${{ steps.tags.outputs.tag }}"
          git push

GitOps: Argo CD ile Reconciliation

Pipeline image tag’ini gitops repo’ya commit eder. Argo CD bu repo’yu izliyor, değişiklik tespit edince cluster’a apply ediyor.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: api-service-prod
  namespace: argocd
spec:
  project: production
  source:
    repoURL: https://github.com/myorg/gitops.git
    targetRevision: main
    path: apps/api/production
  destination:
    server: https://kubernetes.default.svc
    namespace: api-prod
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
    retry:
      limit: 5
      backoff:
        duration: 30s
        maxDuration: 5m
        factor: 2

selfHeal=true: Cluster state ile manifest farklıysa Argo CD otomatik manifest’e dönderiyor. Drift önleme.

prune=true: Manifest’ten kaldırılan resource cluster’dan da silinir.

Multi-Environment Promotion

Klasik akış: dev → staging → production. Her ortam ayrı namespace, ayrı manifest klasörü.

gitops/
├── apps/
│   └── api/
│       ├── base/
│       │   ├── deployment.yaml
│       │   ├── service.yaml
│       │   └── kustomization.yaml
│       ├── dev/
│       │   ├── kustomization.yaml  # base + dev-specific patches
│       │   └── deployment.yaml     # image tag: main-abc123
│       ├── staging/
│       │   └── deployment.yaml     # image tag: main-xyz789
│       └── production/
│           └── deployment.yaml     # image tag: v1.4.7

Promotion: Staging’de doğrulanan image tag’i production manifest’ine kopyalanıyor (manuel commit veya automation script ile).

Canary Deployment

Production’a yeni versiyon çıkarken hep aynı anda %100’üne değil, önce %10’una vermek. Trafik gözlemlenir, problem yoksa kademeli olarak %100’e çıkılır.

Argo Rollouts ile canary tanımı:

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: api-service
spec:
  replicas: 10
  strategy:
    canary:
      steps:
      - setWeight: 10
      - pause: {duration: 5m}
      - setWeight: 25
      - pause: {duration: 10m}
      - setWeight: 50
      - pause: {duration: 10m}
      - setWeight: 100
      analysis:
        templates:
        - templateName: success-rate
        startingStep: 1
        args:
        - name: service-name
          value: api-service
  template:
    spec:
      containers:
      - name: api
        image: registry.cloudspark.com.tr/api-service:v1.4.7

analysis: Prometheus query çalıştırır (“HTTP 5xx oranı %1’i geçti mi?”). Geçti ise rollback otomatik.

Secret Yönetimi: HashiCorp Vault

Database password, API key gibi secret’lar manifest içine yazılmaz. Vault’tan çekilir.

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: api-db-creds
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-backend
    kind: ClusterSecretStore
  target:
    name: api-db-creds
  data:
  - secretKey: DB_PASSWORD
    remoteRef:
      key: secret/data/api/prod
      property: db_password

External Secrets Operator Vault’tan secret’ı çeker, Kubernetes Secret olarak cluster’a yazar. Pod env var olarak alır. Vault’taki secret rotate edildiğinde 1 saat içinde otomatik güncellenir.

Rollback Otomasyonu

Argo Rollouts canary analysis fail olduğunda otomatik rollback. Manuel rollback gerekirse:

# Önceki revision'a dön
kubectl argo rollouts undo api-service -n api-prod

# Veya specific revision
kubectl argo rollouts undo api-service -n api-prod --to-revision=5

# Rollback durumunu izle
kubectl argo rollouts status api-service -n api-prod -w

SaaS müşterimizde 2 ayda 4 production rollback yapıldı (hepsi otomatik canary fail sonucu, kullanıcı etkilenmedi).

Sahada Düşülen Üç Tuzak

  1. Pipeline yavaş: 30+ dakika commit-to-prod kabul edilemez. Test parallelization, layer caching, image scan’i async.
  2. Manuel onay her aşamada: “Güvenlik için” diye 5 ayrı manuel onay koymak akışı durdurur. Otomatik gate (test pass, security scan pass) ile akış sürmeli, sadece production’a deploy son onay gerekirse.
  3. Rollback test edilmiyor: Otomatik rollback var sanıyorsun, ihtiyaç anında “yanlış yere döndü” yaşıyorsun. Quarter’da 1 rollback drill.

Sonuç: CI/CD Bir Lüks Değil, Modern Yazılım Geliştirmenin Şartı

Manuel deployment 2026’da kabul edilemez. Pipeline kurulduktan sonra geliştirici “kod yazıyorum, prod’a 15 dakika sonra çıkıyor” deneyimini yaşıyor. Bu deneyim ekip moralini, geliştirme hızını, kalite metriklerini doğrudan etkiliyor.

SaaS müşterimizde CI/CD öncesi haftalık 3 release, sonrası günlük 8-12 release. Production incident sayısı azaldı (küçük değişiklikler daha az risk).

CloudSpark olarak GitHub Actions / Azure DevOps / GitLab pipeline kurulumu, GitOps (Argo CD, Flux), CSPK üzerinde Kubernetes deployment ve secret management projelerinde end-to-end danışmanlık veriyoruz.

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