IBM Cloud Docs
在 Kubernetes 集群中运行的应用程序的安全密钥

在 Kubernetes 集群中运行的应用程序的安全密钥

在本教程中,您将学习如何使用 External Secrets Operator 开放式源代码工具,使用 IBM Cloud® Secrets Manager 来管理运行 IBM Cloud Kubernetes Service 集群的应用程序的私钥。

或者,可以使用 Kubernetes Service CLI 插件来管理 TLS 和非 TLS 私钥。 要了解有关此方法的更多信息,请参阅 设置 Kubernetes Ingress

您是一家企业的开发人员,您的团队正在使用 Kubernetes Service 在 IBM Cloud 上部署容器化应用程序和服务。 在当前流中,使用 Kubernetes Secrets 来存储在集群中运行的应用程序和服务所使用的敏感数据,例如密码和 API 密钥。 为了更好地控制应用程序私钥,您希望能够将集群私钥存储在外部私钥管理服务中,在该服务中可以 静态加密监视其活动 以及轻松管理这些私钥。

通过 Secrets Manager,您可以集中并保护在 Kubernetes 集群中运行的应用程序所使用的私钥。 您可以配置应用程序以在运行时从 Secrets Manager 安全检索私钥,而不是在部署时注入私钥。 轮换私钥时,可以从 Secrets Manager执行此操作。 例如,假设有以下场景:

此图显示了 Secrets Manager 与 Kubernetes 集群之间的基本流。
External Secrets flow

  1. 作为开发者,您可以使用 Secrets Manager 来存储要在 Kubernetes 集群中部署的应用程序的私钥。
  2. Secrets Manager 提供私钥的标识。 您将该标识包含在应用程序的 ExternalSecrets 配置文件中,并将该配置应用于集群。
  3. 外部私钥控制器会访存使用 Kubernetes API 定义的配置文件中的 ExternalSecrets 对象。
  4. 在应用程序运行时,控制器从 Secrets Manager检索私钥数据,并将 ExternalSecrets 对象转换为集群的 Kubernetes 私钥。

此方案具有第三方工具,可影响在 Kubernetes 集群中运行的工作负载的合规性准备情况。 如果添加社区或第三方工具,请记住,您负责维护应用程序的合规性,并与相应的提供者一起对任何问题进行故障诊断。 有关更多信息,请参阅 您使用 IBM Cloud Kubernetes Service的职责

准备工作

开始之前,请确保您具有 管理员 平台访问权,以便可以创建帐户凭证和供应资源。 您还需要以下先决条件:

设置环境

要使用 Secrets Manager 和 Kubernetes Service,您需要在 IBM Cloud 帐户中创建集群和 Secrets Manager 实例。 您还需要配置许可权,以便可以对这两个服务运行操作。

在此步骤中,您将通过创建服务标识和 IBM Cloud API 密钥来设置访问环境。 在教程结束时,如果不再需要资源,您可以轻松除去这些资源。 或者,您可以使用 可信概要文件 来授权“外部密钥”操作程序。

创建服务ID和API密钥

首先创建能够对 Secrets Manager 和 Kubernetes Service运行操作所需的帐户凭证。

  1. 从命令行,通过 IBM Cloud CLI 登录到 IBM Cloud。

    ibmcloud login
    

    如果登录失败,请运行 ibmcloud login --sso 命令重试。 使用联合标识登录时需要 --sso 参数。 如果使用此选项,请转至 CLI 输出中列出的链接以生成一次性密码。

  2. 创建服务标识并将其设置为环境变量。

    export SERVICE_ID=`ibmcloud iam service-id-create kubernetes-secrets-tutorial --description "A service ID for testing ESO integration" --output json | jq -r ".id"`; echo $SERVICE_ID
    
  3. 分配服务标识许可权以从 Secrets Manager读取私钥。

    ibmcloud iam service-policy-create $SERVICE_ID --roles "SecretsReader" --service-name secrets-manager
    

    通过分配 SecretsReader 服务访问权,外部密钥控制器具有从 Secrets Manager 读取密钥并在 Kubernetes 集群中填充这些密钥的正确访问级别。

  4. 为您的服务ID创建一个 IBM Cloud API密钥。

    export IBM_CLOUD_API_KEY=`ibmcloud iam service-api-key-create kubernetes-secrets-tutorial $SERVICE_ID --description "An API key for testing ESO integration." --output json | jq -r ".apikey"`
    

    稍后使用此 API 密钥为集群部署配置 Secrets Manager。

创建 Kubernetes 集群和 Secrets Manager 实例

在 IBM Cloud 帐户中创建 Kubernetes 集群和 Secrets Manager 实例。

您可以为每个 IBM Cloud 帐户创建一个免费 Kubernetes 集群和 Secrets Manager 服务实例。 如果您的帐户中已有这两种资源,那么可以使用现有免费集群和 Secrets Manager 实例来完成教程。

  1. 从命令行,选择要在其中创建 Secrets Manager 服务实例的帐户,区域和资源组。

    在本教程中,您将与达拉斯区域进行交互。 如果您已登录到其他区域,请确保通过运行以下命令将达拉斯设置为目标区域。

    ibmcloud target -r us-south -g default
    
  2. 创建一个 Kubernetes 集群。

    ibmcloud ks cluster create classic --zone dal10 --flavor free --name my-test-cluster
    
  3. 创建一个 Secrets Manager 实例。

    ibmcloud resource service-instance-create my-secrets-manager secrets-manager trial us-south
    

    针对 Secrets Manager 和 Kubernetes 集群的供应需要 5-15 分钟才能完成。

  4. 继续执行下一步之前,请验证是否已成功供应集群和 Secrets Manager 实例。

    1. 验证工作程序节点的部署是否已完成。

      ibmcloud ks worker ls --cluster my-test-cluster
      

      当工作程序节点完成供应时,状态将更改为 就绪

      ID                                                       Public IP       Private IP      Flavor   State          Status                Zone    Version
      kube-c39pf4ld0m87o3fv1utg-mytestclust-default-000000dd   169.xx.xx.xxx   10.xxx.xx.xxx   free     normal   Ready   mex01   1.20.7_1543
      
    2. 接下来,验证是否已成功供应 Secrets Manager 实例。

      ibmcloud resource service-instance my-secrets-manager
      

      当实例完成供应时,状态将更改为 活动

      Name:                  my-secrets-manager
      ID:                    crn:v1:bluemix:public:secrets-manager:us-south:a/f047b55a3362ac06afad8a3f2f5586ea:fe06948b-0c6b-4183-8d4b-e6c1d38ff65f::
      GUID:                  fe06948b-0c6b-4183-8d4b-e6c1d38ff65f
      Location:              us-south
      Service Name:          secrets-manager
      Service Plan Name:     trial
      Resource Group Name:   default
      State:                 active
      Type:                  service_instance
      Sub Type:
      Created at:            2021-01-06T17:11:32Z
      Created by:            zara@example.com
      Updated at:            2021-03-31T02:33:26Z
      
  5. 在命令行界面中设置 Kubernetes 集群的上下文。

    ibmcloud ks cluster config --cluster my-test-cluster
    
  6. 验证 kubectl 命令是否正确运行以及 Kubernetes 上下文是否设置为集群。

    kubectl config current-context
    

    示例输出:

    my-test-cluster/<your_cluster_ID>
    

创建可信概要文件

可信概要文件允许“外部密钥”操作程序从 Secrets Manager中读取,而不必创建服务标识或管理 API 密钥。

  1. 获取 Secrets Manager 实例和 Kubernetes 集群的 CRN。

    CLUSTER_CRN=$(ibmcloud ks cluster get --cluster my-test-cluster --output json | jq -r '.crn')
    SECRETS_MANAGER_CRN=$(ibmcloud resource service-instance my-secrets-manager --output JSON | jq -r '.[0].crn')
    
  2. 创建概要文件。

    ibmcloud iam trusted-profile-create 'External Secrets'
    
  3. 授权 Kubernetes 集群使用可信概要文件。

    Kubernetes

    ibmcloud iam trusted-profile-rule-create 'External Secrets' --name kubernetes --type Profile-CR --conditions claim:namespace,operator:EQUALS,value:external-secrets --conditions claim:name,operator:EQUALS,value:external-secrets --conditions claim:crn,operator:EQUALS,value:$CLUSTER_CRN --cr-type IKS_SA
    

    OpenShift

    ibmcloud iam trusted-profile-rule-create 'External Secrets' --name kubernetes --type Profile-CR --conditions claim:namespace,operator:EQUALS,value:external-secrets-operator --conditions claim:name,operator:EQUALS,value:cluster-external-secrets --conditions claim:crn,operator:EQUALS,value:$CLUSTER_CRN --cr-type IKS_SA
    
  4. 创建允许可信概要文件从 Secrets Manager 实例读取私钥的访问策略。

    ibmcloud iam trusted-profile-policy-create 'External Secrets' --roles SecretsReader --service-instance $SECRETS_MANAGER_CRN --service-name secrets-manager
    

准备 Secrets Manager 实例

最后,配置 Secrets Manager 实例以开始使用私钥。

  1. 从命令行验证您是否可以访问 Secrets Manager CLI 插件。

    ibmcloud secrets-manager --help
    

    还没有插件吗? 要安装 Secrets Manager CLI 插件,请运行 ibmcloud plugin install secrets-manager

  2. 使用您唯一的 Secrets Manager API端点 URL 导出环境变量。

    export SECRETS_MANAGER_URL=`ibmcloud resource service-instance my-secrets-manager --output json | jq -r '.[].dashboard_url | .[0:-3]'`; echo $SECRETS_MANAGER_URL
    
  3. 为实例创建私钥组。

    私钥组 是一种组织和控制团队中有权访问实例中特定私钥的人员的方法。 要从 IBM Cloud CLI 创建私钥组,请使用 ibmcloud secrets-manager secret-group-create 命令。 运行以下命令以创建私钥组并将其标识存储为环境变量。

    export SECRET_GROUP_ID=`ibmcloud secrets-manager secret-group-create --name my-test-secret-group --description "Read and write to my test app" --output json --service-url $SECRETS_MANAGER_URL | jq -r '.id'`; echo $SECRET_GROUP_ID
    

    使用 Windows™ 命令提示符 (cmd.exe) 或 PowerShell? 如果在命令行上传递 JSON 内容时迂到错误,那么可能需要调整字符串以满足特定于操作系统的报价转义需求。 有关更多信息,请参阅 在 IBM Cloud CLI 中对字符串使用引号

    成功! 现在,您可以将私钥存储在要在 Kubernetes 集群中填充的 Secrets Manager 中。 继续下一步。

在 Secrets Manager 中创建私钥

私钥是特定于应用程序的私钥,可能根据需要私钥的单个应用程序或服务而有所不同。 私钥可能由用户名,密码,API 密钥或任何其他类型的凭证组成。

Secrets Manager 支持您可以在服务中创建和管理的各种 私钥类型。 例如,如果需要管理受 IBM Cloud IAM 认证保护的应用程序的 API 密钥,那么可以创建 IAM 凭证。 或者,如果需要管理可保存任何类型的结构化或非结构化数据的私钥,那么可以创建 任意私钥

在本教程中,您将创建用户名和密码作为示例。 要从 IBM Cloud CLI 创建私钥,请使用 ibmcloud secrets-manager secret-create 命令。 运行以下命令以创建私钥并将其标识存储为环境变量。

export SECRET_ID=`ibmcloud secrets-manager secret-create --secret-type=username_password --secret-name example_username_password --username-password-username user123 --username-password-password cloudy-rainy-coffee-book --secret-labels "my-test-cluster, tutorial" --secret-group-id $SECRET_GROUP_ID --output json $SECRETS_MANAGER_URL | jq -r '.id'`; echo $SECRET_ID

请确保将 instance_idregion 更新为您的内容。

输出将显示新创建的私钥的标识。 例如:

e0246cea-d668-aba7-eef2-58ca11ad3707

设置外部密钥操作程序

既然您具有应用程序的私钥,那么可以为集群设置 外部私钥操作程序 工具。 此包通过为应用程序创建转换为 Kubernetes 私钥的 ExternalSecrets 对象来配置 Secrets Manager 与集群之间的连接。

External Secret Operator 是 IBM未维护的开放式源代码工具。 有关此工具的更多信息或要对任何问题进行故障诊断,请参阅 项目文档

为集群配置外部密钥操作程序

Kubernetes

首先,通过安装官方 Helm Chart 将 external-secrets 资源添加到集群。 有关更多安装选项,请查看 入门指南

  1. 运行以下命令以安装 External Secrets Operator Helm 存储库:

    helm repo add external-secrets https://charts.external-secrets.io
    
  2. 配置 External Secrets Operator 与 Secrets Manager之间的认证。

    如果要使用服务标识进行认证:

    kubectl -n default create secret generic secret-api-key --from-literal=apikey=$IBM_CLOUD_API_KEY
    helm install external-secrets external-secrets/external-secrets -n external-secrets --create-namespace --set installCRDs=true
    

    如果使用可信概要文件进行认证:

    echo '
    installCRDs: true
    extraVolumes:
    - name: sa-token
      projected:
        defaultMode: 420
        sources:
        - serviceAccountToken:
            path: sa-token
            expirationSeconds: 3600
            audience: iam
    extraVolumeMounts:
    - mountPath: /var/run/secrets/tokens
      name: sa-token
    webhook:
      extraVolumes:
      - name: sa-token
        projected:
          defaultMode: 420
          sources:
          - serviceAccountToken:
              path: sa-token
              expirationSeconds: 3600
              audience: iam
      extraVolumeMounts:
      - mountPath: /var/run/secrets/tokens
        name: sa-token' >values.yml
    helm install external-secrets external-secrets/external-secrets -n external-secrets --create-namespace -f values.yml
    

OpenShift

  1. 通过创建以下资源来安装 External Secrets 操作程序:

    echo '
    apiVersion: v1
    kind: Namespace
    metadata:
      name: external-secrets-operator
    ---
    apiVersion: operators.coreos.com/v1
    kind: OperatorGroup
    metadata:
      name: external-secrets-operator
      namespace: external-secrets-operator
    spec:
      targetNamespaces:
        - external-secrets-operator
    ---
    apiVersion: operators.coreos.com/v1alpha1
    kind: Subscription
    metadata:
      name: external-secrets-operator
      namespace: external-secrets-operator
    spec:
      channel: stable
      installPlanApproval: Automatic
      name: external-secrets-operator
      source: community-operators
      sourceNamespace: openshift-marketplace
    ' | oc create -f-
    
  2. 配置 External Secrets Operator 与 Secrets Manager之间的认证。

    如果要使用服务标识进行认证:

    echo "
    apiVersion: operator.external-secrets.io/v1alpha1
    kind: OperatorConfig
    metadata:
      name: cluster
      namespace: external-secrets-operator
    spec: {}
    ---
    apiVersion: v1
    kind: Secret
    metadata:
      name: secret-api-key
      namespace: default
    type: Opaque
    stringData:
      apikey: $IBM_CLOUD_API_KEY
    " | oc create -f-
    

    如果使用可信概要文件进行认证:

    echo '
    apiVersion: operator.external-secrets.io/v1alpha1
    kind: OperatorConfig
    metadata:
      name: cluster
      namespace: external-secrets-operator
    spec:
      extraVolumeMounts:
      - mountPath: /var/run/secrets/tokens
        name: sa-token
      extraVolumes:
      - name: sa-token
        projected:
          defaultMode: 420
          sources:
          - serviceAccountToken:
              audience: iam
              expirationSeconds: 3600
              path: sa-token
      webhook:
        extraVolumeMounts:
        - mountPath: /var/run/secrets/tokens
          name: sa-token
        extraVolumes:
        - name: sa-token
          projected:
            defaultMode: 420
            sources:
            - serviceAccountToken:
                audience: iam
                expirationSeconds: 3600
                path: sa-token
    ' | oc create -f-
    

更新应用程序配置

在集群中安装 External Secrets Operator 后,可以将 Secrets Manager 定义为应用程序的私钥后端。 首先在要使用的 Secrets Manager 中创建以私钥为目标的配置文件。

  1. 在应用程序的根目录中,创建 external-secrets-example.yml 文件。

    touch external-secrets-example.yml
    
  2. 修改文件以包含有关要从 Secrets Manager 实例访存的私钥的信息。

    apiVersion: external-secrets.io/v1beta1
    kind: SecretStore
    metadata:
      name: ibmcloud-secrets-manager-example
    spec:
      provider:
        ibm:
          serviceUrl: <endpoint_url>
          auth:
            secretRef:
              secretApiKeySecretRef:
                name: secret-api-key
                key: apikey
    ---
    apiVersion: external-secrets.io/v1beta1
    kind: ExternalSecret
    metadata:
      name: ibmcloud-secrets-manager-example
    spec:
      secretStoreRef:
        name: ibmcloud-secrets-manager-example
        kind: SecretStore
      target:
        name: ibmcloud-secrets-manager-example
      data:
      - secretKey: username
        remoteRef:
          property: username
          key: username_password/<SECRET_ID>
      - secretKey: password
        remoteRef:
          property: password
          key: username_password/<SECRET_ID>
    

    您可以选择按私钥标识或私钥名称使用两种方式。 如果选择私钥名称,那么格式将从 secret_type/secret_id 更改为 secret_group/secret_type/secret_name

    <endpoint_url> 替换 为您之前 获取的 Secrets Manager 端点 URL。 将 <SECRET_ID> 替换为您在上一步中创建的私钥的唯一标识。

    如果要使用可信概要文件进行认证,请将 auth 块替换为以下片段。

          auth:
            containerAuth:
              profile: "External Secrets"
              iamEndpoint: https://iam.cloud.ibm.com
              tokenLocation: /var/run/secrets/tokens/sa-token
    
  3. 将配置应用于集群。

    kubectl apply -f external-secrets-example.yml
    
  4. 验证外部私钥操作程序是否能够访存存储在 Secrets Manager 实例中的私钥。

    kubectl get secret ibmcloud-secrets-manager-example -o json | jq '.data | map_values(@base64d)'
    

    示例输出:

    {
        "password": "cloudy-rainy-coffee-book",
        "username": "user123"
    }
    

    成功! 现在,您可以访存存储在 Secrets Manager 实例中的私钥数据。 继续下一步。

将应用程序部署到集群

最后,可以在集群中部署使用 external-secret-example.yml 文件中定义的 Secrets Manager 私钥的应用程序。 在应用程序运行时,从 Secrets Manager 访存的私钥数据将转换为可供集群使用的 Kubernetes 私钥。

查找有关如何部署应用程序的示例? 请查看 在集群中部署 Kubernetes-native 应用程序,以了解有关部署单个应用程序实例的更多信息。

(可选) 清除资源

如果您不再需要在本教程中创建的资源,那么可以完成以下步骤以从帐户中除去这些资源。

  1. 删除测试 Kubernetes 集群。

    ibmcloud ks cluster rm --cluster my-test-cluster
    
  2. 删除测试 Secrets Manager 实例。

    ibmcloud resource service-instance-delete my-secrets-manager
    
  3. 删除您的授权。

    如果您正在使用服务标识。

    ibmcloud iam service-id-delete $SERVICE_ID
    

    如果您正在使用可信概要文件。

    ibmcloud iam trusted-profile-delete 'External Secrets'
    

相关说明

在构造 YAML 文档 时,请记住,通过使用 Secrets Manager 实例中的 REST 来定期轮询数据部分中的每个密钥。 请注意:

  1. 默认情况下,轮询时间间隔设置为 1 小时,这是首选设置值。 您可以在“外部秘密”模板中使用 spec.refreshInterval 更改该值。 区间可以以 smh 为单位表示。
  2. 如果将 YAML 设置为按名称而不是按标识 (keyByName: true) 访存 Secrets Manager 私钥,那么 ESO 将发出额外调用以访存相关私钥标识。 有关更多信息,请参阅 外部密钥文档

后续步骤

太棒了! 在本教程中,您学习了如何设置 Secrets Manager 以安全地向集群填充应用程序私钥。 请查看更多资源,以帮助您开始使用 Secrets Manager。