Skip to content

Support direct GitOps deployment without clusterctl preprocessing #13146

@broboa

Description

@broboa

What would you like to be added (User Story)?

As a platform engineer using GitOps tools (ArgoCD, Flux) with automated dependency management (Renovate, Dependabot), I want to deploy Cluster API components directly from GitHub releases without requiring clusterctl or preprocessing, so that I can maintain declarative infrastructure with automatic version updates.

Detailed Description

Currently, release artifacts contain bash-style variable substitutions (e.g., ${CAPI_DIAGNOSTICS_ADDRESS:=:8443}) in container args that are intended for clusterctl processing. When these manifests are applied directly via GitOps tools, the variables are passed as literal strings, causing controller startup failures:

invalid argument "${CAPI_INSECURE_DIAGNOSTICS:=false}" for "--insecure-diagnostics" flag: strconv.ParseBool: parsing "${CAPI_INSECURE_DIAGNOSTICS:=false}": invalid syntax

Affected files:

  • core-components.yaml - capi-controller-manager deployment
  • control-plane-components.yaml - capi-kubeadm-control-plane-controller-manager deployment
  • bootstrap-components.yaml - capi-kubeadm-bootstrap-controller-manager deployment

Reproduction:

  1. Create ArgoCD Application pointing to https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.12.0/core-components.yaml
  2. Deploy the application
  3. Controller manager crashes with variable parsing errors

Current workarounds and their limitations:

  1. clusterctl generate provider - Requires local execution and committing output, breaking automated dependency updates
  2. Kustomize patches - Maintenance burden, must be updated when new variables are added
  3. Custom ArgoCD plugin with envsubst - Treats symptom, adds complexity
  4. capi-operator - Overkill for basic single-provider deployments where ArgoCD's reconciliation is sufficient

Proposed solutions:

  1. Provide additional release artifacts with pre-substituted variables (e.g., core-components-gitops.yaml or core-components-defaults.yaml)

    • Least disruptive: existing clusterctl workflows continue unchanged
    • GitOps users get directly consumable artifacts
    • Enables automated dependency tracking via Renovate/Dependabot
  2. Use Kubernetes environment variables

    • Define args using standard Kubernetes env var syntax: --diagnostics-address=$(CAPI_DIAGNOSTICS_ADDRESS)
    • Set default values in container's env section
    • Allows customization through standard Kustomize patches that both clusterctl and GitOps tools support
    • Strategic merge patches can target env vars by name without needing array indices
    • Kubernetes-native pattern
  3. Use ConfigMap-based configuration

    • Move configuration from command-line args to ConfigMaps
    • Allows customization through standard Kustomize patches that both clusterctl and GitOps tools support
    • Kubernetes-native pattern
  4. Provide official Kustomize bases

    • Structure releases as Kustomize bases referenceable via URL: https://github.com/kubernetes-sigs/cluster-api//config/default?ref=v1.12.0
    • Users reference in their kustomization.yaml and apply patches as needed
    • Similar to Kubebuilder project structure

Anything else you would like to add?

The current design assumes clusterctl as the primary installation method, which conflicts with modern GitOps practices. Many organizations use tools like Renovate to automatically track GitHub releases and create PRs for dependency updates. This workflow is impossible when manifests require preprocessing.

While capi-operator exists, it introduces significant complexity for simple use cases (single provider, static configuration) where ArgoCD's built-in reconciliation is sufficient. The operator shouldn't be required just to work around variable substitution in static manifests.

Related documentation:

Label(s) to be applied

/kind feature
/area clusterctl
/area provider/core
/area provider/bootstrap-kubeadm
/area provider/control-plane-kubeadm

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/clusterctlIssues or PRs related to clusterctlarea/provider/bootstrap-kubeadmIssues or PRs related to CAPBKarea/provider/control-plane-kubeadmIssues or PRs related to KCParea/provider/coreIssues or PRs related to the core providerkind/featureCategorizes issue or PR as related to a new feature.needs-priorityIndicates an issue lacks a `priority/foo` label and requires one.needs-triageIndicates an issue or PR lacks a `triage/foo` label and requires one.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions