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

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

概览

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

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

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

节点启动磁盘

节点启动磁盘是集群节点池的一部分。创建集群和节点池时,您可以创建由 CMEK 加密的节点启动磁盘。

挂接的磁盘

挂接的磁盘是 Pod 用于持久性存储的 PersistentVolume。由 CMEK 加密的挂接永久性磁盘以动态预配的 PersistentVolume 的形式在 GKE 中提供。

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

准备工作

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

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

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

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

    启用 Cloud KMS API

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

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

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

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

    启用 Cloud KMS API

  • 确保您已安装 Cloud SDK

  • 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 Console 向此服务帐号授予访问权限。

gcloud

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

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

替换以下内容:

  • key 是您的密钥名称。
  • location 是您创建密钥环的区域。
  • key-ring 是您的密钥环名称。
  • service-account 是您的 Compute Engine 服务帐号的名称。
  • key-project-id 是您的密钥项目 ID。

控制台

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

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

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

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

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

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

  6. 点击保存

创建由 CMEK 保护的启动磁盘

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

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

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

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

您可以使用 gcloud 命令或 Google Cloud Console 创建使用由 CMEK 保护的节点启动磁盘的集群。

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

gcloud

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

    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

替换以下内容:

  • cluster 是您为集群选择的名称。
  • zone 是您要创建实例的地区。
  • key-project-id 是您的密钥项目 ID。
  • location 是您的密钥环的位置。
  • key-ring 是您的密钥环名称。
  • key 是您的密钥名称。
  • cluster-project-id 是您的集群项目 ID。
  • disk-typepd-standard(默认值)或 pd-ssd

控制台

  1. 转到 Cloud Console 中的 Google Kubernetes Engine 页面:

    转到 Google Kubernetes Engine

  2. 点击 创建

  3. 根据需要配置集群。

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

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

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

  7. 点击创建

更新使用由 CMEK 保护的节点启动磁盘的集群

如需在现有集群上创建启用了 CMEK 的新节点池,您可以使用 gcloud 命令或 Google Cloud Console。

gcloud

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

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

替换以下内容:

  • node-pool-name 是您为节点池选择的名称。
  • zone 是您要创建集群的区域。
  • disk-typepd-standard(默认值)或 pd-ssd
  • key-project-id 是您的密钥项目 ID。
  • location 是您的密钥环的位置。
  • ring-name 是您的密钥环名称。
  • key-name 是您的密钥名称。
  • cluster-project-id 是您的集群项目 ID。
  • cluster-name 是您在上一步中创建的集群的名称。

控制台

  1. 访问 Cloud Console 中的 Google Kubernetes Engine 菜单。

    访问 Google Kubernetes Engine 菜单

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

  3. 点击 添加节点池

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

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

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

  7. 点击创建

创建由 CMEK 保护的挂接磁盘

请按照以下说明加密新创建的永久性磁盘。您可以使用新的或现有的 Cloud KMS 密钥在新集群或现有集群上启用 CMEK。

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

创建引用 Cloud KMS 密钥的 StorageClass

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

    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
    
    • disk-encryption-kms-key 字段必须是用于加密新磁盘的密钥的完全限定资源标识符
    • disk-encryption-kms-key 中的值(例如:keyRingscryptoKeys)区分大小写。使用错误值预配新卷会导致出现 invalidResourceUsage 错误。
    • 您可以将 StorageClass 设为默认值

    您无法将 disk-encryption-kms-key 参数添加到现有的 StorageClass。但是,您可以删除 StorageClass,然后使用相同的名称和不同的参数集来重新创建它。如果您执行此操作,请确保现有类的预配工具为 pd.csi.storage.gke.io

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

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

    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 对象的名称匹配:

    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

    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 文档中的说明进行操作。

后续步骤