Kubernetes 的 secret 并不是真正的 secret(下)

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: Kubernetes 的 secret 并不是真正的 secret

使用 HashiCorp Vault

HashiCorp Vault 是一个流行的 secret 管理器,提供不同的 secret 引擎。ESO 只能与 Vault 提供的 KV Secrets Engine 一起使用。Vault 在 HashiCorp 云平台 (HCP) 上提供了一个您可以自行管理的免费开源版本和一个带有免费等级的托管版本。

确保您在本地 Vault 实例或 HCP cloud 中设置了键值 secret 存储。您还可以使用 Vault Helm chart 将 Vault 部署到 Kubernetes 集群。

  1. 创建一个新的 SecretStore CRD,vault-backend.yaml,以定义与 Vault 的连接详细信息。
# vault-backend.yaml
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: vault-backend
spec:
  provider:
    vault:
      server: 'YOUR_VAULT_ADDRESS'
      path: 'secret'
      version: 'v2'
      namespace: 'admin' # required for HCP Vault
      auth:
        # points to a secret that contains a vault token
        # https://www.vaultproject.io/docs/auth/token
        tokenSecretRef:
          name: 'vault-token'
          key: 'token'
  1. 创建一个 secret 资源来保存 Vault token。使用具有对 Vault KV 存储中的 secret/ 路径具有读取权限的策略的令牌。
kubectl create secret generic vault-token \
  --dry-run=client \
  --from-literal=token=YOUR_VAULT_TOKEN
  1. 在 Vault 中创建一个 secret 。如果您使用的是 Vault CLI,则可以使用以下命令创建一个 secret 。确保您使用适当的策略从 CLI 登录到 vault 实例。
vault kv put secret/mysecret my-value=supersecret
  1. 创建一个 ExternalSecret CRD 来定义需要从 Vault 中获取的数据。
# vault-secret.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: vault-example
spec:
  refreshInterval: '15s'
  secretStoreRef:
    name: vault-backend
    kind: SecretStore
  target:
    name: vault-example-sync
  data:
    - secretKey: secret-from-vault
      remoteRef:
        key: secret/mysecret
        property: my-value
  1. 将上述 CRD 应用到集群,它应该使用从 Vault 获取的数据创建一个名为 vault-example-sync 的 Kubernetes secret。
kubectl apply -f vault-backend.yaml
kubectl apply -f vault-secret.yaml

您可以使用 kubectl describe 命令查看集群中的 secret。

kubectl describe secret vault-example-sync
# output should have the below data
Name:         vault-example-sync
Namespace:    default
Labels:       <none>
Annotations:  reconcile.external-secrets.io/data-hash: ...
Type:  Opaque
Data
====
secret-from-vault:  16 bytes

如果您在创建 secret 时遇到问题,请检查 ExternalSecret 资源描述输出的 events 部分。

kubectl describe externalsecret vault-example

如果您看到权限错误,请确保使用具有正确策略的令牌。

其他 secret managers

设置其他 secret 管理器与上述步骤类似。唯一的区别是 SecretStore CRD 和 ExternalSecret CRD 中的 remoteRef 部分。您可以在 ESO 文档中找到针对不同提供商的官方指南。


Secrets Store CSI Driver

Secrets Store CSI Driver 是一个原生的上游 Kubernetes 驱动程序,可用于从工作负载中抽象出 secret 的存储位置。如果您想使用云提供商的 secret 管理器而不将 secret 公开为 Kubernetes secret 对象,您可以使用 CSI 驱动程序将 secret 作为卷安装在您的 pod 中。如果您使用云提供商来托管您的 Kubernetes 集群,这是一个很好的选择。该驱动程序支持许多云提供商,并且可以与不同的 secret 管理器一起使用。

Secrets Store CSI Driver

Secrets Store CSI Driver 是一个 daemonset 守护进程,它与 secret 提供者通信以检索 SecretProviderClass 自定义资源中指定的 secret 。

它的工作原理如下;

  1. 创建一个 SecretProviderClassCRD 来定义从 secret 提供者获取的 secret 的详细信息。
  2. 在 pod 的 volume spec 中引用 SecretProviderClass
  3. 驱动程序将从 secret 提供者那里获取 secret ,并在 pod 启动期间将其作为 tmpfs 卷挂载到 pod 中。该卷也将在 pod 删除后被删除。

驱动程序还可以同步对 secret 的更改。该驱动程序目前支持 Vault、AWS、Azure 和 GCP 提供商。Secrets Store CSI Driver 也可以将加密数据同步为 Kubernetes secret,只需要在安装期间明确启用此行为。

优点

  • secret 存储在安全的外部 secret 管理器中,而不是代码存储库中。
  • 使机密与外部机密管理器保持同步。它还支持 secret 的轮换。
  • 与所有主要的外部 secret 管理者合作。
  • 将密钥作为卷安装在 pod 中,因此它们不会作为 Kubernetes secret 公开。它也可以配置为创建 Kubernetes secret。

缺点

  • 需要精心设置才能使用,并且比 ESO 更复杂。
  • 使用比 ESO 更多的资源,因为它需要在每个节点上运行。
  • 依赖于外部 secret 存储及其访问策略来确保安全。

使用 Google Secret Manager provider

让我们看看如何配置 driver 以使用 Google Secret Manager (GSM) 作为 secret provider。

确保您使用的是启用了 Workload Identity 功能的 Google Kubernetes Engine (GKE) 集群。Workload Identity 允许 GKE 集群中的工作负载模拟身份和访问管理 (IAM) 服务帐户来访问 Google Cloud 服务。您还需要为项目启用 Kubernetes Engine API、Secret Manager API 和 Billing。如果未启用, gcloud CLI 会提示您启用这些 API。

可以使用以下 gcloud CLI 命令创建启用了 Workload Identity 的新集群。

export PROJECT_ID=<your gcp project>
gcloud config set project $PROJECT_ID
gcloud container clusters create hello-hipster \
  --workload-pool=$PROJECT_ID.svc.id.goog

安装 Secrets Store CSI Driver

可以使用 Helm 命令在集群上安装 Secrets Store CSI 驱动程序:

helm repo add secrets-store-csi-driver https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts
helm install csi-secrets-store \
    secrets-store-csi-driver/secrets-store-csi-driver \
    --namespace kube-system

这将在 kube-system 命名空间下安装驱动程序和 CRD 。您还需要将所需的 provider 安装到集群中。

安装 GSM provider

让我们将 GSM provider 安装到集群中:

kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/secrets-store-csi-driver-provider-gcp/main/deploy/provider-gcp-plugin.yaml

创建 secret

首先,您需要设置一个工作负载身份服务帐户。

# Create a service account for workload identity
gcloud iam service-accounts create gke-workload
# Allow "default/mypod" to act as the new service account
gcloud iam service-accounts add-iam-policy-binding \
    --role roles/iam.workloadIdentityUser \
    --member "serviceAccount:$PROJECT_ID.svc.id.goog[default/mypodserviceaccount]" \
    gke-workload@$PROJECT_ID.iam.gserviceaccount.com

现在让我们创建一个该服务帐户可以访问的密钥。

# Create a secret with 1 active version
echo "mysupersecret" > secret.data
gcloud secrets create testsecret --replication-policy=automatic --data-file=secret.data
rm secret.data
# grant the new service account permission to access the secret
gcloud secrets add-iam-policy-binding testsecret \
    --member=serviceAccount:gke-workload@$PROJECT_ID.iam.gserviceaccount.com \
    --role=roles/secretmanager.secretAccessor

现在您可以创建一个 SecretProviderClass 资源,用于从 GSM 获取密钥。请记住将 $PROJECT_ID 替换为您的 GCP 项目 ID。

# secret-provider-class.yaml
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: app-secrets
spec:
  provider: gcp
  parameters:
    secrets: |
      - resourceName: "projects/$PROJECT_ID/secrets/testsecret/versions/latest"
        path: "good1.txt"
      - resourceName: "projects/$PROJECT_ID/secrets/testsecret/versions/latest"
        path: "good2.txt"

创建一个 Pod

现在您可以创建一个 pod 去使用该 SecretProviderClass 资源从 GSM 获取密钥。请记住将 $PROJECT_ID 替换为您的 GCP 项目 ID。

# my-pod.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: mypodserviceaccount
  namespace: default
  annotations:
    iam.gke.io/gcp-service-account: gke-workload@$PROJECT_ID.iam.gserviceaccount.com
---
apiVersion: v1
kind: Pod
metadata:
  name: mypod
  namespace: default
spec:
  serviceAccountName: mypodserviceaccount
  containers:
    - image: gcr.io/google.com/cloudsdktool/cloud-sdk:slim
      imagePullPolicy: IfNotPresent
      name: mypod
      resources:
        requests:
          cpu: 100m
      stdin: true
      stdinOnce: true
      terminationMessagePath: /dev/termination-log
      terminationMessagePolicy: File
      tty: true
      volumeMounts:
        - mountPath: '/var/secrets'
          name: mysecret
  volumes:
    - name: mysecret
      csi:
        driver: secrets-store.csi.k8s.io
        readOnly: true
        volumeAttributes:
          secretProviderClass: 'app-secrets'

将上述资源应用到集群中。

kubectl apply -f secret-provider-class.yaml
kubectl apply -f my-pod.yaml

等待 pod 启动,然后 exec 进入 pod 查看挂载文件的内容。

kubectl exec -it mypod /bin/bash
# execute the below command in the pod to see the contents of the mounted secret file
root@mypod:/# cat /var/secrets/good1.txt

其他 secret 管理器

您可以找到服务提供商的类似指南:AWS CSI provider、Azure CSI provider 和 Vault CSI provider。


结论

Sealed Secrets 是小型团队和项目在 Git 中保护 secret 的绝佳解决方案。对于较大的团队和项目,External Secrets OperatorSecrets Store CSI Driver 是安全管理密钥的更好的解决方案。External Secrets Operator 可以与许多 secret 管理系统一起使用,并不限于上述系统。当然,这应该与 RBAC 一起使用,以防止非管理员读取集群中的 secret 。Secrets Store CSI Driver 可能比 ESO 涉及更多,但它是一个更原生的解决方案。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
1月前
|
Kubernetes 关系型数据库 MySQL
|
3月前
|
运维 Kubernetes 容器
【Azure K8S】演示修复因AKS密钥过期而导致创建服务不成功的问题(The provided client secret keys for app ****** are expired)
【Azure K8S】演示修复因AKS密钥过期而导致创建服务不成功的问题(The provided client secret keys for app ****** are expired)
【Azure K8S】演示修复因AKS密钥过期而导致创建服务不成功的问题(The provided client secret keys for app ****** are expired)
|
1月前
|
存储 Kubernetes 数据安全/隐私保护
k8s学习--Secret详细解释与应用
Secret 支持四种类型: - **Opaque Secrets**:存储任意类型机密数据,需自行加密。 - **Service Account Token Secrets**:自动管理 API 访问令牌。 - **Docker Registry Secrets**:存储 Docker 私有仓库认证信息。 - **TLS Secrets**:存储 TLS 证书和私钥,用于加密通信。
128 0
|
3月前
|
存储 Kubernetes 数据安全/隐私保护
k8s学习笔记之ConfigMap和Secret
k8s学习笔记之ConfigMap和Secret
|
3月前
|
存储 Kubernetes 安全
在k8S中,Secret 有哪些使用方式?
在k8S中,Secret 有哪些使用方式?
|
3月前
|
Kubernetes 数据安全/隐私保护 容器
Kubernetes(K8S) 配置管理 Secret 介绍
Kubernetes(K8S) 配置管理 Secret 介绍
47 1
|
3月前
|
Prometheus Kubernetes 数据安全/隐私保护
使用kubeseal加密和管理k8s集群的secret
使用kubeseal加密和管理k8s集群的secret
59 2
|
3月前
|
Kubernetes 容器 Perl
在K8S中,请问harbor的secret创建能否直接创建资源清单?
在K8S中,请问harbor的secret创建能否直接创建资源清单?
|
3月前
|
存储 Kubernetes 安全
在k8S中,Kubernetes Secret 作用是什么?
在k8S中,Kubernetes Secret 作用是什么?
|
6月前
|
存储 Kubernetes 数据安全/隐私保护
Kubernetes的ConfigMap和Secret
Kubernetes的ConfigMap和Secret
120 0