Rekayasa GitOps Multi-Cluster Skala Enterprise: Konvergensi ArgoCD vs Flux v2, Zero-Trust Supply-Chain via Sigstore Cosign, dan Modular Terragrunt IaC
Paradigma Rekayasa GitOps & Kebutuhan Deklaratif Skala Fleet
Pada era komputasi cloud-native terdistribusi, mengelola puluhan kluster Kubernetes menggunakan pendekatan CI/CD berbasis push tradisional (di mana runner CI seperti GitLab CI atau GitHub Actions mengeksekusi kubectl apply secara langsung) menciptakan celah keamanan dan kelemahan arsitektural yang fatal:
- Eksfiltrasi Kredensial Berhak Tinggi: Runner CI luar harus memegang token
cluster-adminatau sertifikat TLS kubeconfig dari setiap kluster target. Apabila satu runner atau pipeline dependency disusupi, penyerang memperoleh akses penuh (blast radius total) ke seluruh infrastruktur. - Ketiadaan Rekonsiliasi Otomatis (Configuration Drift): Apabila terjadi intervensi manual darurat (hotfix ad-hoc via
kubectl edit) atau anomali controller internal, pipeline push tidak menyadari perubahan tersebut sampai eksekusi pipeline berikutnya. - Konkurensi & Mutasi parsial: Eksekusi simultan antar-developer dapat menyebabkan state overwrites yang merusak integritas desired state.
Paradigma GitOps merevolusi tata kelola ini dengan menetapkan repositori Git yang terenkripsi dan terlindungi (protected branch) sebagai satu-satunya representasi sah (single source of truth). Melalui pendekatan pull-based reconciliation, agen di dalam kluster secara otonom menyinkronkan live state di etcd dengan target state di Git tanpa membuka port ingress kube-apiserver ke internet publik.
Artikel ini mengupas arsitektur internal GitOps multi-cluster, komparasi mendalam reconciliation engine ArgoCD versus Flux v2, integrasi Zero-Trust Software Supply Chain berbasis kriptografi Sigstore Cosign & Kyverno, orkestrasi rahasia dinamis External Secrets Operator (ESO) bersama HashiCorp Vault, serta orkestrasi infrastruktur modular menggunakan Terragrunt Directed Acyclic Graph (DAG)βseluruhnya disajikan dengan data sintetis sesuai standar RFC 5737.
1. Anatomi Mesin Rekonsiliasi: ArgoCD Controller vs Flux v2 Micro-Controllers
Meskipun ArgoCD dan Flux v2 memiliki tujuan konseptual yang sejalanβyakni Continuous State Convergenceβarsitektur internal dan interaksi keduanya dengan Linux kernel memory serta Kubernetes API server memiliki perbedaan fundamental.
========================================================================================
ARGOCD CONTROLLER RECONCILIATION ENGINE
========================================================================================
[ Git Repo (Source of Truth) ] ββ (Webhook / 3m Resync) βββΊ [ argocd-repo-server ]
β
βΌ (Kustomize / Helm Build)
[ Manifest Memory Stream ]
β
ββββββββββββββββββββββββββ argocd-application-controller ββββββββββΌββββββββββββββββββββββ
β β
β [ SharedIndexInformer (Kube-API Cache) ] βββ (WATCH) ββ [ Target K8s Clusters ] β
β β β
β βΌ β
β [ Three-Way Diffing Engine ] ββββ (Target Manifests vs Live State vs Last-Applied)
β β β
β βββ Identical? ββββββββΊ Status: Synced (Emit Prometheus Metrics) β
β βββ Out of Sync? β
β β β
β βΌ β
β [ Sync Task Execution Engine ] β
β - Phase PreSync (Hooks & Migrations) β
β - Apply Sync Waves (Wave 0 -> Wave 1 -> Wave n) β
β - Dynamic Client Server-Side Apply (SSA) β
β - Phase PostSync (Health Check Validation) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
1.1 ArgoCD: Centralized Hub-and-Spoke Control Plane
ArgoCD mengadopsi model centralized management. Satu kontrol kluster ArgoCD mengawasi puluhan hingga ratusan kluster beban kerja (workload clusters):
- Informer Cache Footprint: Komponen
argocd-application-controllermenginstansiasi objekSharedIndexInformeruntuk setiap API resource pada setiap kluster yang terhubung. Pada 50 kluster dengan masing-masing 2.000 resources, cache internal di memori controller dapat melampaui 16β32 GB RAM. - Three-Way Merge Algorithm: Perbedaan dihitung secara matematis antara manifest target dari
argocd-repo-server, manifest riil dietcd, dan metadata anotasikubectl.kubernetes.io/last-applied-configuration. - Sync Waves & Phases: ArgoCD memiliki fitur bawaan untuk mengatur urutan provisioning (misalnya: CRD dan Namespace pada Wave -1, Secret dan Database pada Wave 0, Web Application pada Wave 1).
1.2 Flux v2: Modular Micro-Controllers & GitOps Toolkit
Flux v2 memecah monolitik controller menjadi sekumpulan Kubernetes-native custom controllers mandiri:
source-controller: Mengunduh Git repository, Helm repository, atau OCI registry, mengekstraknya ke tarball kompresi in-memory, dan menyajikannya via HTTP server internal bertarif hemat CPU.kustomize-controller: Bertanggung jawab atas rendering Kustomize dan menerapkan manifest langsung via Kubernetes Server-Side Apply (SSA) tanpa perantarakubectlbinary.helm-controller: Menangani siklus hidup Helm Release deklaratif dengan dry-run testing otomatis.- Decentralized Security Model: Setiap kluster menjalankan pod Flux lokal. Tidak ada pengiriman master token kluster target ke satu hub sentral, secara drastis mengeliminasi risiko hub-compromise.
2. Arsitektur Zero-Trust Supply-Chain: Cryptographic Attestation Pipeline
Dalam model Zero-Trust sejati, sebuah container image tidak boleh diizinkan berjalan di kluster hanya karena tersimpan di private registry. Container image harus membawa bukti integritas kriptografis yang tak terbantahkan (cryptographic provenance) sejak proses kompilasi hingga eksekusi pod.
[ Developer Git Commit ]
β
βΌ
[ Hardened CI Runner (Rootless Buildah / Kaniko) ]
β
ββββΊ 1. Build OCI Container (Deterministic Layer Hash sha256:7a9f...)
ββββΊ 2. Generate SBOM (Software Bill of Materials) via Syft
ββββΊ 3. Vulnerability Scan (Grype) βββΊ Fail on Critical CVE
β
βΌ
[ OCI Registry Push (Subnet RFC 5737: 198.51.100.50:5000) ]
β
ββββΊ 4. Cosign Sign Digest (Keyless Sigstore OIDC / Private Key)
ββββΊ 5. Cosign Attest SBOM (In-toto Predicate Format)
ββββΊ 6. Rekor Transparency Log Append
β
βΌ
βββββββββββββββββββββββ Kubernetes Cluster Edge βββββββββββββββββββββββββββββββββββββββ
β β
β [ GitOps Engine Sync ] βββΊ [ Kube-Apiserver (VIP: 198.51.100.10:6443) ] β
β β β
β βΌ (AdmissionReview HTTPS Webhook) β
β [ Kyverno Admission Controller ] β
β β β
β ββββββββββββββββββββββββββ΄βββββββββββββββββββββββββ β
β β β β
β βΌ βΌ β
β [ Verify Cosign Signature ] [ Verify In-Toto SBOM ] β
β - Check Rekor Log & Fulcio Cert - Validate Vulnerability Report β
β - Match Public Key PEM payload - Assert CycloneDX Schema 1.4 β
β β β β
β ββββββββββββββββββββββββββ¬βββββββββββββββββββββββββ β
β β β
β ββββββββββββββββββββββ΄βββββββββββββββββββββ β
β βΌ βΌ β
β [ Signature Match ] [ Invalid / Tampered ] β
β Allow Pod Creation Reject Pod (403 Forbidden) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Rootless Image Construction: Memutus ketergantungan pada
/var/run/docker.sock. Pemanfaatan Buildah atau Kaniko mencegah serangan container escape ke hak akses root host selama fase kompilasi CI. - Sigstore Cosign Signing: Image OCI ditandatangani secara kriptografis menggunakan algoritma kurva eliptik (ECDSA P-256). Signature disimpan sebagai layer artefak OCI berdampingan dengan digest image.
- Kyverno Admission Enforcement: Sebelum Kubelet menarik layer image dari registry, admission webhook Kyverno mencegat request
Pod/CREATE. Jika signature tidak terverifikasi atau payload SBOM memuat pelanggaran compliance, pembuatan Pod dibatalkan secara atomik.
3. Secret Flow Architecture: External Secrets Operator (ESO) & HashiCorp Vault
Penyimpanan kredensial di Git repositoryβsekalipun dikaburkan menggunakan enkripsi dasarβmerupakan anti-pattern pada lingkungan teregulasi tinggi (seperti PCI-DSS atau SOC2). Pendekatan enterprise memisahkan definisi deployment dari storage credential aktual melalui External Secrets Operator (ESO) yang berkomunikasi secara asynchronous dengan HashiCorp Vault.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β HASHICORP VAULT CLUSTER (198.51.100.20:8200) β
β Path: secret/data/production/financial/payment β
β Payload: { "DB_PASS": "Encrypted#Synth99" } β
ββββββββββββββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
β
β TLS 1.3 / Projected ServiceAccount JWT
βΌ
ββββββββββββββββββββββββββββββββββββ KUBERNETES WORKLOAD CLUSTER ββββββββββββββββββββββ
β β
β [ Git Repository ] β
β β (ArgoCD Sync) β
β βΌ β
β [ ExternalSecret CRD ] β
β - Spec: storeRef: enterprise-vault-backend β
β remoteRef: key=production/financial/payment, property=DB_PASS β
β β β
β βΌ β
β [ External Secrets Operator (ESO) Controller ] β
β β β
β βββ 1. Request Vault Token via K8s Auth (`/v1/auth/kubernetes/login`) β
β βββ 2. Fetch Decrypted Secret Payload over Mutual TLS β
β βββ 3. Render Native K8s Secret (`kind: Secret`) β
β βββ 4. Rotate Secret secara periodik (interval: 1h) β
β β β
β βΌ β
β [ Native Kubernetes Secret: "payment-db-secret" ] β
β β² β
β βββ (Mounted as volume / injected envFrom) ββ [ Microservice Pods ] β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
4. Konfigurasi Produksi & Manifests Siap Pakai
Berikut adalah implementasi manifest deklaratif berbobot enterprise menggunakan data sintetis RFC 5737 (198.51.100.0/24, 192.0.2.0/24, dan 203.0.113.0/24).
4.1 ArgoCD Enterprise ApplicationSet: Matrix Generator & Progressive Sync
Manifest ini mengimplementasikan generator matriks yang menggabungkan direktori Git microservice dengan kluster produksi terdaftar, lengkap dengan strategi peluncuran bertahap (Rolling Progressive Sync):
# /infrastructure/gitops/argocd/applicationset-matrix-enterprise.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: fleet-microservices-matrix
namespace: argocd
labels:
tier: production
managed-by: gitops-control-plane
spec:
goTemplate: true
goTemplateOptions: ["missingkey=error"]
strategy:
type: RollingSync
rollingSync:
steps:
- matchExpressions:
- key: environment
operator: In
values:
- staging
maxUpdate: 100%
- matchExpressions:
- key: environment
operator: In
values:
- production
maxUpdate: 25% # Canary deployment antar cluster bertahap
generators:
- matrix:
generators:
# Generator 1: Memetakan struktur direktori microservices di Git
- git:
repoURL: https://git.example.net/enterprise-core/cloud-platform-manifests.git
revision: HEAD
directories:
- path: apps/services/*
# Generator 2: Memilih target cluster berdasarkan metadata labels
- clusters:
selector:
matchLabels:
fleet.argoproj.io/tier: tier-1-production
values:
region: '{{ index .metadata.labels "topology.kubernetes.io/region" }}'
environment: '{{ index .metadata.labels "environment" }}'
template:
metadata:
name: '{{ .path.basename }}-{{ .name }}'
namespace: argocd
labels:
app.kubernetes.io/name: '{{ .path.basename }}'
env: '{{ .values.environment }}'
region: '{{ .values.region }}'
spec:
project: default
source:
repoURL: https://git.example.net/enterprise-core/cloud-platform-manifests.git
targetRevision: HEAD
path: '{{ .path.path }}/overlays/{{ .values.environment }}'
kustomize:
images:
- 'release-image=198.51.100.50:5000/microservices/{{ .path.basename }}:v2.4.1'
destination:
server: '{{ .server }}'
namespace: '{{ .path.basename }}'
syncPolicy:
automated:
prune: true
selfHeal: true
allowEmpty: false
syncOptions:
- CreateNamespace=true
- PrunePropagationPolicy=foreground
- PruneLast=true
- ApplyOutOfSyncOnly=true
- ServerSideApply=true
retry:
limit: 5
backoff:
duration: 10s
factor: 2
maxDuration: 3m
ignoreDifferences:
- group: apps
kind: Deployment
jsonPointers:
- /spec/replicas # Membiarkan HorizontalPodAutoscaler mengontrol replikasi
- group: ""
kind: Service
jsonPointers:
- /spec/clusterIP
- /spec/ports/0/nodePort
4.2 Kyverno ClusterPolicy: Enforce Cosign Cryptographic Signature & Attestation
Kebijakan berikut memblokir unauthenticated image dan kontainer non-root pada namespace operasional:
# /infrastructure/gitops/policies/kyverno-verify-supply-chain.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: enforce-supply-chain-signature-sbom
annotations:
policies.kyverno.io/title: "Verify Container Signature & SBOM Attestation"
policies.kyverno.io/category: "Zero-Trust Supply Chain"
policies.kyverno.io/severity: "critical"
spec:
validationFailureAction: Enforce
background: false
failurePolicy: Fail
webhookTimeoutSeconds: 30
rules:
- name: verify-cosign-image-signature
match:
any:
- resources:
kinds:
- Pod
namespaces:
- production-*
- financial-*
exclude:
any:
- resources:
namespaces:
- kube-system
- kyverno
- monitoring
verifyImages:
- imageReferences:
- "198.51.100.50:5000/microservices/*"
attestors:
- entries:
- keys:
publicKeys: |
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE24F7sX3Bv6jCqR4E/rU2sK8QpQZf
G3s9e4R6sYw/5jZqH9kE3tP4Q7uL1nB9w0yV3xR8oF7kL5sN4aB9cD1eFg==
-----END PUBLIC KEY-----
attestations:
- predicateType: https://cyclonedx.org/schema/1.4
conditions:
- all:
- key: "{{ cyclonedx.metadata.component.type }}"
operator: Equals
value: "application"
- name: block-root-and-privileged-containers
match:
any:
- resources:
kinds:
- Pod
namespaces:
- production-*
validate:
message: "Menjalankan container sebagai root atau privileged dilarang pada tier produksi!"
pattern:
spec:
=(securityContext):
=(runAsNonRoot): true
containers:
- securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
4.3 External Secrets Operator: Integrasi HashiCorp Vault
Penyambungan workload cluster dengan Vault cluster yang terisolasi via Kubernetes ServiceAccount Token Projector:
# /infrastructure/gitops/secrets/eso-vault-store.yaml
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
name: enterprise-vault-backend
spec:
provider:
vault:
server: "https://vault.internal.example.net:8200"
path: "secret"
version: "v2"
auth:
kubernetes:
mountPath: "kubernetes"
role: "k8s-platform-workload-role"
serviceAccountRef:
name: eso-vault-auth-sa
namespace: external-secrets
caProvider:
type: ConfigMap
name: internal-root-ca
key: ca.crt
namespace: external-secrets
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: payment-gateway-credentials
namespace: payment-system
spec:
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: enterprise-vault-backend
target:
name: payment-live-secret
creationPolicy: Owner
template:
engineVersion: v2
metadata:
labels:
security.enterprise.net/classification: pci-dss-regulated
data:
DATABASE_URL: "postgresql://{{ .DB_USER }}:{{ .DB_PASS }}@192.0.2.30:5432/transact?sslmode=verify-full"
STRIPE_SECRET_KEY: "{{ .STRIPE_KEY }}"
data:
- secretKey: DB_USER
remoteRef:
key: production/financial/payment
property: username
- secretKey: DB_PASS
remoteRef:
key: production/financial/payment
property: password
- secretKey: STRIPE_KEY
remoteRef:
key: production/financial/payment
property: stripe_live_token
4.4 Terragrunt Production Architecture: Global DRY Engine
Terragrunt mengelola dependensi antar-modul infrastruktur sebagai Directed Acyclic Graph (DAG), mengisolasi kegagalan state file, dan menyediakan distributed locking via DynamoDB.
# /infrastructure/live/terragrunt.hcl (Root Terragrunt Configuration)
locals {
path_segments = split("/", path_relative_to_include())
environment = local.path_segments[0] # e.g. "prod", "staging"
region = local.path_segments[1] # e.g. "ap-southeast-1"
component = local.path_segments[2] # e.g. "vpc", "eks", "gitops"
global_vars = yamldecode(file(find_in_parent_folders("global_vars.yaml")))
env_vars = yamldecode(file("${get_parent_terragrunt_dir()}/environments/${local.environment}.yaml"))
}
# Dynamic Provider Injection ke seluruh child modules
generate "provider" {
path = "provider_override.tf"
if_exists = "overwrite_terragrunt"
contents = <<EOF
terraform {
required_version = ">= 1.8.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.50"
}
}
}
provider "aws" {
region = "${local.region}"
default_tags {
tags = {
Environment = "${local.environment}"
ManagedBy = "Terragrunt"
CostCenter = "${local.env_vars.cost_center}"
Repository = "https://git.example.net/enterprise-core/infrastructure-live"
}
}
}
EOF
}
# Remote State Backend Configuration (S3 + DynamoDB State Lock)
remote_state {
backend = "s3"
generate = {
path = "backend.tf"
if_exists = "overwrite_terragrunt"
}
config = {
bucket = "enterprise-tf-state-${local.global_vars.account_id}-${local.region}"
key = "${path_relative_to_include()}/terraform.tfstate"
region = local.region
encrypt = true
dynamodb_table = "enterprise-tf-state-locks"
s3_bucket_tags = {
Owner = "DevOps Core Team"
PurgePolicy = "Never"
}
}
}
inputs = merge(
local.global_vars,
local.env_vars,
{
environment = local.environment
region = local.region
}
)
Child module eks/terragrunt.hcl yang mengonsumsi output dari modul vpc secara otomatis:
# /infrastructure/live/prod/ap-southeast-1/eks/terragrunt.hcl
include "root" {
path = find_in_parent_folders()
}
terraform {
source = "git::git@git.example.net:terraform-modules/eks.git?ref=v20.8.5"
}
dependency "vpc" {
config_path = "../vpc"
mock_outputs = {
vpc_id = "vpc-00000000000000000"
private_subnets = ["subnet-00000001", "subnet-00000002", "subnet-00000003"]
}
mock_outputs_allowed_terraform_commands = ["validate", "plan"]
}
inputs = {
cluster_name = "enterprise-k8s-prod-sg"
cluster_version = "1.30"
vpc_id = dependency.vpc.outputs.vpc_id
subnet_ids = dependency.vpc.outputs.private_subnets
cluster_endpoint_public_access = false
cluster_endpoint_private_access = true
enable_cluster_creator_admin_permissions = false
authentication_mode = "API_AND_CONFIG_MAP"
eks_managed_node_groups = {
core_system = {
min_size = 3
max_size = 10
desired_size = 3
instance_types = ["m6i.2xlarge"]
capacity_type = "ON_DEMAND"
labels = {
tier = "platform-core"
}
}
}
}
5. Skrip Otomasi Validasi, Audit, dan Benchmarking
5.1 Pipeline Validation & Supply-Chain Attestation Runner
Skrip ini memverifikasi bahwa container image memenuhi kriteria Zero-Trust sebelum didaftarkan ke manifest GitOps:
#!/usr/bin/env bash
# ==============================================================================
# verify-supply-chain.sh β Zero-Trust Supply-Chain Attestation Validator
# Author: La Nina
# ==============================================================================
set -euo pipefail
IMAGE_REF="${1:-198.51.100.50:5000/microservices/payment-engine:v2.4.1}"
COSIGN_KEY_FILE="${2:-/etc/cosign/cosign.pub}"
echo "======================================================================"
echo " ZERO-TRUST SUPPLY-CHAIN ATTESTATION & SECURITY AUDITOR"
echo " Target OCI Artifact: ${IMAGE_REF}"
echo "======================================================================"
TMP_DIR=$(mktemp -d)
trap 'rm -rf "${TMP_DIR}"' EXIT
# 1. Verifikasi Cosign Cryptographic Signature
echo "[STEP 1] Memvalidasi signature kriptografis image..."
if [ -f "${COSIGN_KEY_FILE}" ]; then
if cosign verify --key "${COSIGN_KEY_FILE}" "${IMAGE_REF}" > "${TMP_DIR}/cosign_verify.json" 2>&1; then
echo " [OK] Signature valid terotentikasi oleh: ${COSIGN_KEY_FILE}"
else
echo " [FATAL] SIGNATURE INVALID! Citra kontainer dimanipulasi atau tidak sah!"
exit 1
fi
fi
# 2. Verifikasi In-toto SBOM Attestation
echo "[STEP 2] Memeriksa attestation format CycloneDX..."
if [ -f "${COSIGN_KEY_FILE}" ]; then
if cosign verify-attestation --key "${COSIGN_KEY_FILE}" --type cyclonedx "${IMAGE_REF}" > "${TMP_DIR}/attestation.json" 2>&1; then
echo " [OK] Attestation CycloneDX SBOM terverifikasi sah."
else
echo " [WARN] Attestation SBOM tidak ditemukan atau tidak match."
fi
fi
echo "======================================================================"
echo "[SUCCESS] Citra OCI memenuhi seluruh syarat keamanan Zero-Trust."
echo "======================================================================"
5.2 GitOps Reconciliation Latency & Admission Benchmark
Skrip untuk mengukur latensi end-to-end dari saat manifest diterapkan hingga pod mencapai status Running di bawah beban konkurensi webhook:
#!/usr/bin/env bash
# ==============================================================================
# benchmark-gitops-perf.sh β High-Concurrency Admission & Convergence Benchmark
# Author: La Nina
# ==============================================================================
set -euo pipefail
NAMESPACE="benchmark-gitops-$(date +%s)"
ITERATIONS="${1:-20}"
CONCURRENCY="${2:-5}"
echo "======================================================================"
echo " KUBERNETES GITOPS RECONCILIATION & ADMISSION BENCHMARK"
echo " Namespace: ${NAMESPACE} | Iterasi: ${ITERATIONS} | Concurrency: ${CONCURRENCY}"
echo "======================================================================"
kubectl create namespace "${NAMESPACE}"
trap 'kubectl delete namespace "${NAMESPACE}" --wait=false >/dev/null 2>&1 || true' EXIT
START_TIME=$(date +%s%3N)
for i in $(seq 1 "${ITERATIONS}"); do
cat <<EOF | kubectl apply -f - >/dev/null &
apiVersion: apps/v1
kind: Deployment
metadata:
name: bench-app-${i}
namespace: ${NAMESPACE}
spec:
replicas: 1
selector:
matchLabels:
app: bench-app-${i}
template:
metadata:
labels:
app: bench-app-${i}
spec:
containers:
- name: pause
image: 198.51.100.50:5000/microservices/pause:3.9
resources:
limits: { cpu: 20m, memory: 32Mi }
requests: { cpu: 5m, memory: 16Mi }
EOF
if (( i % CONCURRENCY == 0 )); then wait; fi
done
wait
END_APPLY=$(date +%s%3N)
APPLY_DURATION=$(( END_APPLY - START_TIME ))
echo "[METRIC] Selesai menerapkan ${ITERATIONS} deployments dalam ${APPLY_DURATION} ms"
# Tunggu konvergensi pod
while true; do
READY_COUNT=$(kubectl get pods -n "${NAMESPACE}" --field-selector=status.phase=Running --no-headers 2>/dev/null | wc -l || echo 0)
if [ "${READY_COUNT}" -ge "${ITERATIONS}" ]; then break; fi
sleep 1
done
END_WATCH=$(date +%s%3N)
TOTAL_LATENCY=$(( END_WATCH - START_TIME ))
echo "======================================================================"
echo " Total Manifests : ${ITERATIONS}"
echo " Client Apply Latency: ${APPLY_DURATION} ms"
echo " Total Convergence : ${TOTAL_LATENCY} ms"
echo " Rata-rata per-pod : $(( TOTAL_LATENCY / ITERATIONS )) ms / pod"
echo "======================================================================"
6. Skenario Troubleshooting Kasus Nyata (Root Cause Analysis & SOP)
Kasus 1: ArgoCD Application Out-of-Sync Loop Akibat Mutating Webhook
- Gejala: Aplikasi terus berganti status antara
SynceddanOutOfSyncsetiap beberapa detik. Logargocd-application-controllermelaporkan perbedaan pada field/spec/template/metadata/annotations/vault.hashicorp.com/agent-inject-token. - Akar Masalah (RCA): ArgoCD menyinkronkan manifest bersih dari Git. Sesaat setelah objek Deployment dibuat, mutating admission webhook HashiCorp Vault Agent Injector mencegat request dan menyuntikkan annotation serta sidecar container secara dinamis. Informer ArgoCD mendeteksi perbedaan antara live object di
etcddan target state di Git, lalu opsiselfHeal: truememicu perbaikan kembali yang tiada henti (infinite reconciliation thrashing). - Resolusi: Tambahkan direktif
ignoreDifferencesdengan pointer JSON spesifik pada Application CRD atau secara terpusat diargocd-cmConfigMap:spec: ignoreDifferences: - group: apps kind: Deployment jsonPointers: - /spec/template/metadata/annotations/vault.hashicorp.com~1agent-inject-token - /spec/template/metadata/annotations/vault.hashicorp.com~1agent-init-status - /spec/template/spec/initContainers - /spec/template/spec/volumes
Kasus 2: Controller OOMKilled & Kube-Apiserver CPU Throttling pada Skala 50+ Kluster
- Gejala: Pod
argocd-application-controllermengalami crash berulang dengan exit code137 (OOMKilled). Latensi kube-apiserver pada kluster target melonjak hingga mengalami HTTP 504 Gateway Timeout. - Akar Masalah (RCA): Informer cache ArgoCD memantau seluruh resource secara default, termasuk entitas dengan churn rate sangat tinggi seperti
Event,Endpoints, danEndpointSlice. Cache snapshot di RAM membengkak eksponensial seiring pertambahan kluster. - Resolusi: Terapkan resource exclusion pada
argocd-cmdan aktifkan controller sharding:Kemudian ubah deployment menjadi StatefulSet ber-sharding:apiVersion: v1 kind: ConfigMap metadata: name: argocd-cm namespace: argocd data: resource.exclusions: | - apiGroups: [""] kinds: ["Event", "Endpoints"] - apiGroups: ["discovery.k8s.io"] kinds: ["EndpointSlice"] timeout.reconciliation: "600s"kubectl scale statefulset argocd-application-controller -n argocd --replicas=3 kubectl set env statefulset/argocd-application-controller -n argocd ARGOCD_CONTROLLER_REPLICAS=3
Kasus 3: Kegagalan Verifikasi Cosign pada Lingkungan Air-Gapped Private Registry
- Gejala: Kyverno webhook menolak pembuatan Pod dengan pesan:
rule verify-cosign-image-signature failed: no matching signatures found. - Akar Masalah (RCA): Prosedur migrasi image menggunakan
docker pulldandocker pushstandar hanya menyalin image manifest utama. Metadata signature Cosign disimpan sebagai tag referensial terpisah (berakhiran.sigdan.att). Akibatnya, file signature tidak ada di registry lokal internal. - Resolusi: Pergunakan tool mirroring OCI-native seperti
craneatauskopeoyang mendukung penyalinan tag turunan secara rekursif:DIGEST=$(crane digest "198.51.100.50:5000/microservices/payment:v2.0") crane copy "198.51.100.50:5000/microservices/payment:v2.0" "192.0.2.80:5000/microservices/payment:v2.0" crane copy "198.51.100.50:5000/microservices/payment:${DIGEST/:/-}.sig" "192.0.2.80:5000/microservices/payment:${DIGEST/:/-}.sig" crane copy "198.51.100.50:5000/microservices/payment:${DIGEST/:/-}.att" "192.0.2.80:5000/microservices/payment:${DIGEST/:/-}.att"
7. Matriks Evaluasi & Ringkasan Best Practices
| Domain Rekayasa | Pendekatan Enterprise Terkompilasi | Praktik Buruk (Anti-Pattern) |
|---|---|---|
| Delivery Engine | ArgoCD ApplicationSet dengan Server-Side Apply & Progressive Rollouts. | Menjalankan client-side kubectl apply secara langsung dari runner CI pihak ketiga. |
| Topologi Kluster | Desentralisasi Informer Sharding atau agen lokal Flux v2 micro-controllers. | Satu instance controller monolitik tanpa sharding mengelola lebih dari 100 remote kluster. |
| Supply Chain | Rootless container build (Buildah) + Cosign ECDSA Signature + Kyverno Webhook. | Menjalankan build container dengan me-mount /var/run/docker.sock ke daemon host. |
| Manajemen Rahasia | External Secrets Operator (ESO) dengan integrasi dinamis ke HashiCorp Vault. | Menyimpan token atau credentials terenkripsi base64 mentah di dalam repositori Git. |
| Infrastructure as Code | Terragrunt DRY hierarchy, isolasi modular state per-komponen, S3 + DynamoDB locking. | Monolitik main.tf raksasa yang menggabungkan deklarasi VPC hingga workload Kubernetes. |
Melalui implementasi terintegrasi antara ArgoCD / Flux v2, penegakan Zero-Trust Supply-Chain, dan orkestrasi Terragrunt DAG, tim platform enterprise dapat menjamin keandalan, keterlacakan audit (traceability), dan integritas keamanan operasional tanpa mengorbankan kecepatan delivery aplikasi modern.