Skip to content
Merged
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
59 changes: 59 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,68 @@ Now you can use one of following storageClasses:
* `csi-driver-lvm-linear`
* `csi-driver-lvm-mirror`
* `csi-driver-lvm-striped`
* `csi-driver-lvm-linear-encrypted`
* `csi-driver-lvm-mirror-encrypted`
* `csi-driver-lvm-striped-encrypted`

To get the previous old and now deprecated `csi-lvm-sc-linear`, ... storageclasses, set helm-chart value `compat03x=true`.

## Encryption ##

csi-driver-lvm supports LUKS2 encryption for volumes at rest. When encryption is enabled, the LVM logical volume is formatted with LUKS2 and a dm-crypt mapper device is used transparently for all I/O.

### Setup ###

1. Create a Kubernetes Secret containing the LUKS passphrase:

```bash
kubectl create secret generic csi-lvm-encryption-secret \
--from-literal=passphrase='my-secret-passphrase'
```

2. Enable the encrypted StorageClasses in your Helm values (they are disabled by default):

```yaml
storageClasses:
linearEncrypted:
enabled: true
mirrorEncrypted:
enabled: true
stripedEncrypted:
enabled: true
```

3. Create PVCs using one of the encrypted StorageClasses. The encryption is handled transparently by the driver.

### How it works ###

- **NodeStageVolume**: LUKS-formats the LV (first use only), then opens it via `cryptsetup luksOpen`, creating a `/dev/mapper/csi-lvm-<volumeID>` device
- **NodePublishVolume**: Mounts the mapper device (instead of the raw LV) to the target path
- **NodeUnpublishVolume**: Unmounts as usual
- **NodeUnstageVolume**: Closes the LUKS device via `cryptsetup luksClose`
- **Volume expansion**: The LV is extended first, then the LUKS layer is resized, then the filesystem

Both filesystem and raw block access types are supported with encryption.

### Encrypted Ephemeral Volumes ###

Encryption is also supported for CSI ephemeral (inline) volumes. Since ephemeral volumes bypass `NodeStageVolume`, the LUKS formatting and opening is handled directly during `NodePublishVolume`, and the LUKS device is closed during `NodeUnpublishVolume`.

To use an encrypted ephemeral volume, specify `encryption: "true"` in `volumeAttributes` and reference the encryption secret via `nodePublishSecretRef`:

```yaml
volumes:
- name: encrypted-ephemeral
csi:
driver: lvm.csi.metal-stack.io
volumeAttributes:
size: "100Mi"
type: "linear"
encryption: "true"
nodePublishSecretRef:
name: csi-lvm-encryption-secret
```

## Migration ##

If you want to migrate your existing PVC to / from csi-driver-lvm, you can use [korb](https://github.com/BeryJu/korb).
Expand Down
5 changes: 5 additions & 0 deletions charts/csi-driver-lvm/templates/daemonset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,8 @@ spec:
- mountPath: /run/lock/lvm
name: lvmlock
mountPropagation: Bidirectional
- mountPath: /run/cryptsetup
name: cryptsetup-run
- name: liveness-probe
args:
- --csi-address=/csi/csi.sock
Expand Down Expand Up @@ -367,4 +369,7 @@ spec:
path: {{ .Values.lvm.hostWritePath }}/lock
type: DirectoryOrCreate
name: lvmlock
- emptyDir:
medium: Memory
name: cryptsetup-run
---
72 changes: 72 additions & 0 deletions charts/csi-driver-lvm/templates/storageclasses.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,75 @@ allowVolumeExpansion: true
parameters:
type: "striped"
{{ end }}
---
{{- $storageClass := .Values.storageClasses.linearEncrypted -}}
{{ if $storageClass.enabled }}
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: {{ .Values.lvm.storageClassStub }}-linear-encrypted
{{- if not (empty $storageClass.additionalAnnotations) }}
annotations:
{{- $storageClass.additionalAnnotations | toYaml | nindent 4 -}}
{{ end }}
labels:
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
provisioner: {{ .Values.lvm.driverName }}
reclaimPolicy: {{ $storageClass.reclaimPolicy }}
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
parameters:
type: "linear"
encryption: "true"
csi.storage.k8s.io/node-stage-secret-name: {{ $storageClass.encryptionSecret.name }}
csi.storage.k8s.io/node-stage-secret-namespace: {{ $storageClass.encryptionSecret.namespace }}
{{ end }}
---
{{- $storageClass := .Values.storageClasses.mirrorEncrypted -}}
{{ if $storageClass.enabled }}
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: {{ .Values.lvm.storageClassStub }}-mirror-encrypted
{{- if not (empty $storageClass.additionalAnnotations) }}
annotations:
{{- $storageClass.additionalAnnotations | toYaml | nindent 4 -}}
{{ end }}
labels:
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
provisioner: {{ .Values.lvm.driverName }}
reclaimPolicy: {{ $storageClass.reclaimPolicy }}
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
parameters:
type: "mirror"
encryption: "true"
csi.storage.k8s.io/node-stage-secret-name: {{ $storageClass.encryptionSecret.name }}
csi.storage.k8s.io/node-stage-secret-namespace: {{ $storageClass.encryptionSecret.namespace }}
{{ end }}
---
{{- $storageClass := .Values.storageClasses.stripedEncrypted -}}
{{ if $storageClass.enabled }}
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: {{ .Values.lvm.storageClassStub }}-striped-encrypted
{{- if not (empty $storageClass.additionalAnnotations) }}
annotations:
{{- $storageClass.additionalAnnotations | toYaml | nindent 4 -}}
{{ end }}
labels:
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
provisioner: {{ .Values.lvm.driverName }}
reclaimPolicy: {{ $storageClass.reclaimPolicy }}
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
parameters:
type: "striped"
encryption: "true"
csi.storage.k8s.io/node-stage-secret-name: {{ $storageClass.encryptionSecret.name }}
csi.storage.k8s.io/node-stage-secret-namespace: {{ $storageClass.encryptionSecret.namespace }}
{{ end }}
21 changes: 21 additions & 0 deletions charts/csi-driver-lvm/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,27 @@ storageClasses:
enabled: true
additionalAnnotations: []
reclaimPolicy: Delete
linearEncrypted:
enabled: false
additionalAnnotations: []
reclaimPolicy: Delete
encryptionSecret:
name: csi-lvm-encryption-secret
namespace: default
stripedEncrypted:
enabled: false
additionalAnnotations: []
reclaimPolicy: Delete
encryptionSecret:
name: csi-lvm-encryption-secret
namespace: default
mirrorEncrypted:
enabled: false
additionalAnnotations: []
reclaimPolicy: Delete
encryptionSecret:
name: csi-lvm-encryption-secret
namespace: default
Comment thread
chbmuc marked this conversation as resolved.

nodeSelector:
# The plugin daemonset will run on all nodes if it has a toleration,
Expand Down
2 changes: 1 addition & 1 deletion cmd/lvmplugin/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ FROM alpine:3.23
ARG TARGETPLATFORM
LABEL maintainer="metal-stack authors <info@metal-stack.io>"

RUN apk add lvm2 lvm2-extra e2fsprogs e2fsprogs-extra smartmontools nvme-cli util-linux device-mapper xfsprogs xfsprogs-extra
RUN apk add lvm2 lvm2-extra e2fsprogs e2fsprogs-extra smartmontools nvme-cli util-linux device-mapper xfsprogs xfsprogs-extra cryptsetup
COPY --chmod=755 bin/${TARGETPLATFORM}/lvmplugin /lvmplugin
USER root
ENTRYPOINT ["/lvmplugin"]
8 changes: 8 additions & 0 deletions examples/csi-encryption-secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: v1
kind: Secret
metadata:
name: csi-lvm-encryption-secret
namespace: default
type: Opaque
stringData:
passphrase: "my-secret-passphrase"
13 changes: 13 additions & 0 deletions examples/csi-storageclass-linear-encrypted.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-lvm-sc-linear-encrypted
provisioner: lvm.csi.metal-stack.io
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
parameters:
type: "linear"
encryption: "true"
csi.storage.k8s.io/node-stage-secret-name: csi-lvm-encryption-secret
csi.storage.k8s.io/node-stage-secret-namespace: default
13 changes: 13 additions & 0 deletions examples/csi-storageclass-mirror-encrypted.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-lvm-sc-mirror-encrypted
provisioner: lvm.csi.metal-stack.io
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
parameters:
type: "mirror"
encryption: "true"
csi.storage.k8s.io/node-stage-secret-name: csi-lvm-encryption-secret
csi.storage.k8s.io/node-stage-secret-namespace: default
13 changes: 13 additions & 0 deletions examples/csi-storageclass-striped-encrypted.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-lvm-sc-striped-encrypted
provisioner: lvm.csi.metal-stack.io
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
parameters:
type: "striped"
encryption: "true"
csi.storage.k8s.io/node-stage-secret-name: csi-lvm-encryption-secret
csi.storage.k8s.io/node-stage-secret-namespace: default
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ require (
k8s.io/api v0.34.0
k8s.io/apimachinery v0.34.0
k8s.io/client-go v0.34.0
k8s.io/mount-utils v0.35.3
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4
sigs.k8s.io/controller-runtime v0.21.0
)

Expand All @@ -36,6 +38,7 @@ require (
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.9.0 // indirect
github.com/moby/sys/mountinfo v0.7.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
Expand Down Expand Up @@ -64,7 +67,6 @@ require (
k8s.io/apiextensions-apiserver v0.33.0 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
Expand Down
12 changes: 8 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
github.com/metal-stack/v v1.0.3 h1:Sh2oBlnxrCUD+mVpzfC8HiqL045YWkxs0gpTvkjppqs=
github.com/metal-stack/v v1.0.3/go.mod h1:YTahEu7/ishwpYKnp/VaW/7nf8+PInogkfGwLcGPdXg=
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand All @@ -96,16 +98,16 @@ github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
Expand Down Expand Up @@ -204,6 +206,8 @@ k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA=
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts=
k8s.io/mount-utils v0.35.3 h1:/XcRtfxqIdUVOyTc68NnAGeE+Mdw3T1nlv3RWbdo/yE=
k8s.io/mount-utils v0.35.3/go.mod h1:ppC4d+mUpfbAJr/V2E8vvxeCEckNM+S5b0kQBQjd3Pw=
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck=
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8=
Expand Down
Loading
Loading