1. Prinsip GitOps
GitOps adalah paradigma deployment di mana Git repository menjadi single source of truth untuk infrastruktur dan aplikasi. Perubahan pada sistem dilakukan melalui pull request, dan tool otomatis (seperti ArgoCD) memastikan bahwa state aktual di cluster sesuai dengan yang didefinisikan di Git.
manifest di Git
Single source of truth
Drift detection
Self-healing
sama dengan
desired state
1.1 Empat Prinsip GitOps
- Declarative: Semua config didefinisikan secara deklaratif (YAML/JSON)
- Versioned & Immutable: Semua perubahan tercatat di Git history
- Pulled Automatically: Agent (ArgoCD) menarik perubahan dari Git, bukan push dari CI
- Continuously Reconciled: Agent terus memastikan actual state = desired state
2. Instalasi ArgoCD
# Buat namespace
kubectl create namespace argocd
# Install ArgoCD menggunakan manifest resmi
kubectl apply -n argocd \
-f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# Tunggu semua pods ready
kubectl wait --for=condition=Ready pods --all -n argocd --timeout=300s
# Cek status pods
kubectl get pods -n argocd
# Ambil initial admin password
kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d
# Install ArgoCD CLI
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
# Login via CLI
argocd login localhost:8080 --username admin --password <password>
# Port-forward untuk akses web UI
kubectl port-forward svc/argocd-server -n argocd 8080:443
2.1 Production Installation dengan Helm
# values.yaml untuk production ArgoCD
global:
domain: argocd.example.com
server:
ingress:
enabled: true
ingressClassName: nginx
tls: true
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
replicas: 2
resources:
limits:
cpu: 500m
memory: 512Mi
controller:
replicas: 1
resources:
limits:
cpu: "1"
memory: 1Gi
repoServer:
replicas: 2
resources:
limits:
cpu: 500m
memory: 512Mi
redis-ha:
enabled: true
configs:
params:
server.insecure: false # HTTPS only
cm:
url: https://argocd.example.com
# Enable status badge
statusbadge.enabled: "true"
# Tambahkan ArgoCD Helm repository helm repo add argo https://argoproj.github.io/argo-helm helm repo update # Install dengan custom values helm install argocd argo/argo-cd \ --namespace argocd \ --create-namespace \ --values argo-cd-values.yaml \ --version 7.3.0
3. Application CRD
Application adalah Custom Resource Definition (CRD) utama di ArgoCD yang mendefinisikan hubungan antara Git repository dan target cluster/namespace.
3.1 Basic Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
# Finalizer untuk cascade delete
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: https://github.com/my-org/k8s-manifests.git
targetRevision: main
path: apps/my-app/overlays/production
# Kustomize specific
kustomize:
images:
- my-app=ghcr.io/my-org/my-app:v1.2.3
destination:
server: https://kubernetes.default.svc
namespace: my-app
syncPolicy:
automated:
prune: true # Hapus resource yang tidak ada di Git
selfHeal: true # Revert manual changes
allowEmpty: false # Jangan prune semua resource
syncOptions:
- CreateNamespace=true
- PrunePropagationPolicy=foreground
- PruneLast=true
- ServerSideApply=true
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m
3.2 Application dengan Helm
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: nginx-ingress
namespace: argocd
spec:
project: infrastructure
source:
repoURL: https://kubernetes.github.io/ingress-nginx
chart: ingress-nginx
targetRevision: 4.8.0
helm:
releaseName: ingress-nginx
values: |
controller:
replicaCount: 3
resources:
limits:
cpu: 500m
memory: 512Mi
service:
type: LoadBalancer
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: nlb
metrics:
enabled: true
defaultBackend:
enabled: true
# Values file dari repo
valueFiles:
- values-production.yaml
destination:
server: https://kubernetes.default.svc
namespace: ingress-nginx
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
3.3 Multi-Source Application
# Multi-source: Helm chart dari satu repo, values dari repo lain
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
project: default
sources:
# Source 1: Helm chart
- repoURL: https://charts.my-org.com
chart: my-app
targetRevision: 2.0.0
helm:
valueFiles:
- $values/apps/my-app/values-production.yaml
# Source 2: Values dari repo Git
- repoURL: https://github.com/my-org/gitops-config.git
targetRevision: main
ref: values # Reference name untuk $values
destination:
server: https://kubernetes.default.svc
namespace: my-app
4. Sync Strategies
| Strategy | Deskripsi | Penggunaan |
|---|---|---|
Manual | Sync hanya saat diminta manual | Production kritis |
Auto (prune) | Sync otomatis + hapus resource lama | Staging/Dev |
Auto (selfHeal) | Sync otomatis + revert manual changes | Enforcing GitOps |
Auto (full) | prune + selfHeal + retry | Development cepat |
# Sync Waves β urutan sinkronisasi berdasarkan annotation
# Wave default = 0, semakin tinggi semakin akhir di-sync
# Database harus di-deploy duluan
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
namespace: my-app
annotations:
argocd.argoproj.io/sync-wave: "-1" # Sync duluan
spec:
# ...
---
# Migration harus setelah database ready
apiVersion: batch/v1
kind: Job
metadata:
name: db-migration
namespace: my-app
annotations:
argocd.argoproj.io/sync-wave: "0" # Sync kedua
argocd.argoproj.io/hook: PreSync # Jalankan sebelum sync utama
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: migrate
image: my-app:latest
command: ["./migrate", "up"]
restartPolicy: Never
---
# App deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: my-app
annotations:
argocd.argoproj.io/sync-wave: "1" # Sync terakhir
spec:
# ...
# Sync Hooks yang tersedia:
# PreSync β Sebelum apply manifests
# Sync β Selama apply (jarang digunakan)
# PostSync β Setelah semua manifests berhasil
# SyncFail β Saat sync gagal
# Skip β Tidak pernah di-apply ArgoCD
Hindari automated sync untuk production critical apps. Gunakan manual sync dengan approval process. Jika Anda mengaktifkan selfHeal dan seseorang melakukan perubahan manual via kubectl, ArgoCD akan langsung merubahnya kembali. Ini bisa berbahaya jika ada emergency fix yang perlu dilakukan langsung.
5. RBAC & SSO
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-rbac-cm
namespace: argocd
data:
# Default policy: read-only
policy.default: role:readonly
# Policy definitions
policy.csv: |
# Admin β full access
p, role:admin, applications, *, */*, allow
p, role:admin, clusters, *, *, allow
p, role:admin, repositories, *, *, allow
p, role:admin, projects, *, *, allow
# Developer β deploy ke staging, view production
p, role:developer, applications, get, staging/*, allow
p, role:developer, applications, sync, staging/*, allow
p, role:developer, applications, get, production/*, allow
p, role:developer, logs, get, staging/*, allow
# SRE β full access ke semua environment
p, role:sre, applications, *, */*, allow
p, role:sre, clusters, get, *, allow
p, role:sre, logs, get, */*, allow
# Assign groups dari SSO
g, devops-team, role:admin
g, backend-team, role:developer
g, sre-team, role:sre
# Scopes β claim yang dibaca dari JWT
scopes: '[groups, email]'
---
# SSO Configuration (OIDC)
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
data:
url: https://argocd.example.com
oidc.config: |
name: Google
issuer: https://accounts.google.com
clientID: $argo-cd-oidc:clientID
clientSecret: $argo-cd-oidc:clientSecret
requestedScopes:
- openid
- profile
- email
- groups
requestedIDTokenClaims:
groups:
essential: true
6. Notifications
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
namespace: argocd
data:
# Service configurations
service.slack: |
token: $slack-token
signingSecret: $slack-signing-secret
service.teams: |
recipientUrls:
my-channel: $teams-webhook-url
# Template definitions
template.app-sync-succeeded: |
message: |
β
Application {{.app.metadata.name}} sync berhasil!
Revision: {{.app.status.sync.revision}}
Environment: {{.app.spec.destination.namespace}}
slack:
attachments: |
[{
"color": "#18be52",
"fields": [{
"title": "Repository",
"value": "{{.app.spec.source.repoURL}}",
"short": true
},{
"title": "Revision",
"value": "{{.app.status.sync.revision}}",
"short": true
}]
}]
template.app-sync-failed: |
message: |
β Application {{.app.metadata.name}} sync GAGAL!
Error: {{.app.status.operationState.message}}
slack:
attachments: |
[{
"color": "#f4c542",
"fields": [{
"title": "Error",
"value": "{{.app.status.operationState.message}}",
"short": false
}]
}]
# Trigger definitions
trigger.on-sync-succeeded: |
- when: app.status.operationState.phase in ['Succeeded']
send: [app-sync-succeeded]
trigger.on-sync-failed: |
- when: app.status.operationState.phase in ['Error', 'Failed']
send: [app-sync-failed]
trigger.on-health-degraded: |
- when: app.status.health.status == 'Degraded'
send: [app-sync-failed]
---
# Aktifkan notifikasi pada Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
annotations:
notifications.argoproj.io/subscribe.on-sync-succeeded.slack: "#deployments"
notifications.argoproj.io/subscribe.on-sync-failed.slack: "#alerts"
notifications.argoproj.io/subscribe.on-health-degraded.teams: my-channel
spec:
# ... konfigurasi application
7. ApplicationSet
ApplicationSet adalah controller yang memungkinkan Anda membuat banyak ArgoCD Application secara dinamis dari satu template. Ini sangat berguna untuk multi-environment dan multi-cluster deployment.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: my-app-multi-env
namespace: argocd
spec:
generators:
# List generator β define environments secara manual
- list:
elements:
- env: dev
cluster: https://dev-cluster.example.com
revision: develop
autoSync: "true"
- env: staging
cluster: https://staging-cluster.example.com
revision: main
autoSync: "true"
- env: production
cluster: https://prod-cluster.example.com
revision: main
autoSync: "false"
template:
metadata:
name: 'my-app-{{env}}'
annotations:
notifications.argoproj.io/subscribe.on-sync-succeeded.slack: '#deploy-{{env}}'
spec:
project: default
source:
repoURL: https://github.com/my-org/k8s-manifests.git
targetRevision: '{{revision}}'
path: apps/my-app/overlays/{{env}}
destination:
server: '{{cluster}}'
namespace: my-app
syncPolicy:
automated:
prune: '{{autoSync}}'
selfHeal: '{{autoSync}}'
syncOptions:
- CreateNamespace=true
# Strategy untuk rollout update
strategy:
type: RollingSync
rollingSync:
steps:
- matchExpressions:
- key: env
operator: In
values:
- dev
- matchExpressions:
- key: env
operator: In
values:
- staging
- matchExpressions:
- key: env
operator: In
values:
- production
7.1 Git Directory Generator
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: all-apps
namespace: argocd
spec:
generators:
# Scan direktori di Git β otomatis buat app
- git:
repoURL: https://github.com/my-org/gitops.git
revision: main
directories:
- path: apps/*
- path: apps/legacy-* # Exclude pattern
exclude: true
template:
metadata:
name: '{{path.basename}}'
spec:
project: default
source:
repoURL: https://github.com/my-org/gitops.git
targetRevision: main
path: '{{path}}'
destination:
server: https://kubernetes.default.svc
namespace: '{{path.basename}}'
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
8. Best Practices Production
- App of Apps / ApplicationSet: Gunakan pattern ini untuk mengelola banyak aplikasi dari satu tempat
- Separate Config Repo: Pisahkan repo kode aplikasi dengan repo manifest/deployment
- RBAC Ketat: Jangan berikan admin access ke semua tim
- Notifications: Setup Slack/Teams notifications untuk sync events
- Resource Limits: Selalu set resource limits di ArgoCD components
- Disable Admin User: Setelah SSO aktif, disable admin user default
- Monitoring: Expose ArgoCD metrics ke Prometheus
# ArgoCD sudah expose metrics secara default
# Port-forward untuk melihat metrics:
kubectl port-forward svc/argocd-metrics -n argocd 8083:8083
# ServiceMonitor untuk 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
interval: 30s
# Contoh alert rules
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: argocd-alerts
namespace: argocd
spec:
groups:
- name: argocd
rules:
- alert: ArgoAppOutOfSync
expr: |
argocd_app_info{sync_status="OutOfSync"} == 1
for: 10m
labels:
severity: warning
annotations:
summary: "App {{ $labels.name }} out of sync"
- alert: ArgoAppDegraded
expr: |
argocd_app_info{health_status="Degraded"} == 1
for: 5m
labels:
severity: critical
9. Quiz: Uji Pemahamanmu!
Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut: