2.7. 使用外部 secret 存储为 pod 提供敏感数据


有些应用程序需要密码和用户名等敏感信息,但您不希望开发人员持有这些信息。

使用 Kubernetes Secret 对象提供敏感信息的一个替代选择是,使用外部 secret 存储来存储敏感信息。您可以使用 Secrets Store CSI Driver Operator 与外部 secret 存储集成,并将 secret 内容挂载为 pod 卷。

重要

Secret Store CSI Driver Operator 只是一个技术预览功能。技术预览功能不受红帽产品服务等级协议(SLA)支持,且功能可能并不完整。红帽不推荐在生产环境中使用它们。这些技术预览功能可以使用户提早试用新的功能,并有机会在开发阶段提供反馈意见。

有关红帽技术预览功能支持范围的更多信息,请参阅技术预览功能支持范围

2.7.1. 关于 Secret Store CSI Driver Operator

Kubernetes secret 以 Base64 编码的形式存储。etcd 为这些 secret 提供加密,但在检索 secret 时,它们会被解密并提供给用户。如果没有在集群中正确配置基于角色的访问控制,则具有 API 或 etcd 访问权限的任何人都可以检索或修改 secret。另外,有权在命名空间中创建 pod 的任何人都可以使用该命名空间中的任何 secret 来读取该命名空间中的任何 secret。

要安全地存储和管理您的 secret,您可以将 OpenShift Container Platform Secrets Store Container Storage Interface (CSI) Driver Operator 配置为使用供应商插件从外部 secret 管理系统(如 Azure Key Vault)挂载 secret。应用程序可以使用 secret,但 secret 在应用程序 pod 被销毁后不会在系统中保留。

Secret Store CSI Driver Operator(secrets-store.csi.k8s.io)允许 OpenShift Container Platform 将存储在企业级外部 secret 中的多个 secret、密钥和证书作为卷挂载到 pod 中。Secrets Store CSI Driver Operator 使用 gRPC 与供应商通信,以从指定的外部 secret 存储获取挂载内容。附加卷后,其中的数据将挂载到容器的文件系统。Secret 存储卷以 in-line 形式挂载。

2.7.1.1. Secret 存储供应商

以下 secret 存储供应商可用于 Secret Store CSI Driver Operator:

  • AWS Secrets Manager
  • AWS Systems Manager Parameter Store
  • Azure Key Vault
  • HashiCorp Vault

2.7.1.2. 自动轮转

Secrets Store CSI 驱动程序会定期使用外部 secret 存储中的内容轮转挂载卷中的内容。如果外部 secret 存储中更新了 secret,secret 将在挂载的卷中更新。Secrets Store CSI Driver Operator 每 2 分钟轮询一次更新。

如果启用了将挂载内容作为 Kubernetes secret 同步,则 Kubernetes secret 也会被轮转。

使用 secret 数据的应用程序必须监视是否有对 secret 的更新。

2.7.2. 安装 Secret Store CSI 驱动程序

先决条件

  • 访问 OpenShift Container Platform Web 控制台。
  • 集群的管理员访问权限。

流程

安装 Secret Store CSI 驱动程序:

  1. 安装 Secret Store CSI Driver Operator:

    1. 登录到 web 控制台。
    2. Operators OperatorHub
    3. 通过在过滤器框中输入 "Secrets Store CSI" 来查找 Secrets Store CSI Driver Operator。
    4. Secrets Store CSI Driver Operator 按钮。
    5. Secrets Store CSI Driver Operator 页面中,点 Install
    6. Install Operator 页面中,确保:

      • 选择 All namespaces on the cluster (default)
      • 安装的命名空间 被设置为 openshift-cluster-csi-drivers
    7. Install

      安装完成后,Secret Store CSI Driver Operator 会在 web 控制台的 Installed Operators 部分列出。

  2. 为驱动程序创建 ClusterCSIDriver 实例 (secrets-store.csi.k8s.io):

    1. Administration CustomResourceDefinitions ClusterCSIDriver
    2. Instances 选项卡上,单击 Create ClusterCSIDriver

      使用以下 YAML 文件:

      apiVersion: operator.openshift.io/v1
      kind: ClusterCSIDriver
      metadata:
          name: secrets-store.csi.k8s.io
      spec:
        managementState: Managed
    3. Create

2.7.3. 将 secret 从外部 secret 存储挂载到 CSI 卷

安装 Secret Store CSI Driver Operator 后,您可以将 secret 从以下外部 secret 存储挂载到 CSI 卷:

2.7.3.1. 从 AWS Secrets Manager 挂载 secret

您可以使用 Secrets Store CSI Driver Operator 将 secret 从 AWS Secrets Manager 挂载到 OpenShift Container Platform 中的 CSI 卷。要从 AWS Secrets Manager 挂载 secret,您的集群必须安装在 AWS 上,并使用 AWS 安全令牌服务 (STS)。

先决条件

  • 您的集群安装在 AWS 上,并使用 AWS 安全令牌服务 (STS)。
  • 已安装 Secrets Store CSI Driver Operator。具体步骤请参阅 安装 Secret Store CSI 驱动程序
  • 您已将 AWS Secrets Manager 配置为存储所需的 secret。
  • 您已提取并准备好 ccoctl 二进制文件。
  • 已安装 jq CLI 工具。
  • 您可以使用具有 cluster-admin 角色的用户访问集群。

流程

  1. 安装 AWS Secrets Manager 供应商:

    1. 使用供应商资源的以下配置创建一个 YAML 文件:

      重要

      Secret Store CSI 驱动程序的 AWS Secrets Manager 供应商是一个上游供应商。

      此配置会根据上游 AWS 文档中提供的配置进行修改,以便它可以与 OpenShift Container Platform 正常工作。对此配置的更改可能会影响功能。

      aws-provider.yaml 文件示例

      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: csi-secrets-store-provider-aws
        namespace: openshift-cluster-csi-drivers
      ---
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRole
      metadata:
        name: csi-secrets-store-provider-aws-cluster-role
      rules:
      - apiGroups: [""]
        resources: ["serviceaccounts/token"]
        verbs: ["create"]
      - apiGroups: [""]
        resources: ["serviceaccounts"]
        verbs: ["get"]
      - apiGroups: [""]
        resources: ["pods"]
        verbs: ["get"]
      - apiGroups: [""]
        resources: ["nodes"]
        verbs: ["get"]
      ---
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRoleBinding
      metadata:
        name: csi-secrets-store-provider-aws-cluster-rolebinding
      roleRef:
        apiGroup: rbac.authorization.k8s.io
        kind: ClusterRole
        name: csi-secrets-store-provider-aws-cluster-role
      subjects:
      - kind: ServiceAccount
        name: csi-secrets-store-provider-aws
        namespace: openshift-cluster-csi-drivers
      ---
      apiVersion: apps/v1
      kind: DaemonSet
      metadata:
        namespace: openshift-cluster-csi-drivers
        name: csi-secrets-store-provider-aws
        labels:
          app: csi-secrets-store-provider-aws
      spec:
        updateStrategy:
          type: RollingUpdate
        selector:
          matchLabels:
            app: csi-secrets-store-provider-aws
        template:
          metadata:
            labels:
              app: csi-secrets-store-provider-aws
          spec:
            serviceAccountName: csi-secrets-store-provider-aws
            hostNetwork: false
            containers:
              - name: provider-aws-installer
                image: public.ecr.aws/aws-secrets-manager/secrets-store-csi-driver-provider-aws:1.0.r2-50-g5b4aca1-2023.06.09.21.19
                imagePullPolicy: Always
                args:
                    - --provider-volume=/etc/kubernetes/secrets-store-csi-providers
                resources:
                  requests:
                    cpu: 50m
                    memory: 100Mi
                  limits:
                    cpu: 50m
                    memory: 100Mi
                securityContext:
                  privileged: true
                volumeMounts:
                  - mountPath: "/etc/kubernetes/secrets-store-csi-providers"
                    name: providervol
                  - name: mountpoint-dir
                    mountPath: /var/lib/kubelet/pods
                    mountPropagation: HostToContainer
            tolerations:
            - operator: Exists
            volumes:
              - name: providervol
                hostPath:
                  path: "/etc/kubernetes/secrets-store-csi-providers"
              - name: mountpoint-dir
                hostPath:
                  path: /var/lib/kubelet/pods
                  type: DirectoryOrCreate
            nodeSelector:
              kubernetes.io/os: linux

    2. 运行以下命令,授予 csi-secrets-store-provider-aws 服务帐户的特权访问权限:

      $ oc adm policy add-scc-to-user privileged -z csi-secrets-store-provider-aws -n openshift-cluster-csi-drivers
    3. 运行以下命令来创建供应商资源:

      $ oc apply -f aws-provider.yaml
  2. 授予服务帐户读取 AWS secret 对象的权限:

    1. 运行以下命令,创建一个目录使其包含凭证请求:

      $ mkdir credentialsrequest-dir-aws
    2. 使用以下配置为凭证请求创建 YAML 文件:

      credentialsrequest.yaml 文件示例

      apiVersion: cloudcredential.openshift.io/v1
      kind: CredentialsRequest
      metadata:
        name: aws-provider-test
        namespace: openshift-cloud-credential-operator
      spec:
        providerSpec:
          apiVersion: cloudcredential.openshift.io/v1
          kind: AWSProviderSpec
          statementEntries:
          - action:
            - "secretsmanager:GetSecretValue"
            - "secretsmanager:DescribeSecret"
            effect: Allow
            resource: "arn:*:secretsmanager:*:*:secret:testSecret-??????"
        secretRef:
          name: aws-creds
          namespace: my-namespace
        serviceAccountNames:
        - aws-provider

    3. 运行以下命令来检索 OIDC 供应商:

      $ oc get --raw=/.well-known/openid-configuration | jq -r '.issuer'

      输出示例

      https://<oidc_provider_name>

      从输出中复制 OIDC 供应商名称 <oidc_provider_name>,在下一步中使用。

    4. 运行以下命令,使用 ccoctl 工具处理凭证请求:

      $ ccoctl aws create-iam-roles \
          --name my-role --region=<aws_region> \
          --credentials-requests-dir=credentialsrequest-dir-aws \
          --identity-provider-arn arn:aws:iam::<aws_account>:oidc-provider/<oidc_provider_name> --output-dir=credrequests-ccoctl-output

      输出示例

      2023/05/15 18:10:34 Role arn:aws:iam::<aws_account_id>:role/my-role-my-namespace-aws-creds created
      2023/05/15 18:10:34 Saved credentials configuration to: credrequests-ccoctl-output/manifests/my-namespace-aws-creds-credentials.yaml
      2023/05/15 18:10:35 Updated Role policy for Role my-role-my-namespace-aws-creds

      从输出中复制 <aws_role_arn> 以在下一步中使用。例如,arn:aws:iam::<aws_account_id>:role/my-role-my-namespace-aws-creds

    5. 运行以下命令,使用角色 ARN 绑定服务帐户:

      $ oc annotate -n my-namespace sa/aws-provider eks.amazonaws.com/role-arn="<aws_role_arn>"
  3. 创建 secret 供应商类以定义您的 secret 存储供应商:

    1. 创建定义 SecretProviderClass 对象的 YAML 文件:

      secret-provider-class-aws.yaml示例

      apiVersion: secrets-store.csi.x-k8s.io/v1
      kind: SecretProviderClass
      metadata:
        name: my-aws-provider                   1
        namespace: my-namespace                 2
      spec:
        provider: aws                           3
        parameters:                             4
          objects: |
            - objectName: "testSecret"
              objectType: "secretsmanager"

      1 1
      指定 secret 供应商类的名称。
      2
      指定 secret 供应商类的命名空间。
      3
      将供应商指定为 aws
      4
      指定特定于供应商的配置参数。
    2. 运行以下命令来创建 SecretProviderClass 对象:

      $ oc create -f secret-provider-class-aws.yaml
  4. 创建部署以使用此 secret 供应商类:

    1. 创建定义 Deployment 对象的 YAML 文件:

      deployment.yaml 示例

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: my-aws-deployment                              1
        namespace: my-namespace                              2
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: my-storage
        template:
          metadata:
            labels:
              app: my-storage
          spec:
            serviceAccountName: aws-provider
            containers:
            - name: busybox
              image: k8s.gcr.io/e2e-test-images/busybox:1.29
              command:
                - "/bin/sleep"
                - "10000"
              volumeMounts:
              - name: secrets-store-inline
                mountPath: "/mnt/secrets-store"
                readOnly: true
            volumes:
              - name: secrets-store-inline
                csi:
                  driver: secrets-store.csi.k8s.io
                  readOnly: true
                  volumeAttributes:
                    secretProviderClass: "my-aws-provider" 3

      1
      指定部署的名称。
      2
      指定部署的命名空间。这必须与 secret 供应商类相同。
      3
      指定 secret 供应商类的名称。
    2. 运行以下命令来创建 Deployment 对象:

      $ oc create -f deployment.yaml

验证

  • 验证您可以从 pod 卷挂载中的 AWS Secrets Manager 访问 secret:

    1. 列出 pod 挂载中的 secret:

      $ oc exec busybox-<hash> -n my-namespace -- ls /mnt/secrets-store/

      输出示例

      testSecret

    2. 查看 pod 挂载中的 secret:

      $ oc exec busybox-<hash> -n my-namespace -- cat /mnt/secrets-store/testSecret

      输出示例

      <secret_value>

2.7.3.2. 从 AWS Systems Manager Parameter Store 中挂载 secret

您可以使用 Secrets Store CSI Driver Operator 将 secret 从 AWS Systems Manager Parameter Store 挂载到 OpenShift Container Platform 中的 CSI 卷。要从 AWS Systems Manager Parameter Store 挂载 secret,您的集群必须安装在 AWS 上,并使用 AWS 安全令牌服务(STS)。

先决条件

  • 您的集群安装在 AWS 上,并使用 AWS 安全令牌服务 (STS)。
  • 已安装 Secrets Store CSI Driver Operator。具体步骤请参阅 安装 Secret Store CSI 驱动程序
  • 您已配置了 AWS Systems Manager Parameter Store 以存储所需的 secret。
  • 您已提取并准备好 ccoctl 二进制文件。
  • 已安装 jq CLI 工具。
  • 您可以使用具有 cluster-admin 角色的用户访问集群。

流程

  1. 安装 AWS Systems Manager Parameter Store 供应商:

    1. 使用供应商资源的以下配置创建一个 YAML 文件:

      重要

      Secret Store CSI 驱动程序的 AWS Systems Manager Parameter Store 供应商是一个上游供应商。

      此配置会根据上游 AWS 文档中提供的配置进行修改,以便它可以与 OpenShift Container Platform 正常工作。对此配置的更改可能会影响功能。

      aws-provider.yaml 文件示例

      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: csi-secrets-store-provider-aws
        namespace: openshift-cluster-csi-drivers
      ---
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRole
      metadata:
        name: csi-secrets-store-provider-aws-cluster-role
      rules:
      - apiGroups: [""]
        resources: ["serviceaccounts/token"]
        verbs: ["create"]
      - apiGroups: [""]
        resources: ["serviceaccounts"]
        verbs: ["get"]
      - apiGroups: [""]
        resources: ["pods"]
        verbs: ["get"]
      - apiGroups: [""]
        resources: ["nodes"]
        verbs: ["get"]
      ---
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRoleBinding
      metadata:
        name: csi-secrets-store-provider-aws-cluster-rolebinding
      roleRef:
        apiGroup: rbac.authorization.k8s.io
        kind: ClusterRole
        name: csi-secrets-store-provider-aws-cluster-role
      subjects:
      - kind: ServiceAccount
        name: csi-secrets-store-provider-aws
        namespace: openshift-cluster-csi-drivers
      ---
      apiVersion: apps/v1
      kind: DaemonSet
      metadata:
        namespace: openshift-cluster-csi-drivers
        name: csi-secrets-store-provider-aws
        labels:
          app: csi-secrets-store-provider-aws
      spec:
        updateStrategy:
          type: RollingUpdate
        selector:
          matchLabels:
            app: csi-secrets-store-provider-aws
        template:
          metadata:
            labels:
              app: csi-secrets-store-provider-aws
          spec:
            serviceAccountName: csi-secrets-store-provider-aws
            hostNetwork: false
            containers:
              - name: provider-aws-installer
                image: public.ecr.aws/aws-secrets-manager/secrets-store-csi-driver-provider-aws:1.0.r2-50-g5b4aca1-2023.06.09.21.19
                imagePullPolicy: Always
                args:
                    - --provider-volume=/etc/kubernetes/secrets-store-csi-providers
                resources:
                  requests:
                    cpu: 50m
                    memory: 100Mi
                  limits:
                    cpu: 50m
                    memory: 100Mi
                securityContext:
                  privileged: true
                volumeMounts:
                  - mountPath: "/etc/kubernetes/secrets-store-csi-providers"
                    name: providervol
                  - name: mountpoint-dir
                    mountPath: /var/lib/kubelet/pods
                    mountPropagation: HostToContainer
            tolerations:
            - operator: Exists
            volumes:
              - name: providervol
                hostPath:
                  path: "/etc/kubernetes/secrets-store-csi-providers"
              - name: mountpoint-dir
                hostPath:
                  path: /var/lib/kubelet/pods
                  type: DirectoryOrCreate
            nodeSelector:
              kubernetes.io/os: linux

    2. 运行以下命令,授予 csi-secrets-store-provider-aws 服务帐户的特权访问权限:

      $ oc adm policy add-scc-to-user privileged -z csi-secrets-store-provider-aws -n openshift-cluster-csi-drivers
    3. 运行以下命令来创建供应商资源:

      $ oc apply -f aws-provider.yaml
  2. 授予服务帐户读取 AWS secret 对象的权限:

    1. 运行以下命令,创建一个目录使其包含凭证请求:

      $ mkdir credentialsrequest-dir-aws
    2. 使用以下配置为凭证请求创建 YAML 文件:

      credentialsrequest.yaml 文件示例

      apiVersion: cloudcredential.openshift.io/v1
      kind: CredentialsRequest
      metadata:
        name: aws-provider-test
        namespace: openshift-cloud-credential-operator
      spec:
        providerSpec:
          apiVersion: cloudcredential.openshift.io/v1
          kind: AWSProviderSpec
          statementEntries:
          - action:
            - "ssm:GetParameter"
            - "ssm:GetParameters"
            effect: Allow
            resource: "arn:*:ssm:*:*:parameter/testParameter*"
        secretRef:
          name: aws-creds
          namespace: my-namespace
        serviceAccountNames:
        - aws-provider

    3. 运行以下命令来检索 OIDC 供应商:

      $ oc get --raw=/.well-known/openid-configuration | jq -r '.issuer'

      输出示例

      https://<oidc_provider_name>

      从输出中复制 OIDC 供应商名称 <oidc_provider_name>,在下一步中使用。

    4. 运行以下命令,使用 ccoctl 工具处理凭证请求:

      $ ccoctl aws create-iam-roles \
          --name my-role --region=<aws_region> \
          --credentials-requests-dir=credentialsrequest-dir-aws \
          --identity-provider-arn arn:aws:iam::<aws_account>:oidc-provider/<oidc_provider_name> --output-dir=credrequests-ccoctl-output

      输出示例

      2023/05/15 18:10:34 Role arn:aws:iam::<aws_account_id>:role/my-role-my-namespace-aws-creds created
      2023/05/15 18:10:34 Saved credentials configuration to: credrequests-ccoctl-output/manifests/my-namespace-aws-creds-credentials.yaml
      2023/05/15 18:10:35 Updated Role policy for Role my-role-my-namespace-aws-creds

      从输出中复制 <aws_role_arn> 以在下一步中使用。例如,arn:aws:iam::<aws_account_id>:role/my-role-my-namespace-aws-creds

    5. 运行以下命令,使用角色 ARN 绑定服务帐户:

      $ oc annotate -n my-namespace sa/aws-provider eks.amazonaws.com/role-arn="<aws_role_arn>"
  3. 创建 secret 供应商类以定义您的 secret 存储供应商:

    1. 创建定义 SecretProviderClass 对象的 YAML 文件:

      secret-provider-class-aws.yaml示例

      apiVersion: secrets-store.csi.x-k8s.io/v1
      kind: SecretProviderClass
      metadata:
        name: my-aws-provider                   1
        namespace: my-namespace                 2
      spec:
        provider: aws                           3
        parameters:                             4
          objects: |
            - objectName: "testParameter"
              objectType: "ssmparameter"

      1
      指定 secret 供应商类的名称。
      2
      指定 secret 供应商类的命名空间。
      3
      将供应商指定为 aws
      4
      指定特定于供应商的配置参数。
    2. 运行以下命令来创建 SecretProviderClass 对象:

      $ oc create -f secret-provider-class-aws.yaml
  4. 创建部署以使用此 secret 供应商类:

    1. 创建定义 Deployment 对象的 YAML 文件:

      deployment.yaml 示例

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: my-aws-deployment                              1
        namespace: my-namespace                              2
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: my-storage
        template:
          metadata:
            labels:
              app: my-storage
          spec:
            serviceAccountName: aws-provider
            containers:
            - name: busybox
              image: k8s.gcr.io/e2e-test-images/busybox:1.29
              command:
                - "/bin/sleep"
                - "10000"
              volumeMounts:
              - name: secrets-store-inline
                mountPath: "/mnt/secrets-store"
                readOnly: true
            volumes:
              - name: secrets-store-inline
                csi:
                  driver: secrets-store.csi.k8s.io
                  readOnly: true
                  volumeAttributes:
                    secretProviderClass: "my-aws-provider" 3

      1
      指定部署的名称。
      2
      指定部署的命名空间。这必须与 secret 供应商类相同。
      3
      指定 secret 供应商类的名称。
    2. 运行以下命令来创建 Deployment 对象:

      $ oc create -f deployment.yaml

验证

  • 验证您可以从 pod 卷挂载中的 AWS Systems Manager Parameter Store 访问 secret:

    1. 列出 pod 挂载中的 secret:

      $ oc exec busybox-<hash> -n my-namespace -- ls /mnt/secrets-store/

      输出示例

      testParameter

    2. 查看 pod 挂载中的 secret:

      $ oc exec busybox-<hash> -n my-namespace -- cat /mnt/secrets-store/testSecret

      输出示例

      <secret_value>

2.7.3.3. 从 Azure Key Vault 挂载 secret

您可以使用 Secrets Store CSI Driver Operator 将 secret 从 Azure Key Vault 挂载到 OpenShift Container Platform 中的 CSI 卷。要从 Azure Key Vault 挂载 secret,您的集群必须安装在 Microsoft Azure 上。

先决条件

  • 集群安装在 Azure 上。
  • 已安装 Secrets Store CSI Driver Operator。具体步骤请参阅 安装 Secret Store CSI 驱动程序
  • 您已将 Azure Key Vault 配置为存储所需的 secret。
  • 已安装 Azure CLI (az)。
  • 您可以使用具有 cluster-admin 角色的用户访问集群。

流程

  1. 安装 Azure Key Vault 供应商:

    1. 使用供应商资源的以下配置创建一个 YAML 文件:

      重要

      Secrets Store CSI 驱动程序的 Azure Key Vault 供应商是一个上游供应商。

      此配置会根据上游 Azure 文档中提供的配置进行修改,以便它可以与 OpenShift Container Platform 正常工作。对此配置的更改可能会影响功能。

      azure-provider.yaml 文件示例

      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: csi-secrets-store-provider-azure
        namespace: openshift-cluster-csi-drivers
      ---
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRole
      metadata:
        name: csi-secrets-store-provider-azure-cluster-role
      rules:
      - apiGroups: [""]
        resources: ["serviceaccounts/token"]
        verbs: ["create"]
      - apiGroups: [""]
        resources: ["serviceaccounts"]
        verbs: ["get"]
      - apiGroups: [""]
        resources: ["pods"]
        verbs: ["get"]
      - apiGroups: [""]
        resources: ["nodes"]
        verbs: ["get"]
      ---
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRoleBinding
      metadata:
        name: csi-secrets-store-provider-azure-cluster-rolebinding
      roleRef:
        apiGroup: rbac.authorization.k8s.io
        kind: ClusterRole
        name: csi-secrets-store-provider-azure-cluster-role
      subjects:
      - kind: ServiceAccount
        name: csi-secrets-store-provider-azure
        namespace: openshift-cluster-csi-drivers
      ---
      apiVersion: apps/v1
      kind: DaemonSet
      metadata:
        namespace: openshift-cluster-csi-drivers
        name: csi-secrets-store-provider-azure
        labels:
          app: csi-secrets-store-provider-azure
      spec:
        updateStrategy:
          type: RollingUpdate
        selector:
          matchLabels:
            app: csi-secrets-store-provider-azure
        template:
          metadata:
            labels:
              app: csi-secrets-store-provider-azure
          spec:
            serviceAccountName: csi-secrets-store-provider-azure
            hostNetwork: true
            containers:
              - name: provider-azure-installer
                image: mcr.microsoft.com/oss/azure/secrets-store/provider-azure:v1.4.1
                imagePullPolicy: IfNotPresent
                args:
                  - --endpoint=unix:///provider/azure.sock
                  - --construct-pem-chain=true
                  - --healthz-port=8989
                  - --healthz-path=/healthz
                  - --healthz-timeout=5s
                livenessProbe:
                  httpGet:
                    path: /healthz
                    port: 8989
                  failureThreshold: 3
                  initialDelaySeconds: 5
                  timeoutSeconds: 10
                  periodSeconds: 30
                resources:
                  requests:
                    cpu: 50m
                    memory: 100Mi
                  limits:
                    cpu: 50m
                    memory: 100Mi
                securityContext:
                  allowPrivilegeEscalation: false
                  readOnlyRootFilesystem: true
                  runAsUser: 0
                  capabilities:
                    drop:
                    - ALL
                volumeMounts:
                  - mountPath: "/provider"
                    name: providervol
            affinity:
              nodeAffinity:
                requiredDuringSchedulingIgnoredDuringExecution:
                  nodeSelectorTerms:
                  - matchExpressions:
                    - key: type
                      operator: NotIn
                      values:
                      - virtual-kubelet
            volumes:
              - name: providervol
                hostPath:
                  path: "/var/run/secrets-store-csi-providers"
            tolerations:
            - operator: Exists
            nodeSelector:
              kubernetes.io/os: linux

    2. 运行以下命令,授予 csi-secrets-store-provider-azure 服务帐户的特权访问权限:

      $ oc adm policy add-scc-to-user privileged -z csi-secrets-store-provider-azure -n openshift-cluster-csi-drivers
    3. 运行以下命令来创建供应商资源:

      $ oc apply -f azure-provider.yaml
  2. 创建服务主体来访问密钥库:

    1. 运行以下命令,将服务主体客户端 secret 设置为环境变量:

      $ SERVICE_PRINCIPAL_CLIENT_SECRET="$(az ad sp create-for-rbac --name https://$KEYVAULT_NAME --query 'password' -otsv)"
    2. 运行以下命令,将服务主体客户端 ID 设置为环境变量:

      $ SERVICE_PRINCIPAL_CLIENT_ID="$(az ad sp list --display-name https://$KEYVAULT_NAME --query '[0].appId' -otsv)"
    3. 运行以下命令,使用服务主体客户端 secret 和 ID 创建通用 secret:

      $ oc create secret generic secrets-store-creds -n my-namespace --from-literal clientid=${SERVICE_PRINCIPAL_CLIENT_ID} --from-literal clientsecret=${SERVICE_PRINCIPAL_CLIENT_SECRET}
    4. 应用 secrets-store.csi.k8s.io/used=true 标签,以允许供应商查找此 nodePublishSecretRef secret:

      $ oc -n my-namespace label secret secrets-store-creds secrets-store.csi.k8s.io/used=true
  3. 创建 secret 供应商类以定义您的 secret 存储供应商:

    1. 创建定义 SecretProviderClass 对象的 YAML 文件:

      secret-provider-class-azure.yaml 示例

      apiVersion: secrets-store.csi.x-k8s.io/v1
      kind: SecretProviderClass
      metadata:
        name: my-azure-provider                 1
        namespace: my-namespace                 2
      spec:
        provider: azure                         3
        parameters:                             4
          usePodIdentity: "false"
          useVMManagedIdentity: "false"
          userAssignedIdentityID: ""
          keyvaultName: "kvname"
          objects: |
            array:
              - |
                objectName: secret1
                objectType: secret
          tenantId: "tid"

      1
      指定 secret 供应商类的名称。
      2
      指定 secret 供应商类的命名空间。
      3
      将供应商指定为 azure
      4
      指定特定于供应商的配置参数。
    2. 运行以下命令来创建 SecretProviderClass 对象:

      $ oc create -f secret-provider-class-azure.yaml
  4. 创建部署以使用此 secret 供应商类:

    1. 创建定义 Deployment 对象的 YAML 文件:

      deployment.yaml 示例

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: my-azure-deployment                            1
        namespace: my-namespace                              2
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: my-storage
        template:
          metadata:
            labels:
              app: my-storage
          spec:
            containers:
            - name: busybox
              image: k8s.gcr.io/e2e-test-images/busybox:1.29
              command:
                - "/bin/sleep"
                - "10000"
              volumeMounts:
              - name: secrets-store-inline
                mountPath: "/mnt/secrets-store"
                readOnly: true
            volumes:
              - name: secrets-store-inline
                csi:
                  driver: secrets-store.csi.k8s.io
                  readOnly: true
                  volumeAttributes:
                    secretProviderClass: "my-azure-provider" 3
                  nodePublishSecretRef:
                    name: secrets-store-creds                4

      1
      指定部署的名称。
      2
      指定部署的命名空间。这必须与 secret 供应商类相同。
      3
      指定 secret 供应商类的名称。
      4
      指定包含用于访问 Azure Key Vault 的服务主体凭证的 Kubernetes secret 名称。
    2. 运行以下命令来创建 Deployment 对象:

      $ oc create -f deployment.yaml

验证

  • 验证您可以从 pod 卷挂载中的 Azure Key Vault 访问 secret:

    1. 列出 pod 挂载中的 secret:

      $ oc exec busybox-<hash> -n my-namespace -- ls /mnt/secrets-store/

      输出示例

      secret1

    2. 查看 pod 挂载中的 secret:

      $ oc exec busybox-<hash> -n my-namespace -- cat /mnt/secrets-store/secret1

      输出示例

      my-secret-value

2.7.3.4. 从 HashiCorp Vault 挂载 secret

您可以使用 Secrets Store CSI Driver Operator 将 secret 从 HashiCorp Vault 挂载到 OpenShift Container Platform 中的 CSI 卷。

重要

使用 Secrets Store CSI Driver Operator 从 HashiCorp Vault 挂载 secret 已使用以下云供应商测试:

  • Amazon Web Services (AWS)
  • Microsoft Azure

其他云供应商可能可以正常工作,但还没有测试。以后可能会测试其他云供应商。

先决条件

  • 已安装 Secrets Store CSI Driver Operator。具体步骤请参阅 安装 Secret Store CSI 驱动程序
  • 您已安装 Helm。
  • 您可以使用具有 cluster-admin 角色的用户访问集群。

流程

  1. 运行以下命令来添加 HashiCorp Helm 仓库:

    $ helm repo add hashicorp https://helm.releases.hashicorp.com
  2. 运行以下命令,更新所有仓库以确保 Helm 了解最新版本:

    $ helm repo update
  3. 安装 HashiCorp Vault 供应商:

    1. 运行以下命令,为 Vault 创建一个新项目:

      $ oc new-project vault
    2. 运行以下命令,为 pod 安全准入标记 vault 命名空间:

      $ oc label ns vault security.openshift.io/scc.podSecurityLabelSync=false pod-security.kubernetes.io/enforce=privileged pod-security.kubernetes.io/audit=privileged pod-security.kubernetes.io/warn=privileged --overwrite
    3. 运行以下命令,授予 vault 服务帐户的特权访问权限:

      $ oc adm policy add-scc-to-user privileged -z vault -n vault
    4. 运行以下命令,授予 vault-csi-provider 服务帐户的访问权限:

      $ oc adm policy add-scc-to-user privileged -z vault-csi-provider -n vault
    5. 运行以下命令来部署 HashiCorp Vault:

      $ helm install vault hashicorp/vault --namespace=vault \
        --set "server.dev.enabled=true" \
        --set "injector.enabled=false" \
        --set "csi.enabled=true" \
        --set "global.openshift=true" \
        --set "injector.agentImage.repository=docker.io/hashicorp/vault" \
        --set "server.image.repository=docker.io/hashicorp/vault" \
        --set "csi.image.repository=docker.io/hashicorp/vault-csi-provider" \
        --set "csi.agent.image.repository=docker.io/hashicorp/vault" \
        --set "csi.daemonSet.providersDir=/var/run/secrets-store-csi-providers"
    6. 运行以下命令,修补 vault-csi-driver 守护进程,将 securityContext 设置为 privileged

      $ oc patch daemonset -n vault vault-csi-provider --type='json' -p='[{"op": "add", "path": "/spec/template/spec/containers/0/securityContext", "value": {"privileged": true} }]'
    7. 运行以下命令,验证 vault-csi-provider pod 是否已正确启动:

      $ oc get pods -n vault

      输出示例

      NAME                       READY   STATUS    RESTARTS   AGE
      vault-0                    1/1     Running   0          24m
      vault-csi-provider-87rgw   1/2     Running   0          5s
      vault-csi-provider-bd6hp   1/2     Running   0          4s
      vault-csi-provider-smlv7   1/2     Running   0          5s

  4. 配置 HashiCorp Vault 以存储所需的 secret:

    1. 运行以下命令来创建 secret:

      $ oc exec vault-0 --namespace=vault -- vault kv put secret/example1 testSecret1=my-secret-value
    2. 运行以下命令,验证 secret/example1 的路径是否可读:

      $ oc exec vault-0 --namespace=vault -- vault kv get secret/example1

      输出示例

      = Secret Path =
      secret/data/example1
      
      ======= Metadata =======
      Key                Value
      ---                -----
      created_time       2024-04-05T07:05:16.713911211Z
      custom_metadata    <nil>
      deletion_time      n/a
      destroyed          false
      version            1
      
      === Data ===
      Key            Value
      ---            -----
      testSecret1    my-secret-value

  5. 将 Vault 配置为使用 Kubernetes 身份验证:

    1. 运行以下命令来启用 Kubernetes auth 方法:

      $ oc exec vault-0 --namespace=vault -- vault auth enable kubernetes

      输出示例

      Success! Enabled kubernetes auth method at: kubernetes/

    2. 配置 Kubernetes auth 方法:

      1. 运行以下命令,将令牌查看器设置为环境变量:

        $ TOKEN_REVIEWER_JWT="$(oc exec vault-0 --namespace=vault -- cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
      2. 运行以下命令,将 Kubernetes 服务 IP 地址设置为环境变量:

        $ KUBERNETES_SERVICE_IP="$(oc get svc kubernetes -o go-template="{{ .spec.clusterIP }}")"
      3. 运行以下命令来更新 Kubernetes auth 方法:

        $ oc exec -i vault-0 --namespace=vault -- vault write auth/kubernetes/config \
          issuer="https://kubernetes.default.svc.cluster.local" \
          token_reviewer_jwt="${TOKEN_REVIEWER_JWT}" \
          kubernetes_host="https://${KUBERNETES_SERVICE_IP}:443" \
          kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt

        输出示例

        Success! Data written to: auth/kubernetes/config

    3. 运行以下命令,为应用程序创建一个策略:

      $ oc exec -i vault-0 --namespace=vault -- vault policy write csi -<<EOF
        path "secret/data/*" {
        capabilities = ["read"]
        }
        EOF

      输出示例

      Success! Uploaded policy: csi

    4. 运行以下命令,创建一个身份验证角色来访问应用程序:

      $ oc exec -i vault-0 --namespace=vault -- vault write auth/kubernetes/role/csi \
        bound_service_account_names=default \
        bound_service_account_namespaces=default,test-ns,negative-test-ns,my-namespace \
        policies=csi \
        ttl=20m

      输出示例

      Success! Data written to: auth/kubernetes/role/csi

    5. 运行以下命令,验证所有 vault pod 是否都正常运行:

      $ oc get pods -n vault

      输出示例

      NAME                       READY   STATUS    RESTARTS   AGE
      vault-0                    1/1     Running   0          43m
      vault-csi-provider-87rgw   2/2     Running   0          19m
      vault-csi-provider-bd6hp   2/2     Running   0          19m
      vault-csi-provider-smlv7   2/2     Running   0          19m

    6. 运行以下命令,验证所有 secrets-store-csi-driver pod 是否正常运行:

      $ oc get pods -n openshift-cluster-csi-drivers | grep -E "secrets"

      输出示例

      secrets-store-csi-driver-node-46d2g                  3/3     Running   0             45m
      secrets-store-csi-driver-node-d2jjn                  3/3     Running   0             45m
      secrets-store-csi-driver-node-drmt4                  3/3     Running   0             45m
      secrets-store-csi-driver-node-j2wlt                  3/3     Running   0             45m
      secrets-store-csi-driver-node-v9xv4                  3/3     Running   0             45m
      secrets-store-csi-driver-node-vlz28                  3/3     Running   0             45m
      secrets-store-csi-driver-operator-84bd699478-fpxrw   1/1     Running   0             47m

  6. 创建 secret 供应商类以定义您的 secret 存储供应商:

    1. 创建定义 SecretProviderClass 对象的 YAML 文件:

      secret-provider-class-vault.yaml 示例

      apiVersion: secrets-store.csi.x-k8s.io/v1
      kind: SecretProviderClass
      metadata:
        name: my-vault-provider                   1
        namespace: my-namespace                   2
      spec:
        provider: vault                           3
        parameters:                               4
          roleName: "csi"
          vaultAddress: "http://vault.vault:8200"
          objects:  |
            - secretPath: "secret/data/example1"
              objectName: "testSecret1"
              secretKey: "testSecret1

      1
      指定 secret 供应商类的名称。
      2
      指定 secret 供应商类的命名空间。
      3
      将提供程序指定为 vault
      4
      指定特定于供应商的配置参数。
    2. 运行以下命令来创建 SecretProviderClass 对象:

      $ oc create -f secret-provider-class-vault.yaml
  7. 创建部署以使用此 secret 供应商类:

    1. 创建定义 Deployment 对象的 YAML 文件:

      deployment.yaml 示例

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: busybox-deployment                                    1
        namespace: my-namespace                                     2
        labels:
          app: busybox
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: busybox
        template:
          metadata:
            labels:
              app: busybox
          spec:
            terminationGracePeriodSeconds: 0
            containers:
            - image: registry.k8s.io/e2e-test-images/busybox:1.29-4
              name: busybox
              imagePullPolicy: IfNotPresent
              command:
              - "/bin/sleep"
              - "10000"
              volumeMounts:
              - name: secrets-store-inline
                mountPath: "/mnt/secrets-store"
                readOnly: true
            volumes:
              - name: secrets-store-inline
                csi:
                  driver: secrets-store.csi.k8s.io
                  readOnly: true
                  volumeAttributes:
                    secretProviderClass: "my-vault-provider"        3

      1
      指定部署的名称。
      2
      指定部署的命名空间。这必须与 secret 供应商类相同。
      3
      指定 secret 供应商类的名称。
    2. 运行以下命令来创建 Deployment 对象:

      $ oc create -f deployment.yaml

验证

  • 验证您是否可以从 pod 卷挂载中的 HashiCorp Vault 访问 secret:

    1. 运行以下命令,列出 pod 挂载中的 secret:

      $ oc exec busybox-<hash> -n my-namespace -- ls /mnt/secrets-store/

      输出示例

      testSecret1

    2. 运行以下命令,查看 pod 挂载中的 secret:

      $ oc exec busybox-<hash> -n my-namespace -- cat /mnt/secrets-store/testSecret1

      输出示例

      my-secret-value

2.7.4. 启用对作为 Kubernetes secret 挂载的内容进行同步

您可以启用同步,从挂载的卷中的内容创建 Kubernetes secret。您可能要启用同步的示例是使用部署中的环境变量来引用 Kubernetes secret。

警告

如果您不想将 secret 存储在 OpenShift Container Platform 集群和 etcd 中,请不要启用同步。仅在需要它时启用此功能,比如当您想要使用环境变量来引用 secret 时。

如果启用了同步,在启动挂载 secret 的 pod 后,来自挂载卷的 secret 会同步为 Kubernetes secret。

当所有挂载内容的 pod 被删除时,同步的 Kubernetes secret 会被删除。

先决条件

  • 已安装 Secrets Store CSI Driver Operator。
  • 已安装 secret 存储供应商。
  • 您已创建了 secret 供应商类。
  • 您可以使用具有 cluster-admin 角色的用户访问集群。

流程

  1. 运行以下命令来编辑 SecretProviderClass 资源:

    $ oc edit secretproviderclass my-azure-provider 1
    1
    my-azure-provider 替换为 secret 供应商类的名称。
  2. 使用同步的 Kubernetes secret 配置添加 secretsObjects 部分:

    apiVersion: secrets-store.csi.x-k8s.io/v1
    kind: SecretProviderClass
    metadata:
      name: my-azure-provider
      namespace: my-namespace
    spec:
      provider: azure
      secretObjects:                                   1
        - secretName: tlssecret                        2
          type: kubernetes.io/tls                      3
          labels:
            environment: "test"
          data:
            - objectName: tlskey                       4
              key: tls.key                             5
            - objectName: tlscrt
              key: tls.crt
      parameters:
        usePodIdentity: "false"
        keyvaultName: "kvname"
        objects:  |
          array:
            - |
              objectName: tlskey
              objectType: secret
            - |
              objectName: tlscrt
              objectType: secret
        tenantId: "tid"
    1
    指定同步的 Kubernetes secret 的配置。
    2
    指定要创建的 Kubernetes Secret 对象的名称。
    3
    指定要创建的 Kubernetes Secret 对象的类型。例如:Opaquekubernetes.io/tls
    4
    指定要同步内容的对象名称或别名。
    5
    指定指定 objectName 中的 data 字段来填充 Kubernetes secret。
  3. 保存文件以使改变生效。

2.7.5. 查看 pod 卷挂载中的 secret 状态

您可以查看 pod 卷挂载中 secret 的详细信息,包括版本。

Secrets Store CSI Driver Operator 在与 pod 相同的命名空间中创建一个 SecretProviderClassPodStatus 资源。您可以查看此资源来查看详细信息,包括版本,以及 pod 卷挂载中的 secret。

先决条件

  • 已安装 Secrets Store CSI Driver Operator。
  • 已安装 secret 存储供应商。
  • 您已创建了 secret 供应商类。
  • 您已部署了从 Secrets Store CSI Driver Operator 挂载卷的 pod。
  • 您可以使用具有 cluster-admin 角色的用户访问集群。

流程

  • 运行以下命令,查看 pod 卷挂载中 secret 的详细信息:

    $ oc get secretproviderclasspodstatus <secret_provider_class_pod_status_name> -o yaml 1
    1
    secret 供应商类 pod 状态对象的名称采用 <pod_name>-<namespace>-<secret_provider_class_name> 的格式。

    输出示例

    ...
    status:
      mounted: true
      objects:
      - id: secret/tlscrt
        version: f352293b97da4fa18d96a9528534cb33
      - id: secret/tlskey
        version: 02534bc3d5df481cb138f8b2a13951ef
      podName: busybox-<hash>
      secretProviderClassName: my-azure-provider
      targetPath: /var/lib/kubelet/pods/f0d49c1e-c87a-4beb-888f-37798456a3e7/volumes/kubernetes.io~csi/secrets-store-inline/mount

2.7.6. 卸载 Secret Store CSI Driver Operator

先决条件

  • 访问 OpenShift Container Platform Web 控制台。
  • 集群的管理员访问权限。

流程

卸载 Secret Store CSI Driver Operator:

  1. 停止所有使用 secrets-store.csi.k8s.io 供应商的应用程序 pod。
  2. 为所选 secret 存储删除任何第三方供应商插件。
  3. 删除 Container Storage Interface (CSI) 驱动程序和相关清单:

    1. Administration CustomResourceDefinitions ClusterCSIDriver
    2. Instances 选项卡上,对于 secrets-store.csi.k8s.io,点左侧的下拉菜单,然后点 Delete ClusterCSIDriver
    3. 出现提示时,单击 Delete
  4. 验证 CSI 驱动程序 pod 是否不再运行。
  5. 卸载 Secret Store CSI Driver Operator:

    注意

    在卸载 Operator 前,必须先删除 CSI 驱动程序。

    1. Operators Installed Operators
    2. Installed Operators 页面中,在 Search by name 框中输入 "Secrets Store CSI" 来查找 Operator,然后点击它。
    3. Installed Operators > Operator 详情页面 的右上角,点 Actions Uninstall Operator
    4. 当在 Uninstall Operator 窗口中提示时,点 Uninstall 按钮从命名空间中删除 Operator。Operator 在集群中部署的任何应用程序都需要手动清理。

      卸载后,Secret Store CSI Driver Operator 不再列在 web 控制台的 Installed Operators 部分。

Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.