使用客户管理的加密密钥 (CMEK)


本页面介绍如何在 Google Kubernetes Engine (GKE) 上使用 CMEK。如果您需要控制密钥的管理,可以使用 Cloud Key Management Service 和 CMEK 来保护 GKE 集群中挂接的永久性磁盘和自定义启动磁盘

概览

默认情况下,Google Cloud 会加密静态的客户内容,GKE 为您处理和管理此默认加密,您无需进行任何其他操作。

如果您希望自行控制和管理加密密钥轮替,则可以使用 CMEK。这些密钥会对加密您的数据的数据加密密钥进行加密。如需了解详情,请参阅密钥管理

您还可以使用自己管理的密钥对集群中的 Secret 进行加密。如需了解详情,请参阅应用层 Secret 加密

在 GKE 中,CMEK 可以保护两类存储磁盘的数据:节点启动磁盘和挂接的磁盘。

节点启动磁盘
节点启动磁盘是集群节点池的一部分。创建集群和节点池时,您可以创建由 CMEK 加密的节点启动磁盘。
挂接的磁盘
挂接的磁盘是 Pod 用于持久性存储的 PersistentVolume。在 GKE 中,由 CMEK 加密的挂接磁盘以动态预配的 PersistentVolume 的形式提供。

如需详细了解存储磁盘,请参阅存储选项。 用于 GKE 控制层面的控制层面磁盘无法通过 CMEK 进行保护。

准备工作

  1. 为了完成本主题中的练习,您需要两个 Google Cloud 项目:

    • 密钥项目:您在此创建加密密钥。

    • 集群项目:您在此创建启用 CMEK 的集群。

  2. 在密钥项目中,确保您已启用 Cloud KMS API。

    启用 Cloud KMS API

  3. 密钥项目中,创建密钥环和密钥的用户需要拥有以下 IAM 权限:

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

    这些权限授予预定义的 roles/cloudkms.admin Identity and Access Management 角色。您可以参阅 Cloud KMS 文档,详细了解授予管理密钥的权限

  4. 集群项目中,确保您已启用 Cloud KMS API。

    启用 Cloud KMS API

  5. 确保您已安装 gcloud CLI

  6. gcloud 更新到最新版本:

    gcloud components update
    

创建 Cloud KMS 密钥

您需要 Cloud KMS 密钥环和密钥,然后才能使用 CMEK 保护节点启动磁盘或挂接的磁盘。

您的密钥环和密钥具有以下要求:

  • 您的密钥应使用对称加密。

  • 您需要向 GKE 服务账号授予使用密钥的权限

  • 您的密钥环必须具有与 GKE 集群位置匹配的位置:

    • 可用区级集群应使用超集位置的密钥环。例如,us-central1-a 可用区中的集群只能使用 us-central1 区域中的密钥。

    • 区域级集群应使用同一位置的密钥环。例如,asia-northeast1 区域中的集群应使用 asia-northeast1 区域中的密钥环予以保护。

    • 无法在 Cloud KMS global 区域使用 GKE。

如需了解如何创建密钥环和密钥,请参阅创建对称密钥

授予使用密钥的权限

您必须为您的集群节点所用的 Compute Engine 服务账号分配 Cloud KMS CryptoKey Encrypter/Decrypter 角色。 这是 GKE 永久性磁盘访问和使用加密密钥的必要条件。

Compute Engine 服务账号的名称采用以下格式:

service-PROJECT_NUMBER@compute-system.iam.gserviceaccount.com

PROJECT_NUMBER 替换为您的集群的项目编号

您可以使用 gcloud 命令或 Google Cloud 控制台向此服务账号授予访问权限。

gcloud

向 Compute Engine 服务账号授予 Cloud KMS CryptoKey Encrypter/Decrypter 角色

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

替换以下内容:

  • KEY_NAME:密钥的名称。
  • LOCATION:您创建密钥环的区域。
  • RING_NAME:密钥环的名称。
  • SERVICE_ACCOUNT:您的 Compute Engine 服务账号的名称。
  • KEY_PROJECT_ID:您的密钥项目 ID。

控制台

向 Compute Engine 服务账号授予 Cloud KMS CryptoKey Encrypter/Decrypter 角色

  1. 在 Google Cloud 控制台中打开 Cloud Key Management Service 密钥浏览器。
    打开 Cloud KMS 密钥浏览器
  2. 点击包含所需密钥的密钥环的名称。

  3. 选中所需密钥对应的复选框。

    右侧窗格中的权限标签变为可用。

  4. 添加成员对话框中,指定您要授予其访问权限的 Compute Engine 服务账号的电子邮件地址。

  5. 选择角色下拉列表中,选择 Cloud KMS CryptoKey Encrypter/Decrypter

  6. 点击保存

使用受 CMEK 保护的节点启动磁盘

在此部分中,您将新建一个集群或节点池,并在其中使用由 CMEK 保护的启动磁盘。

您不能为现有集群上的节点启动磁盘启用客户管理的加密,因为无法更改现有集群或节点池的启动磁盘类型。不过,您可以为启用了客户管理的加密的集群创建新的节点池,并删除原有的节点池。

您也不能为现有集群或现有节点池中的节点启动磁盘停用客户管理的加密。不过,您可以为集群创建停用客户管理的加密的新节点池,并删除原有的节点池。

创建使用由 CMEK 保护的节点启动磁盘的集群

您可以通过 gcloud CLI 或 Google Cloud 控制台创建使用由 CMEK 保护的节点启动磁盘的集群。

对于标准集群,只有标准永久性磁盘 (pd-standard) 或 SSD 永久性磁盘 (pd-ssd) 才能使用 CMEK 密钥进行加密。

gcloud

如需创建使用 CMEK 密钥加密启动磁盘的集群,请在集群创建命令中指定 --boot-disk-kms-key 参数的值。

创建标准集群

如需创建使用 CMEK 密钥加密启动磁盘的标准集群,请使用以下命令:

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

创建 Autopilot 集群

如需创建使用 CMEK 密钥加密启动磁盘的 Autopilot 集群,请使用以下命令:

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

替换以下内容:

  • CLUSTER_NAME:新集群的名称。
  • COMPUTE_REGION:集群控制层面的计算区域
  • KEY_PROJECT_ID:您的密钥项目 ID。
  • LOCATION:密钥环的位置。
  • RING_NAME:密钥环的名称。
  • KEY_NAME:密钥的名称。
  • CLUSTER_PROJECT_ID 是您的集群项目 ID。
  • DISK_TYPEpd-standard(默认)或 pd-ssd

控制台

创建标准集群

如需创建使用 CMEK 密钥加密启动磁盘的标准集群,请执行以下步骤:

  1. 转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。

    转到 Google Kubernetes Engine

  2. 点击 创建

  3. 标准部分中,点击配置

  4. 根据需要配置集群。

  5. 在导航窗格的节点池下,点击节点

  6. 启动磁盘类型下拉列表中,选择标准永久性磁盘SSD 永久性磁盘

  7. 选中为启动磁盘启用客户管理的加密复选框,然后选择您在上文中创建的 Cloud KMS 加密密钥。

  8. 点击创建

创建 Autopilot 集群

如需创建使用 CMEK 密钥加密启动磁盘的 Autopilot 集群,请执行以下步骤:

  1. 转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。

    转到 Google Kubernetes Engine

  2. 点击 创建

  3. Autopilot 部分中,点击配置

  4. 根据需要配置集群。

  5. 展开高级选项部分,然后找到安全选项。

  6. 选中为启动磁盘启用客户管理的加密复选框,然后选择您在上文中创建的 Cloud KMS 加密密钥。

  7. 点击创建

使用由 CMEK 保护的节点启动磁盘创建新节点池

如需在现有 Standard 集群上创建启用了 CMEK 的新节点池,您可以使用 gcloud CLI 或 Google Cloud 控制台。

gcloud

若要创建节点池并在节点启动磁盘中使用客户管理的加密,请在创建命令中指定 --boot-disk-kms-key 参数的值。

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

替换以下内容:

  • NODE_POOL_NAME:您为节点池选择的名称。
  • COMPUTE_REGION:集群控制层面的计算区域
  • DISK_TYPEpd-standard(默认)或 pd-ssd
  • KEY_PROJECT_ID:您的密钥项目 ID。
  • LOCATION:密钥环的位置。
  • RING_NAME:密钥环的名称。
  • KEY_NAME:密钥的名称。
  • CLUSTER_PROJECT_ID:您的集群项目 ID。
  • CLUSTER_NAME:您在上一步中创建的标准集群的名称。

控制台

  1. 转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。

    前往 Google Kubernetes Engine

  2. 在集群列表中,点击您要修改的集群的名称。

  3. 点击 添加节点池

  4. 在导航窗格中,点击节点

  5. 机器配置部分中,确保启动磁盘类型标准永久性磁盘SSD 永久性磁盘

  6. 选中为启动磁盘启用客户管理的加密复选框,然后选择您创建的 Cloud KMS 加密密钥。

  7. 点击创建

使用受 CMEK 保护的 Filestore 实例或永久性磁盘

以下信息介绍如何加密新建的 Filestore 实例或永久性磁盘。您可以使用新的或现有的 Cloud KMS 密钥在新集群或现有集群上启用 CMEK。

每个 GKE 集群都需要您按照这些说明操作一次。

创建引用 Cloud KMS 密钥的 StorageClass

  1. 将以下内容复制到名为 cmek-sc.yaml 的 YAML 文件中。此配置启用了加密卷的动态预配。

    Filestore 实例

    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
    
    • instance-encryption-kms-key 字段必须是用于加密新 Filestore 实例的密钥的完全限定资源标识符
    • instance-encryption-kms-key 中的值(例如:keyRingscryptoKeys)区分大小写。使用错误值预配新卷会导致出现 invalidResourceUsage 错误。
    • 您无法将 instance-encryption-kms-key 参数添加到现有 StorageClass 对象。但是,您可以删除 StorageClass 对象,然后使用相同的名称和不同的参数集来重新创建它。

    永久性磁盘

    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
    
    • disk-encryption-kms-key 字段必须是用于加密新磁盘的密钥的完全限定资源标识符
    • disk-encryption-kms-key 中的值(例如:keyRingscryptoKeys)区分大小写。使用错误值预配新卷会导致出现 invalidResourceUsage 错误。
    • 您无法将 disk-encryption-kms-key 参数添加到现有 StorageClass 对象。但是,您可以删除 StorageClass 对象,然后使用相同的名称和不同的参数集来重新创建它。请确保现有类的预配工具为 pd.csi.storage.gke.io

    您可以将 StorageClass 设为默认值

  2. 使用 kubectl 在您的 GKE 集群上部署 StorageClass

    kubectl apply -f cmek-sc.yaml
    
  3. 验证您的 StorageClass 使用了 Compute Engine Filestore 或永久性磁盘 CSI 驱动程序并包含密钥的 ID:

    Filestore 实例

    kubectl describe storageclass csi-filestore-cmek
    

    在该命令的输出中,验证以下各项:

    • 预配工具已设置为 filestore.csi.storage.gke.io。
    • 密钥的 ID 遵循 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
    

    永久性磁盘

    kubectl describe storageclass csi-gce-pd-cmek
    

    在该命令的输出中,验证以下各项:

    • 预配工具设置为 pd.csi.storage.gke.io
    • 密钥 ID 采用 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
    

在 GKE 中创建加密的存储卷

在本部分中,您将使用新的 StorageClass 和 Cloud KMS 密钥动态预配加密的 Kubernetes 存储卷。

  1. 将以下内容复制到名为 pvc.yaml 的新文件中,并确保 storageClassName 的值与 StorageClass 对象的名称匹配:

    Filestore 实例

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: podpvc
    spec:
      accessModes:
        - ReadWriteMany
      storageClassName: csi-filestore-cmek
      resources:
        requests:
          storage: 1Ti
    

    永久性磁盘

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: podpvc
    spec:
      accessModes:
        - ReadWriteOnce
      storageClassName: csi-gce-pd-cmek
      resources:
        requests:
          storage: 6Gi
    
  2. 在您的 GKE 集群上应用 PersistentVolumeClaim (PVC):

    kubectl apply -f pvc.yaml
    
  3. 如果 StorageClassvolumeBindingMode 字段设置为 WaitForFirstConsumer,则必须先创建 Pod 才能使用 PVC,然后才能进行验证。将以下内容复制到名为 pod.yaml 的新文件中,并确保 claimName 的值与 PersistentVolumeClaim 对象的名称匹配:

    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
    
  4. 在您的 GKE 集群上应用 Pod:

    kubectl apply -f pod.yaml
    
  5. 获取集群的 PersistentVolumeClaim 的状态,并验证 PVC 是否已创建并绑定到新预配的 PersistentVolume

    Filestore 实例

    kubectl get pvc
    

    输出内容类似如下:

    NAME      STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS     AGE
    podpvc    Bound     pvc-e36abf50-84f3-11e8-8538-42010a800002   1Ti        RWO            csi-filestore-cmek  9s
    

    永久性磁盘

    kubectl get pvc
    

    输出内容类似如下:

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

现在,您可以将 CMEK 保护的永久性磁盘与 GKE 集群配合使用。

移除 CMEK 保护

要从永久性磁盘移除 CMEK 保护,请按照 Compute Engine 文档中的说明进行操作。

无法从 Filestore 实例中移除 CMEK 加密。

GKE 和 CMEK 组织政策

GKE 支持可以要求 CMEK 保护并且可以限制可用于 CMEK 保护的 Cloud KMS 密钥的 CMEK 组织政策(预览版)。

constraints/gcp.restrictNonCmekServices 限制条件的服务 Deny 政策列表中包含 container.googleapis.com 时,如果您未启用 CMEK 保护,GKE 将拒绝创建以下资源:

  • 新集群和节点池
  • 新 Filestore 实例和永久性磁盘

在组织政策中配置 constraints/gcp.restrictNonCmekCryptoKeyProjects 限制条件后,GKE 只会创建使用允许的项目、文件夹或组织中加密密钥的 CMEK 保护资源。

后续步骤