持久卷加密

概述

持久卷(PV)加密有助于保护有状态工作负载的数据机密性和租户隔离。 对于 ACP 分布式存储,CSI 置备的 PV 的静态数据加密通过外部密钥管理系统(KMS)和启用加密的 StorageClass 实现。

本章介绍如何:

  • 配置 KMS 访问凭证和连接详细信息
  • 创建启用加密的 StorageClass
  • 启用和禁用密钥轮换策略
WARNING

本章中的持久卷加密适用于 RBD 支持的 PV。不涵盖对象存储桶。

密钥管理系统(KMS)的访问配置

首先配置 KMS 访问。基于 StorageClass 的 PV 加密依赖于有效的 KMS 凭证和连接元数据。

每种提供商模式的身份验证和元数据模型不同:

模式encryptionKMSType身份验证材料
Vault 令牌模式vaulttokens存储在 Secret 中的静态 Vault 令牌
Vault 租户 ServiceAccount 模式vaulttenantsa映射到 Vault 角色的 Kubernetes ServiceAccount 身份
Thales CipherTrust Manager 模式kmipKMIP 端点 + 客户端证书链 + 密钥 UID

⚠️ 重要:Alpha 功能免责声明

使用 vaulttenantsa 访问 KMS 目前处于 Alpha 阶段,仅严格用于早期技术验证和评估。作为功能提供方,我们不对其稳定性、可靠性或数据完整性提供任何保证。通过配置和使用此功能,您确认并接受以下技术限制:

  • 不适用于生产环境: 此功能尚未经过全面的系统级验证。在生产环境中部署此功能存在较高的流程失败或数据损坏风险。
  • 不保证 SLA: 此功能不属于标准服务级别协议(SLA)的范围。我们不保证技术支持响应时间,也不提供紧急修复程序。
  • 重大变更和弃用: API 端点、配置架构和核心处理逻辑可能会在未来版本中发生不向后兼容的变化。此功能也可能在不事先通知的情况下被完全弃用。
  • 不提供平滑升级路径: 我们不提供版本之间的升级脚本或数据迁移工具。升级到后续版本通常需要完全清除现有资源并重新部署。由此造成的任何状态或数据丢失均由用户自行承担。

使用 vaulttokens 配置访问

前提条件

  • ACP 分布式存储集群处于 Ready 状态。
  • 您具有 cluster-admin 权限。
  • 集群节点可以访问 Vault。
  • 您拥有可访问目标后端路径的有效 Vault 令牌。

操作步骤

  1. 创建用于存储 Vault 令牌的 Secret。

    kubectl -n rook-ceph create secret generic ceph-csi-kms-token \
      --from-literal=token='<vault_token>'
  2. 创建或更新 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>"
        }

    参数

    参数描述必需
    encryptionKMSTypeKMS 提供商模式。对于静态 Vault 令牌身份验证,请使用 vaulttokens。是
    vaultAddressVault 服务端点,包括协议和端口。是
    vaultBackendVault Secret 引擎,默认为 kv-v2否
    vaultBackendPath用于数据加密密钥(DEK)的 Vault Secret 引擎路径。默认为 secret/否
    vaultTLSServerName用于 SNI 和证书主机名验证的 TLS 服务器名称。否
    vaultCAVerify连接到 Vault 服务器时是否需要 CA 身份验证,默认为 true否
    vaultCAFromSecret存储 Vault CA 证书的 Secret 名称。否
    vaultClientCertFromSecret存储 Vault 客户端证书的 Secret 名称。否
    vaultClientCertKeyFromSecret存储 Vault 客户端私钥的 Secret 名称。否

验证步骤

  1. 验证令牌 Secret:

    kubectl -n rook-ceph get secret ceph-csi-kms-token
  2. 验证 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 进行身份验证。

  1. 在工作负载命名空间中创建租户 ServiceAccount。

    kubectl -n <tenant_namespace> create serviceaccount ceph-csi-vault-sa
  2. 在存储命名空间中应用用于 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
  3. 为令牌审查器 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
  4. 读取审查器 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}")
  5. 在 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"
  6. 为租户命名空间创建 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 来覆盖这些默认值。
  7. 使用 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>"
        }

    参数

    参数描述必需
    encryptionKMSType设置为 vaulttenantsa,以使用服务账户向 Vault 进行身份验证。是
    vaultAddressVault 服务器的主机名或 IP 地址及端口号。是
    vaultBackendPathVault 中用于存储加密密钥的后端路径。否
    vaultTLSServerName用于验证 Vault 证书主机名的 TLS 服务器名称。否
    vaultAuthPath在 Vault 中启用 kubernetes 身份验证方法的路径。默认路径为 kubernetes。如果身份验证方法启用在不同于 kubernetes 的路径中,则需要将此变量设置为 /v1/auth/<path>/login。否
    vaultAuthNamespace启用 kubernetes 身份验证方法的 Vault 命名空间。否
    vaultNamespace存在用于存储密钥的后端路径的 Vault 命名空间。否
    vaultCAFromSecret包含 CSI 使用的 Vault CA 证书的 Secret。否
    vaultClientCertFromSecret包含用于与 Vault 建立 mTLS 连接的客户端证书的 Secret。否
    vaultClientCertKeyFromSecret包含与 vaultClientCertFromSecret 匹配的私钥的 Secret。否
    vaultRole绑定到租户 ServiceAccount 和策略的 Vault Kubernetes 身份验证角色。否
    tenantSAName工作负载使用的租户 ServiceAccount 名称,通常为 ceph-csi-vault-sa。否

验证步骤

  1. 验证 ServiceAccount 创建:

    kubectl -n <tenant_namespace> get sa ceph-csi-vault-sa
    kubectl -n rook-ceph get sa rbd-csi-vault-token-review
  2. 验证令牌审查权限:

    kubectl auth can-i create tokenreviews.authentication.k8s.io \
      --as=system:serviceaccount:rook-ceph:rbd-csi-vault-token-review
  3. 验证 ConfigMap 条目并确认 encryptionKMSType: vaulttenantsa 和 tenantSAName。

  4. 在 <tenant_namespace> 中创建测试加密 PVC,并验证其是否成功绑定。

使用 Thales CipherTrust Manager(kmip)配置访问

前提条件

  • 您可以访问已启用 KMIP 的 Thales CipherTrust Manager。
  • 您拥有 KMIP 端点(<kmip_address>:5696)、客户端证书链和密钥唯一标识符(UID)。
  • 您具有在 rook-ceph 中创建 Secret 和 ConfigMap 的权限。

操作步骤

  1. 在 Thales CipherTrust Manager 中创建 KMIP 客户端配置文件并注册客户端。

  2. 从配置文件中下载客户端证书、私钥和 CA 证书。

  3. 为 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>
  4. 创建或更新 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>"
        }

验证步骤

  1. 验证 KMIP 凭证 Secret:

    kubectl -n rook-ceph get secret thales-kmip-client
  2. 验证 ConfigMap 条目并确认 encryptionKMSType: kmip。

  3. 确认 KMS 条目中的密钥 UID 与 Thales CipherTrust Manager 中生成的密钥匹配。

NOTE

对于 kmip,关键区别在于,加密密钥通过 KMIP 密钥 UID 和双向 TLS 信任链解析,而不是通过 Vault 令牌解析。

创建用于持久卷加密的 StorageClass

配置 KMS 访问权限后,创建包含加密参数的 StorageClass。

先决条件

  • 你具有创建 StorageClass 的权限。
  • 你知道目标 KMS 配置 ID(<kms_config_id>)。

操作步骤

  1. 转到管理员。

  2. 在左侧导航栏中,点击存储 > StorageClasses。

  3. 点击创建 Storage Class。

    注意:以下内容是表单格式示例,你也可以选择 YAML 完成操作。

  4. 选择CephRBD 块存储,然后点击下一步。

  5. 切换到 YAML 视图

  6. 在参数中启用加密:

    • encrypted: "true"
    • encryptionKMSID: "<kms_config_id>"
  7. 点击创建。

验证步骤

  1. 验证 StorageClass 参数:

    kubectl get sc encrypted-rbd-sc -o yaml
  2. 确认存在 encrypted: "true" 和预期的 encryptionKMSID。

  3. 使用此 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 中为该命名空间创建的加密持久卷所设置的值。

操作步骤

  1. 在 ACP 控制台中,导航到Alauda Container Platform -> 配置 -> ConfigMaps。

  2. 切换到目标租户项目/命名空间。

  3. 点击创建 ConfigMap,并输入 ceph-csi-kms-config 作为名称。

  4. 添加特定于租户的 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>"
  5. 点击创建。

验证步骤

  1. 验证租户覆盖 ConfigMap:

    kubectl -n <tenant_namespace> get configmap ceph-csi-kms-config -o yaml
  2. 在同一命名空间中创建新的加密 PVC,并确认其达到 Bound。

  3. 如果密钥访问失败,请检查命名空间事件和 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

设置卷复制环境

  1. 设置 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 地址。
  2. 启用 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

为特定持久卷声明禁用密钥轮换

  1. 确定要禁用密钥轮换的 PVC 对应的 EncryptionKeyRotationCronJob CR:

    kubectl get encryptionkeyrotationcronjob -o jsonpath='{range .items[?(@.spec.jobTemplate.spec.target.persistentVolumeClaim=="<PVC_NAME>")]}{.metadata.name}{"\n"}{end}'

    其中,<PVC_NAME> 是要禁用密钥轮换的 PVC 名称。

  2. 对上一步中的 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
  3. 保存并退出。PVC 的密钥轮换将被禁用。