Hetzner Cloud Volumes

The Hetzner Cloud CSI driver provisions Hetzner Cloud Volumes for Pods on the Hetzner Cloud nodes of your Fleet. Hetzner Cloud does not support identity federation, so the driver authenticates with an API token. It reuses the token that your Fleet already stores in the cluster, so you do not create or manage a second credential.

Prerequisites

When you create a Hetzner Cloud Fleet, CFKE stores its API token in the FLEET_NAME-secrets secret in the kube-system namespace, under the hetzner key. Replace FLEET_NAME in the examples with the name of your Fleet.

Step 1: Install the driver

Create a file named hcloud-csi.yaml:

yaml
controller:
  replicaCount: 2
  priorityClassName: system-node-critical
  hcloudToken:
    existingSecret:
      name: FLEET_NAME-secrets
      key: hetzner
  nodeSelector:
    cfke.io/provider: hetzner
  image:
    csiAttacher:
      name: quay.io/cloudfleet/csi-attacher
    csiResizer:
      name: quay.io/cloudfleet/csi-resizer
    csiProvisioner:
      name: quay.io/cloudfleet/csi-provisioner
    livenessProbe:
      name: quay.io/cloudfleet/livenessprobe
node:
  priorityClassName: system-node-critical
  hostNetwork: true
  nodeSelector:
    cfke.io/provider: hetzner
  image:
    csiNodeDriverRegistrar:
      name: quay.io/cloudfleet/csi-node-driver-registrar
    livenessProbe:
      name: quay.io/cloudfleet/livenessprobe
    hcloudCSIDriver:
      name: quay.io/cloudfleet/hcloud-csi-driver

The controller authenticates with the API token of your Fleet. The controller and the node plugin run on Hetzner Cloud nodes. The images come from Cloudfleet’s mirror on quay.io/cloudfleet.

Install the driver with Helm:

bash
helm repo add hcloud https://charts.hetzner.cloud
helm repo update hcloud
helm upgrade --install hcloud-csi hcloud/hcloud-csi -n kube-system --values hcloud-csi.yaml

Check that the controller and the node plugins are running:

bash
kubectl get pods -n kube-system -l app.kubernetes.io/name=hcloud-csi

The cluster runs two controller Pods and one node plugin Pod on each Hetzner Cloud node.

Step 2: Check the storage class

The chart creates the hcloud-volumes storage class with volumeBindingMode: WaitForFirstConsumer and volume expansion enabled:

bash
kubectl get storageclass hcloud-volumes

The chart also marks the class as the cluster default, so claims without a storageClassName get Hetzner Cloud Volumes. In a Fleet with several clouds, set storageClassName on every claim.

Step 3: Use a volume

Create a StatefulSet that requests a Hetzner Cloud Volume and runs on Hetzner Cloud nodes:

yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: hcloud-example
spec:
  serviceName: hcloud-example
  replicas: 1
  selector:
    matchLabels:
      app: hcloud-example
  template:
    metadata:
      labels:
        app: hcloud-example
    spec:
      nodeSelector:
        cfke.io/provider: hetzner
      containers:
        - name: app
          image: busybox:1.37
          command: ["sh", "-c", "date >> /data/boots; cat /data/boots; exec sleep infinity"]
          resources:
            requests:
              cpu: 10m
              memory: 16Mi
          volumeMounts:
            - name: data
              mountPath: /data
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        storageClassName: hcloud-volumes
        resources:
          requests:
            storage: 10Gi

Check that the claim is bound:

bash
kubectl get pvc data-hcloud-example-0

Each start of the Pod appends a line to /data/boots. Delete the Pod, or the node it runs on, and check the log of the new Pod. It lists the earlier starts, because the volume moved with the Pod to a node in the same location. You can also see the volume in the Hetzner Cloud Console.

Limitations

Hetzner Cloud API tokens grant access to the whole project. To isolate the token, run your Fleet in a dedicated Hetzner Cloud project, as described in Fleet configuration.

Next steps

On this page