This page describes how to use Customer Managed Encryption Keys (CMEK) on Google Kubernetes Engine (GKE). If you need to control management of your keys, you can use Cloud Key Management Service and CMEK to protect attached Persistent Disks and custom boot disks in your GKE cluster.
Overview
By default, Google Cloud encrypts customer content at rest, and GKE manages encryption for you without any action on your part.
If you want to control and manage encryption key rotation yourself, you can use CMEK. These keys encrypt the data encryption keys that encrypt your data. For more information, see Key management.
You can also encrypt secrets in your cluster using keys that you manage. For details, see Application-layer secrets encryption.
In GKE, CMEK can protect data of two types of storage disks: node boot disks and attached disks.
- Node boot disks
- Node boot disks are part of your cluster's node pools. You can create a CMEK-encrypted node boot disk when you create clusters and node pools.
- Attached disks
- Attached disks are PersistentVolumes used by Pods for durable storage. CMEK-encrypted attached persistent disks are available in GKE as a dynamically provisioned PersistentVolume.
To learn more about storage disks, see Storage options. Control plane disks, used for GKE control planes, cannot be protected with CMEK.
Before you begin
To do the exercises in this document, you need two Google Cloud projects:
Key project: This is where you create an encryption key.
Cluster project: This is where you create a cluster that enables CMEK.
In your key project, ensure that you have enabled the Cloud KMS API.
In your key project, the user who creates the key ring and key needs the following IAM permissions:
cloudkms.keyRings.getIamPolicy
cloudkms.keyRings.setIamPolicy
These permissions are granted to the predefined
roles/cloudkms.admin
Identity and Access Management role. You can learn more about granting permissions to manage keys in the Cloud KMS documentation.In your cluster project, ensure that you have enabled the Cloud KMS API.
Ensure that you have installed the gcloud CLI.
Update
gcloud
to the latest version:gcloud components update
Create a Cloud KMS key
Before you can protect your node boot disk or attached disk with a CMEK, you need a Cloud KMS key ring and key.
Your key ring and key have the following requirements:
Your key should use symmetric encryption.
You need to grant the GKE service account permissions to use the key.
Your key ring must have a location that matches the location of your GKE cluster:
A zonal cluster should use a key ring from a superset location. For example, a cluster in the
us-central1-a
zone can only use a key in theus-central1
region.A regional cluster should use a key ring from the same location. For example, a cluster in the
asia-northeast1
region should be protected with a key ring from theasia-northeast1
region.The Cloud KMS
global
region is not supported for use with GKE.
For instructions on how to create a key ring and key, see Creating symmetric keys.
Grant permission to use the key
You must assign the Compute Engine service account used by nodes in your cluster the Cloud KMS CryptoKey Encrypter/Decrypter role. This is required for GKE Persistent Disks to access and use your encryption key.
The Compute Engine service account's name has the following format:
service-PROJECT_NUMBER@compute-system.iam.gserviceaccount.com
Replace PROJECT_NUMBER
with your cluster's
project number.
To grant access to the service account, you can use the gcloud
command or the Google Cloud console.
gcloud
Grant your Compute Engine service account the Cloud KMS CryptoKey Encrypter/Decrypter role:
gcloud kms keys add-iam-policy-binding KEY_NAME \
--location LOCATION \
--keyring RING_NAME \
--member serviceAccount:SERVICE_ACCOUNT \
--role roles/cloudkms.cryptoKeyEncrypterDecrypter \
--project KEY_PROJECT_ID
Replace the following:
KEY_NAME
: the name of your key.LOCATION
: the region where you created your key ring.RING_NAME
: the name of your key ring.SERVICE_ACCOUNT
: the name of your Compute Engine service account.KEY_PROJECT_ID
: your key project ID.
Console
Grant your Compute Engine service account the Cloud KMS CryptoKey Encrypter/Decrypter role:
- Open the Cloud Key Management Service Keys browser in the Google Cloud console.
Open the Cloud KMS Keys browser Click the name of the key ring that contains the key you want.
Select the checkbox for the key.
The Permissions tab in the right window pane becomes available.
In the Add members dialog, specify the email address of the Compute Engine service account you are granting access.
In the Select a role drop down, select Cloud KMS CryptoKey Encrypter/Decrypter.
Click Save.
Use CMEK-protected node boot disks
In this section, you create a new cluster or node pool with a CMEK protected boot disk.
You cannot enable customer-managed encryption for node boot disks on an existing cluster, as you cannot change the boot disk type of an existing cluster or node pool. However, you can create a new node pool for your cluster with customer- managed encryption enabled, and delete the previous node pool.
You also cannot disable customer-managed encryption for node boot disks on an existing cluster or an existing node pool. However, you can create a new node pool for your cluster with customer-managed encryption disabled, and delete the previous node pool.
Create a cluster with a CMEK-protected node boot disk
You can create a cluster with a CMEK-protected node boot disk using the gcloud CLI or the Google Cloud console.
For Standard clusters, only a standard Persistent Disk (pd-standard
)
or an SSD Persistent Disk (pd-ssd
) can be encrypted with a CMEK key.
gcloud
To create a cluster whose boot disk is encrypted with a CMEK key, specify a
value for the --boot-disk-kms-key
parameter in your cluster creation command.
Create a Standard cluster
To create a Standard cluster whose boot disk is encrypted with a CMEK key, use the following command:
gcloud container clusters create CLUSTER_NAME \
--cluster-version=latest \
--region COMPUTE_REGION \
--boot-disk-kms-key projects/KEY_PROJECT_ID/locations/LOCATION/keyRings/RING_NAME/cryptoKeys/KEY_NAME \
--project CLUSTER_PROJECT_ID \
--disk-type DISK_TYPE
Create an Autopilot cluster
To create an Autopilot cluster whose boot disk is encrypted with a CMEK key, use the following command:
gcloud container clusters create-auto CLUSTER_NAME \
--cluster-version=latest \
--region COMPUTE_REGION \
--boot-disk-kms-key projects/KEY_PROJECT_ID/locations/LOCATION/keyRings/RING_NAME/cryptoKeys/KEY_NAME \
--project CLUSTER_PROJECT_ID
Replace the following:
CLUSTER_NAME
: the name for your new cluster.COMPUTE_REGION
: the compute region for the cluster control plane.KEY_PROJECT_ID
: your key project ID.LOCATION
: the location of your key ring.RING_NAME
: the name of your key ring.KEY_NAME
: the name of your key.CLUSTER_PROJECT_ID
is your cluster project ID.DISK_TYPE
:pd-standard
(default) orpd-ssd
.
Console
Create a Standard cluster
To create a Standard cluster whose boot disk is encrypted with a CMEK key, perform the following steps:
Go to the Google Kubernetes Engine page in the Google Cloud console.
Click add_box Create.
In the Standard section, click Configure.
Configure your cluster as needed.
From the navigation menu, under Node Pools, click Nodes.
In the Boot disk type drop-down list, select Standard persistent disk or SSD Persistent Disk.
Select the Enable customer-managed encryption for Boot Disk checkbox and choose the Cloud KMS encryption key you created earlier.
Click Create.
Create an Autopilot cluster
To create an Autopilot cluster whose boot disk is encrypted with a CMEK key, perform the following steps:
Go to the Google Kubernetes Engine page in the Google Cloud console.
Click add_box Create.
In the Autopilot section, click Configure.
Configure your cluster as needed.
Expand the Advanced Options section and locate the Security options.
Select the Enable customer-managed encryption for Boot Disk checkbox and choose the Cloud KMS encryption key you created earlier.
Click Create.
Create a new node pool with CMEK-protected node boot disks
To create a new node pool with CMEK enabled on an existing standard cluster, you can use the gcloud CLI or the Google Cloud console.
gcloud
To create a node pool with customer-managed encryption for node boot disks,
specify a value for the --boot-disk-kms-key
parameter in your creation
command.
gcloud container node-pools create NODE_POOL_NAME \
--region COMPUTE_REGION \
--disk-type DISK_TYPE \
--boot-disk-kms-key projects/KEY_PROJECT_ID/locations/LOCATION/keyRings/RING_NAME/cryptoKeys/KEY_NAME \
--project CLUSTER_PROJECT_ID \
--cluster CLUSTER_NAME
Replace the following:
NODE_POOL_NAME
: the name you choose for your node pool.COMPUTE_REGION
: the compute region for the cluster control plane.DISK_TYPE
:pd-standard
(default) orpd-ssd
.KEY_PROJECT_ID
:your key project ID.LOCATION
: the location of your key ring.RING_NAME
: the name of your key ring.KEY_NAME
: the name of your key.CLUSTER_PROJECT_ID
: your cluster project ID.CLUSTER_NAME
: the name of the Standard cluster you created in the previous step.
Console
Go to the Google Kubernetes Engine page in the Google Cloud console.
In the cluster list, click the name of the cluster you want to modify.
Click add_box Add Node Pool.
From the navigation menu, click Nodes.
In the Machine Configuration section, ensure Boot disk type is either Standard persistent disk or SSD persistent disk.
Select the Enable customer-managed encryption for boot disk checkbox and select the Cloud KMS encryption key you created.
Click Create.
Use CMEK-protected Filestore instances or Persistent Disks
The following information covers how to encrypt newly created Filestore instances or Persistent Disks. You can enable CMEK on a new or existing cluster, using a new or existing Cloud KMS key.
These instructions need to be completed once per GKE cluster:
- Create a GKE cluster, if you don't already have one available.
- Deploy the Filestore CSI Driver or Compute Engine Persistent Disk CSI Driver to your cluster.
- Create a Cloud KMS key ring and key version, if you don't already have one available.
- Grant key access permissions to the Filestore service account.
- Create a StorageClass that enables disks provisioned by Kubernetes to automatically be encrypted with that Cloud KMS key. For details on how to do this, see the following section.
Create a StorageClass referencing the Cloud KMS key
Copy the content below into a YAML file named
cmek-sc.yaml
. This configuration enables dynamic provisioning of encrypted volumes.Filestore instances
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: csi-filestore-cmek provisioner: filestore.csi.storage.gke.io allowVolumeExpansion: true parameters: tier: enterprise instance-encryption-kms-key: projects/KEY_PROJECT_ID/locations/LOCATION/keyRings/RING_NAME/cryptoKeys/KEY_NAME
- The
instance-encryption-kms-key
field must be the fully qualified resource identifier for the key that will be used to encrypt new Filestore instances. - The values in
instance-encryption-kms-key
are case sensitive (for example:keyRings
andcryptoKeys
). Provisioning a new volume with incorrect values results in aninvalidResourceUsage
error. - You cannot add the
instance-encryption-kms-key
parameter to an existingStorageClass
object. However, you can delete theStorageClass
object and recreate it with the same name, but a different set of parameters.
Persistent Disks
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: csi-gce-pd-cmek provisioner: pd.csi.storage.gke.io volumeBindingMode: "WaitForFirstConsumer" allowVolumeExpansion: true parameters: type: pd-standard disk-encryption-kms-key: projects/KEY_PROJECT_ID/locations/LOCATION/keyRings/RING_NAME/cryptoKeys/KEY_NAME
- The
disk-encryption-kms-key
field must be the fully qualified resource identifier for the key that will be used to encrypt new disks. - The values in
disk-encryption-kms-key
are case sensitive (for example:keyRings
andcryptoKeys
). Provisioning a new volume with incorrect values results in aninvalidResourceUsage
error. - You cannot add the
disk-encryption-kms-key
parameter to an existingStorageClass
object. However, you can delete theStorageClass
object and recreate it with the same name, but a different set of parameters. Make sure the provisioner of the existing class ispd.csi.storage.gke.io
.
You can set the StorageClass as the default.
- The
Deploy the
StorageClass
on your GKE cluster usingkubectl
:kubectl apply -f cmek-sc.yaml
Verify that your
StorageClass
used the Compute Engine Filestore or Persistent Disk CSI driver and includes the ID of your key:Filestore instances
kubectl describe storageclass csi-filestore-cmek
In the output of the command, verify the following:
- The provisioner is set as filestore.csi.storage.gke.io.
- The ID of your key follows instance-encryption-kms-key.
Name: csi-filestore-cmek IsDefaultClass: No Annotations: None Provisioner: filestore.csi.storage.gke.io Parameters: instance-encryption-kms-key=projects/KEY_PROJECT_ID/locations/LOCATION/keyRings/RING_NAME/cryptoKeys/KEY_NAME,type=pd-standard AllowVolumeExpansion: true MountOptions: none ReclaimPolicy: Delete VolumeBindingMode: WaitForFirstConsumer Events: none
Persistent Disks
kubectl describe storageclass csi-gce-pd-cmek
In the output of the command, verify the following:
- The provisioner is set as
pd.csi.storage.gke.io
. - The ID of your key follows
disk-encryption-kms-key
.
Name: csi-gce-pd-cmek IsDefaultClass: No Annotations: None Provisioner: pd.csi.storage.gke.io Parameters: disk-encryption-kms-key=projects/KEY_PROJECT_ID/locations/LOCATION/keyRings/RING_NAME/cryptoKeys/KEY_NAME,type=pd-standard AllowVolumeExpansion: unset MountOptions: none ReclaimPolicy: Delete VolumeBindingMode: WaitForFirstConsumer Events: none
Create an encrypted storage volume in GKE
In this section, you dynamically provision encrypted Kubernetes storage
volumes with your new StorageClass
and Cloud KMS key.
Copy the following contents into a new file named
pvc.yaml
, and make sure the value forstorageClassName
matches the name of yourStorageClass
object:Filestore instances
kind: PersistentVolumeClaim apiVersion: v1 metadata: name: podpvc spec: accessModes: - ReadWriteMany storageClassName: csi-filestore-cmek resources: requests: storage: 1Ti
Persistent Disks
kind: PersistentVolumeClaim apiVersion: v1 metadata: name: podpvc spec: accessModes: - ReadWriteOnce storageClassName: csi-gce-pd-cmek resources: requests: storage: 6Gi
Apply the
PersistentVolumeClaim
(PVC) on your GKE cluster:kubectl apply -f pvc.yaml
If your
StorageClass
has thevolumeBindingMode
field set toWaitForFirstConsumer
, you must create a Pod to use the PVC before you can verify it. Copy the following contents into a new file namedpod.yaml
, and make sure the value forclaimName
matches the name of yourPersistentVolumeClaim
object:apiVersion: v1 kind: Pod metadata: name: web-server spec: containers: - name: web-server image: nginx volumeMounts: - mountPath: /var/lib/www/html name: mypvc volumes: - name: mypvc persistentVolumeClaim: claimName: podpvc readOnly: false
Apply the Pod on your GKE cluster:
kubectl apply -f pod.yaml
Get the status of your cluster's
PersistentVolumeClaim
and verify that the PVC is created and bound to a newly provisionedPersistentVolume
.Filestore instances
kubectl get pvc
The output is similar to the following:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE podpvc Bound pvc-e36abf50-84f3-11e8-8538-42010a800002 1Ti RWO csi-filestore-cmek 9s
Persistent Disks
kubectl get pvc
The output is similar to the following:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE podpvc Bound pvc-e36abf50-84f3-11e8-8538-42010a800002 6Gi RWO csi-gce-pd-cmek 9s
You can now use your CMEK-protected Persistent Disk with your GKE cluster.
Remove CMEK protection
To remove CMEK protection from a Persistent Disk, follow the instructions in the Compute Engine documentation.
CMEK encryption cannot be removed from Filestore instances.
GKE and CMEK organization policies
GKE supports CMEK organization policies (Preview) that can require CMEK protection and can limit which Cloud KMS keys you can use for CMEK protection.
When container.googleapis.com
is in the Deny
policy list of services for the
constraints/gcp.restrictNonCmekServices
constraint, GKE refuses
to create the following resources if you don't enable CMEK protection:
- New clusters and node pools
- New Filestore instances and Persistent Disks
When the constraints/gcp.restrictNonCmekCryptoKeyProjects
constraint is
configured in an organization policy, GKE only creates
CMEK-protected resources that use an encryption key from an allowed project,
folder, or organization.
What's next
- Read the Cloud Key Management Service FAQ.
- Learn about protecting resources with Cloud KMS Keys.