Skip to content

feat: add support for CSI volumes encryption and extraParams. #100

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,80 @@ cluster_autoscaler_helm_values = {
```
</details>

<!-- CSI Driver Storage Class -->
<details>
<summary><b>CSI Driver Storage Class</b></summary>

The Hetzner Cloud Container Storage Interface (CSI) driver supports additional configuration options through the StorageClass resource:

- **Volume encryption**: Enables automatic LUKS2 encryption using a passphrase stored within the Kubernetes cluster.
- **Volume filesystem**: Specify the desired filesystem (e.g., `ext4` or `xfs`) via the `csi.storage.k8s.io/fstype` parameter.
- **Additional format options**: Provide custom formatting options that will be passed directly to `mkfs.<FSTYPE>` during volume provisioning using the `fsFormatOption` parameter.

For full documentation, refer to the [HCloud CSI Driver documentation](https://github.com/hetznercloud/csi-driver/tree/main/docs/kubernetes).

**Example `kubernetes.tf` snippet:**

```hcl
# Enable the HCloud CSI driver
hcloud_csi_enabled = true

# Enable volume encryption; a 32-byte random passphrase is generated by default
hcloud_csi_storage_class_encryption_enabled = true

# Optionally, specify your own encryption key
hcloud_csi_storage_class_encryption_key = "passphrase"

# Define PVs reclaim policy
hcloud_csi_storage_class_reclaim_policy = "Retain"

# Define additional StorageClass parameters
hcloud_csi_storage_class_extra_parameters = {
"csi.storage.k8s.io/fstype" = "xfs"
"fsFormatOption" = "-i nrext64=1"
}
```

**Defining additional StorageClasses**

You can define custom StorageClasses in addition to the default one (`hcloud-volumes`) using the `hcloud_csi_additional_storage_classes` variable:

```hcl
hcloud_csi_additional_storage_classes = [
{
name = "hcloud-volumes-ext4" # Name of the StorageClass
defaultStorageClass = false # Whether this StorageClass should be marked as the default (default: false)
reclaimPolicy = "Delete" # Reclaim policy for persistent volumes using this class (default: "Delete")

# Extra parameters passed to the CSI driver, such as volume format
extraParameters = {
"csi.storage.k8s.io/fstype" = "ext4"
}
},
{
name = "hcloud-volumes-xfs"
extraParameters = {
"csi.storage.k8s.io/fstype" = "xfs"
}
}
]
```

**: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:

```bash
module.kubernetes.terraform_data.synchronize_manifests (local-exec): StorageClass.storage.k8s.io "hcloud-volumes" is invalid: parameters: Forbidden: updates to parameters are forbidden.
```

If you still need to modify the StorageClass, you must delete the existing one manually **before** running `terraform apply` again:

```bash
kubectl delete storageclass hcloud-volumes
storageclass.storage.k8s.io "hcloud-volumes" deleted
```

</details>

<!-- Egress Gateway -->
<details>
<summary><b>Egress Gateway</b></summary>
Expand Down
38 changes: 37 additions & 1 deletion hcloud.tf
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,32 @@ locals {
}
})
}
hcloud_csi_storage_class_encryption_key_manifest = var.hcloud_csi_enabled ? var.hcloud_csi_storage_class_encryption_enabled ? {
apiVersion = "v1"
kind = "Secret"
type = "Opaque"
metadata = {
name = "hcloud-csi-secret"
namespace = "kube-system"
}
data = {
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)
}
} : null : null
hcloud_csi_default_storage_class = [
{
name = "hcloud-volumes"
defaultStorageClass = true
reclaimPolicy = var.hcloud_csi_storage_class_reclaim_policy
extraParameters = merge(
var.hcloud_csi_storage_class_encryption_enabled ? {
"csi.storage.k8s.io/node-publish-secret-name" = "hcloud-csi-secret"
"csi.storage.k8s.io/node-publish-secret-namespace" = "kube-system"
} : {},
var.hcloud_csi_storage_class_extra_parameters
)
}
]
}

# Hcloud CCM
Expand Down Expand Up @@ -54,6 +80,11 @@ locals {
}

# Hcloud CSI
resource "random_bytes" "hcloud_csi_encryption_key" {
count = var.hcloud_csi_enabled ? var.hcloud_csi_storage_class_encryption_enabled ? var.hcloud_csi_storage_class_encryption_key == null ? 1 : 0 : 0 : 0
length = 32
}

data "helm_template" "hcloud_csi" {
count = var.hcloud_csi_enabled ? 1 : 0

Expand Down Expand Up @@ -92,6 +123,7 @@ data "helm_template" "hcloud_csi" {
}
]
}
storageClasses = concat(local.hcloud_csi_default_storage_class, var.hcloud_csi_additional_storage_classes)
}),
yamlencode(var.hcloud_csi_helm_values)
]
Expand All @@ -100,6 +132,10 @@ data "helm_template" "hcloud_csi" {
locals {
hcloud_csi_manifest = var.hcloud_csi_enabled ? {
name = "hcloud-csi"
contents = data.helm_template.hcloud_csi[0].manifest
contents = <<-EOF
${data.helm_template.hcloud_csi[0].manifest}
---
${var.hcloud_csi_storage_class_encryption_enabled ? yamlencode(local.hcloud_csi_storage_class_encryption_key_manifest) : yamlencode({})}
EOF
} : null
}
5 changes: 5 additions & 0 deletions terraform.tf
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ terraform {
source = "hashicorp/tls"
version = "~>4.0.0"
}

random = {
source = "hashicorp/random"
version = "~>3.7.2"
}
}
}

Expand Down
36 changes: 36 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,42 @@ variable "hcloud_csi_enabled" {
description = "Enables the Hetzner Container Storage Interface (CSI)."
}

variable "hcloud_csi_storage_class_encryption_enabled" {
type = bool
default = false
description = "Enable Hcloud CSI default storage class LUKS encryption."
}

variable "hcloud_csi_storage_class_encryption_key" {
type = string
default = null
description = "User defined Hcloud CSI default storage class LUKS encryption key."
sensitive = true
}

variable "hcloud_csi_storage_class_reclaim_policy" {
type = string
default = "Delete"
description = "Hcloud CSI default storage class reclaim policy."
sensitive = true
}

variable "hcloud_csi_storage_class_extra_parameters" {
type = map(string)
default = {}
description = "Hcloud CSI default storage class extra parameters."
}

variable "hcloud_csi_additional_storage_classes" {
description = "Additional user defined Hcloud CSI storage classes"
type = list(object({
name = string
defaultStorageClass = optional(bool, false)
reclaimPolicy = optional(string, "Delete")
extraParameters = optional(map(string), {})
}))
default = []
}

# Longhorn
variable "longhorn_helm_repository" {
Expand Down