Skip to content

Commit 8ea0a55

Browse files
authored
Merge pull request #100 from mlinares1998/feature/csi-configuration
feat: add support for CSI volumes encryption and extraParams.
2 parents 83255df + 8f7895d commit 8ea0a55

File tree

4 files changed

+164
-1
lines changed

4 files changed

+164
-1
lines changed

README.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,85 @@ cluster_autoscaler_helm_values = {
349349
```
350350
</details>
351351

352+
<!-- CSI Driver Storage Class -->
353+
<details>
354+
<summary><b>CSI Driver Storage Class</b></summary>
355+
356+
The Hetzner Cloud Container Storage Interface (CSI) driver supports additional configuration options through the StorageClass resource:
357+
358+
- **Volume encryption**: Enables automatic LUKS2 encryption using a passphrase stored within the Kubernetes cluster.
359+
- **Volume filesystem**: Specify the desired filesystem (e.g., `ext4` or `xfs`) via the `csi.storage.k8s.io/fstype` parameter.
360+
- **Additional format options**: Provide custom formatting options that will be passed directly to `mkfs.<FSTYPE>` during volume provisioning using the `fsFormatOption` parameter.
361+
362+
For full documentation, refer to the [HCloud CSI Driver documentation](https://github.com/hetznercloud/csi-driver/tree/main/docs/kubernetes).
363+
364+
**Example `kubernetes.tf` snippet:**
365+
366+
```hcl
367+
# Enable the HCloud CSI driver
368+
hcloud_csi_enabled = true
369+
370+
# Enable volume encryption; a 32-byte random passphrase is generated by default
371+
hcloud_csi_storage_class_encryption_enabled = true
372+
373+
# Optionally, specify your own encryption key
374+
hcloud_csi_storage_class_encryption_key = "passphrase"
375+
376+
# Define PVs reclaim policy
377+
hcloud_csi_storage_class_reclaim_policy = "Retain"
378+
379+
# Define additional StorageClass parameters
380+
hcloud_csi_storage_class_extra_parameters = {
381+
"csi.storage.k8s.io/fstype" = "xfs"
382+
"fsFormatOption" = "-i nrext64=1"
383+
}
384+
385+
# Add default labels to all newly created volumes
386+
hcloud_csi_volume_extra_labels = {
387+
"environment" = "production"
388+
"team" = "platform"
389+
"backup" = "enabled"
390+
}
391+
392+
```
393+
394+
**Defining additional StorageClasses**
395+
396+
You can define custom StorageClasses in addition to the default one (`hcloud-volumes`) using the `hcloud_csi_additional_storage_classes` variable:
397+
398+
```hcl
399+
hcloud_csi_additional_storage_classes = [
400+
{
401+
name = "hcloud-volumes-ext4" # Name of the StorageClass
402+
defaultStorageClass = false # Whether this StorageClass should be marked as the default (default: false)
403+
reclaimPolicy = "Delete" # Reclaim policy for persistent volumes using this class (default: "Delete")
404+
405+
# Extra parameters passed to the CSI driver, such as volume format
406+
extraParameters = {
407+
"csi.storage.k8s.io/fstype" = "ext4"
408+
}
409+
},
410+
{
411+
name = "hcloud-volumes-xfs"
412+
extraParameters = {
413+
"csi.storage.k8s.io/fstype" = "xfs"
414+
}
415+
}
416+
]
417+
```
418+
419+
**:warning: Warning:** Due to the immutable nature of StorageClasses in Kubernetes, the default StorageClass settings cannot be modified after the initial cluster provisioning. Attempting to do so will result in the following error:
420+
421+
```bash
422+
module.kubernetes.terraform_data.synchronize_manifests (local-exec): StorageClass.storage.k8s.io "hcloud-volumes" is invalid: parameters: Forbidden: updates to parameters are forbidden.
423+
```
424+
425+
If you still need to modify the StorageClass, you must delete the existing one manually **before** running `terraform apply` again:
426+
427+
```bash
428+
kubectl delete storageclass hcloud-volumes
429+
storageclass.storage.k8s.io "hcloud-volumes" deleted
430+
```
352431

353432
<!-- Cilium Advanced Configuration -->
354433
<details>

hcloud.tf

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,32 @@ locals {
1616
}
1717
})
1818
}
19+
hcloud_csi_storage_class_encryption_key_manifest = var.hcloud_csi_enabled ? var.hcloud_csi_storage_class_encryption_enabled ? {
20+
apiVersion = "v1"
21+
kind = "Secret"
22+
type = "Opaque"
23+
metadata = {
24+
name = "hcloud-csi-secret"
25+
namespace = "kube-system"
26+
}
27+
data = {
28+
encryption-passphrase = var.hcloud_csi_storage_class_encryption_key != null ? base64encode(var.hcloud_csi_storage_class_encryption_key) : base64encode(random_bytes.hcloud_csi_encryption_key[0].hex)
29+
}
30+
} : null : null
31+
hcloud_csi_default_storage_class = [
32+
{
33+
name = "hcloud-volumes"
34+
defaultStorageClass = true
35+
reclaimPolicy = var.hcloud_csi_storage_class_reclaim_policy
36+
extraParameters = merge(
37+
var.hcloud_csi_storage_class_encryption_enabled ? {
38+
"csi.storage.k8s.io/node-publish-secret-name" = "hcloud-csi-secret"
39+
"csi.storage.k8s.io/node-publish-secret-namespace" = "kube-system"
40+
} : {},
41+
var.hcloud_csi_storage_class_extra_parameters
42+
)
43+
}
44+
]
1945
}
2046

2147
# Hcloud CCM
@@ -54,6 +80,11 @@ locals {
5480
}
5581

5682
# Hcloud CSI
83+
resource "random_bytes" "hcloud_csi_encryption_key" {
84+
count = var.hcloud_csi_enabled ? var.hcloud_csi_storage_class_encryption_enabled ? var.hcloud_csi_storage_class_encryption_key == null ? 1 : 0 : 0 : 0
85+
length = 32
86+
}
87+
5788
data "helm_template" "hcloud_csi" {
5889
count = var.hcloud_csi_enabled ? 1 : 0
5990

@@ -91,7 +122,9 @@ data "helm_template" "hcloud_csi" {
91122
operator = "Exists"
92123
}
93124
]
125+
volumeExtraLabels = var.hcloud_csi_volume_extra_labels
94126
}
127+
storageClasses = concat(local.hcloud_csi_default_storage_class, var.hcloud_csi_additional_storage_classes)
95128
}),
96129
yamlencode(var.hcloud_csi_helm_values)
97130
]
@@ -100,6 +133,10 @@ data "helm_template" "hcloud_csi" {
100133
locals {
101134
hcloud_csi_manifest = var.hcloud_csi_enabled ? {
102135
name = "hcloud-csi"
103-
contents = data.helm_template.hcloud_csi[0].manifest
136+
contents = <<-EOF
137+
${data.helm_template.hcloud_csi[0].manifest}
138+
---
139+
${var.hcloud_csi_storage_class_encryption_enabled ? yamlencode(local.hcloud_csi_storage_class_encryption_key_manifest) : yamlencode({})}
140+
EOF
104141
} : null
105142
}

terraform.tf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ terraform {
2626
source = "hashicorp/tls"
2727
version = "~> 4.1.0"
2828
}
29+
30+
random = {
31+
source = "hashicorp/random"
32+
version = "~>3.7.2"
33+
}
2934
}
3035
}
3136

variables.tf

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -968,6 +968,48 @@ variable "hcloud_csi_enabled" {
968968
description = "Enables the Hetzner Container Storage Interface (CSI)."
969969
}
970970

971+
variable "hcloud_csi_storage_class_encryption_enabled" {
972+
type = bool
973+
default = false
974+
description = "Enable Hcloud CSI default storage class LUKS encryption."
975+
}
976+
977+
variable "hcloud_csi_storage_class_encryption_key" {
978+
type = string
979+
default = null
980+
description = "User defined Hcloud CSI default storage class LUKS encryption key."
981+
sensitive = true
982+
}
983+
984+
variable "hcloud_csi_storage_class_reclaim_policy" {
985+
type = string
986+
default = "Delete"
987+
description = "Hcloud CSI default storage class reclaim policy."
988+
sensitive = true
989+
}
990+
991+
variable "hcloud_csi_storage_class_extra_parameters" {
992+
type = map(string)
993+
default = {}
994+
description = "Hcloud CSI default storage class extra parameters."
995+
}
996+
997+
variable "hcloud_csi_additional_storage_classes" {
998+
description = "Additional user defined Hcloud CSI storage classes"
999+
type = list(object({
1000+
name = string
1001+
defaultStorageClass = optional(bool, false)
1002+
reclaimPolicy = optional(string, "Delete")
1003+
extraParameters = optional(map(string), {})
1004+
}))
1005+
default = []
1006+
}
1007+
1008+
variable "hcloud_csi_volume_extra_labels" {
1009+
type = map(string)
1010+
default = {}
1011+
description = "Specifies default labels to apply to all newly created volumes. The value must be a map in the format key: value."
1012+
}
9711013

9721014
# Longhorn
9731015
variable "longhorn_helm_repository" {

0 commit comments

Comments
 (0)