Kubernetes Q&A: What to bundle in the Argo CD application and best practices to manage other resources

What to Bundle in Argo CD Applications (And How to Manage the Rest) If you're deploying apps with Argo CD, you're already halfway to a solid GitOps workflow. B.

JR

3 minute read

What to Bundle in Argo CD Applications (And How to Manage the Rest)

If you’re deploying apps with Argo CD, you’re already halfway to a solid GitOps workflow. But when it comes to bundling resources like Gateways, HTTPRoutes, and StorageClasses, confusion sets in fast. Let’s cut through the noise with production-tested patterns.

Core Principle: Separate Cluster-Scoped and Namespace-Scoped Resources

Cluster-scoped resources (e.g., Gateways, StorageClasses, CRDs) belong in dedicated infrastructure apps. Namespace-scoped resources (e.g., Deployments, Services, HTTPRoutes) stay with their applications. This separation prevents conflicts, simplifies ownership, and avoids “works on my cluster” syndrome.

What to Bundle in Your Argo Application

For a typical app (e.g., a microservice):

  • Helm chart: Your app’s Deployment, Service, and environment-specific configs.
  • HTTPRoute: If using Gateway APIs or Ingress controllers that support CRDs.
  • ConfigMaps/Secrets: App-specific non-sensitive data and credentials (e.g., API keys).
  • ServiceEntry/PeerAuthentication: If your app talks to external services or uses mTLS.

Do not bundle:

  • StorageClasses: These are cluster-wide. Define them once in an infra app.
  • Gateways: Deploy these separately unless you’re in a multi-tenant cluster with per-team Gateways.
  • CRDs: If your app uses custom resources, deploy the CRD as a standalone app first (Argo CD struggles with CRD sync order).

App-of-Apps Pattern: Deploy Hierarchically

Use a root application to manage dependencies. Example structure:

infra-app/         # Gateways, StorageClasses, CRDs
apps-app-of-apps/  # SyncWave-controlled deployment of app groups
app-a/             # App A’s Helm chart + HTTPRoute
app-b/             # App B’s Helm chart + HTTPRoute

Sync Waves for Dependency Ordering

Use argoproj.io/sync-wave annotations to ensure Gateways deploy before apps that depend on them:

metadata:
  annotations:
    argoproj.io/sync-wave: "1"  # Gateway deploys first

For apps that share a database:

# In database app
metadata:
  annotations:
    argoproj.io/sync-wave: "1"
# In app-a
metadata:
  annotations:
    argoproj.io/sync-wave: "2"

ApplicationSets: Scale Beyond App-of-Apps

For 10+ apps, use Argo ApplicationSets to generate applications dynamically:

  • GitDirectory Generator: Auto-deploy apps from a clusters/ or apps/ directory structure.
  • Cluster Generator: Deploy the same app to dev/staging/prod clusters.

Example ApplicationSet manifest:

spec:
  generators:
    - gitDirectory:
        repoURL: https://github.com/your-org/infra
        path: apps/
        exclude:
          - apps/legacy/
  templates:
    - app:
        project: default
        repoURL: https://github.com/your-org/infra
        path: apps/{{.App}}
        destination: server=https://kubernetes.default

Tooling That Won’t Let You Down

  • Argo CD: Obvious, but ensure you’re on v2.8+ for improved HTTPRoute support.
  • Kustomize: For overlaying environment-specific configs without Helm (if that’s your jam).
  • OPA Gatekeeper: Enforce policies like “no apps without HTTPRoute” or “StorageClasses must be read-only”.
  • Prometheus + Grafana: Monitor Argo CD sync health and app availability.

Policy Example: Enforce HTTPRoute for Ingress Resources

If your cluster uses Ingress instead of Gateway APIs:

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredProhibited
metadata:
  name: ingress-must-have-httproute
spec:
  match:
    kinds:
      - apiGroups: ["networking.k8s.io"]
        kinds: ["Ingress"]
  parameters:
    prohibitedList:
      - field: ["metadata.annotations.httpRoute"]

Practical Workflow for Adding a New App

  1. Define ownership: Is this app’s resource cluster-wide or namespace-specific?
  2. Structure your repo:
    • /infra for Gateways, StorageClasses, CRDs.
    • /apps for Helm charts + HTTPRoutes.
  3. Create Argo apps:
    • One for infra resources.
    • One app-of-apps for your app group.
  4. Set Sync Waves for dependencies.
  5. Test health checks: Argo CD doesn’t auto-detect HTTPRoute health—add health.argoproj.io/health-check=true to Ingress/HTTPRoute resources.

Final Words

Argo CD excels at declarative deployments but doesn’t solve architecture decisions for you. Bundle apps with their routing and config, separate infra resources, and use Sync Waves/ApplicationSets to manage complexity. When in doubt, ask: “Would this resource break if another team changes it?” If yes, it belongs in a dedicated infra app.

Now go deploy something that won’t wake you up at 3 AM.

Source thread: What to bundle in the Argo CD application and best practices to manage other resources?

comments powered by Disqus