As cloud-native architectures transitioned from monolithic virtual machines to dynamic, multi-tenant Kubernetes clusters, traditional deployment automation mechanisms began to experience severe architectural strain. In conventional push-based continuous delivery, external CI/CD runners (such as Jenkins or GitHub Actions workers) are granted elevated administrative access to the Kubernetes control plane, executing imperative kubectl apply commands over public or federated networks. This paradigm introduces critical security vulnerabilities, configuration drift between environments, and operational opacity during incident mitigation.
GitOps fundamentally resolves these structural challenges by establishing Git as the single, immutable source of truth for declarative infrastructure and application state. By deploying in-cluster reconciliation operators that continuously pull and synchronize desired configurations from Git repositories, GitOps transforms deployment into a self-healing, auditable control loop. This comprehensive guide analyzes the theoretical foundations of OpenGitOps, examines the micro-architectures of ArgoCD and Flux v2, explores state drift detection, details secure secret management, and evaluates multi-cluster governance.
The Four Principles of OpenGitOps#
The OpenGitOps working group (under the Cloud Native Computing Foundation) formalizes GitOps through four core, platform-agnostic principles:
- Declarative Specification: The entire desired system state—including application manifests, networking policies, storage definitions, and RBAC rules—must be expressed declaratively rather than imperatively. The system specifies what the desired state is, not the procedural steps needed to achieve it.
- Versioned and Immutable State Store: The desired state is stored in an immutable, version-controlled repository (typically Git). Every modification creates a permanent cryptographic commit hash, providing an indelible audit log of who changed what, why, and when.
- Pulled Automatically by Software Agents: Software agents running directly inside the target execution environment automatically pull the declared state from the repository. The target environment never exposes inbound administrative credentials to the outside world.
- Continuously Reconciled: Software agents continuously observe the actual runtime state of the cluster, compute differences (drift) against the desired state stored in Git, and apply automated reconciliation to converge actual state back into desired state without human intervention.
+-----------------------------------------------------------------------------------------+
| The OpenGitOps Control Loop |
+-----------------------------------------------------------------------------------------+
| |
| +------------------------------------+ |
| | Git Repository (Source of Truth) | |
| | - Declared Manifests (v1.2.0) | |
| +------------------------------------+ |
| | |
| | 1. Periodic Git Fetch / Webhook |
| v |
| +------------------------------------+ |
| | In-Cluster GitOps Operator | |
| | (ArgoCD / Flux v2 Controller) | |
| +------------------------------------+ |
| | ^ |
| 2. Compute| Diff | 3. Continuous Telemetry |
| v | (k8s Informers / Watch) |
| +------------------------------------+ |
| | Actual Kubernetes Cluster State | |
| | - Live Pods, Services, Deployments | |
| +------------------------------------+ |
| |
+-----------------------------------------------------------------------------------------+Pull-Based vs. Push-Based Deployment Architecture#
The architectural distinction between push-based CI/CD and pull-based GitOps is rooted in network topology, credential management, and blast radius containment.
+----------------------------------------------------------------------------------------------------+
| Push vs. Pull Architectural Comparison |
+---------------------------+-----------------------------------+------------------------------------+
| Feature | Push-Based CI/CD (e.g., Jenkins) | Pull-Based GitOps (ArgoCD / Flux) |
+---------------------------+-----------------------------------+------------------------------------+
| Direction of Execution | CI runner pushes to k8s API | In-cluster operator pulls from Git |
| Cluster API Ingress | Must be exposed to external CI | Completely closed / Private VPC |
| Administrative Credential | CI runner stores cluster admin | Zero cluster credentials outside |
| Drift Correction | None (Drift remains until deploy) | Continuous automated self-healing |
| Out-of-Band Changes | Overwrites or fails on collision | Instantly detected & reverted |
| Multi-Cluster Scalability | Linearly increases CI credentials | Centralized Git control repository |
+---------------------------+-----------------------------------+------------------------------------+The Push-Based Security Flaw#
In a push-based workflow, every external CI worker must possess elevated Kubernetes cluster-admin credentials (e.g., a kubeconfig token or client TLS certificate). If a vulnerability exists in any CI dependency, build script, or third-party pull request action, an attacker can extract the cluster credentials and achieve total administrative compromise of the production Kubernetes cluster.
The Pull-Based Security Advantage#
In a pull-based GitOps workflow, the Kubernetes cluster initiates all connections outbound to the Git repository (over HTTPS or SSH). The Kubernetes API server is completely isolated inside a private VPC with zero ingress from the public Internet or CI workers. Even if the CI runner is compromised, the attacker only has access to application build artifacts, never the cluster control plane.
ArgoCD: Architecture & Internal Mechanics#
ArgoCD is a declarative, Kubernetes-native GitOps continuous delivery tool maintained under the CNCF. It implements a three-tier microservice architecture deployed directly into the cluster.
+---------------------------------------------------------------------------------------+
| ArgoCD System Architecture |
+---------------------------------------------------------------------------------------+
| |
| Users / UI / CLI ---> [ argocd-server (API Server: gRPC / REST) ] |
| | |
| v |
| +-----------------------------------------------+ |
| | argocd-repo-server (Repository Server) | |
| | - Clones Git repos / fetches Helm charts | |
| | - Generates raw manifests (Kustomize/Helm) | |
| +-----------------------------------------------+ |
| | |
| v |
| +-----------------------------------------------+ |
| | argocd-application-controller | |
| | - Runs reconciliation loops | |
| | - Compares Desired State vs Live Cluster State| |
| | - Enforces Sync & Self-Heal Policies | |
| +-----------------------------------------------+ |
| | |
| v |
| [ Kubernetes API Server ] |
| |
+---------------------------------------------------------------------------------------+Component Responsibilities#
- `argocd-server`: Exposes the Web UI, gRPC API, and REST API. It handles user authentication (integrating with OpenID Connect, OAuth2, and GitHub/Okta SSO), enforces fine-grained Role-Based Access Control (RBAC), and translates user actions into Application updates.
- `argocd-repo-server`: An internal, unexposed service responsible for maintaining local Git repository caches. When a reconciliation occurs, the repo-server clones the designated commit SHA, renders any templating engines (Kustomize overlays, Helm values files, or Jsonnet scripts), and outputs pristine, raw Kubernetes YAML manifests to the Application Controller.
- `argocd-application-controller`: The continuous reconciliation engine. It uses Kubernetes client-go informers to watch the live state of the cluster in memory, compares it against the rendered desired state emitted by the repo-server, computes structural diffs, and executes synchronization actions.
The `Application` Custom Resource Definition (CRD)#
The core unit of management in ArgoCD is the Application CRD, which binds a target Git repository source to a destination cluster and namespace:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: payment-microservice
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: 'https://github.com/devthesis/infrastructure-gitops.git'
targetRevision: main
path: environments/production/services/payment
helm:
valueFiles:
- values.yaml
- values-prod.yaml
destination:
server: 'https://kubernetes.default.svc'
namespace: payments
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
- ApplyOutOfSyncOnly=true
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m- `prune: true`: Automatically deletes Kubernetes resources from the cluster when their corresponding manifest files are removed from Git.
- `selfHeal: true`: If a human operator manually modifies or deletes a live cluster resource (e.g., via
kubectl editorkubectl delete), the controller immediately detects the drift and overwrites the cluster state back to the Git specification.
Multi-Cluster Scaling with `ApplicationSet`#
Managing hundreds of microservices across dozens of regional clusters using individual Application manifests introduces severe duplication. The ApplicationSet controller automates the dynamic generation of ArgoCD applications using powerful generators:
- List Generator: Generates applications based on a static list of cluster targets.
- Cluster Generator: Dynamically discovers Kubernetes clusters registered in ArgoCD secrets.
- Git Generator: Scans directories or files inside a Git repository, creating applications dynamically for each folder matching a path pattern (e.g.,
apps/*/*). - Matrix Generator: Combines multiple generators using a Cartesian product (e.g., deploying all 10 services across all 5 geographical clusters = 50 dynamic applications).
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: regional-microservices
namespace: argocd
spec:
generators:
- matrix:
generators:
- clusters:
selector:
matchLabels:
tier: production
- git:
repoURL: https://github.com/devthesis/gitops-catalog.git
revision: main
directories:
- path: services/*
template:
metadata:
name: '{{path.basename}}-{{name}}'
spec:
project: default
source:
repoURL: https://github.com/devthesis/gitops-catalog.git
targetRevision: main
path: '{{path}}'
destination:
server: '{{server}}'
namespace: '{{path.basename}}'
syncPolicy:
automated:
prune: true
selfHeal: trueFlux v2: The GitOps Toolkit#
Flux v2 adopts a fundamentally different architectural philosophy from ArgoCD. While ArgoCD is an integrated application with a rich centralized GUI, Flux v2 is composed of modular, composable, single-purpose Kubernetes controllers known collectively as the GitOps Toolkit.
+---------------------------------------------------------------------------------------+
| Flux v2 Controller Suite |
+---------------------------------------------------------------------------------------+
| |
| Git Repo / OCI Registry / S3 Bucket |
| | |
| v |
| [ source-controller ] ----------------------------------------------+ |
| - Pulls Git, OCI, Helm repos | |
| - Produces compressed .tar.gz artifacts in-cluster | |
| | | |
| +-----------------------+ | |
| | | | |
| v v v |
| [ kustomize-controller ] [ helm-controller ] [ notification-controller ] |
| - Renders Kustomize - Evaluates HelmReleases - Emits alerts to Slack, |
| - Applies manifests - Upgrades Helm charts Teams, Webhooks |
| | | |
| +-----------+-----------+ |
| | |
| v |
| [ Kubernetes API Server ] |
| ^ |
| | |
| [ image-automation-controller ] |
| - Watches container registries (ECR, DockerHub, GHCR) |
| - Automatically commits new image tags back to Git |
| |
+---------------------------------------------------------------------------------------+Core Controllers of the GitOps Toolkit#
- `source-controller`: The acquisition engine. It watches external artifact sources declared in
GitRepository,HelmRepository,OCIRepository, orBucketCRDs, fetches updates, verifies cryptographic GPG/Cosign signatures, and serves them locally as gzipped tarballs. - `kustomize-controller`: Reconciles cluster state with Kustomize overlays, handling dependency ordering, health checks, and garbage collection.
- `helm-controller`: Declaratively manages Helm chart releases via the
HelmReleaseCRD, automating chart installations, upgrades, and rollbacks natively. - `notification-controller`: Handles inbound webhooks (e.g., from GitHub to trigger immediate reconciliation without waiting for the polling interval) and outbound notifications (dispatching sync events to Slack, Discord, or PagerDuty).
- `image-automation-controller` & `image-reflector-controller`: Closes the loop on continuous deployment. It scans container registries for new semantic image tags matching defined policies (e.g.,
semver: ^1.2.0), checks out the Git repository, updates the image tag directly in the manifest, and commits the change back to Git.
State Drift Detection & Continuous Reconciliation#
State drift occurs whenever the observed state of a cluster resource deviates from the desired state declared in the version control repository. Drift can occur through manual administrative intervention (kubectl edit), third-party mutating admission webhooks, or failure of underlying node infrastructure.
The Reconciliation Control Loop#
The mathematical control loop executed by GitOps operators follows an infinite continuous evaluation function:
State_desired = Render(Git_Commit_SHA)
State_observed = Query(Kube_API_Server)
Drift = Diff(State_desired, State_observed)
if Drift != ∅:
if Policy.SelfHeal == True:
Execute(Kube_API_Server.Patch(State_desired))
else:
Alert("Drift detected: OutOfSync")Handling Benign Mutating Drift#
Not all deviations between live state and Git state represent unwanted drift. In modern Kubernetes environments:
- Horizontal Pod Autoscalers (HPA): Modify the
spec.replicasfield of a Deployment dynamically based on traffic spikes. - Mutating Admission Controllers: Inject sidecar proxies (e.g., Istio Envoy, Datadog tracing agents) or security contexts at runtime.
If a GitOps operator strictly enforces spec.replicas: 3 as defined in Git, it will enter a continuous fight against the HPA, creating an infinite oscillation (HPA scales to 10 pods, GitOps operator scales back to 3 pods).
To solve this, GitOps controllers support field-level drift ignoring:
# ArgoCD ignoreDifferences Configuration
spec:
ignoreDifferences:
- group: apps
kind: Deployment
jsonPointers:
- /spec/replicas
- group: ""
kind: Service
jsonPointers:
- /spec/clusterIPSecret Management in GitOps Workflows#
Storing plaintext Kubernetes Secret manifests containing Base64-encoded passwords or private keys inside a Git repository violates fundamental security principles, even within private repositories.
Modern GitOps relies on three primary architectures for secure credential handling:
+-----------------------------------------------------------------------------------------+
| GitOps Secret Architectures |
+-----------------------------------------------------------------------------------------+
| Strategy 1: Asymmetric In-Git Encryption (Sealed Secrets / SOPS) |
| Developer ---> [ Encrypt with Public Key ] ---> Commit to Git |
| Cluster Operator ---> [ In-Cluster Private Key ] ---> Decrypts to Native Secret |
+-----------------------------------------------------------------------------------------+
| Strategy 2: External Key Management Sync (External Secrets Operator - ESO) |
| Git contains 'ExternalSecret' CRD (references vault path) |
| ESO Operator ---> Pulls from AWS Secrets Manager / Vault ---> Creates Native Secret |
+-----------------------------------------------------------------------------------------+1. Sealed Secrets (Bitnami)#
Sealed Secrets uses asymmetric cryptography. A controller inside the cluster generates a public/private RSA key pair.
- Developers use the
kubesealCLI with the cluster's public key to encrypt a raw secret into aSealedSecretcustom resource. - The
SealedSecretcan be safely committed to public Git because only the private key stored inside the specific cluster can decrypt it. - When applied to the cluster, the Sealed Secrets operator unseals the manifest and creates a standard Kubernetes
Secret.
2. External Secrets Operator (ESO)#
External Secrets Operator decouples secret storage entirely from Git.
- Secrets reside in enterprise credential management systems (AWS Secrets Manager, HashiCorp Vault, Azure Key Vault, Google Cloud Secret Manager).
- Git contains only an
ExternalSecretmanifest pointing to the secret path:
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: database-credentials
namespace: backend
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secrets-manager
kind: ClusterSecretStore
target:
name: db-secret-native
creationPolicy: Owner
data:
- secretKey: DB_PASSWORD
remoteRef:
key: production/rds/postgres
property: passwordSynchronization Ordering: Sync Waves & Resource Hooks#
In complex enterprise applications, resources cannot be applied in arbitrary order. For instance, a Custom Resource Definition (CRD) must exist before instances of that Custom Resource (CR) can be applied; database schema migration jobs must complete successfully before new web API pods boot up.
ArgoCD coordinates multi-phase deployments using Sync Waves and Resource Hooks:
- Sync Waves (`argocd.argoproj.io/sync-wave`): An integer annotation (positive or negative). ArgoCD groups resources by wave value, applying wave
nand waiting for all resources in wavento reach a Healthy state before initiating waven + 1. - Resource Hooks (`argocd.argoproj.io/hook`): Special annotations that execute transient batch jobs during lifecycle phases:
PreSync,Sync,PostSync, andSyncFail.
apiVersion: batch/v1
kind: Job
metadata:
name: schema-migration-v2
annotations:
argocd.argoproj.io/hook: PreSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
argocd.argoproj.io/sync-wave: "1"
spec:
template:
spec:
containers:
- name: migrate
image: devthesis/migrator:v2.1.0
command: ["./migrate.sh", "up"]
restartPolicy: NeverWave -2: Namespaces, NetworkPolicies
Wave -1: CustomResourceDefinitions (CRDs)
Wave 0: ConfigMaps, Secrets, StorageVolumes
Wave 1: PreSync Database Migration Job (Blocks until Exit Code 0)
Wave 2: Deployments, StatefulSets (Waits for Ready status)
Wave 3: Services, Ingresses, DNS routing
Wave 4: PostSync Health Check & Smoke Test JobEnterprise GitOps Repository Architecture: Mono-Repo vs. Poly-Repo#
Designing the Git repository topology is one of the most critical foundational architectural decisions in enterprise GitOps. Organizations must choose between consolidating all infrastructure manifests into a single centralized repository (Mono-repo) or distributing manifests across dedicated per-service repositories (Poly-repo).
1. The Multi-Repo (Separated Application and Config) Model#
In high-maturity enterprises, application source code and deployment configuration are strictly decoupled across two distinct repositories:
- Application Source Repository (`github.com/org/payment-service`):
Contains application business logic, unit tests, integration test suites, and the Dockerfile. Developers commit feature branches and trigger CI pipelines here. This repository publishes compiled container images to an OCI registry (e.g., ghcr.io/org/payment:v2.1.0).
- Infrastructure / GitOps Repository (`github.com/org/gitops-environments`):
Contains the declarative Kubernetes manifests, Kustomize overlays, Helm charts, and environment-specific configuration values (dev, staging, prod). The GitOps operator monitors this repository exclusively.
+---------------------------------------------------------------------------------------+
| Decoupled Multi-Repo GitOps Architecture |
+---------------------------------------------------------------------------------------+
| |
| [ App Repository: payment-service ] |
| - Business code & Dockerfile |
| - CI Pipeline runs test, builds image |
| | |
| v Pushes Image |
| [ Container Registry: payment:v2.1.0 ] |
| ^ |
| | Reads / Updates Image Tag |
| [ GitOps Config Repository: gitops-prod ] |
| - environments/prod/payment/kustomization.yaml |
| | |
| v In-Cluster Pull |
| [ ArgoCD / Flux Controller ] ---> Deploys to Production Kubernetes Cluster |
| |
+---------------------------------------------------------------------------------------+- Security Advantage: Developers do not need write access to production deployment manifests. The CI pipeline updates the config repository via a scoped deploy token or pull request bot, enforcing strict branch protection and approval gates.
- Separation of Concerns: Prevents noisy Git commit history; application code changes do not trigger false infrastructure rollouts, and infrastructure updates (such as tuning memory limits) do not require rebuilding container images.
Disaster Recovery & Total Cluster Re-hydration#
In traditional infrastructure management, recovering from a catastrophic regional cloud outage or cluster failure involves executing complex runbooks, configuring databases, restoring backup scripts, and manually redeploying applications over multiple stressful hours.
Under GitOps, the entire cluster configuration is captured deterministically in Git. This enables instant cluster re-hydration:
- Infrastructure as Code (Terraform / Pulumi): Provisions a fresh, empty Kubernetes cluster in an alternative cloud region (e.g., failover from AWS
us-east-1tous-west-2) in ~10 minutes. - Bootstrap GitOps Operator: A lightweight bootstrap script installs the ArgoCD or Flux operator into the empty cluster:
```bash
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
```
- Apply Root Application (App of Apps Pattern): Apply a single root
Applicationmanifest that points to the GitOps repository:
```bash
kubectl apply -f https://github.com/devthesis/gitops-config/root-app.yaml
```
- Automated Convergence: The in-cluster operator pulls the entire repository, establishes sync waves, creates namespaces, installs CRDs, provisions ingress controllers, decrypts secrets via external secret operators, and deploys all 200 microservices in perfect topological order.
Within minutes, the replacement cluster achieves 100% parity with the destroyed production cluster without a single manual kubectl apply command executed by engineers.
Common Architectural Pitfalls in GitOps#
1. Repository Feedback Loops (Git Commit Storms)#
If an automated CI tool or in-cluster controller (e.g., image updater) commits updates back to Git without proper branch or path filtering, it can trigger an infinite recursive feedback loop:
- Controller updates image tag and commits to Git.
- Git webhook triggers CI pipeline.
- CI pipeline builds new container and pushes tag.
- Controller detects new tag and commits to Git again.
- Mitigation: Decouple application source code repositories from environment configuration repositories. Maintain separate branches or configure path filters (
ignore: ["*.md", ".github/*"]).
2. Excessive Git Polling Throttling & API Rate Limits#
When hundreds of microservices poll GitHub or GitLab every 30 seconds for state drift, the organization quickly exhausts Git provider API rate limits, resulting in HTTP 429 Too Many Requests and halted reconciliation loops.
- Mitigation: Configure inbound Git webhooks from GitHub/GitLab directly to the ArgoCD/Flux webhook endpoints. This enables event-driven reconciliation: repository polling intervals can be reduced from 30 seconds to 1 hour, reserving polling purely as a fail-safe backup.
3. Cascading Resource Deletion on Namespace Pruning#
If an Application manifest that manages a core namespace is accidentally deleted from Git while prune: true is enabled, the GitOps operator interprets this as an instruction to delete the entire namespace and all encapsulated stateful workloads (PVCs, databases, secrets).
- Mitigation: Apply the
argocd.argoproj.io/sync-options: Delete=falseannotation to mission-critical stateful resources; implement Kyverno or OPA gatekeeper policies prohibiting namespace deletion via automated GitOps service accounts.
Checkpoint Practice Problems#
Problem 1 (GitOps Reconciliation Latency & Event-Driven Acceleration): A cluster hosts M = 150 independent ArgoCD applications.
- Under standard polling mode, ArgoCD polls the Git repository every T_poll = 180 seconds. In the worst case, a developer commit takes up to 180 seconds to be recognized.
- Under webhook-driven mode, GitHub triggers the ArgoCD webhook instantly upon commit with network transit latency T_webhook = 250 milliseconds.
- The repo-server manifest generation time is T_gen = 1.2 seconds, and the Kubernetes API apply phase takes T_apply = 2.5 seconds.
Calculate:
- The worst-case Total Synchronization Latency (TSL_poll) under polling mode.
- The Total Synchronization Latency (TSL_webhook) under event-driven webhook mode.
- The absolute time saved by implementing event-driven webhooks for developer feedback.
Solution:
- Polling Mode Latency (worst-case):
```
TSL_poll = T_poll + T_gen + T_apply
TSL_poll = 180.0 s + 1.2 s + 2.5 s = 183.7 seconds (~3 minutes 3.7 seconds)
```
- Webhook Mode Latency:
Convert T_webhook to seconds: 250 ms = 0.25 seconds.
```
TSL_webhook = T_webhook + T_gen + T_apply
TSL_webhook = 0.25 s + 1.2 s + 2.5 s = 3.95 seconds
```
- Latency Improvement:
```
Time Saved = 183.7 s - 3.95 s = 179.75 seconds
```
Webhooks accelerate synchronization feedback from over 3 minutes down to less than 4 seconds.
Problem 2 (Sync Wave Deployment Dependency Graph Duration): An enterprise deployment plan is structured across five sequential Sync Waves:
- Wave -1 (CRDs): Execution duration = 4 seconds.
- Wave 0 (Storage & Secrets): Execution duration = 6 seconds.
- Wave 1 (PreSync Database Migration Job): Execution duration = 45 seconds.
- Wave 2 (Application Deployments): Boot, initialization, and Readiness probe interval = 30 seconds.
- Wave 3 (Ingress & PostSync Smoke Tests): Execution duration = 15 seconds.
Between each sequential wave, the ArgoCD controller incurs a reconciliation evaluation overhead of T_overhead = 3 seconds.
- Compute the minimum total elapsed execution time for a successful end-to-end synchronization.
- If the database migration job in Wave 1 fails with an error (exit code 1) at second 20, state whether Wave 2 will execute, and calculate the exact timestamp at which the pipeline halts.
Solution:
- Total Sync Time:
The waves execute sequentially with 4 transition overhead intervals between the 5 waves:
```
T_total = T_wave(-1) + T_wave(0) + T_wave(1) + T_wave(2) + T_wave(3) + (4 · T_overhead)
T_total = 4 + 6 + 45 + 30 + 15 + (4 · 3)
T_total = 100 + 12 = 112 seconds
```
- Failure Scenario Analysis:
* Wave -1 completes: 4 seconds.
* Overhead: 3 seconds (Cumulative = 7 s).
* Wave 0 completes: 6 seconds (Cumulative = 13 s).
* Overhead: 3 seconds (Cumulative = 16 s).
* Wave 1 runs and fails at second 20 of its execution: 16 s + 20 s = 36 seconds.
Because Wave 1 failed to reach a Healthy state, ArgoCD halts execution immediately. Wave 2 will never execute*.
The pipeline halts in SyncFailed state at exactly timestamp T = 36 seconds.
Problem 3 (Pull vs Push Blast Radius Risk Assessment): An organization operates C = 20 Kubernetes clusters across 4 geographical regions.
- Under Architecture A (Push-based CI): The central CI server stores administrative service account tokens for all 20 clusters in its build runner environment.
- Under Architecture B (Pull-based GitOps): Each cluster runs an isolated internal GitOps operator. The central Git repository stores encrypted manifests, and no cluster possesses credentials to any other cluster.
If a severe supply-chain vulnerability allows an adversary to execute remote code execution (RCE) inside a CI build runner:
- What percentage of clusters are vulnerable to immediate total control plane compromise under Architecture A?
- What percentage of clusters are vulnerable to direct control plane compromise under Architecture B?
- What is the blast radius under Architecture B if the adversary modifies a manifest in the Git repository?
Solution:
- Architecture A (Push-based):
Because the CI runner stores valid administrative tokens for all 20 clusters, the adversary can extract all tokens and immediately control all 20 clusters.
```
Compromised Clusters = 20 / 20 = 100%
```
- Architecture B (Pull-based):
The CI runner possesses zero cluster credentials. The attacker cannot connect to any Kubernetes API server.
```
Direct Control Plane Compromise = 0 / 20 = 0%
```
- Indirect Git Manipulation Blast Radius:
If the attacker modifies the Git repository, the change must still pass Git branch protection rules, cryptographically signed commit verifications, and in-cluster admission controller validations (Kyverno/OPA). The blast radius is constrained strictly by policy-as-code rather than unlimited cluster-admin credentials.
Problem 4 (ApplicationSet Matrix Generator Application Sizing): A platform team defines an ApplicationSet using a Matrix Generator:
- Generator 1 (Clusters): Targets all production clusters labeled with
environment: production. There are N_clusters = 8 registered production clusters. - Generator 2 (Services): Discovers directories in the
services/path in Git. There are N_services = 25 distinct microservice directories. - Each microservice Deployment declares
replicas: 4.
Calculate:
- The total number of ArgoCD
Applicationcustom resources dynamically generated by the Matrix Generator. - The total number of active Pods running across all production clusters managed by this single ApplicationSet.
Solution:
- Calculate dynamic Applications:
The Matrix generator computes the Cartesian product of the two generators:
```
Total Applications = N_clusters · N_services
Total Applications = 8 · 25 = 200 Applications
```
- Calculate total running Pods:
Each application manages a Deployment with 4 replicas:
```
Total Pods = Total Applications · Replicas_per_app
Total Pods = 200 · 4 = 800 Pods
```
The single ApplicationSet declaratively provisions and continuously reconciles 200 distinct applications comprising 800 production pods across 8 global clusters.