Skip to main content

CCM Hetzner

Wrapper chart for the upstream hcloud-cloud-controller-manager chart (dependency aliased to ccm-hetzner, pinned to 1.34.0). Per the chart description, this replaces the legacy syself/hetzner-cloud-controller-manager fork — upstream gained Hetzner Robot (bare-metal) support and forwards kubelet's --node-ip to InternalIP as of v1.24.0, which the syself fork never did.

Why it's in KubeAid

This one chart directory backs two distinct Argo CD Applications on Hetzner clusters, differentiated only by values file and nameOverride:

  • ccm-hetzner — rendered for bare-metal and hybrid modes (HetznerCCMNonSecretTemplateNames). Owns Hetzner Robot (bare-metal) node lifecycle; in hybrid mode its controllers are scoped to cloud-node,cloud-node-lifecycle so it doesn't fight ccm-hcloud over Services.
  • ccm-hcloud — rendered for hcloud and hybrid modes (HCloudCCMNonSecretTemplateNames). Owns HCloud node routing/InternalIP and all HCloud LoadBalancer reconciliation.

In a hybrid cluster both run simultaneously in kube-system, each scoped to its own node population.

Prerequisites

  • HCLOUD_TOKEN / ROBOT_USER / ROBOT_PASSWORD from the kube-system/cloud-credentials Secret that kubeaid-cli provisions (pkg/core/hcloud_credentials.go) — this chart's values.yaml points every secretKeyRef at that Secret's hcloud / robot-user / robot-password keys (overriding the upstream chart's own hcloud/token default naming so the existing Secret works unmodified).

Key values / KubeAid-specific configuration

Upstream values live under the ccm-hetzner: key.

  • nameOverride: ccm-hetzner — matches the syself-era resource name so an in-place chart switch replaces the existing Deployment/ServiceAccount instead of leaving two CCMs racing for ownership of node.status.
  • robot.enabled — gates Robot (bare-metal) support; kubeaid-cli's overlay sets it true for bare-metal/hybrid and false otherwise (upstream defaults it to true).
  • networking.enabled (default false) — HCloud private-network pod routing; kubeaid-cli flips this on via --set in hybrid mode (HCloud CPs reaching bare-metal workers over the private network).
  • env.HCLOUD_TOKEN / ROBOT_USER / ROBOT_PASSWORD / networking.network — wired to cloud-credentials as above (robot-user/robot-password marked optional: true).
  • nodeSelector: node-role.kubernetes.io/control-plane: "" — runs on control-plane nodes only.
  • For the ccm-hcloud instance specifically: nameOverride: ccm-hcloud, robot.enabled: false, env.HCLOUD_LOAD_BALANCERS_NETWORK_ZONE, and conditionally HCLOUD_LOAD_BALANCERS_DISABLE_PUBLIC_NETWORK / HCLOUD_LOAD_BALANCERS_USE_PRIVATE_IP depending on cluster topology (workload-behind-VPN, private nodes).

Operational notes

  • Both instances mirror the node.kubernetes.io/not-ready:Exists:NoSchedule toleration the bootstrap postKubeadm step sets, so Argo CD's desired state matches and doesn't strip it on the next sync — CCM itself must be able to schedule before it clears node.cloudprovider.kubernetes.io/uninitialized.
  • Switching from the syself fork: the old ccm-hetznercluster-admin ClusterRoleBinding is orphaned until Argo CD prunes it (bootstrap-time kubectl apply won't remove it). Acceptable short-term — the orphan grants the same ServiceAccount, so there's no auth regression in the gap.