K8S Secret 和 Vault
Secret
secret 用于存敏感信息,避免将密码等敏感数据硬编码到配置文件中,比如所有要用到 PG 的 pod 都使用同一个已经配置好的 secret,这样 PG 的用户密码就在 secret 被统一管理了,并且每个 pod 的配置都只需要指向 secret 不会暴露密码数据
主要有两种方式把 secret 传给 Pod
- 配置环境变量,设置其来源为某个 secret
- 挂载 Volumn,设置其来源为某个 secret
- imagePullSecrets
但 Secret 本身并不是很安全
sudo kubectl get secret flux-system -o yaml 命令就能看到数据
在 git 代码库也能看到
虽然值是 base64 编码,但和明文其实差不多
所以前面的做法只是统一了敏感数据的管理,其他 deployment 只引用 secret,减少部分风险
可以采取措施进一步保证安全
- 使用 RBAC 限制哪些 Pod 或 Account 才能访问 Secret
- 加密数据,即使被暴露也不会被破解
- 定期更改密码
- 使用专门的密钥管理服务,将密钥与应用解耦
最理想的是使用专门的密码管理服务
Vault
Vault 是一个被广泛使用的密码管理服务,包括一个 Vault 服务器,和装在 K8S 上的 vault-agent-injector 等
可以把 Vault 服务器也装在 K8S 上(可以通过 Helm 命令安装)
这样密码等敏感信息就统一存在 Vault 上,由 Vault 管理,只要限制少数有权限的人去配置就可以
然后 Deployment 可以通过不同方法(变量、文件等)指向 Vault 上的配置,这样就不会有 Secret 被暴露的问题
当然如果能登陆上 Vault 或 App 的 Pod 的话还是会暴露的
安装 Vault
sudo helm repo add hashicorp https://helm.releases.hashicorp.com
sudo helm install vault hashicorp/vault --version 0.19.0 --set "server.dev.enabled=true" -n vault
安装好后查看 vault 这个 namespace 下的 pod
$ sudo kubectl get pods -n vault
NAME READY STATUS RESTARTS AGE
vault-0 1/1 Running 0 174m
vault-agent-injector-6cd49f8bbd-xflhm 1/1 Running 0 174m
可以看到有两个 pod
vault-0 是 vault 服务器
vault-agent-injector 用于 Deployment 获取 vault 配置的数据
查看 vault 的登录 token
sudo kubectl logs vault-0 -n vault
Unseal Key: FHrkeZnLwHHMWJScB4iTTa71JA49QlDxh0pIYCM34Mg=
Root Token: root
由于默认没有暴露 HTTP 端口,可以自己配置 NodePort
apiVersion: v1
kind: Service
metadata:
name: vault-node
namespace: vault
spec:
type: NodePort
selector:
app.kubernetes.io/instance: vault
app.kubernetes.io/name: vault
component: server
ports:
- name: http
port: 8200
protocol: TCP
targetPort: 8200
nodePort: 30820
- name: https-internal
port: 8201
protocol: TCP
targetPort: 8201
nodePort: 30821
这样就可以使用 root token 登录 Vault UI
http://localhost:30820/ui
上面可以配置查看数据
也可以直接登录 Pod 配置查看
在 Vault 配置数据
配置 PG 数据库的用户密码
~$ sudo kubectl exec -it vault-0 /bin/sh -n vault
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ $
/ $ vault secrets enable -path=internal kv-v2
Success! Enabled the kv-v2 secrets engine at: internal/
/ $
/ $
/ $ vault kv put internal/database/config username="pg-username" password="pg-password"
Key Value
--- -----
created_time 2023-12-21T09:32:53.353327656Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
/ $
/ $ vault kv get internal/database/config
======= Metadata =======
Key Value
--- -----
created_time 2023-12-21T09:32:53.353327656Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
====== Data ======
Key Value
--- -----
password pg-password
username pg-username
/ $
为了 K8S 能访问到,还要开启 vault 的 kubernetes 认证
/ $ vault auth enable kubernetes
Success! Enabled kubernetes auth method at: kubernetes/
配置 kubernetes 认证
vault write auth/kubernetes/config \
token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443" \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
Success! Data written to: auth/kubernetes/config
授予用户访问 internal/database/config 的权限
vault policy write internal-app - <<EOH
path "internal/data/database/config" {
capabilities = ["read"]
}
EOH
Success! Uploaded policy: internal-app
关联 service account
vault write auth/kubernetes/role/internal-app \
bound_service_account_names=internal-app \
bound_service_account_namespaces=default \
policies=internal-app \
ttl=24h
Success! Data written to: auth/kubernetes/role/internal-app
这样就可以用 Deployment 访问 Vault 数据了
Deployment 读取 Vault 数据
创建 service account
apiVersion: v1
kind: ServiceAccount
metadata:
name: internal-app
namespace: default
创建 deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: vault-demo
labels:
app: vault-demo
spec:
selector:
matchLabels:
app: vault-demo
template:
metadata:
labels:
app: vault-demo
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "internal-app"
vault.hashicorp.com/agent-inject-secret-database-config.txt: "internal/data/database/config"
spec:
serviceAccountName: internal-app
containers:
- name: vault-demo
image: busybox:1.28.4
imagePullPolicy: IfNotPresent
command: [ 'sh', '-c', "while true; do echo hello; sleep 6000; done" ]
annotations 下的 vault.hashicorp.com 几个配置,会被 vault-agent-injector 检查到
然后会依据 role 的权限,把 internal/data/database/config 的数据存到 database-config.txt 文件里(agent-inject-secret- 配置是前缀会被去掉)
部署 app 然后查看
$ sudo kubectl get pods
NAME READY STATUS RESTARTS AGE
vault-demo-5bc4656884-cmlqw 2/2 Running 0 9s
Pod 下面有两个 container 分别是 vault-demo 和 vault-agent-init
vault-agent-init 作为 sidecar 把 secret 添加到 vault-demo 应用容器
登录 vault-demo 并读取数据
~$ sudo kubectl exec -it vault-demo-5bc4656884-cmlqw -c vault-demo /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ #
/ # cat /vault/secrets/database-config.txt
data: map[password:pg-password username:pg-username]
metadata: map[created_time:2023-12-21T09:32:53.353327656Z custom_metadata:<nil> deletion_time: destroyed:false version:1]
这样所有敏感数据都不会暴露在外面,除非能登上 Pod
如果想自定义文件的内容,可以加一个 agent-inject-template-database-config.txt
注意 agent-inject-template- 后面的值要和 agent-inject-secret- 的值一样
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "internal-app"
vault.hashicorp.com/agent-inject-secret-database-config.txt: "internal/data/database/config"
vault.hashicorp.com/agent-inject-template-database-config.txt: |
{{- with secret "internal/data/database/config" -}}
export username="{{ .Data.data.username }}"
export password="{{ .Data.data.password }}"
{{- end }}
再上 Pod 查看
/ # cat /vault/secrets/database-config.txt
export username="pg-username"
export password="pg-password"
可以看到,变成自定义的格式了
Vault Secrets Operator
Vault Secrets Operator 可以把 Vault 数据导入到 Secrets
sudo helm repo add hashicorp https://helm.releases.hashicorp.com
sudo helm install vault-secrets-operator hashicorp/vault-secrets-operator -n vault
如果下载不了 gcr.io/kubebuilder/kube-rbac-proxy 而无法启动 vault-secrets-operator
尝试设置代理,通过 docker info | grep -i proxy 命令可以查看有没有代理
如果没有,可以添加文件
$ cat /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=xxx"
Environment="HTTPS_PROXY=xxx"
$
$
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
$
或者从其他地方下载,再改名字
docker pull anjia0532/kubebuilder.kube-rbac-proxy:v0.15.0
docker tag anjia0532/kubebuilder.kube-rbac-proxy:v0.15.0 gcr.io/kubebuilder/kube-rbac-proxy:v0.15.0
使用 Vault Secrets Operator 具体例子可以参考
https://github.com/hashicorp/vault-secrets-operator/tree/main/config/samples
里面的 setup.sh 是在 Vault 做配置
还有配置 vault 的链接认证的
secrets_v1beta1_vaultconnection.yaml
secrets_v1beta1_vaultauth.yaml
最后是设置 VaultStaticSecret 和 Pod
secrets_v1beta1_vaultstaticsecret.yaml
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 提示词工程——AI应用必不可少的技术
· 地球OL攻略 —— 某应届生求职总结
· 字符编码:从基础到乱码解决
· SpringCloud带你走进微服务的世界