为在 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 集群中部署的应用程序的私钥。
- Secrets Manager 提供私钥的标识。 您将该标识包含在应用程序的
ExternalSecrets配置文件中,并将该配置应用于集群。 - 外部私钥控制器会访存使用 Kubernetes API 定义的配置文件中的
ExternalSecrets对象。 - 在应用程序运行时,控制器从 Secrets Manager检索私钥数据,并将
ExternalSecrets对象转换为集群的 Kubernetes 私钥。
这种情况下,第三方工具会影响 Kubernetes 集群中运行的工作负载的合规性。 如果添加社区或第三方工具,请记住,您负责维护应用程序的合规性,并与相应的提供者一起对任何问题进行故障诊断。 更多信息,请参见 您有责任使用 IBM Cloud Kubernetes Service。
准备工作
开始之前,请确保您具有 管理员 平台访问权,以便可以创建帐户凭证和供应资源。 您还需要以下先决条件:
-
jq可帮助您对 JSON 数据进行切片和过滤。 在本教程中使用jq来抓取和使用存储的环境变量。
设置环境
要使用 Secrets Manager 和 Kubernetes Service,您需要在 IBM Cloud 帐户中创建集群和 Secrets Manager 实例。 您还需要配置许可权,以便可以对这两个服务运行操作。
在此步骤中,您将通过创建服务标识和 IBM Cloud API 密钥来设置访问环境。 在教程结束时,如果不再需要资源,您可以轻松除去这些资源。 或者,您可以使用 可信概要文件 来授权“外部密钥”操作程序。
创建服务 ID 和 API 密钥
首先创建能够对 Secrets Manager 和 Kubernetes Service运行操作所需的帐户凭证。
-
从命令行,通过 IBM Cloud CLI 登录到 IBM Cloud。
ibmcloud login如果登录失败,请运行
ibmcloud login --sso命令重试。 使用联合标识登录时需要--sso参数。 如果使用此选项,请转至 CLI 输出中列出的链接以生成一次性密码。 -
创建服务标识并将其设置为环境变量。
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 -
分配服务标识许可权以从 Secrets Manager读取私钥。
ibmcloud iam service-policy-create $SERVICE_ID --roles "SecretsReader" --service-name secrets-manager通过分配 SecretsReader 服务访问权,外部密钥控制器具有从 Secrets Manager 读取密钥并在 Kubernetes 集群中填充这些密钥的正确访问级别。
-
为您的服务 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 实例来完成教程。
-
从命令行,选择要在其中创建 Secrets Manager 服务实例的帐户,区域和资源组。
在本教程中,您将与达拉斯区域进行交互。 如果您已登录到其他区域,请确保通过运行以下命令将达拉斯设置为目标区域。
ibmcloud target -r us-south -g default -
创建 Kubernetes 集群。
ibmcloud ks cluster create classic --zone dal10 --flavor free --name my-test-cluster -
创建 Secrets Manager 实例。
ibmcloud resource service-instance-create my-secrets-manager secrets-manager trial us-south针对 Secrets Manager 和 Kubernetes 集群的供应需要 5-15 分钟才能完成。
-
继续执行下一步之前,请验证是否已成功供应集群和 Secrets Manager 实例。
-
验证工作程序节点的部署是否已完成。
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 -
接下来,验证是否已成功供应 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
-
-
在 CLI 中为 Kubernetes 群集设置上下文。
ibmcloud ks cluster config --cluster my-test-cluster -
验证
kubectl命令是否正确运行以及 Kubernetes 上下文是否设置为集群。kubectl config current-context示例输出:
my-test-cluster/<your_cluster_ID>
通过 CLI 创建受信任的配置文件
可信概要文件允许“外部密钥”操作程序从 Secrets Manager中读取,而不必创建服务标识或管理 API 密钥。
-
获取 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') -
创建概要文件。
ibmcloud iam trusted-profile-create 'External Secrets' -
授权 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_SAOpenShift
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 -
创建允许可信概要文件从 Secrets Manager 实例读取私钥的访问策略。
ibmcloud iam trusted-profile-policy-create 'External Secrets' --roles SecretsReader --service-instance $SECRETS_MANAGER_CRN --service-name secrets-manager
使用 Terraform 创建可信配置文件
可信概要文件允许“外部密钥”操作程序从 Secrets Manager中读取,而不必创建服务标识或管理 API 密钥。 您可以按照 Terraform 中的示例执行创建受信任配置文件的所有步骤:
```sh {: pre}
//Get your cluster details
data "ibm_container_vpc_cluster" "cluster" {
name = var.cluster_name
resource_group_id = var.resource_group_id
}
//Get details of Secret Manager Instance
data "ibm_resource_instance" "secrets_manager" {
name = var.sm_name
resource_group_id = var.resource_group_id
service = "secrets-manager"
}
//Create Trusted Profile
resource "ibm_iam_trusted_profile" "eso_profile" {
name = var.profile_name
description = var.profile_description
}
//Attach IAM Policy for Secrets Manager Access
resource "ibm_iam_trusted_profile_policy" "secrets_policy" {
iam_id = ibm_iam_trusted_profile.eso_profile.id
roles = ["SecretsReader"]
resources {
service = "secrets-manager"
resource_instance_id = data.ibm_resource_instance.secrets_manager.guid
}
}
//Add Claim Rule for Kubernetes Service Account
resource "ibm_iam_trusted_profile_claim_rule" "eso_claim_rule" {
profile_id = ibm_iam_trusted_profile.eso_profile.id
type = "Profile-CR"
cr_type = "IKS_SA"
conditions {
claim = "name"
operator = "EQUALS"
value = var.service_account_name
}
conditions {
claim = "namespace"
operator = "EQUALS"
value = var.namespace
}
conditions {
claim = "crn"
operator = "EQUALS"
value = data.ibm_container_vpc_cluster.cluster.crn
}
}
//Variables
variable "resource_group_id" {
description = "Resource Group ID"
type = string
}
variable "sm_name" {
description = "Secret Manager Instance ID"
type = string
}
variable "cluster_name" {
description = "IKS Cluster name"
type = string
}
variable "profile_name" {
type = string
description = "Name of the trusted profile"
}
variable "profile_description" {
type = string
description = "Description of the trusted profile"
}
variable "service_account_name" {
description = "Kubernetes service account name for claim rule"
type = string
}
variable "namespace" {
description = "Kubernetes namespace for claim rule"
type = string
}
```
准备 Secrets Manager 实例
最后,配置 Secrets Manager 实例以开始使用私钥。
-
从命令行验证您是否可以访问 Secrets Manager CLI 插件。
ibmcloud secrets-manager --help还没有插件吗? 要安装 Secrets Manager CLI 插件,请运行
ibmcloud plugin install secrets-manager。 -
使用您唯一的 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 -
为实例创建私钥组。
私钥组 是一种组织和控制团队中有权访问实例中特定私钥的人员的方法。 要从 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_id 和 region 更新为您的内容。
输出将显示新创建的私钥的标识。 例如:
e0246cea-d668-aba7-eef2-58ca11ad3707
设置外部密钥操作程序
既然您具有应用程序的私钥,那么可以为集群设置 外部私钥操作程序 工具。 此包通过为应用程序创建转换为 Kubernetes 私钥的 ExternalSecrets 对象来配置 Secrets Manager 与集群之间的连接。
外部秘密操作员是一个开放源代码工具,不由 IBM 维护。 有关此工具的更多信息或要对任何问题进行故障诊断,请参阅 项目文档。
为集群配置外部密钥操作程序
Kubernetes
首先,通过安装官方 Helm Chart 将 external-secrets 资源添加到集群。 有关更多安装选项,请查看 入门指南。
-
运行以下命令以安装 External Secrets Operator Helm 存储库:
helm repo add external-secrets https://charts.external-secrets.io -
配置 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
-
通过创建以下资源来安装 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- -
配置 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 中创建以私钥为目标的配置文件。
-
在应用程序的根目录中,创建
external-secrets-example.yml文件。touch external-secrets-example.yml -
修改文件以包含有关要从 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 -
将配置应用于集群。
kubectl apply -f external-secrets-example.yml -
验证外部私钥操作程序是否能够访存存储在 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 应用程序,以了解有关部署单个应用程序实例的更多信息。
(可选) 清除资源
如果您不再需要在本教程中创建的资源,那么可以完成以下步骤以从帐户中除去这些资源。
-
删除测试 Kubernetes 集群。
ibmcloud ks cluster rm --cluster my-test-cluster -
删除测试 Secrets Manager 实例。
ibmcloud resource service-instance-delete my-secrets-manager -
删除您的授权。
如果您正在使用服务标识。
ibmcloud iam service-id-delete $SERVICE_ID如果您正在使用可信概要文件。
ibmcloud iam trusted-profile-delete 'External Secrets'
相关说明
在构造 YAML 文档 时,请记住,通过使用 Secrets Manager 实例中的 REST 来定期轮询数据部分中的每个密钥。 请注意:
- 默认情况下,轮询时间间隔设置为 1 小时,这是首选设置值。 您可以在“外部秘密”模板中使用
spec.refreshInterval更改该值。 区间可以以s,m或h为单位表示。 - 如果将 YAML 设置为按名称而不是按标识 (
keyByName: true) 访存 Secrets Manager 私钥,那么 ESO 将发出额外调用以访存相关私钥标识。 有关更多信息,请参阅 外部密钥文档。
后续步骤
太棒了! 在本教程中,您学习了如何设置 Secrets Manager 以安全地向集群填充应用程序私钥。 请查看更多资源,以帮助您开始使用 Secrets Manager。
- 查看 External Secrets Operator 支持的 Secrets Manager 中的私钥类型。
- 了解有关 Secrets Manager API 的更多信息。