持久卷加密
概述
持久卷(PV)加密有助于保护有状态工作负载的数据机密性和租户隔离。
对于 ACP 分布式存储,CSI 预配的 PV 的静态加密通过外部密钥管理系统(KMS)和启用加密的 StorageClass 实现。
本章介绍如何:
- 配置 KMS 访问凭证和连接详情
- 创建启用加密的 StorageClass
- 启用和禁用密钥轮转策略
WARNING
本章中的持久卷加密适用于基于 RBD 的 PV。不包含对象存储存储桶。
密钥管理系统(KMS)的访问配置
请先配置 KMS 访问。基于 StorageClass 的 PV 加密依赖于有效的 KMS 凭证和连接元数据。
不同的提供商模式使用不同的认证和元数据模型:
⚠️ 重要:Alpha 功能免责声明
使用 vaulttenantsa 访问 KMS 处于 Alpha 阶段,仅用于早期技术验证和评估。作为功能提供方,我们不对其稳定性、可靠性或数据完整性提供任何保证。通过配置和使用此功能,您即表示已知悉并接受以下技术限制:
- 不适用于生产环境: 此功能缺少全面的系统级验证。将其部署到生产环境会带来较高的进程失败或数据损坏风险。
- 不保证 SLA: 此功能不在标准服务级别协议(SLA)范围内。我们不保证技术支持响应时间,也不提供紧急热修复。
- Breaking Changes 与弃用: API 端点、配置 schema 和核心处理逻辑在未来版本中可能发生不向后兼容的更改。该功能也可能在未提前通知的情况下被完全弃用。
- 无法平滑升级: 我们不提供版本之间的升级脚本或数据迁移工具。升级到后续版本通常需要完全清除现有资源并重新部署。由此导致的任何状态或数据丢失均由用户自行承担责任。
使用 vaulttokens 配置访问
前提条件
- ACP 分布式存储集群处于
Ready 状态。
- 您具有
cluster-admin 权限。
- 集群节点可以访问 Vault。
- 您拥有一个可访问目标后端路径的有效 Vault token。
操作步骤
-
创建一个用于存储 Vault token 的 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>"
}
参数
验证步骤
-
验证 token 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)中,
- 确保已存在 policy,并且 Vault 中的 key value backend path 已启用。
- 确保 Vault server 使用的是签名证书。
操作步骤
在 ACP 分布式存储可以使用 Vault 进行认证并开始使用之前,需要先配置 Kubernetes 认证方式。以下说明将创建并配置 ACP 分布式存储通过 Vault 进行认证所需的 serviceAccount、ClusterRole 和 ClusterRoleBinding。
-
在工作负载 namespace 中创建 tenant ServiceAccount。
kubectl -n <tenant_namespace> create serviceaccount ceph-csi-vault-sa
-
在存储 namespace 中应用用于 Vault token review 的 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
-
为 token reviewer 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
-
读取 reviewer JWT、cluster CA 和 API endpoint。
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"
-
为 tenant namespace 创建 Vault role。
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 中查找的默认 role 名称。
- ACP 分布式存储集群中 tenant namespace 里的默认 ServiceAccount 名称是
ceph-csi-vault-sa。
- 可以通过在 tenant namespace 中创建 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
-
验证 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 endpoint(
<kmip_address>:5696)、客户端证书链和 key unique identifier(UID)。
- 您有权限在
rook-ceph 中创建 Secret 和 ConfigMap。
操作步骤
-
在 Thales CipherTrust Manager 中,创建一个 KMIP client profile 并注册客户端。
-
从 profile 中下载客户端证书、私钥和 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 条目中的 key UID 与 Thales CipherTrust Manager 中生成的 key 一致。
NOTE
对于 kmip,关键区别在于:加密密钥通过 KMIP key UID 和 mutual TLS 信任链进行解析,而不是通过 Vault token。
为持久卷加密创建 StorageClass
完成 KMS 访问配置后,创建带有加密参数的 StorageClass。
前提条件
- 您有权限创建 StorageClass。
- 您知道目标 KMS 配置 ID(
<kms_config_id>)。
操作步骤
-
进入 Administrator。
-
在左侧导航栏中,点击 Storage > StorageClasses。
-
点击 Create Storage Class。
注意:以下内容是表单形式的示例,您也可以选择 YAML 完成该操作。
-
选择 CephRBD Block Storage,然后点击 Next。
-
切换到 YAML 视图
-
在参数中启用加密:
encrypted: "true"
encryptionKMSID: "<kms_config_id>"
-
点击 Create。
验证步骤
-
验证 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
使用 tenant ConfigMap 覆盖 Vault 连接详情
可以通过在 ACP namespace 中创建一个 ConfigMap 来按 tenant 重新配置 Vault 连接详情,该 ConfigMap 中的配置选项与 rook-ceph namespace 中 csi-kms-connection-details ConfigMap 的值不同。该 ConfigMap 需要位于 tenant namespace 中。tenant namespace 中 ConfigMap 的值将覆盖该 namespace 中已创建的加密 Persistent Volume 所使用的 csi-kms-connection-details ConfigMap 值。
操作步骤
-
在 ACP 控制台中,导航到 Alauda Container Platform -> Configuration -> ConfigMaps。
-
切换到目标 tenant project/namespace。
-
点击 Create ConfigMap,并将名称设置为 ceph-csi-kms-config。
-
添加 tenant 特定的 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>"
-
点击 Create。
验证步骤
-
验证 tenant 覆盖 ConfigMap:
kubectl -n <tenant_namespace> get configmap ceph-csi-kms-config -o yaml
-
在同一 namespace 中创建一个新的加密 PVC,并确认其进入 Bound。
-
如果密钥访问失败,请检查 namespace 事件和 CSI provisioner 日志中的 Vault endpoint 和 auth-path 是否不匹配。
启用和禁用密钥轮转(可选)
密钥轮转支持对加密 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
在 Control 节点上执行以下命令:
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
参数:
-
启用 CsiAddons sidecar
在 Control 节点上执行以下命令:
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
(可选)强制密钥轮转优先级
在密钥轮转中,优先级指系统检查计划注解的顺序。默认优先级设置为 storage class(推荐)。这意味着系统只读取 storage class 中的注解。
但是,如果您希望系统先检查 persistent volume claim(PVC),再回退到 storage class,可以在 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> 添加到 PersistentVolumeClaim、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"
禁用密钥轮转
您可以针对以下对象禁用密钥轮转:
- 某个 storage class 下的所有 persistent volume claims(PVCs)
- 某个特定 PVC
为某个 storage class 下的所有 PVC 禁用密钥轮转
kubectl annotate storageclass encrypted-rbd-sc \
"keyrotation.csiaddons.openshift.io/enable=false" --overwrite
为某个特定 persistent volume claim 禁用密钥轮转
-
找出您要禁用密钥轮转的 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 的密钥轮转将被禁用。