持久卷加密
概述
持久卷(PV)加密有助于保护有状态工作负载的数据机密性和租户隔离。
对于 ACP 分布式存储,CSI 置备的 PV 的静态数据加密通过外部密钥管理系统(KMS)和启用加密的 StorageClass 实现。
本章介绍如何:
- 配置 KMS 访问凭证和连接详细信息
- 创建启用加密的 StorageClass
- 启用和禁用密钥轮换策略
WARNING
本章中的持久卷加密适用于 RBD 支持的 PV。不涵盖对象存储桶。
密钥管理系统(KMS)的访问配置
首先配置 KMS 访问。基于 StorageClass 的 PV 加密依赖于有效的 KMS 凭证和连接元数据。
每种提供商模式的身份验证和元数据模型不同:
⚠️ 重要:Alpha 功能免责声明
使用 vaulttenantsa 访问 KMS 目前处于 Alpha 阶段,仅严格用于早期技术验证和评估。作为功能提供方,我们不对其稳定性、可靠性或数据完整性提供任何保证。通过配置和使用此功能,您确认并接受以下技术限制:
- 不适用于生产环境: 此功能尚未经过全面的系统级验证。在生产环境中部署此功能存在较高的流程失败或数据损坏风险。
- 不保证 SLA: 此功能不属于标准服务级别协议(SLA)的范围。我们不保证技术支持响应时间,也不提供紧急修复程序。
- 重大变更和弃用: API 端点、配置架构和核心处理逻辑可能会在未来版本中发生不向后兼容的变化。此功能也可能在不事先通知的情况下被完全弃用。
- 不提供平滑升级路径: 我们不提供版本之间的升级脚本或数据迁移工具。升级到后续版本通常需要完全清除现有资源并重新部署。由此造成的任何状态或数据丢失均由用户自行承担。
使用 vaulttokens 配置访问
前提条件
- ACP 分布式存储集群处于
Ready 状态。
- 您具有
cluster-admin 权限。
- 集群节点可以访问 Vault。
- 您拥有可访问目标后端路径的有效 Vault 令牌。
操作步骤
-
创建用于存储 Vault 令牌的 Secret。
kubectl -n rook-ceph create secret generic ceph-csi-kms-token \
--from-literal=token='<vault_token>'
-
创建或更新 KMS 连接 ConfigMap 条目。
apiVersion: v1
kind: ConfigMap
metadata:
name: csi-kms-connection-details
namespace: rook-ceph
data:
vault-token-kms: |
{
"encryptionKMSType": "vaulttokens",
"vaultAddress": "<https://hostname_or_ip_of_vault_server:port>",
"vaultBackend": "<vault backend>",
"vaultBackendPath": "<vault backend path name>",
"vaultTLSServerName": "<vault TLS server name>",
"vaultCAVerify": "true",
"vaultCAFromSecret": "<secret containing CA cert>",
"vaultClientCertFromSecret": "<secret containing client cert>",
"vaultClientCertKeyFromSecret": "<secret containing client private key>"
}
参数
验证步骤
-
验证令牌 Secret:
kubectl -n rook-ceph get secret ceph-csi-kms-token
-
验证 ConfigMap 条目并确认 encryptionKMSType: vaulttokens:
kubectl -n rook-ceph get configmap csi-kms-connection-details -o yaml
使用 vaulttenantsa 配置访问
前提条件
- ACP 分布式存储集群处于
Ready 状态。
- 在外部密钥管理系统(KMS)上:
- 确保已存在策略,并且 Vault 中的密钥值后端路径已启用。
- 确保 Vault 服务器使用签名证书。
操作步骤
在 ACP 分布式存储能够向 Vault 进行身份验证并开始使用它之前,您需要配置 Kubernetes 身份验证方法。以下说明将创建并配置 serviceAccount、ClusterRole 和 ClusterRoleBinding,以允许 ACP 分布式存储向 Vault 进行身份验证。
-
在工作负载命名空间中创建租户 ServiceAccount。
kubectl -n <tenant_namespace> create serviceaccount ceph-csi-vault-sa
-
在存储命名空间中应用用于 Vault 令牌审查的 RBAC 资源。
cat << EOF | kubectl create -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: rbd-csi-vault-token-review
namespace: rook-ceph
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: rbd-csi-vault-token-review
rules:
- apiGroups: ["authentication.k8s.io"]
resources: ["tokenreviews"]
verbs: ["create", "get", "list"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: rbd-csi-vault-token-review
subjects:
- kind: ServiceAccount
name: rbd-csi-vault-token-review
namespace: rook-ceph
roleRef:
kind: ClusterRole
name: rbd-csi-vault-token-review
apiGroup: rbac.authorization.k8s.io
EOF
-
为令牌审查器 ServiceAccount 创建 service-account-token Secret。
cat << EOF | kubectl create -f -
apiVersion: v1
kind: Secret
metadata:
name: rbd-csi-vault-token-review-token
namespace: rook-ceph
annotations:
kubernetes.io/service-account.name: rbd-csi-vault-token-review
type: kubernetes.io/service-account-token
EOF
-
读取审查器 JWT、集群 CA 和 API 端点。
SA_JWT_TOKEN=$(kubectl -n rook-ceph get secret rbd-csi-vault-token-review-token \
-o jsonpath="{.data['token']}" | base64 --decode; echo)
SA_CA_CRT=$(kubectl -n rook-ceph get secret rbd-csi-vault-token-review-token \
-o jsonpath="{.data['ca\.crt']}" | base64 --decode; echo)
ACP_HOST=$(kubectl config view --minify --flatten -o jsonpath="{.clusters[0].cluster.server}")
-
在 Vault 中配置 Kubernetes 身份验证。
vault auth enable kubernetes
vault write auth/kubernetes/config \
token_reviewer_jwt="$SA_JWT_TOKEN" \
kubernetes_host="$ACP_HOST" \
kubernetes_ca_cert="$SA_CA_CRT"
-
为租户命名空间创建 Vault 角色。
vault write "auth/kubernetes/role/csi-kubernetes" \
bound_service_account_names="ceph-csi-vault-sa" \
bound_service_account_namespaces="<tenant_namespace>" \
policies="<policy_name_in_vault>"
NOTE
csi-kubernetes 是 ACP 分布式存储在 Vault 中查找的默认角色名称。
- ACP 分布式存储集群中租户命名空间的默认服务账户名称为
ceph-csi-vault-sa。
- 可以通过在租户命名空间中创建 ConfigMap 来覆盖这些默认值。
-
使用 encryptionKMSType: vaulttenantsa 创建或更新 KMS 连接条目。
apiVersion: v1
kind: ConfigMap
metadata:
name: csi-kms-connection-details
namespace: rook-ceph
data:
vault-tenant-sa-kms: |
{
"encryptionKMSType": "vaulttenantsa",
"vaultAddress": "<https://hostname_or_ip_of_vault_server:port>",
"vaultTLSServerName": "<vault TLS server name>",
"vaultAuthPath": "/v1/auth/kubernetes/login",
"vaultAuthNamespace": "<vault auth namespace name>",
"vaultNamespace": "<vault namespace name>",
"vaultBackendPath": "<vault backend path name>",
"vaultCAFromSecret": "<secret containing CA cert>",
"vaultClientCertFromSecret": "<secret containing client cert>",
"vaultClientCertKeyFromSecret": "<secret containing client private key>",
"tenantSAName": "<service account name in the tenant namespace>"
}
参数
验证步骤
-
验证 ServiceAccount 创建:
kubectl -n <tenant_namespace> get sa ceph-csi-vault-sa
kubectl -n rook-ceph get sa rbd-csi-vault-token-review
-
验证令牌审查权限:
kubectl auth can-i create tokenreviews.authentication.k8s.io \
--as=system:serviceaccount:rook-ceph:rbd-csi-vault-token-review
-
验证 ConfigMap 条目并确认 encryptionKMSType: vaulttenantsa 和 tenantSAName。
-
在 <tenant_namespace> 中创建测试加密 PVC,并验证其是否成功绑定。
使用 Thales CipherTrust Manager(kmip)配置访问
前提条件
- 您可以访问已启用 KMIP 的 Thales CipherTrust Manager。
- 您拥有 KMIP 端点(
<kmip_address>:5696)、客户端证书链和密钥唯一标识符(UID)。
- 您具有在
rook-ceph 中创建 Secret 和 ConfigMap 的权限。
操作步骤
-
在 Thales CipherTrust Manager 中创建 KMIP 客户端配置文件并注册客户端。
-
从配置文件中下载客户端证书、私钥和 CA 证书。
-
为 KMIP 客户端凭证创建 Secret。
kubectl -n rook-ceph create secret generic thales-kmip-client \
--from-file=client.crt=<client_crt_path> \
--from-file=client.key=<client_key_path> \
--from-file=ca.crt=<ca_crt_path>
-
创建或更新 KMS 连接 ConfigMap 条目。
apiVersion: v1
kind: ConfigMap
metadata:
name: csi-kms-connection-details
namespace: rook-ceph
data:
thales-kmip-kms: |
{
"encryptionKMSType": "kmip",
"kmipAddress": "<kmip_address>",
"kmipPort": 5696,
"kmipCAPath": "/etc/ceph-csi-kms-config/ca.crt",
"keyIdentifier": "<thales_key_uid>"
}
验证步骤
-
验证 KMIP 凭证 Secret:
kubectl -n rook-ceph get secret thales-kmip-client
-
验证 ConfigMap 条目并确认 encryptionKMSType: kmip。
-
确认 KMS 条目中的密钥 UID 与 Thales CipherTrust Manager 中生成的密钥匹配。
NOTE
对于 kmip,关键区别在于,加密密钥通过 KMIP 密钥 UID 和双向 TLS 信任链解析,而不是通过 Vault 令牌解析。
创建用于持久卷加密的 StorageClass
配置 KMS 访问权限后,创建包含加密参数的 StorageClass。
先决条件
- 你具有创建 StorageClass 的权限。
- 你知道目标 KMS 配置 ID(
<kms_config_id>)。
操作步骤
-
转到管理员。
-
在左侧导航栏中,点击存储 > StorageClasses。
-
点击创建 Storage Class。
注意:以下内容是表单格式示例,你也可以选择 YAML 完成操作。
-
选择CephRBD 块存储,然后点击下一步。
-
切换到 YAML 视图
-
在参数中启用加密:
encrypted: "true"
encryptionKMSID: "<kms_config_id>"
-
点击创建。
验证步骤
-
验证 StorageClass 参数:
kubectl get sc encrypted-rbd-sc -o yaml
-
确认存在 encrypted: "true" 和预期的 encryptionKMSID。
-
使用此 StorageClass 创建测试 PVC,并确认其达到 Bound 状态:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: encrypted-rbd-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: encrypted-rbd-sc
kubectl apply -f <encrypted-rbd-pvc.yaml>
kubectl get pvc encrypted-rbd-pvc
使用租户 ConfigMap 覆盖 Vault 连接详细信息
通过在 ACP 命名空间中创建 ConfigMap,可以按租户重新配置 Vault 连接详细信息,并使用与 rook-ceph 命名空间中 csi-kms-connection-details ConfigMap 中设置的值不同的配置选项。ConfigMap 必须位于租户命名空间中。租户命名空间中的 ConfigMap 值将覆盖 csi-kms-connection-details ConfigMap 中为该命名空间创建的加密持久卷所设置的值。
操作步骤
-
在 ACP 控制台中,导航到Alauda Container Platform -> 配置 -> ConfigMaps。
-
切换到目标租户项目/命名空间。
-
点击创建 ConfigMap,并输入 ceph-csi-kms-config 作为名称。
-
添加特定于租户的 Vault 覆盖值:
apiVersion: v1
kind: ConfigMap
metadata:
name: ceph-csi-kms-config
namespace: <tenant_namespace>
data:
vaultAddress: "<vault_address:port>"
vaultBackendPath: "<backend_path>"
vaultTLSServerName: "<vault_tls_server_name>"
vaultNamespace: "<vault_namespace>"
-
点击创建。
验证步骤
-
验证租户覆盖 ConfigMap:
kubectl -n <tenant_namespace> get configmap ceph-csi-kms-config -o yaml
-
在同一命名空间中创建新的加密 PVC,并确认其达到 Bound。
-
如果密钥访问失败,请检查命名空间事件和 CSI provisioner 日志,确认 Vault 端点和身份验证路径是否匹配。
启用和禁用密钥轮换(可选)
密钥轮换支持定期刷新加密 PV 使用的加密密钥。
前提条件
- 请确保以下两个镜像已上传到平台的私有镜像仓库:
quay.io/csiaddons/k8s-controller:v0.14.0 -> <registry>/csiaddons/k8s-controller:v0.14.0
quay.io/csiaddons/k8s-sidecar:v0.14.0 -> <registry>/csiaddons/k8s-sidecar:v0.14.0
设置卷复制环境
-
设置 CsiAddons Controller
在控制平面节点上执行以下命令:
kubectl create -f https://raw.githubusercontent.com/csi-addons/kubernetes-csi-addons/v0.14.0/deploy/controller/crds.yaml
kubectl create -f https://raw.githubusercontent.com/csi-addons/kubernetes-csi-addons/v0.14.0/deploy/controller/setup-controller.yaml
kubectl create -f https://raw.githubusercontent.com/csi-addons/kubernetes-csi-addons/v0.14.0/deploy/controller/rbac.yaml
kubectl create -f https://raw.githubusercontent.com/csi-addons/kubernetes-csi-addons/v0.14.0/deploy/controller/csi-addons-config.yaml
kubectl -n csi-addons-system set image deployment/csi-addons-controller-manager manager=<registry>/csiaddons/k8s-controller:v0.14.0
参数:
<registry>:平台的 Registry 地址。
-
启用 CsiAddons sidecar
在控制平面节点上执行以下命令:
kubectl patch cm rook-ceph-operator-config -n rook-ceph --type json --patch \
'[
{
"op": "add",
"path": "/data/CSI_ENABLE_CSIADDONS",
"value": "true"
},
{
"op": "add",
"path": "/data/ROOK_CSIADDONS_IMAGE",
"value": "<registry>/csiaddons/k8s-sidecar:v0.14.0"
}
]'
等待所有 csi pod 成功重启
kubectl get po -n rook-ceph -w | grep csi
(可选)强制设置密钥轮换的优先级
在密钥轮换中,优先级是指系统检查计划注解的顺序。默认优先级设置为 StorageClass(推荐)。这意味着系统只从 StorageClass 读取注解。
但是,如果希望系统先检查持久卷声明(PVC),然后回退到 StorageClass,则可以在 CSI-addons ConfigMap 中将 schedule-precedence 设置为 PVC,以配置此行为。
可以按如下所示定义 csi-addons 的 ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: csi-addons-config
namespace: rook-ceph
data:
schedule-precedence: "pvc"
重启 csi-addons operator pod 以使更改生效:
kubectl apply -f <csi-addons-config.yaml>
kubectl -n rook-ceph delete pod -l app.kubernetes.io/name=csi-addons
启用密钥轮换
要启用密钥轮换,请按优先级从高到低的顺序,将注解 keyrotation.csiaddons.openshift.io/schedule: <value> 添加到 PersistentVolumeClaims、Namespace 或 StorageClass。
<value> 可以是 @hourly、@daily、@weekly、@monthly 或 @yearly。如果 <value> 为空,则默认值为 @weekly。以下示例使用 @weekly。
为 Namespace 添加注解
kubectl annotate namespace <tenant_namespace> \
"keyrotation.csiaddons.openshift.io/schedule=@weekly"
为 StorageClass 添加注解
kubectl annotate storageclass encrypted-rbd-sc \
"keyrotation.csiaddons.openshift.io/schedule=@weekly"
为 PersistentVolumeClaims 添加注解
kubectl annotate pvc <encrypted_pvc_name> \
"keyrotation.csiaddons.openshift.io/schedule=@weekly"
禁用密钥轮换
可以针对以下对象禁用密钥轮换:
- StorageClass 的所有持久卷声明(PVC)
- 特定 PVC
为 StorageClass 的所有 PVC 禁用密钥轮换
kubectl annotate storageclass encrypted-rbd-sc \
"keyrotation.csiaddons.openshift.io/enable=false" --overwrite
为特定持久卷声明禁用密钥轮换
-
确定要禁用密钥轮换的 PVC 对应的 EncryptionKeyRotationCronJob CR:
kubectl get encryptionkeyrotationcronjob -o jsonpath='{range .items[?(@.spec.jobTemplate.spec.target.persistentVolumeClaim=="<PVC_NAME>")]}{.metadata.name}{"\n"}{end}'
其中,<PVC_NAME> 是要禁用密钥轮换的 PVC 名称。
-
对上一步中的 EncryptionKeyRotationCronJob CR 应用以下更改,以禁用密钥轮换:
-
将 csiaddons.openshift.io/state 注解从 managed 更新为 unmanaged:
kubectl annotate encryptionkeyrotationcronjob <encryptionkeyrotationcronjob_name> "csiaddons.openshift.io/state=unmanaged" --overwrite=true
其中,<encryptionkeyrotationcronjob_name> 是 EncryptionKeyRotationCronJob CR 的名称。
-
在 spec 字段下添加 suspend: true:
kubectl patch encryptionkeyrotationcronjob <encryptionkeyrotationcronjob_name> -p '{"spec": {"suspend": true}}' --type=merge
-
保存并退出。PVC 的密钥轮换将被禁用。