Encrypting Kubernetes PVCs with Vault


Portworx Encrypted Volumes

Portworx has two different kinds of encrypted volumes:

  • Encrypted Volumes

Encrypted volumes are regular volumes which can be accessed from only one node.

  • Encrypted Shared Volumes

Encrypted shared volume allows access to the same encrypted volume from multiple nodes.

There are two ways in which Portworx volumes can be encrypted and are dependent on how the Vault secret key is provided to Portworx.

Encryption using Storage Class

In this method, Portworx will use the cluster wide secret key to encrypt PVCs.

Step 1: Set a cluster wide secret

A cluster wide secret key is a common key that can be used to encrypt all your volumes. This common key needs to be pre-created in your KMS provider. You can set the cluster secret key using the following command.

pxctl secrets set-cluster-key
Enter cluster wide secret key: *****
Successfully set cluster secret key!

In the above prompt you need to enter the secret key that you created in your KMS. This command needs to be run just once for the cluster.

If you are using Vault Namespaces use the following command to set the cluster-wide secret key in a specific vault namespace:

pxctl secrets set-cluster-key --secret_options=vault-namespace=<name of vault-namespace>

Step 2: Create a StorageClass

Create a storage class with the secure parameter set to true.

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: px-secure-sc
provisioner: kubernetes.io/portworx-volume
parameters:
  secure: "true"
  repl: "3"

To create a shared encrypted volume set the shared parameter to true as well.

Step 3: Create Persistent Volume Claim

Create a PVC that uses the above px-secure-sc storage class.

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: secure-pvc
spec:
  storageClassName: px-secure-sc
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi

Step 4: Verify the volume

Once the PVC has been created, verify the volume created in Portworx is encrypted.

PX_POD=$(kubectl get pods -l name=portworx -n kube-system -o jsonpath='{.items[0].metadata.name}')
kubectl exec $PX_POD -n kube-system -- /opt/pwx/bin/pxctl volume list
ID                 NAME                                      ...  ENCRYPTED  ...
10852605918962284  pvc-5a885584-44ca-11e8-a17b-080027ee1df7  ...  yes        ...

Encryption using PVC annotations

In this method, each PVC can be encrypted with its own secret key.

Step 1: Create a Storage Class

Create a storage class with the secure parameter set to true.

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: px-secure-sc
provisioner: kubernetes.io/portworx-volume
parameters:
  secure: "true"
  repl: "3"

To create a shared encrypted volume set the shared parameter to true as well.

Step 2: Create a PVC with annotations

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: secure-mysql-pvc
  annotations:
    px/secret-name: your-secret-key
spec:
  storageClassName: portworx-sc
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi
IMPORTANT: Make sure secret your-secret-key exists in Vault.

Encryption using PVC annotations with Vault Namespaces

If you have Vault Namespaces enabled and your secret resides inside a specific namespace, you must provide the name of that namespace and the secret key to Portworx.

Step 1: Create a Storage Class

Create a storage class with the secure parameter set to true.

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: px-secure-sc
provisioner: kubernetes.io/portworx-volume
parameters:
  secure: "true"
  repl: "3"

To create a shared encrypted volume set the shared parameter to true as well.

Step 2: Create a PVC with annotations

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: secure-mysql-pvc
  annotations:
    px/secret-name: <your-secret-key>
    px/vault-namespace: <your-vault-namesapce>
spec:
  storageClassName: portworx-sc
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi

The PVC requires an extra annotation px/vault-namespace to indicate the Vault namespace where the secret key resides. If your key resides in the global vault namespace set in Portworx using the parameter VAULT_NAMESPACE, you don’t need to specify this annotation. However if the key resides in any other namespace then this annotation is required.

IMPORTANT: Make sure the secret your-secret-key exists in the namespace your-vault-namespace in Vault.

Last edited: Monday, Mar 8, 2021