diff --git a/chart/.snapshots/default.yaml b/chart/.snapshots/default.yaml index 6fbcb4c8b1eab826fd76949dc94617e5c3724666..7b2da5de48938631b7fc30373f877592956bc790 100644 --- a/chart/.snapshots/default.yaml +++ b/chart/.snapshots/default.yaml @@ -142,6 +142,10 @@ spec: operator: NotIn values: - "true" + - key: instance.hetzner.cloud/provided-by + operator: NotIn + values: + - robot tolerations: - effect: NoExecute operator: Exists diff --git a/chart/.snapshots/full.values.yaml b/chart/.snapshots/full.values.yaml index b766cfe2f1acdfd359faa8ae23f418d1ac13c450..51ac7aa2d28481fe67a99a3326f7ba67d16f68d1 100644 --- a/chart/.snapshots/full.values.yaml +++ b/chart/.snapshots/full.values.yaml @@ -370,3 +370,5 @@ storageClasses: - name: foobar defaultStorageClass: false reclaimPolicy: Keep + allowedTopologyCloudServer: false + diff --git a/chart/.snapshots/full.yaml b/chart/.snapshots/full.yaml index afcdf916d11821b4e65d5aac21d857b47a3a0e36..411864768a034f1e7124028dee2cef8a506f31a0 100644 --- a/chart/.snapshots/full.yaml +++ b/chart/.snapshots/full.yaml @@ -245,6 +245,10 @@ spec: operator: NotIn values: - "true" + - key: instance.hetzner.cloud/provided-by + operator: NotIn + values: + - robot nodeSelector: foo: bar tolerations: diff --git a/chart/templates/core/storageclass.yaml b/chart/templates/core/storageclass.yaml index 1bc246d210fde2e2ff7173bf620cb03133d60508..5771edcaad2f5fe97a4ab0256999b9e8ab907cba 100644 --- a/chart/templates/core/storageclass.yaml +++ b/chart/templates/core/storageclass.yaml @@ -10,6 +10,13 @@ provisioner: csi.hetzner.cloud volumeBindingMode: WaitForFirstConsumer allowVolumeExpansion: true reclaimPolicy: {{ $val.reclaimPolicy | quote }} +{{- if $val.allowedTopologyCloudServer }} +allowedTopologies: +- matchLabelExpressions: + - key: instance.hetzner.cloud/provided-by + values: + - "cloud" +{{- end }} --- {{- end }} {{- end }} \ No newline at end of file diff --git a/chart/values.yaml b/chart/values.yaml index 431f3169808fab3f30ddaed795e87ed9cd0ea43c..3508ecb8afd96ff3d52a3a7481559e035606624d 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -556,6 +556,10 @@ node: operator: NotIn values: - "true" + - key: "instance.hetzner.cloud/provided-by" + operator: NotIn + values: + - "robot" ## @param node.nodeSelector Node labels for node pods assignment ## ref: https://kubernetes.io/docs/user-guide/node-selection/ @@ -724,3 +728,5 @@ storageClasses: - name: hcloud-volumes defaultStorageClass: true reclaimPolicy: Delete + ## @param storageClass.allowedTopologyCloudServer Prevents pods from being scheduled on nodes, specifically Robot servers, where Hetzner volumes are unavailable + allowedTopologyCloudServer: false diff --git a/deploy/kubernetes/hcloud-csi.yml b/deploy/kubernetes/hcloud-csi.yml index f1078d979a3a3f2fea843d3d342f886e2e74de2e..a8ebfbd12184e4878eff68de1e6ecf82e22e8760 100644 --- a/deploy/kubernetes/hcloud-csi.yml +++ b/deploy/kubernetes/hcloud-csi.yml @@ -174,6 +174,10 @@ spec: operator: NotIn values: - "true" + - key: instance.hetzner.cloud/provided-by + operator: NotIn + values: + - robot tolerations: - effect: NoExecute operator: Exists diff --git a/docs/kubernetes/README.md b/docs/kubernetes/README.md index e80ad1dc1eb3a64ea1935f2add5315ce358b0efa..b73d0c99a960fc88d6481503cbf933808bd05721 100644 --- a/docs/kubernetes/README.md +++ b/docs/kubernetes/README.md @@ -106,7 +106,7 @@ metadata: stringData: encryption-passphrase: foobar ---- +--- apiVersion: storage.k8s.io/v1 kind: StorageClass @@ -209,8 +209,43 @@ $ kubectl apply -f https://raw.githubusercontent.com/hetznercloud/csi-driver/v2. ## Integration with Root Servers -Root servers can be part of the cluster, but the CSI plugin doesn't work there. Taint the root server as follows to skip that node for the DaemonSet. +Root servers can be part of the cluster, but the CSI plugin doesn't work there and the current behaviour of the scheduler can cause Pods to be stuck in `Pending`. +In the Helm Chart you can set `allowedTopologyCloudServer` to true to prevent pods from being scheduled on nodes, specifically Robot servers, where Hetzner volumes are unavailable. This value can not be changed after the initial creation of a storage class. + +```yaml +storageClasses: + - name: hcloud-volumes + defaultStorageClass: true + reclaimPolicy: Delete + allowedTopologyCloudServer: true # <--- +``` + +To ensure proper topology evaluation, labels are needed to indicate whether a node is a cloud VM or a dedicated server from Robot. If you are using the `hcloud-cloud-controller-manager` version 1.21.0 or later, these labels are added automatically. Otherwise, you will need to label the nodes manually. + +### Adding labels manually + +**Cloud Servers** +```bash +kubectl label nodes <node name> instance.hetzner.cloud/provided-by=cloud +``` + +**Root Servers** +```bash +kubectl label nodes <node name> instance.hetzner.cloud/provided-by=robot +``` + + +### DEPRECATED: Old Label + +We prefer that you use our [new label](#new-label). The label `instance.hetzner.cloud/is-robot-server` will be deprecated in future releases. + +**Cloud Servers** +```bash +kubectl label nodes <node name> instance.hetzner.cloud/is-root-server=false +``` + +**Root Servers** ```bash kubectl label nodes <node name> instance.hetzner.cloud/is-root-server=true ``` diff --git a/internal/driver/driver.go b/internal/driver/driver.go index 86e1dcb8c869478107046ca11eafdd6ff919c24b..f2a9db016928a2269ab65ade2b3a93fb96475f40 100644 --- a/internal/driver/driver.go +++ b/internal/driver/driver.go @@ -9,4 +9,5 @@ const ( DefaultVolumeSize = MinVolumeSize TopologySegmentLocation = PluginName + "/location" + ProvidedByLabel = "instance.hetzner.cloud/provided-by" ) diff --git a/internal/driver/node.go b/internal/driver/node.go index 5b084ea1022198be27ad798c4c5b9c65e63d6658..6716ff0220d1668f52ba028333806900f71dc7b7 100644 --- a/internal/driver/node.go +++ b/internal/driver/node.go @@ -178,6 +178,7 @@ func (s *NodeService) NodeGetInfo(_ context.Context, _ *proto.NodeGetInfoRequest AccessibleTopology: &proto.Topology{ Segments: map[string]string{ TopologySegmentLocation: s.serverLocation, + ProvidedByLabel: "cloud", }, }, }