Cluster API Provider for Proxmox VE (CAPMOX)

repository·main·Indexed 19 days ago

https://github.com/ionos-cloud/cluster-api-provider-proxmox

CAPMOX is a Cluster API (CAPI) provider for the declarative management of Kubernetes clusters on Proxmox Virtual Environment (VE). It enables creating, configuring, and managing clusters using Kubernetes-style APIs. Key features include support for dual-stack (IPv4/IPv6) clusters, BGP-based LoadBalancer nodes via Cilium, tag-based VM template selection, and a convert CLI tool for upgrading manifests from v1alpha1 to v1alpha2.

Tokens
17.7K
Snippets
42
Records
64
Agent score
66%

What's inside cluster-api-provider-proxmox

  1. Configure additive IP pools for ProxmoxMachine network devices

    main

    In v1alpha2, IP address assignment uses network.networkDevices and ipPoolRef.

    Important: Pool references are additive.

    • defaultIPv4 or defaultIPv6 (set to true) attaches addresses from the selected cluster zone (or the default zone if network.zone is not specified).
    • networkDevices[].ipPoolRef adds additional addresses from the listed pools.

    If both are configured on the same NIC, that NIC will receive multiple addresses (one for each configured pool reference).

    apiVersion: infrastructure.cluster.x-k8s.io/v1alpha2
    kind: ProxmoxMachineTemplate
    metadata:
      name: "test-control-plane"
    spec:
      template:
        spec:
          network:
            networkDevices:
              - name: net0
                bridge: ${BRIDGE}
                defaultIPv4: true
                ipPoolRef:
                  - apiGroup: ipam.cluster.x-k8s.io
                    kind: GlobalInClusterIPPool
                    name: shared-inclusterippool
  2. Automatic conversion of existing cluster resources

    main

    CAPMOX v0.8 uses a conversion webhook to support both v1alpha1 and v1alpha2.

    • Automatic etcd conversion: Resources already stored in the cluster (etcd) are converted to v1alpha2 automatically upon upgrade.
    • Storage Version: v1alpha2 is the internal storage version. You can still read resources via the v1alpha1 API, but all new writes should target v1alpha2.
    • Lossy Conversions: Some v1alpha2-only fields (e.g., zoneConfigs, per-device defaultIPv4/defaultIPv6) have no v1alpha1 equivalent. If reading via v1alpha1, these fields will be absent, though the provider preserves them via annotations during round-trips.
    • Status Changes: FailureReason and FailureMessage on status objects are removed in v1alpha2 to comply with the Cluster API v1beta2 contract, which uses structured conditions instead.
  3. Understand breaking changes in CAPMOX v0.8 (v1alpha2)

    main

    Upgrading to v0.8 introduces several breaking changes that require manual updates to your YAML manifests, Helm charts, or GitOps templates. While existing resources in the cluster are converted automatically via a webhook, your source files must be updated.

    Key Breaking Changes

    ChangeImpact
    API version v1alpha1v1alpha2All CAPMOX resources
    Cluster API v1beta1v1beta2All Cluster, KubeadmControlPlane, MachineDeployment, KubeadmConfigTemplate resources
    Unsigned integer fields → signed integersAll CAPMOX resources with numeric fields
    Network: default + additionalDevicesnetworkDevices listProxmoxMachineTemplate
    IP pool refs: ipv4PoolRef / ipv6PoolRefipPoolRef listProxmoxMachineTemplate
    kubeletExtraArgs format changed from map to name/value listKubeadmControlPlane, KubeadmConfigTemplate
    CloneSpec removed from ProxmoxClusterProxmoxCluster
    machineTemplate.infrastructureRef moved into machineTemplate.specKubeadmControlPlane
  4. Use Tag-based Template Selection

    main

    CAPMOX can look up Proxmox VM templates using tags instead of explicit IDs. This is managed via the TemplateSelector on the ProxmoxMachine resource.

    Resolution Policies:

    • exact (default): The template's tags must be an exact 1:1 match with the requested matchTags.
    • subset: The template's tags must contain all of the matchTags, but can include additional tags.

    Integration with ClusterClass: When using a ClusterClass, you can drive selection via the spec.topology.variables.templateSelector field on the Cluster resource. If set, the ClusterClass injects the selector into all ProxmoxMachineTemplate resources and ignores sourceNode/templateID.

  5. Use Cluster Templates and Flavors

    main

    CAPMOX provides several templates (flavors) for different use cases. Some flavors, like cilium and calico, require creating ConfigMaps containing ClusterResourceSet (CRS) files before deployment to enable CNI.

    | Flavor              | Template File                                | CRS File                                |
    |---------------------|----------------------------------------------|-----------------------------------------|
    | cilium              | templates/cluster-template-cilium.yaml       | templates/crs/cni/cilium.yaml           |
    | calico              | templates/cluster-template-calico.yaml     | templates/crs/cni/calico.yaml           |
    | multiple-vlans      | templates/cluster-template-multiple-vlans.yaml | -                                       |
    | default             | templates/cluster-template.yaml             | -                                       |
    | cilium loadbalancer | templates/cluster-template-cilium-load-balancer.yaml | templates/crs/cni/cilium.yaml, templates/crs/metallb.yaml |
    | external-creds      | templates/cluster-template-external-creds.yaml | -                                       |
    | flatcar             | templates/cluster-template-flatcar.yaml     | -                                       |
  6. Set up a CAPMOX development environment with Tilt

    main

    To develop CAPMOX using Tilt, you must set up a specific directory structure containing the Cluster API ecosystem repositories. Tilt manages the orchestration of these components.

    Prerequisites

    • Required Tools: git, make, Go, Docker, Tilt, kubectl, kind, clusterctl.
    • Proxmox Access: A running Proxmox VE instance and an API token.

    Setup Steps

    1. Clone Repositories: Create a parent directory and clone the following into it:

      • cluster-api (This will be your working directory for Tilt)
      • cluster-api-ipam-provider-in-cluster
      • cluster-api-provider-proxmox
    2. Configure Tilt: Inside the cluster-api directory, create a tilt-settings.json file:

      {
        "default_registry": "ghcr.io/ionos-cloud",
        "provider_repos": ["../cluster-api-provider-proxmox/", "../cluster-api-ipam-provider-in-cluster/"],
        "enable_providers": ["ipam-in-cluster", "proxmox", "kubeadm-bootstrap", "kubeadm-control-plane"],
        "allowed_contexts": ["minikube"],
        "kustomize_substitutions": {},
        "extra_args": {
          "proxmox": ["--v=4"]
        },
        "debug": {
          "proxmox": {
            "port": 30000
          }
        }
      }

      Note: The debug section enables a Delve remote debugger on port 30000. To use it, run: kubectl port-forward deployments/capmox-controller-manager 30000:30000 -n capmox-system.

    3. Configure Proxmox Environment Variables:

      • Copy ../cluster-api-provider-proxmox/envfile.example to ../cluster-api-provider-proxmox/envfile.
      • Populate it with your Proxmox credentials (refer to Usage.md#environment-variables).
      • If using a specific kind cluster name, add CAPI_KIND_CLUSTER_NAME=<yourclustername> to this file.
    4. Launch: From the cluster-api directory, run:

      . ../cluster-api-provider-proxmox/envfile && tilt up
    . ../cluster-api-provider-proxmox/envfile && tilt up
  7. Resolve node deployment failures with mixed interface models

    main

    Kubelet selects the first interface to acquire a node-ip based on the in-kernel order (determined by PCI bus scan order and driver loading). If you have mixed interface types (e.g., virtio and e1000), the wrong interface might be chosen.

    Example Scenario: If e1000 interfaces are detected before virtio interfaces, they will be assigned lower index numbers (e.g., eth0), causing Kubelet to pick them as the primary interface.

    Fix: If you must use mixed interface types, ensure the intended default network interface is the one that appears first in the kernel/PCI scan order.

  8. Configure LoadBalancer nodes with BGP

    main

    The cilium-load-balancer flavor provides specialized nodes for load balancing. These nodes feature an extra network card connected to BGP receiving switches. All services of type LoadBalancer will use IPs from METALLB_IPV4_RANGE or METALLB_IPV6_RANGE, which are announced via BGP.

    Technical Requirements:

    • Routing: Uses source IP-based routing. This requires all nodes to be created with ipvs in kube-proxy and strictARP enabled to prevent reverse path filter issues.
    • Immutability: If you need to change METALLB_IPV{4,6}_RANGE after deployment, you must redeploy the load balancer nodes because these variables are used during bootstrap for routing.
    • Node Behavior: LoadBalancer nodes are tainted to ensure only load-balancing pods run on them.
    # Example environment variables for BGP LoadBalancer setup
    export LOAD_BALANCER_MACHINE_COUNT=2
    export EXT_SERVICE_BRIDGE="vmbr2"
    export LB_BGP_IPV4_RANGES="[172.16.4.10-172.16.4.20]"
    export LB_BGP_IPV4_PREFIX="24"
    export METALLB_IPV4_ASN="65400"
    export METALLB_IPV4_BGP_PEER="172.16.4.1"
    export METALLB_IPV4_BGP_PEER2="172.16.4.2"
    export METALLB_IPV4_BGP_PEER_ASN="65500"
    export METALLB_IPV4_RANGE="7.6.5.0/24"
    
    # Generate the cluster
    clusterctl generate cluster test-bgp-lb  \\
      --infrastructure proxmox \\
      --kubernetes-version v1.34.8 \\
      --control-plane-machine-count=1 \\
      --worker-machine-count=2 \\
      --flavor=cilium-load-balancer > cluster.yaml
  9. Update CAPI v1beta2 kubeletExtraArgs and infrastructureRef

    main

    When upgrading to Cluster API (CAPI) v1beta2, two structural changes are required in your KubeadmControlPlane or KubeadmConfigTemplate resources:

    1. kubeletExtraArgs: This field has changed from a flat map to a list of name/value pairs. This applies to initConfiguration, joinConfiguration, and other locations where it appears.
    2. infrastructureRef: This field has moved one level deeper, under machineTemplate.spec. Additionally, the apiVersion field is replaced by apiGroup in all resource references.

    Example Changes

    kubeletExtraArgs:

    # v1beta1
    kubeletExtraArgs:
      provider-id: "proxmox://..."
    
    # v1beta2
    kubeletExtraArgs:
    - name: provider-id
      value: "proxmox://..."

    infrastructureRef:

    # v1beta1
    spec:
      machineTemplate:
        infrastructureRef:
          kind: ProxmoxMachineTemplate
          apiVersion: infrastructure.cluster.x-k8s.io/v1alpha1
          name: my-cluster-control-plane
    
    # v1beta2
    spec:
      machineTemplate:
        spec:
          infrastructureRef:
            kind: ProxmoxMachineTemplate
            apiGroup: infrastructure.cluster.x-k8s.io
            name: my-cluster-control-plane
  10. Provision a cluster with External Credentials

    main

    The external-creds flavor allows you to use different Proxmox Datacenters by referencing a Kubernetes Secret instead of using environment variables directly in the manifest. The secret must include a label platform.ionos.com/secret-type: "proxmox-credentials".

    apiVersion: infrastructure.cluster.x-k8s.io/v1alpha2
    kind: ProxmoxCluster
    metadata:
      name: "my-cluster"
    spec:
      controlPlaneEndpoint:
        host: ${CONTROL_PLANE_ENDPOINT_IP}
        port: 6443
      # ...  
      credentialsRef:
        name: "my-cluster-proxmox-credentials"
    ---
    apiVersion: v1
    kind: Secret
    metadata:
      name: my-cluster-proxmox-credentials
      labels:
        platform.ionos.com/secret-type: "proxmox-credentials"
    stringData:
      secret: ${PROXMOX_SECRET}
      token: ${PROXMOX_TOKEN}
      url: ${PROXMOX_URL}
  11. Dependencies for CAPMOX

    main

    To deploy a Kubernetes cluster using the Cluster API Provider for Proxmox VE (CAPMOX), you must satisfy the following requirements:

    • Proxmox VE Template: Required for cluster creation. You can build these using:
    • clusterctl: The Cluster API CLI, available via CAPI releases.
    • Management Cluster: A running Kubernetes cluster to host the CAPMOX controller.
    • Proxmox VE Bridge: A configured bridge (e.g., vmbr0) with an available IP range for the VMs.
    • IPAM Provider: The cluster-api provider IPAM in-cluster is required to manage IPv4 and/or IPv6 addresses for machines without DHCP and to support dual-stack setups.