Versions
Probably important to show you the versions of the various components that I used to achieve this:
- vCenter 8.0.3, build 24091160
- VMware ESXi, 8.0.3, 24022510
- Native Key Provider enabled on vSphere
- Host Encryption Mode is enabled in the Security Profile of the ESXi hosts
- Storage Policy using both vSAN and Encryption provided by Native KP
- Ubuntu OS version 24.04
- Upstream K8s version 1.30.3
- vSphere Container Storage Plugin / CSI driver version v3.0.0
- Works with and without vTPM devices on K8s node/VM, so vTPM is optional
Encryption Storage Policy
I built the storage policy using a combination of vSAN rules and Encryption rules. Here is the policy:
Encrypted Kubernetes Nodes
Next, I created a simple Kubernetes cluster, stood up the hard way with kubeadm. I used the storage policy with encryption enabled when deploying the VM. This would become the K8s node. I also ensured that the disk.EnableUUID was set to true on all nodes, and swap was disabled. I installed the vSphere Container Storage Plugin using the official docs. Once the cluster was deployed, I checked the node/VM encryption state in the vSphere Client. Everything appeared to be as expected, and the node/VM was encrypted using the Native KP:
Create and use Encrypted Persistent Volume
Now it was time to test whether or not I could create some encrypted Persistent Volumes on this K8s cluster. What follows are 3 YAML manifests, one for Storage Class (which uses encryption), one for Persistent Volume Claim (PVC) and a final one for a Pod which will mount the volume.
Storage Class
kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: vsan-encrypt-sc provisioner: csi.vsphere.vmware.com parameters: storagepolicyname: "vSAN+VMCrypt"
PVC
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: encrypt-pvc spec: storageClassName: vsan-encrypt-sc accessModes: - ReadWriteOnce resources: requests: storage: 3Gi
Pod
apiVersion: v1 kind: Pod metadata: name: encrypt-pod-a spec: containers: - name: encrypt-pod-a image: "k8s.gcr.io/busybox" volumeMounts: - name: encrypt-vol mountPath: "/mnt/volume1" command: [ "sleep", "1000000" ] volumes: - name: encrypt-vol persistentVolumeClaim: claimName: encrypt-pvc
Once deployed, the following objects are created, including the Persistent Volume (which of course should now be encrypted):
$ kubectl get pod,pvc,pv,sc NAME READY STATUS RESTARTS AGE pod/encrypt-pod-a 1/1 Running 0 16h NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE persistentvolumeclaim/encrypt-pvc Bound pvc-c391df7d-1e6c-4488-b44a-a96917540d6f 3Gi RWO vsan-encrypt-sc <unset> 18h NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE persistentvolume/pvc-c391df7d-1e6c-4488-b44a-a96917540d6f 3Gi RWO Delete Bound default/encrypt-pvc vsan-encrypt-sc <unset> 17h NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE storageclass.storage.k8s.io/vsan-encrypt-sc csi.vsphere.vmware.com Delete Immediate false 20h
And if we check the VM/node settings back on the vSphere Client and examine the Hard Disk which represents the Persistent Volume, we do indeed see that it is encrypted:
Summary
This is a great new feature in vSphere 8.0U3. Customers can now use the embedded vSphere Native Key Provider to encrypt Kubernetes nodes and Persistent Volumes. I am certain that this is a feature that many of our customers will be keen to leverage for their Kubernetes on vSphere deployments.