External Secrets是一个开源的Kubernetes运营商,它与AWS Secrets Manager、HashiCorp Vault、Google Secret Manager和Azure Key Vault等外部秘密管理系统集成,旨在实现将秘密从外部API同步到Kubernetes。该项目是作为 最近宣布的 CS实验室的一部分来管理的。
在本系列的前两篇文章中,我们研究了用AWS和GCP设置外部秘密的问题。这一次,我们将使用Hashicorp Vault 作为秘密提供者。在本教程中,我们将建立自己的Hashicorp Vault实例,使用 Kubernetes认证为我们的工作负载配置认证,然后使用External-Secrets从我们的Vault实例获取信息。
开始学习
为了正确地学习本教程,请确保你已经安装了以下工具。
- Helm第3版
- minikube - 或任何其他kubernetes集群
- 部署了external-secrets
- 安装了vault cli
Kubernetes认证
External-secrets允许为Hashicorp Vault提供商配置几种认证方法。为了运行这个例子,我们需要执行以下步骤。
1.设置Hashicorp Vault
2.配置Hashicorp Vault认证。
a.创建一个策略;
b.配置Kubernetes认证端点;
c.创建一个角色;
d.将角色绑定到kubernetes认证端点。
3.配置 "外部机密"。
设置Hashicorp Vault
为了部署Hashicorp Vault,我们将使用他们的Helm图。如果你已经部署了Vault,或者你正在使用Hashicorp云平台,你可以跳过这一步,直接进入配置Hashicorp Vault认证 部分。
我们首先添加helm资源库,然后用以下命令安装Vault。
helm repo add hashicorp https://helm.releases.hashicorp.com helm install vault hashicorp/vault -n vault --create-namespace
vault部署完毕后,下一步是暴露其服务,这样我们就可以用vault cli来配置它。然后,我们将使用vault cli来初始化vault并解封它
export VAULT_ADDR=http://127.0.0.1:8200 kubectl port-forward svc/vault -n vault 8200:8200 & vault operator init
前面的命令输出了5个解封密钥和一个根令牌。我们将使用这5个解封密钥中的3个来初始化我们的Vault。你选择哪个键并不重要,只要有三个不同的键即可。
vault operator unseal <key 1> vault operator unseal <key 2> vault operator unseal <key 3>.
接下来,我们可以用提供的根令牌登录到我们的保险库。
金库登录<根令牌
配置Hashicorp金库认证
在我们初始化了自己的金库后,接下来的步骤是配置安全的方式来允许外部秘密获取它。
第一步是创建一个演示策略。策略是一种在Vault内强制执行特定访问的方式。在这里,我们正在创建一个政策,只允许
从kv/
path/to/my/secretsecret获取秘密。根据你的需要改变该策略。你可以使用通配符来配置全路径访问。
vault policy write demo-policy -<<EOF path "*" { capabilities = ["read"] }
EOF
我们的策略创建后,我们再启用Kubernetes认证,并添加我们的Kubernetes集群信息作为它的来源。
vault auth enable kubernetes k8s_host="$(kubectl exec vault-0 -n vault -- printenv | grep KUBERNETES_PORT_443_TCP_ADDR | cut -f 2- -d "=" | tr -d ")" k8s_port="443"
k8s_cacert="$(kubectl config view --raw --minify --flatten -o jsonpath='{.cluster[].cluster.certificate-authority-data}' | base64 --decode)" secret_name="$(kubectl get serviceaccount vault -o go-template='')" tr_account_token="$(kubectl get secret ${secret_name} -?o go-template='' | base64 --decode)" vault write auth/kubernetes/config token_reviewer_jwt="${tr_account_token}" kubernetes_host="https://${k8s_host}:${k8s_port}" kubernetes_ca_cert="${k8s_cacert}"
disable_issuer_verification=true
注意:在kubernetes v1.21及以上版本中,不再支持vaultissuer
字段。这就是为什么我们在配置中加入
了disable_issuer_verification=tru。你可以在这个拉动请求中找到更多细节。
在我们的Kubernetes端点配置完成后,下一步是创建一个金库角色来访问秘密。
demo_secret_name="$(kubectl get serviceaccount external-secrets -n es -o go-template='')" demo_account_token="$(kubectl get secret ${demo_secret_name} -n es -o go-template=''| base64 --解码)"
vault write auth/kubernetes/role/demo-role / bound_service_account_names=external-secrets / bound_service_account_namespaces=es / policies=demo-policy / ttl=24h vault write auth/kubernetes/login role=demo-role jwt=$demo_account_token isshttps://kubernetes.default.svc.cluster.local
这里有两件事情发生。首先,我们正在定义一个只有我们的外部秘密服务账户可以访问的角色,并将该角色与我们刚刚创建的演示策略绑定。其次,我们正在创建一个Kubernetes认证方法,提供服务账户令牌,以便对其进行认证,并提供我们希望它承担的角色。
虽然Hashicorp Vault支持各种秘密引擎,如KeyValue、SSH、LDAP、PKI等,但在撰写本文时,外部秘密只支持KeyValue引擎。
让我们启用一个KeyValue引擎端点,然后给它添加一个秘密。
vault secrets enable -version=2 kv vault kv put kv/path/to/my/secret password=secretpassword
配置外部机密
一旦我们完成了Vault的配置,下一步是创建一个SecretStore
绑定到我们刚刚创建的demo-role
,然后创建一个ExternalSecret
来从我们存储在path
/to/my/secret的秘密中获取信息
cat << EOF | kubectl apply -f - apiVersion: external-secrets.io/v1alpha1 kind: SecretStore metadata: name: vault-backend spec: provider: vault: server:"http://vault.vault:8200" path:"kv" 版本。"v2" auth: kubernetes: mountPath:"kubernetes" role: "demo-role" EOF
注意:如果你使用Hashicorp云平台解决方案,你还需要添加namespace。"admin "
在保险库会话中。
cat <<EOF | kubectl apply -f - apiVersion: external-secrets.io/v1alpha1 kind:ExternalSecret metadata: name: vault-example spec: secretStoreRef: name: vault-backend kind: SecretStore target: name: example-sync data: - secretKey: foobar remoteRef: key: path/to/my/secret property: password EOF
就这样了!现在,我们检查我们的秘密是否真的以适当的值被创建了
kubectl get secrets example-sync -o jsonpath='{.data.foobar}' | base64 -d secretpassword%。
我们还可以检查ExternalSecretstatus
。
kubectl get externalsecrets.external-secrets.io vault-example NAME STORE REFRESH INTERVAL STATUS vault-example vault-backend 1h SecretSynced
在生产环境中部署外部秘密的提示
在生产环境中,我们可能有数百(甚至数千)个ExternalSecretsobjects
的部署,操作员可能会过载,导致任何秘密同步操作的性能下降,通常表现为秘密需要更长的时间来获得新的值,这反过来可能会对应用程序造成一些干扰。
为了提高可用性,可以将运营商安装为多个副本,并启用领导者选举,让其分配工作负荷。领导者选举功能在用Kube Builder Toolkit创建的运营商中可用,它可以实现负载平衡。当在有多个副本的情况下启用时,在所有副本中选出一个领导者。如果领导者选举被禁用,每个副本将试图协调每个资源,这通常是我们想要避免的。这方面的更多信息可在官方的Kube Builder文档中找到。有了这个功能,就可以运行多个外部秘密副本,而不必在ExternalSecretsobjects
上重复工作。
为了部署启用领导者选举的运营商,我们只需要在Helm图表安装期间传递两个额外的参数。
elm repo add external-secrets https://charts.external-secrets.io helm install external-secrets external-secrets/external-secrets --set replicaCount=3 --set leaderElect=true
就这样了!现在,如果其中一个副本失败,所有三个副本将分担工作负荷。
注意:虽然不是本教程的一部分,但也可以通过使用控制器标签来分配外部秘密中的工作负载。在这个设置中,我们用一组独特的控制器标签(每个操作员一个)部署多个操作员,然后将SecretStore
绑定到一个控制器上(使用fieldpec.controller
)。然后,所有绑定到该
SecretStore的ExternalSecrets
将只由该运营商处理。你可以在文档中阅读更多关于指定控制器标签的内容。
收尾工作
在这篇文章中,我们看到了如何配置external-
secretst以允许使用Hashicorp Vault作为提供者。还有其他支持的认证方法,如令牌认证和AppRole认证。你可以在官方的external-secrets文档中查看。
总结一下我们所做的事情。
- 设置本地Hashicorp Vault实例
- 配置Kubernetes认证
- 配置外部机密
- 配置领导者选举
在下一篇文章中,我们将看到如何将 Azure Key Vault
配置 为
一个SecretStore
!请继续关注!