Using customer-managed encryption keys (CMEK)

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 masters, cannot be protected with CMEK.

Before you begin

  • To do the exercises in this topic, 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.

    Enable 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.

    Enable Cloud KMS API

  • Ensure that you have installed the Cloud SDK.

  • 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 zone us-central1-a can only use a key in the region us-central1.

    • 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 the asia-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 \
  --location location \
  --keyring key-ring \
  --member serviceAccount:service-account \
  --role roles/cloudkms.cryptoKeyEncrypterDecrypter \
  --project key-project-id

Replace the following:

  • key is the name of your key.
  • location is the region where you created your key ring.
  • key-ring is the name of your key ring.
  • service-account is the name of your Compute Engine service account.
  • key-project-id is your key project ID.

Console

Grant your Compute Engine service account the Cloud KMS CryptoKey Encrypter/Decrypter role:

  1. Open the Cloud Key Management Service Keys browser in the Google Cloud Console.
    Open the Cloud KMS Keys browser
  2. Click on the name of the key ring that contains the desired key.

  3. Select the checkbox for the desired key.

    The Permissions tab in the right window pane becomes available.

  4. In the Add members dialog, specify the email address of the Compute Engine service account you are granting access.

  5. In the Select a role drop down, select Cloud KMS CryptoKey Encrypter/Decrypter.

  6. Click Save.

Create a CMEK protected boot disk

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 command or the Google Cloud Console.

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 creation command.

    gcloud container clusters create cluster \
  --cluster-version=latest \
  --zone zone \
  --boot-disk-kms-key projects/key-project-id/locations/location/keyRings/key-ring/cryptoKeys/key \
  --project cluster-project-id\
  --disk-type disk-type

Replace the following:

  • cluster is a name that you choose for your cluster.
  • zone is the zone where you want to create the cluster.
  • key-project-id is your key project ID.
  • location is the location of your key ring.
  • key-ring is the name of your key ring.
  • key is the name of your key.
  • cluster-project-id is your cluster project ID.
  • disk-type is pd-standard (default), or pd-ssd.

Console

  1. Visit the Cloud Key Management Service menu in Cloud Console.

    Visit the Cloud Key Management Service menu

  2. Click the Create cluster button.

  3. Configure your cluster as desired.

  4. From the navigation pane, under Node Pools, click Nodes.

  5. In the Boot disk type drop-down list, select Standard persistent disk or SSD Persistent Disk.

  6. Select the Enable customer-managed encryption for Boot Disk checkbox and choose the Cloud KMS encryption key you created above.

  7. Click Create.

Update a cluster with CMEK-protected node boot disks

To create a new node pool with CMEK enabled on an existing cluster, you can use the gcloud command 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 \
  --zone zone \
  --disk-type disk-type \
  --boot-disk-kms-key projects/key-project-id/locations/location/keyRings/ring-name/cryptoKeys/<var>key-name \
  --project cluster-project-id \
  --cluster cluster-name

Replace the following:

  • node-pool-name is a name that you choose for your node pool.
  • zone is the zone where you want to create the cluster.
  • disk-type is pd-standard (default), or pd-ssd.
  • key-project-id is your key project ID.
  • location is the location of your key ring.
  • ring-name is the name of your key ring.
  • key-name is the name of your key.
  • cluster-project-id is your cluster project ID.
  • cluster-name is the name of the cluster you created in the previous step.

Console

  1. Visit the GKE menu in Cloud Console.

    Visit the GKE menu

  2. Select the cluster that you want to add a node pool to.

  3. Click Add Node Pool.

  4. Ensure Boot disk type is Standard persistent disk or or SSD persistent disk.

  5. Select Enable customer-managed encryption for Boot Disk and select the Cloud KMS encryption key you created.

  6. Click Save.

Create a CMEK protected attached disk

Complete these instructions to encrypt newly created 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 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.
  • 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

  1. Copy the content below into a YAML file named gcepd-sc.yaml. This configuration enables dynamic provisioning of encrypted volumes.

    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/key-ring/cryptoKeys/key
    
    • 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 and cryptoKeys). Provisioning a new volume with incorrect values results in an invalidResourceUsage error.
    • You can set the StorageClass as the default.

    You cannot add the disk-encryption-kms-key parameter to an existing StorageClass. However, you can delete the StorageClass and recreate it with the same name, but a different set of parameters. If you do this, make sure the provisioner of the existing class is pd.csi.storage.gke.io.

  2. Deploy the StorageClass on your GKE cluster using kubectl:

    kubectl apply -f gcepd-sc.yaml
    
  3. Verify that your StorageClass used the Compute Engine Persistent Disk CSI driver and includes the ID of your key:

    kubectl describe storageclass csi-gce-pd-cmek
    

    In the output of the command, verify:

    • 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 Persistent Disk in GKE

In this section, you dynamically provision encrypted Kubernetes storage volumes with your new StorageClass and Cloud KMS key.

  1. Copy the following contents into a new file named pvc.yaml, and make sure the value for storageClassName matches the name of your StorageClass object:

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: podpvc
    spec:
      accessModes:
        - ReadWriteOnce
      storageClassName: csi-gce-pd-cmek
      resources:
        requests:
          storage: 6Gi
    
  2. Apply the PersistentVolumeClaim (PVC) on your GKE cluster:

    kubectl apply -f pvc.yaml
    
  3. Get the status of your cluster's PersistentVolumeClaim and verify that the PVC is created and bound to a newly provisioned PersistentVolume.

    kubectl get pvc
    
    NAME      STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS     AGE
    podpvc    Bound     pvc-e36abf50-84f3-11e8-8538-42010a800002   10Gi       RWO            csi-gce-pd-cmek  9s
    

You can now use your CMEK-protected Persistent Disk with your GKE cluster.

Removing CMEK protection from a Persistent Disk

To remove CMEK protection from a Persistent Disk, follow the instructions in the Compute Engine documentation.

What's next