Skip to content

ctnr-io/cluster-api-provider-contabo

Repository files navigation

cluster-api-provider-contabo

A Kubernetes Cluster API provider for Contabo cloud infrastructure. This provider enables you to create and manage Kubernetes clusters on Contabo's VPS infrastructure using the Cluster API framework.

Description

This Cluster API provider allows you to provision and manage Kubernetes clusters on Contabo's cloud infrastructure. It integrates with the Cluster API ecosystem to provide a consistent way to deploy workload clusters across different cloud providers.

The provider includes:

  • ContaboCluster: Manages cluster-wide infrastructure (private networking, SSH keys, control plane endpoint)
  • ContaboMachine: Manages individual VPS instances with instance reuse pattern and automatic private network assignment
  • ContaboMachineTemplate: Template for creating machines with consistent configuration

Features

  • Instance Reuse Pattern: Efficiently reuses VPS instances between cluster lifecycles
  • Private Networking: Automatic creation and assignment of private networks for cluster communication
  • SSH Key Management: Centralized SSH key configuration at cluster level with automatic distribution
  • State Machine Architecture: Comprehensive condition tracking with proper error handling and recovery
  • OAuth2 Authentication: Secure API access using Contabo's OAuth2 authentication flow
  • Multi-Region Support: Deploy clusters across all Contabo regions (EU, US-central, US-east, US-west, SIN)
  • Cloud-Init Integration: Full support for cloud-init user data for instance customization

Getting Started

Prerequisites

  • go version v1.24.0+
  • docker version 17.03+
  • kubectl version v1.11.3+
  • Access to a Kubernetes v1.11.3+ cluster
  • Contabo API credentials:
    • Client ID and Client Secret (OAuth2 application credentials)
    • API User and API Password (Contabo account credentials) All obtainable from the Contabo customer portal

Quick Start

  1. Install clusterctl

    curl -L https://github.com/kubernetes-sigs/cluster-api/releases/latest/download/clusterctl-linux-amd64 -o clusterctl
    chmod +x clusterctl
    sudo mv clusterctl /usr/local/bin/clusterctl
  2. Set up environment variables

    export CONTABO_CLIENT_ID="your-oauth2-client-id"
    export CONTABO_CLIENT_SECRET="your-oauth2-client-secret"
    export CONTABO_API_USER="your-contabo-username"
    export CONTABO_API_PASSWORD="your-contabo-password"
    export CLUSTER_NAME="my-contabo-cluster"
    export KUBERNETES_VERSION="v1.28.0"
    export CONTROL_PLANE_MACHINE_COUNT=1
    export WORKER_MACHINE_COUNT=2
  3. Configure clusterctl provider

    mkdir -p ~/.cluster-api
    cat << EOF > ~/.cluster-api/clusterctl.yaml
    providers:
      - name: "contabo"
        url: "https://github.com/ctnr-io/cluster-api-provider-contabo/releases/latest/infrastructure-components.yaml"
        type: "InfrastructureProvider"
    EOF
  4. Initialize the management cluster

    clusterctl init --infrastructure contabo
  5. Generate cluster configuration

    clusterctl generate cluster $CLUSTER_NAME \
      --infrastructure contabo \
      --kubernetes-version $KUBERNETES_VERSION \
      --control-plane-machine-count $CONTROL_PLANE_MACHINE_COUNT \
      --worker-machine-count $WORKER_MACHINE_COUNT \
      > $CLUSTER_NAME.yaml
  6. Create the cluster

    kubectl apply -f $CLUSTER_NAME.yaml
  7. Get the kubeconfig for the new cluster

    clusterctl get kubeconfig $CLUSTER_NAME > $CLUSTER_NAME.kubeconfig

Development Setup

Container Images

The provider is available as a Docker image from GitHub Container Registry:

# Pull the latest version
docker pull ghcr.io/ctnr-io/cluster-api-provider-contabo:latest

# Pull a specific version
docker pull ghcr.io/ctnr-io/cluster-api-provider-contabo:1.0.0

# Pull a specific commit
docker pull ghcr.io/ctnr-io/cluster-api-provider-contabo:sha-abc123

Available image tags:

  • latest: Latest build from the main branch
  • x.y.z: Release versions (e.g., 1.0.0)
  • x.y: Minor version tags (e.g., 1.0)
  • sha-*: Specific commit builds

To Deploy on the cluster

Set up your Contabo OAuth2 credentials:

export CONTABO_CLIENT_ID="your-oauth2-client-id"
export CONTABO_CLIENT_SECRET="your-oauth2-client-secret"
export CONTABO_API_USER="your-contabo-username"
export CONTABO_API_PASSWORD="your-contabo-password"

Deploy using the official image:

make deploy IMG=ghcr.io/ctnr-io/cluster-api-provider-contabo:latest

For development, you can build and push your own version:

make docker-build docker-push IMG=ghcr.io/ctnr-io/cluster-api-provider-contabo:dev

Install the CRDs into the cluster:

make install

Deploy the Manager to the cluster with the image specified by IMG:

make deploy IMG=<some-registry>/cluster-api-provider-contabo:tag

NOTE: If you encounter RBAC errors, you may need to grant yourself cluster-admin privileges or be logged in as admin.

Create instances of your solution You can apply the samples (examples) from the config/sample:

kubectl apply -k config/samples/

Important: Before applying the samples, make sure to:

  1. Set the Contabo OAuth2 credentials environment variables in the manager deployment:
    • CONTABO_CLIENT_ID
    • CONTABO_CLIENT_SECRET
    • CONTABO_API_USER
    • CONTABO_API_PASSWORD
  2. Update the sample configurations with your actual Contabo region and SSH keys
  3. Ensure you have valid Contabo instance types and image IDs

NOTE: Ensure that the samples have valid values for your Contabo account.

To Uninstall

Delete the instances (CRs) from the cluster:

kubectl delete -k config/samples/

Delete the APIs(CRDs) from the cluster:

make uninstall

UnDeploy the controller from the cluster:

make undeploy

Configuration

API Types

ContaboCluster

Manages cluster-wide infrastructure including private networking and control plane endpoint.

Key fields:

  • spec.controlPlaneEndpoint: (optional) Kubernetes API server endpoint configuration (host, port)
  • spec.privateNetwork.region: Contabo region for the private network (e.g., "EU", "US-central", "US-east", "US-west", "SIN")

Sample configuration:

spec:
   controlPlaneEndpoint:
      host: "10.0.0.100"
      port: 6443
   privateNetwork:
      region: "EU"

ContaboMachine

Manages individual VPS instances.

Key fields:

  • spec.providerID: (optional) Unique provider identifier for the instance
  • spec.instance.productId: Contabo product ID (instance type, e.g., "V45")
  • spec.instance.provisioningType: (optional) Instance provisioning strategy ("ReuseOnly" or "ReuseOrCreate", defaults to "ReuseOnly")

Sample configuration:

spec:
   providerID: "contabo://123456789"
   instance:
      productId: "V45"
      provisioningType: "ReuseOrCreate"

ContaboMachineTemplate

Template for creating machines with consistent configuration. Wraps a spec field that matches the ContaboMachineSpec.

Key fields:

  • spec.template.spec: The machine spec to use for all created machines

Sample configuration:

spec:
   template:
      spec:
         providerID: "contabo://123456789"
         instance:
            productId: "V45"

Environment Variables

  • CONTABO_CLIENT_ID: OAuth2 Client ID from Contabo (required)
  • CONTABO_CLIENT_SECRET: OAuth2 Client Secret from Contabo (required)
  • CONTABO_API_USER: Contabo account username (required)
  • CONTABO_API_PASSWORD: Contabo account password (required)

Authentication Setup

The Contabo provider uses OAuth2 authentication with client credentials flow. To set up authentication:

  1. Log in to the Contabo Customer Portal
  2. Create OAuth2 Application:
    • Navigate to API settings
    • Create a new OAuth2 application
    • Note down the Client ID and Client Secret
  3. Use your account credentials:
    • Username: Your Contabo account username
    • Password: Your Contabo account password

The authentication flow automatically obtains access tokens from:

https://auth.contabo.com/auth/realms/contabo/protocol/openid-connect/token

Encryption at Rest

The provider templates include support for encrypting Kubernetes secrets at rest using the API server's encryption configuration. The encryption key is stored securely in a Kubernetes Secret in the management cluster, separate from the cluster manifest.

Encryption Provider:

The templates use secretbox encryption provider (based on NaCl/libsodium), which is the recommended option for local key-based encryption. It provides:

  • Modern authenticated encryption (AEAD)
  • Better security than aescbc (vulnerable to padding oracle attacks)
  • Better security than aesgcm (vulnerable to nonce reuse in Kubernetes)
  • Simple implementation with 32-byte keys

For production environments, consider using a KMS provider for envelope encryption with external key management.

Generating an encryption key:

# Generate a random 32-byte encryption key and encode it in base64
export ENCRYPTION_KEY=$(head -c 32 /dev/urandom | base64)

Using the encryption key in cluster templates:

When using clusterctl generate cluster, the template will create a Secret containing the encryption configuration. Pass the encryption key as an environment variable:

export ENCRYPTION_KEY=$(head -c 32 /dev/urandom | base64)

clusterctl generate cluster $CLUSTER_NAME \
  --infrastructure contabo \
  --kubernetes-version $KUBERNETES_VERSION \
  --control-plane-machine-count $CONTROL_PLANE_MACHINE_COUNT \
  --worker-machine-count $WORKER_MACHINE_COUNT \
  > $CLUSTER_NAME.yaml

kubectl apply -f $CLUSTER_NAME.yaml

The template creates a Secret named ${CLUSTER_NAME}-encryption-key that contains the full encryption configuration. The KubeadmControlPlane references this secret using contentFrom.secret, ensuring:

  • The encryption key is not stored in plain text in the manifest
  • The secret can be backed up and managed separately
  • Key rotation can be performed by updating the secret

Important notes:

  • All control plane nodes in a cluster automatically use the same encryption key from the shared Secret
  • Store a backup of the encryption key securely - losing it means you cannot decrypt your secrets
  • The encryption configuration is automatically applied to all control plane nodes via kubeadm
  • For production clusters, consider using a KMS provider instead of local encryption keys
  • To rotate keys, update the Secret and restart the API servers (see Kubernetes documentation for details)

See the Kubernetes documentation on Encrypting Confidential Data at Rest for more details.

See the Contabo documentation for current specifications and pricing.

Project Distribution

Creating a Release

Following the options to release and provide this solution to the users.

By providing a bundle with all YAML files

  1. Build the installer for the image built and published in the registry:
make build-installer IMG=<some-registry>/cluster-api-provider-contabo:tag

NOTE: The makefile target mentioned above generates an 'install.yaml' file in the dist directory. This file contains all the resources built with Kustomize, which are necessary to install this project without its dependencies.

  1. Using the installer

Users can just run 'kubectl apply -f ' to install the project, i.e.:

kubectl apply -f https://raw.githubusercontent.com/<org>/cluster-api-provider-contabo/<tag or branch>/dist/install.yaml

By providing a Helm Chart

  1. Build the chart using the optional helm plugin
kubebuilder edit --plugins=helm/v1-alpha
  1. See that a chart was generated under 'dist/chart', and users can obtain this solution from there.

NOTE: If you change the project, you need to update the Helm Chart using the same command above to sync the latest changes. Furthermore, if you create webhooks, you need to use the above command with the '--force' flag and manually ensure that any custom configuration previously added to 'dist/chart/values.yaml' or 'dist/chart/manager/manager.yaml' is manually re-applied afterwards.

Creating a Release

This provider follows the Cluster API provider pattern for releases. To create a new release:

Release Process

  1. Tag the release:

    git tag v0.1.0
    git push origin v0.1.0
  2. GitHub Actions will automatically:

    • Build and push the Docker image to GHCR
    • Generate provider manifests (infrastructure-components.yaml)
    • Create cluster templates
    • Create a GitHub Release with all artifacts
  3. Release artifacts include:

    • metadata.yaml: Provider metadata for clusterctl
    • infrastructure-components.yaml: Complete provider installation manifest
    • cluster-template.yaml: Basic single-node cluster template
    • cluster-template-ha.yaml: High-availability cluster template

Using a Release

Users can install the provider using clusterctl:

# Set required environment variables
export CONTABO_CLIENT_ID="your-oauth2-client-id"
export CONTABO_CLIENT_SECRET="your-oauth2-client-secret"
export CONTABO_API_USER="your-contabo-username"
export CONTABO_API_PASSWORD="your-contabo-password"

# Initialize the provider
clusterctl init --infrastructure contabo:v0.1.0

# Generate and create a cluster
clusterctl generate cluster my-cluster \
  --infrastructure contabo:v0.1.0 \
  --kubernetes-version v1.28.0 \
  --control-plane-machine-count 1 \
  --worker-machine-count 2 > my-cluster.yaml

kubectl apply -f my-cluster.yaml

Local Release Testing

To test the release process locally:

# Build release manifests
make release-manifests IMG=ghcr.io/ctnr-io/cluster-api-provider-contabo:v0.1.0

# Verify the generated files in the out/ directory
ls -la out/

Contributing

We welcome contributions to the Cluster API Contabo Provider! Here's how you can contribute:

Development Workflow

  1. Fork the repository and clone your fork
  2. Create a feature branch from main
  3. Make your changes and add tests
  4. Run tests and ensure they pass:
    make test
  5. Build and test locally:
    make build
    make docker-build
  6. Submit a pull request with a clear description of your changes

Code Guidelines

  • Follow Go best practices and conventions
  • Add unit tests for new functionality
  • Update documentation for any API changes
  • Ensure all CI checks pass

Testing

Run the full test suite:

make test

Run end-to-end tests (requires a management cluster):

make test-e2e

Troubleshooting

Common Issues

Authentication errors:

  • Verify your OAuth2 credentials are correct:
    • CONTABO_CLIENT_ID and CONTABO_CLIENT_SECRET from OAuth2 application
    • CONTABO_API_USER and CONTABO_API_PASSWORD from your Contabo account
  • Check that all credentials are properly set in the environment
  • Ensure your OAuth2 application has sufficient API permissions

Instance creation failures:

  • Verify the product ID is available in your selected region
  • Check that the image ID is valid and available (use Contabo API to list available images)
  • Ensure your Contabo account has sufficient quota
  • Check the instance display name format follows the required pattern

Private network issues:

  • Verify private networks are created at cluster level before machine creation
  • Check that private network CIDR doesn't conflict with existing networks
  • Ensure private network assignment occurs after instance is in "installing" state

SSH key issues:

  • Verify SSH key IDs exist in your Contabo account
  • Check that SSH keys are properly referenced in cluster or machine specs
  • Ensure SSH keys are accessible in the selected region

Instance state issues:

  • Check instance conditions and status for detailed error information
  • Monitor instance lifecycle transitions (creating → provisioning → installing → running)
  • Verify instance reuse pattern works correctly with display name state management

For more help, please open an issue in the GitHub repository.

NOTE: Run make help for more information on all potential make targets

More information can be found via the Kubebuilder Documentation

License

Copyright 2025.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

About

Cluster API infrastructure provider for Contabo

Resources

Stars

Watchers

Forks

Packages