本页面介绍如何在 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 进行保护。
准备工作
为了完成本主题中的练习,您需要两个 Google Cloud 项目:
密钥项目:您在此创建加密密钥。
集群项目:您在此创建启用 CMEK 的集群。
在密钥项目中,确保您已启用 Cloud KMS API。
在密钥项目中,创建密钥环和密钥的用户需要拥有以下 IAM 权限:
cloudkms.keyRings.getIamPolicy
cloudkms.keyRings.setIamPolicy
这些权限授予预定义的
roles/cloudkms.admin
Identity and Access Management 角色。您可以参阅 Cloud KMS 文档,详细了解授予管理密钥的权限。在集群项目中,确保您已启用 Cloud KMS API。
确保您已安装 gcloud CLI。
将
gcloud
更新到最新版本:gcloud components update
创建 Cloud KMS 密钥
您需要 Cloud KMS 密钥环和密钥,然后才能使用 CMEK 保护节点启动磁盘或挂接的磁盘。
您的密钥环和密钥具有以下要求:
您的密钥应使用对称加密。
您的密钥环必须具有与 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 角色:
- 在 Google Cloud 控制台中打开 Cloud Key Management Service 密钥浏览器。
打开 Cloud KMS 密钥浏览器 点击包含所需密钥的密钥环的名称。
选中所需密钥对应的复选框。
右侧窗格中的权限标签变为可用。
在添加成员对话框中,指定您要授予其访问权限的 Compute Engine 服务账号的电子邮件地址。
在选择角色下拉列表中,选择 Cloud KMS CryptoKey Encrypter/Decrypter。
点击保存。
使用受 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_TYPE
:pd-standard
(默认)或pd-ssd
。
控制台
创建标准集群
如需创建使用 CMEK 密钥加密启动磁盘的标准集群,请执行以下步骤:
转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。
点击 add_box 创建。
在标准部分中,点击配置。
根据需要配置集群。
在导航窗格的节点池下,点击节点。
在启动磁盘类型下拉列表中,选择标准永久性磁盘或 SSD 永久性磁盘。
选中为启动磁盘启用客户管理的加密复选框,然后选择您在上文中创建的 Cloud KMS 加密密钥。
点击创建。
创建 Autopilot 集群
如需创建使用 CMEK 密钥加密启动磁盘的 Autopilot 集群,请执行以下步骤:
转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。
点击 add_box 创建。
在 Autopilot 部分中,点击配置。
根据需要配置集群。
展开高级选项部分,然后找到安全选项。
选中为启动磁盘启用客户管理的加密复选框,然后选择您在上文中创建的 Cloud KMS 加密密钥。
点击创建。
使用由 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_TYPE
:pd-standard
(默认)或pd-ssd
。KEY_PROJECT_ID
:您的密钥项目 ID。LOCATION
:密钥环的位置。RING_NAME
:密钥环的名称。KEY_NAME
:密钥的名称。CLUSTER_PROJECT_ID
:您的集群项目 ID。CLUSTER_NAME
:您在上一步中创建的标准集群的名称。
控制台
转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。
在集群列表中,点击您要修改的集群的名称。
点击 add_box 添加节点池。
在导航窗格中,点击节点。
在机器配置部分中,确保启动磁盘类型为标准永久性磁盘或 SSD 永久性磁盘。
选中为启动磁盘启用客户管理的加密复选框,然后选择您创建的 Cloud KMS 加密密钥。
点击创建。
使用受 CMEK 保护的 Filestore 实例或永久性磁盘
以下信息介绍如何加密新建的 Filestore 实例或永久性磁盘。您可以使用新的或现有的 Cloud KMS 密钥在新集群或现有集群上启用 CMEK。
每个 GKE 集群都需要您按照这些说明操作一次。
- 如果您没有 GKE 集群,请创建一个。
- 将 Filestore CSI 驱动程序或 Compute Engine Persistent Disk CSI Driver 部署到您的集群。
- 如果您没有 Cloud KMS 密钥环和密钥版本,请创建一个。
- 向 Filestore 服务账号授予密钥访问权限。
- 创建 StorageClass,让 Kubernetes 预配的磁盘可以使用该 Cloud KMS 密钥自动加密。如需详细了解如何执行此操作,请参阅以下部分。
创建引用 Cloud KMS 密钥的 StorageClass
将以下内容复制到名为
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
中的值(例如:keyRings
和cryptoKeys
)区分大小写。使用错误值预配新卷会导致出现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
中的值(例如:keyRings
和cryptoKeys
)区分大小写。使用错误值预配新卷会导致出现invalidResourceUsage
错误。- 您无法将
disk-encryption-kms-key
参数添加到现有StorageClass
对象。但是,您可以删除StorageClass
对象,然后使用相同的名称和不同的参数集来重新创建它。请确保现有类的预配工具为pd.csi.storage.gke.io
。
您可以将 StorageClass 设为默认值。
使用
kubectl
在您的 GKE 集群上部署StorageClass
:kubectl apply -f cmek-sc.yaml
验证您的
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 存储卷。
将以下内容复制到名为
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
在您的 GKE 集群上应用
PersistentVolumeClaim
(PVC):kubectl apply -f pvc.yaml
如果
StorageClass
的volumeBindingMode
字段设置为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
在您的 GKE 集群上应用 Pod:
kubectl apply -f pod.yaml
获取集群的
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 保护资源。