# ARTICLE_LOADED
> cat gitops-argocd-kubernetes.md
> rendering content...
status: READING_MODE
security_level: PUBLIC
engagement_tracking: ENABLED
article@tektik:/var/blog/gitops-argocd-kubernetes$
cat metadata.json
"category": "Kubernetes"
"date": "2026-02-16"
"read_time": "14 dk okuma"
"author": "TekTık Yazılım DevOps Ekibi"
Kubernetes16 Şubat 2026

GitOps ve ArgoCD: Modern Kubernetes Deployment Stratejisi

echo"GitOps metodolojisi ve ArgoCD ile Kubernetes deployment'larınızı nasıl otomatikleştirir, güvenli hale getirir ve yönetilebilir kılarsınız? Pratik örnekler ve production best practices ile kapsamlı rehber."
#GitOps#ArgoCD#Kubernetes#CI/CD#DevOps#Automation
14 dk okuma
TekTık Yazılım DevOps Ekibi
content@tektik:/var/articles/gitops-argocd-kubernetes.md$
./render-article --format=html --style=cyber

GitOps ve ArgoCD: Modern Kubernetes Deployment Stratejisi

Kubernetes deployment'larını yönetmek karmaşık ve hata riski yüksek bir süreç olabilir. GitOps metodolojisi ve ArgoCD gibi araçlar, bu süreci Git tabanlı, otomatik ve güvenilir hale getirerek modern DevOps pratiklerinin merkezine yerleşti. Bu yazıda, GitOps prensiplerini ve ArgoCD'nin production ortamlarında nasıl kullanılacağını derinlemesine inceleyeceğiz.

İçindekiler

  1. GitOps Nedir ve Neden Önemli?
  2. ArgoCD'ye Giriş
  3. ArgoCD Kurulumu ve İlk Yapılandırma
  4. Application Tanımlama ve Deployment
  5. Multi-Environment Yönetimi (Dev/Staging/Prod)
  6. Secrets Yönetimi ve Güvenlik
  7. Progressive Delivery: Canary ve Blue-Green
  8. Monitoring ve Notifications
  9. Production Best Practices
  10. Troubleshooting ve Common Issues

GitOps Nedir ve Neden Önemli? {#gitops-nedir}

GitOps Prensipleri

GitOps, infrastructure ve application deployment'larını yönetmek için Git'i tek doğru kaynak (single source of truth) olarak kullanan bir metodoloji. Temel prensipleri:

1. Declarative Configuration

  • Tüm sistem durumu Git repository'lerinde YAML/JSON olarak tanımlanır
  • Imperative komutlar yerine desired state tanımlanır

2. Version Control

  • Her değişiklik Git commit'i olarak kaydedilir
  • Tam audit trail ve rollback yeteneği
  • Code review süreçleri otomatik uygulanır

3. Automated Sync

  • Git'teki değişiklikler otomatik olarak cluster'a uygulanır
  • Cluster state sürekli Git ile senkronize edilir
  • Drift detection: Cluster'daki manuel değişiklikler tespit edilir

4. Continuous Reconciliation

  • Sistem sürekli olarak desired state'e çekilir
  • Self-healing capabilities

GitOps vs Traditional CI/CD

AspectTraditional CI/CDGitOps
**Deployment Trigger**CI pipeline pushGit commit
**Access Control**CI tool cluster erişimiGit permissions
**Audit**CI logsGit history
**Rollback**Manual/scriptGit revert
**State Drift**Tespit edilemezOtomatik tespit + düzeltme
**Security**CI credentialsPull-based (daha güvenli)

GitOps'un Avantajları

Tam Auditability: Kim, ne, ne zaman değiştirdi? → Git history
Kolay Rollback: git revert ile anında geri alma
Code Review: Deployment değişiklikleri PR review sürecinden geçer
Disaster Recovery: Git clone → apply, cluster yeniden oluşur
Security: Pull-based model, cluster credentials CI'da tutulmaz
Developer Experience: Developers know Git, not kubectl commands

ArgoCD'ye Giriş {#argocd-giris}

ArgoCD Nedir?

ArgoCD, Kubernetes için declarative GitOps continuous delivery tool'u. CNCF graduated project statüsünde ve production-ready.

Temel Özellikler:

  • Git repository'leri Kubernetes cluster'ı ile senkronize eder
  • Web UI ve CLI ile kolay yönetim
  • Multi-cluster support
  • SSO/RBAC integration
  • Automated sync, health monitoring
  • Helm, Kustomize, Jsonnet support

ArgoCD Architecture

text
┌─────────────────────────────────────────────┐
│           Git Repository                     │
│  ┌──────────────────────────────────────┐   │
│  │ manifests/                           │   │
│  │  ├── dev/                            │   │
│  │  ├── staging/                        │   │
│  │  └── production/                     │   │
│  └──────────────────────────────────────┘   │
└────────────────┬────────────────────────────┘
                 │ Git Poll/Webhook
                 ▼
┌─────────────────────────────────────────────┐
│        ArgoCD Control Plane                 │
│  ┌──────────────────────────────────────┐   │
│  │ API Server                           │   │
│  │ Repository Server                    │   │
│  │ Application Controller               │   │
│  └──────────────────────────────────────┘   │
└────────────────┬────────────────────────────┘
                 │ Apply manifests
                 ▼
┌─────────────────────────────────────────────┐
│      Kubernetes Cluster (Target)            │
│  ┌──────────────────────────────────────┐   │
│  │ Deployments, Services, ConfigMaps    │   │
│  │ Ingress, Secrets, etc.               │   │
│  └──────────────────────────────────────┘   │
└─────────────────────────────────────────────┘

Components:

  • API Server: Web UI ve CLI için gRPC/REST API
  • Repository Server: Git repo'lardan manifest'leri çeker
  • Application Controller: Kubernetes controller, Git vs cluster state'i karşılaştırır

ArgoCD Kurulumu ve İlk Yapılandırma {#argocd-kurulum}

Kubernetes Cluster'a ArgoCD Kurulumu

Prerequisites:

  • Kubernetes 1.21+ cluster
  • kubectl access
  • (Opsiyonel) Ingress controller

1. ArgoCD Namespace ve Core Components:

bash
# ArgoCD namespace oluştur
kubectl create namespace argocd

# ArgoCD install (stable release)
kubectl apply -n argocd -f \
  https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# Installation durumunu kontrol et
kubectl get pods -n argocd

# Çıktı:
# NAME                                  READY   STATUS    RESTARTS   AGE
# argocd-application-controller-0       1/1     Running   0          2m
# argocd-dex-server-xxx                 1/1     Running   0          2m
# argocd-redis-xxx                      1/1     Running   0          2m
# argocd-repo-server-xxx                1/1     Running   0          2m
# argocd-server-xxx                     1/1     Running   0          2m

2. ArgoCD CLI Kurulumu:

bash
# Linux
curl -sSL -o argocd-linux-amd64 \
  https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
sudo install -m 555 argocd-linux-amd64 /usr/local/bin/argocd
rm argocd-linux-amd64

# macOS
brew install argocd

# Verify
argocd version

3. ArgoCD Server'a Erişim:

Option A: Port-Forward (Development)

bash
kubectl port-forward svc/argocd-server -n argocd 8080:443

# Browser'da aç: https://localhost:8080

Option B: LoadBalancer (Cloud)

bash
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'

# External IP'yi al
kubectl get svc argocd-server -n argocd

Option C: Ingress (Production Recommended)

yaml
# argocd-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-ingress
  namespace: argocd
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
  ingressClassName: nginx
  rules:
  - host: argocd.tektik.tr
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              name: https
  tls:
  - hosts:
    - argocd.tektik.tr
    secretName: argocd-tls
bash
kubectl apply -f argocd-ingress.yaml

4. İlk Login:

bash
# Default admin password'u al (auto-generated)
kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath="{.data.password}" | base64 -d; echo

# CLI ile login
argocd login argocd.tektik.tr

# Username: admin
# Password: <yukarıdaki output>

# Admin password'u değiştir (MUTLAKA!)
argocd account update-password

5. Initial Admin Secret'i Sil (Security Best Practice):

bash
kubectl -n argocd delete secret argocd-initial-admin-secret

Application Tanımlama ve Deployment {#application-deployment}

Basit Bir Application Deploy Etmek

Senaryo: Nginx web uygulamasını GitOps ile deploy edeceğiz.

1. Git Repository Hazırlığı:

bash
# Git repo oluştur
mkdir -p gitops-demo/apps/nginx
cd gitops-demo

git init

2. Kubernetes Manifest'leri Oluştur:

yaml
# apps/nginx/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 200m
            memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: default
spec:
  type: ClusterIP
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80
bash
# Commit ve push
git add .
git commit -m "Add nginx application manifests"
git remote add origin https://github.com/your-org/gitops-demo.git
git push -u origin main

3. ArgoCD Application Oluştur:

Method 1: CLI

bash
argocd app create nginx-app \
  --repo https://github.com/your-org/gitops-demo.git \
  --path apps/nginx \
  --dest-server https://kubernetes.default.svc \
  --dest-namespace default \
  --sync-policy automated \
  --auto-prune \
  --self-heal

Method 2: YAML (Declarative - Recommended)

yaml
# argocd-apps/nginx-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: nginx-app
  namespace: argocd
spec:
  project: default
  
  source:
    repoURL: https://github.com/your-org/gitops-demo.git
    targetRevision: main
    path: apps/nginx
  
  destination:
    server: https://kubernetes.default.svc
    namespace: default
  
  syncPolicy:
    automated:
      prune: true      # Git'ten silinen kaynaklar cluster'dan da silinir
      selfHeal: true   # Cluster'daki manuel değişiklikler otomatik düzeltilir
      allowEmpty: false
    
    syncOptions:
    - CreateNamespace=true
    
    retry:
      limit: 5
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m
bash
kubectl apply -f argocd-apps/nginx-app.yaml

# Application durumunu kontrol et
argocd app get nginx-app

# Web UI'dan izle
# https://argocd.tektik.tr → Applications → nginx-app

4. Sync Durumunu İzle:

bash
# CLI ile watch
argocd app sync nginx-app --watch

# Application health check
argocd app wait nginx-app --health

# Deployed resources
kubectl get deploy,svc -n default -l app=nginx

Application Self-Healing Testi

bash
# Manuel olarak replica count'u değiştir (drift oluştur)
kubectl scale deployment nginx --replicas=5 -n default

# ArgoCD 3 dakika içinde (default polling interval) bunu tespit edip
# Git'teki desired state'e (replicas: 3) geri döndürecek

# Anında sync için:
argocd app sync nginx-app

Multi-Environment Yönetimi (Dev/Staging/Prod) {#multi-environment}

Kustomize ile Environment Separation

Repository Structure:

text
gitops-demo/
├── base/                        # Ortak base manifests
│   ├── deployment.yaml
│   ├── service.yaml
│   └── kustomization.yaml
├── overlays/                    # Environment-specific overrides
│   ├── dev/
│   │   ├── kustomization.yaml
│   │   ├── replica-count.yaml
│   │   └── resources.yaml
│   ├── staging/
│   │   ├── kustomization.yaml
│   │   └── replica-count.yaml
│   └── production/
│       ├── kustomization.yaml
│       ├── replica-count.yaml
│       ├── hpa.yaml
│       └── ingress.yaml
└── argocd-apps/
    ├── dev-app.yaml
    ├── staging-app.yaml
    └── prod-app.yaml

base/deployment.yaml:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 1  # Override edilecek
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: 100m
            memory: 128Mi

base/kustomization.yaml:

yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- deployment.yaml
- service.yaml

overlays/production/kustomization.yaml:

yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

namespace: production

bases:
- ../../base

replicas:
- name: nginx
  count: 5

images:
- name: nginx
  newTag: 1.25-alpine  # Lightweight image for prod

resources:
- hpa.yaml
- ingress.yaml

commonLabels:
  environment: production
  managed-by: argocd

patches:
- path: resources.yaml
  target:
    kind: Deployment
    name: nginx

overlays/production/resources.yaml:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      containers:
      - name: nginx
        resources:
          requests:
            cpu: 500m
            memory: 512Mi
          limits:
            cpu: 1000m
            memory: 1Gi

overlays/production/hpa.yaml:

yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: nginx-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx
  minReplicas: 5
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70

ArgoCD Application for Production:

yaml
# argocd-apps/prod-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: nginx-production
  namespace: argocd
spec:
  project: default
  
  source:
    repoURL: https://github.com/your-org/gitops-demo.git
    targetRevision: main
    path: overlays/production  # Kustomize overlay path
  
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true

App of Apps Pattern (Multi-App Management)

argocd-apps/app-of-apps.yaml:

yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: app-of-apps
  namespace: argocd
spec:
  project: default
  
  source:
    repoURL: https://github.com/your-org/gitops-demo.git
    targetRevision: main
    path: argocd-apps  # Tüm app definition'ları burada
  
  destination:
    server: https://kubernetes.default.svc
    namespace: argocd
  
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Bu pattern ile tek bir ArgoCD Application, diğer tüm Application'ları yönetir. Yeni uygulama eklemek için sadece argocd-apps/ dizinine YAML eklersiniz.

Secrets Yönetimi ve Güvenlik {#secrets-management}

Problem: Git'te Secret Saklamak

Asla Git'te plain-text secret saklamayın!

yaml
# ❌ YANLIŞ - Git'e commit etmeyin!
apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
stringData:
  username: admin
  password: super-secret-password

Çözüm 1: Sealed Secrets (Bitnami)

Sealed Secrets, secret'ları encrypt ederek Git'te güvenle saklamanıza olanak tanır.

Kurulum:

bash
# Sealed Secrets controller
kubectl apply -f \
  https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.24.0/controller.yaml

# CLI (kubeseal)
wget https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.24.0/kubeseal-0.24.0-linux-amd64.tar.gz
tar -xvzf kubeseal-0.24.0-linux-amd64.tar.gz
sudo install -m 755 kubeseal /usr/local/bin/kubeseal

Secret Encrypt Etme:

bash
# Plain secret oluştur (local, Git'e commit etme!)
kubectl create secret generic db-credentials \
  --from-literal=username=admin \
  --from-literal=password=super-secret-password \
  --dry-run=client -o yaml > secret.yaml

# Encrypt et → SealedSecret
kubeseal -f secret.yaml -w sealed-secret.yaml \
  --controller-name=sealed-secrets-controller \
  --controller-namespace=kube-system

# sealed-secret.yaml artık Git'e commit edilebilir!
cat sealed-secret.yaml

sealed-secret.yaml (Git'e commit edilebilir):

yaml
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  name: db-credentials
  namespace: default
spec:
  encryptedData:
    username: AgBy3i4OJSWK+PiTySYZ...  # Encrypted
    password: AgAj5e8K2JN4P+qTyQw...  # Encrypted
  template:
    metadata:
      name: db-credentials
      namespace: default
    type: Opaque

ArgoCD Integration:

yaml
# ArgoCD automatically detects and applies SealedSecrets
# Controller decrypts them in-cluster → regular Secrets

Çözüm 2: External Secrets Operator (ESO)

External secrets'ı cloud provider secret stores'dan (AWS Secrets Manager, Azure Key Vault, GCP Secret Manager, HashiCorp Vault) çeker.

Kurulum:

bash
helm repo add external-secrets \
  https://charts.external-secrets.io

helm install external-secrets \
  external-secrets/external-secrets \
  -n external-secrets-system \
  --create-namespace

AWS Secrets Manager Example:

yaml
# SecretStore tanımla (AWS Secrets Manager'a bağlan)
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: aws-secretstore
  namespace: default
spec:
  provider:
    aws:
      service: SecretsManager
      region: eu-west-1
      auth:
        jwt:
          serviceAccountRef:
            name: external-secrets-sa  # IRSA configured
---
# ExternalSecret tanımla (AWS'den çek)
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: db-credentials
  namespace: default
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secretstore
    kind: SecretStore
  target:
    name: db-credentials  # Oluşturulacak Kubernetes Secret adı
    creationPolicy: Owner
  data:
  - secretKey: username
    remoteRef:
      key: production/database  # AWS Secrets Manager key
      property: username
  - secretKey: password
    remoteRef:
      key: production/database
      property: password

ESO bu ExternalSecret'ı okuyup, AWS Secrets Manager'dan çekip Kubernetes Secret olarak oluşturur. Git'te sadece ExternalSecret definition tutulur, actual secret values AWS'de.

ArgoCD RBAC Configuration

argocd-rbac-cm ConfigMap:

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-rbac-cm
  namespace: argocd
data:
  policy.default: role:readonly
  
  policy.csv: |
    # Developers: read-only access
    p, role:developer, applications, get, */*, allow
    p, role:developer, applications, sync, */dev/*, allow
    g, developers-team, role:developer
    
    # DevOps: full access to dev/staging
    p, role:devops, applications, *, */dev/*, allow
    p, role:devops, applications, *, */staging/*, allow
    p, role:devops, applications, get, */production/*, allow
    g, devops-team, role:devops
    
    # Admins: full access
    p, role:admin, applications, *, */*, allow
    g, admins-team, role:admin

Progressive Delivery: Canary ve Blue-Green {#progressive-delivery}

Argo Rollouts ile Canary Deployment

Argo Rollouts Kurulumu:

bash
kubectl create namespace argo-rollouts

kubectl apply -n argo-rollouts -f \
  https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml

# Rollouts CLI
curl -LO https://github.com/argoproj/argo-rollouts/releases/latest/download/kubectl-argo-rollouts-linux-amd64
sudo install -m 755 kubectl-argo-rollouts-linux-amd64 /usr/local/bin/kubectl-argo-rollouts

Canary Rollout Definition:

yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: nginx-rollout
spec:
  replicas: 10
  revisionHistoryLimit: 3
  
  selector:
    matchLabels:
      app: nginx
  
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80
  
  strategy:
    canary:
      steps:
      - setWeight: 20      # %20 traffic to canary
      - pause: {duration: 5m}
      
      - setWeight: 40
      - pause: {duration: 5m}
      
      - setWeight: 60
      - pause: {duration: 5m}
      
      - setWeight: 80
      - pause: {duration: 5m}
      
      # Analysis başarılıysa %100'e geç
      
      canaryService: nginx-canary  # Canary pods için service
      stableService: nginx-stable  # Stable pods için service
      
      trafficRouting:
        nginx:
          stableIngress: nginx-ingress  # Stable ingress
          annotationPrefix: nginx.ingress.kubernetes.io

AnalysisTemplate (Automated Canary Validation):

yaml
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
  name: success-rate
spec:
  metrics:
  - name: success-rate
    interval: 1m
    successCondition: result >= 0.95  # %95 success rate
    failureLimit: 3
    provider:
      prometheus:
        address: http://prometheus.monitoring:9090
        query: |
          sum(rate(http_requests_total{status=~"2.."}[1m]))
          /
          sum(rate(http_requests_total[1m]))

Rollout ile Analysis Integration:

yaml
spec:
  strategy:
    canary:
      steps:
      - setWeight: 20
      - pause: {duration: 2m}
      
      - analysis:
          templates:
          - templateName: success-rate
          args:
          - name: service-name
            value: nginx-canary
      
      - setWeight: 50
      # ...

Rollout Yönetimi:

bash
# Image update (GitOps ile)
# Git'te image tag'i değiştir → ArgoCD sync → Canary rollout başlar

# Rollout durumu izle
kubectl argo rollouts get rollout nginx-rollout --watch

# Manual promotion
kubectl argo rollouts promote nginx-rollout

# Rollback
kubectl argo rollouts abort nginx-rollout
kubectl argo rollouts undo nginx-rollout

Monitoring ve Notifications {#monitoring-notifications}

Prometheus Metrics

ArgoCD metrics'i Prometheus ile expose edilir:

yaml
# ServiceMonitor (Prometheus Operator)
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-metrics
  namespace: argocd
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-metrics
  endpoints:
  - port: metrics

Önemli Metrics:

  • argocd_app_info: Application metadata
  • argocd_app_sync_total: Sync counts
  • argocd_app_health_status: Health status (0=Missing, 1=Progressing, 2=Suspended, 3=Healthy, 4=Degraded)
  • argocd_git_request_duration_seconds: Git fetch latency

Grafana Dashboard: Import ID 14584 (ArgoCD by Akuity)

Slack/Teams Notifications

argocd-notifications ConfigMap:

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-notifications-cm
  namespace: argocd
data:
  service.slack: |
    token: $slack-token
  
  template.app-deployed: |
    message: |
      ✅ Application {{.app.metadata.name}} deployed successfully!
      🔗 {{.context.argocdUrl}}/applications/{{.app.metadata.name}}
      📦 Image: {{range .app.status.summary.images}}{{.}}{{end}}
  
  template.app-health-degraded: |
    message: |
      ⚠️ Application {{.app.metadata.name}} is DEGRADED!
      🔗 {{.context.argocdUrl}}/applications/{{.app.metadata.name}}
  
  trigger.on-deployed: |
    - when: app.status.operationState.phase == 'Succeeded'
      send: [app-deployed]
  
  trigger.on-health-degraded: |
    - when: app.status.health.status == 'Degraded'
      send: [app-health-degraded]

Secret (Slack Token):

bash
kubectl create secret generic argocd-notifications-secret \
  -n argocd \
  --from-literal=slack-token=xoxb-your-slack-token

Application Annotation (Subscribe to Notifications):

yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: nginx-production
  annotations:
    notifications.argoproj.io/subscribe.on-deployed.slack: devops-channel
    notifications.argoproj.io/subscribe.on-health-degraded.slack: alerts-channel

Production Best Practices {#best-practices}

1. Repository Structure

Monorepo (Recommended for Small/Medium):

text
gitops-repo/
├── infrastructure/      # Cluster-wide resources
│   ├── cert-manager/
│   ├── ingress-nginx/
│   └── monitoring/
├── apps/                # Applications
│   ├── api/
│   ├── frontend/
│   └── worker/
└── argocd-apps/         # ArgoCD Application definitions

Separate Repos (Large Organizations):

  • infrastructure-gitops: Cluster infrastructure
  • app-team-a-gitops: Team A apps
  • app-team-b-gitops: Team B apps

2. Branch Strategy

Option A: Environment Branches

  • main → Production
  • staging → Staging
  • dev → Development

Option B: Single Branch + Directories (Recommended)

  • Single main branch
  • Different directories for environments (overlays/dev, overlays/prod)
  • Less complexity, easier to manage

3. Security Hardening

Disable Anonymous Access:

yaml
# argocd-cm ConfigMap
data:
  users.anonymous.enabled: "false"

Enable SSO (Google/GitHub/OIDC):

yaml
# argocd-cm ConfigMap
data:
  url: https://argocd.tektik.tr
  
  dex.config: |
    connectors:
    - type: github
      id: github
      name: GitHub
      config:
        clientID: $dex.github.clientId
        clientSecret: $dex.github.clientSecret
        orgs:
        - name: your-org

Network Policies:

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: argocd-server
  namespace: argocd
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: argocd-server
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: ingress-nginx
    ports:
    - protocol: TCP
      port: 8080

4. Resource Limits

yaml
# argocd-repo-server Deployment patch
spec:
  template:
    spec:
      containers:
      - name: argocd-repo-server
        resources:
          requests:
            cpu: 500m
            memory: 512Mi
          limits:
            cpu: 1000m
            memory: 1Gi

5. High Availability

3 Replicas for Critical Components:

bash
kubectl scale deployment argocd-server --replicas=3 -n argocd
kubectl scale deployment argocd-repo-server --replicas=3 -n argocd
kubectl scale deployment argocd-dex-server --replicas=3 -n argocd

# Application Controller (StatefulSet)
kubectl scale statefulset argocd-application-controller --replicas=3 -n argocd

Redis HA:

bash
# Use Redis Sentinel or Redis Cluster for production
helm install redis bitnami/redis \
  --set sentinel.enabled=true \
  --set master.persistence.enabled=true

6. Backup Strategy

Backup ArgoCD Application Definitions:

bash
# Export all applications
kubectl get applications -n argocd -o yaml > argocd-apps-backup.yaml

# Restore
kubectl apply -f argocd-apps-backup.yaml

Backup ArgoCD Configuration:

bash
kubectl get configmaps,secrets -n argocd -o yaml > argocd-config-backup.yaml

Automated Backup (Velero):

bash
velero backup create argocd-backup \
  --include-namespaces argocd \
  --storage-location default

Troubleshooting ve Common Issues {#troubleshooting}

Issue 1: Application Stuck in "OutOfSync"

Sebep: Git'teki manifest geçersiz veya cluster'a apply edilemiyor.

Çözüm:

bash
# Diff kontrol et
argocd app diff nginx-app

# Manifests'leri validate et
kubectl apply --dry-run=client -f apps/nginx/

# Force sync
argocd app sync nginx-app --force

# Prune eski resources
argocd app sync nginx-app --prune

Issue 2: "ComparisonError" - Manifest Generation Failed

Sebep: Kustomize/Helm build hatası.

Çözüm:

bash
# Local olarak test et
kustomize build overlays/production

# ArgoCD logs
kubectl logs -n argocd deployment/argocd-repo-server -f

# Application events
kubectl describe application nginx-app -n argocd

Issue 3: Image Update Tespit Edilmiyor

Sebep: Auto-sync kapalı veya image tag değişmemiş (:latest kullanıyorsanız).

Çözüm:

bash
# Specific image tags kullan (semantic versioning)
# ❌ image: nginx:latest
# ✅ image: nginx:1.25.3

# Image updater tool kullan (ArgoCD Image Updater)
kubectl apply -f \
  https://raw.githubusercontent.com/argoproj-labs/argocd-image-updater/stable/manifests/install.yaml

Issue 4: Secrets Senkronize Olmuyor

Sebep: SealedSecrets controller çalışmıyor veya encryption key yanlış.

Çözüm:

bash
# Sealed Secrets controller durumu
kubectl get pods -n kube-system | grep sealed-secrets

# Manually decrypt test
kubeseal --recovery-unseal --recovery-private-key key.pem \
  < sealed-secret.yaml

# Re-encrypt with correct key
kubeseal --cert controller.pem < secret.yaml -w new-sealed-secret.yaml

Issue 5: Performance Degradation

Sebep: Çok fazla application, büyük manifests, frequent polling.

Çözüm:

bash
# Webhook kullan (polling yerine)
# GitHub webhook: https://argocd.tektik.tr/api/webhook

# Application controller sharding
kubectl set env statefulset/argocd-application-controller \
  -n argocd \
  ARGOCD_CONTROLLER_REPLICAS=3

# Resource limits artır
kubectl set resources deployment argocd-repo-server \
  -n argocd \
  --limits=cpu=2,memory=2Gi \
  --requests=cpu=1,memory=1Gi

Sonuç

GitOps ve ArgoCD, modern Kubernetes deployment'larının standart haline geldi. Git-based workflow, otomatik senkronizasyon, self-healing ve tam audit trail özellikleri ile production ortamlarında güvenilir ve ölçeklenebilir deployment sağlar.

Key Takeaways:

Git is the single source of truth → All changes via Git
Automated sync + self-heal → Cluster always matches Git
Secrets management → Sealed Secrets or External Secrets Operator
Progressive delivery → Argo Rollouts ile canary/blue-green
Multi-environment → Kustomize overlays + App of Apps pattern
Security + RBAC → SSO, network policies, least privilege
Monitoring + Alerts → Prometheus metrics + Slack notifications

Bir sonraki adım: Kendi GitOps pipeline'ınızı kurun, başlangıçta basit tutun (tek uygulama, tek environment), sonra kademeli olarak genişletin (multi-env, secrets, progressive delivery).


TekTık Yazılım olarak GitOps ve ArgoCD konusunda danışmanlık, kurulum ve eğitim hizmetleri sunuyoruz. Kubernetes deployment süreçlerinizi modernize etmek için bizimle iletişime geçin: info@tektik.tr

Faydalı Kaynaklar: