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 Customer Managed Encryption Keys (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. See Application-layer secrets encryption for details.

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 Cloud IAM permissions:

    • cloudkms.keyRings.getIamPolicy
    • cloudkms.keyRings.setIamPolicy

    These permissions (and many more) are granted to the pre-defined roles/cloudkms.admin Cloud 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, create a Cloud KMS key ring, key, and key version (if necessary). You can use an existing Cloud KMS key as long as it is the right type (same region, symmetric encryption key, and you grant permissions).

When you create a key ring, specify 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.

To create a Cloud KMS key, you can use the gcloud command or the Google Cloud Console.

  1. In your key project, create a key ring:

    gcloud

    gcloud kms keyrings create ring-name \
        --location location \
        --project key-project-id
    

    where:

    • ring-name is a name that you choose for your key ring.
    • location is the region where you want to create the key ring.
    • key-project-id is your key project ID.

    Console

    1. Go to the Cryptographic Keys page in the Cloud Console.

      Go to the Cryptographic Keys page

    2. Click Create key ring.

    3. In the Key ring name field, enter the name for your key ring.

    4. From the Location dropdown, select the location of your Kubernetes cluster. Your Create key ring page should look similar to:

      Keyring creation screen in Google Cloud web UI

    5. Click Create.

  2. Then, create a key:

    gcloud

    gcloud kms keys create key-name \
      --location location \
      --keyring ring-name \
      --purpose encryption \
      --project key-project-id
    

    where:

    • key-name is a name that you choose for your key.
    • location is the region where you created your key ring.
    • ring-name is the name of your key ring.
    • key-project-id is your key project ID.

    Console

    1. Go to the Cryptographic Keys page in the Cloud Console.

      Go to the Cryptographic Keys page

    2. Click the name of the key ring for which you will create a key.

    3. Click Create key.

    4. In the Key name field, enter the name for your key.

    5. Accept the default values for Rotation period and Starting on, or set a key rotation period and starting time if you want to use different values.

    6. [Optional] In the Labels field, click Add label if you want to add labels to your key.

      Your Create key page should look similar to:

      Key creation screen in Google Cloud web UI

    7. Click Create.

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

where project-number is 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-name \
  --role roles/cloudkms.cryptoKeyEncrypterDecrypter \
  --project key-project-id

where:

  • key-name is the name of your key.
  • location is the region where you created your key ring.
  • ring-name is the name of your key ring.
  • service-account-name 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.

To use CMEK with a node boot disk, ensure you select either a standard persistent disk (pd-standard) or a SSD persistent disks (pd-ssd).

gcloud

To create a cluster with customer-managed encryption for node boot disks, specify a value for the --boot-disk-kms-key parameter in your creation command.

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

where:

  • cluster-name 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.
  • 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.
  • disk-type is pd-standard (default), or pd-ssd.

Console

  1. Visit the GKE menu in Cloud Console.

    Visit the GKE menu

  2. Click Create cluster.

  3. Configure your cluster as desired.

  4. In the default_pool section, click More options. The Edit node pool window appears.

  5. In this window, click the Boot disk type dropdown and select Standard persistent disk or SSD Persistent Disk.

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

  7. Click Save.

Create a node pool with a CMEK-protected node boot disk

You can create a new node pool with a CMEK-protected node boot disk using 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 beta 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/key-name \
--project cluster-project-id \
--cluster cluster-name

where:

  • 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 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.
  2. Deploy the StorageClass on your GKE cluster using kubectl:

    kubectl apply -f gcepd-sc.yaml
  3. Finally, 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