4. Secret基础:Secret概念、类型与编解码
聊到 Kubernetes 里的敏感信息管理,Secret 绝对是绕不开的核心组件。我记得刚接触 K8s 那会儿,有个同事直接把数据库密码写在了 Pod 的 YAML 里——嗯,现在想想都觉得后怕。Secret 就是为了解决这类问题而生的。
4.1 Secret 到底是什么?
说白了,Secret 就是用来存储小量敏感数据的对象。比如密码、Token、SSH 密钥这些。它的设计初衷很明确:把配置和镜像解耦,避免敏感信息暴露在镜像或代码仓库里。
你想想看,如果你的应用代码里硬编码了数据库密码,那每次改密码都得重新构建镜像。这多麻烦?用 Secret 的话,改个密码只需要更新 K8s 资源对象,然后滚动重启 Pod 就行了。
核心要点:Secret 的数据以 Base64 编码存储,但这只是编码,不是加密。很多人误以为 Base64 就是加密,这是个常见的误解。
4.2 Secret 的三种主要类型
K8s 内置了好几种 Secret 类型,但日常工作中最常用的就三种。我一个个说。
4.2.1 Opaque:最通用的类型
Opaque 是默认类型,也是最常用的。说白了就是键值对,值需要你自己 Base64 编码。适合存数据库密码、API Key 这类自定义的敏感信息。
apiVersion: v1
kind: Secret
metadata:
name: my-db-secret
type: Opaque
data:
username: YWRtaW4= # admin
password: MWYyZDFlMmU2N2Rm # 1f2d1e2e67df
我个人习惯用 kubectl create secret generic 命令来创建,省得自己手动编码。比如:
kubectl create secret generic my-db-secret \
--from-literal=username=admin \
--from-literal=password='1f2d1e2e67df'
这样 K8s 会自动帮你做 Base64 编码,省心不少。
4.2.2 Service Account Token:自动挂载的凭证
这种类型你可能每天都在用,只是没注意到。每个 Namespace 创建时,K8s 会自动生成一个 default Service Account,并关联一个 Service Account Token 类型的 Secret。
这个 Secret 会被自动挂载到 Pod 的 /var/run/secrets/kubernetes.io/serviceaccount/ 目录下。里面包含三个文件:
ca.crt:集群 CA 证书namespace:当前 Namespace 名称token:用于 API Server 认证的 JWT Token
我在项目中遇到过一个问题:有个 Pod 需要访问 K8s API,但一直报 403。查了半天发现是 Service Account 权限没配好。后来给这个 SA 绑定了合适的 RoleBinding 才解决。
小提示:从 K8s 1.24 开始,Service Account Token 不再自动创建 Secret 了。改用 TokenRequest API 动态生成,安全性更高。如果你还在用旧版本,建议升级。
4.2.3 dockerconfigjson:镜像仓库的通行证
这种类型专门用来存 Docker 镜像仓库的认证信息。当你从私有仓库拉取镜像时,就需要用到它。
创建方式很简单:
kubectl create secret docker-registry my-registry-secret \
--docker-server=https://index.docker.io/v1/ \
--docker-username=myusername \
--docker-password=mypassword \
--docker-email=myemail@example.com
然后在 Pod 里引用:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: my-private-registry/my-image:latest
imagePullSecrets:
- name: my-registry-secret
我曾经踩过一个坑:在多个 Namespace 里都要拉同一个私有仓库的镜像,结果每个 Namespace 都创建了一个 dockerconfigjson Secret。后来发现其实可以创建一个全局的,通过 serviceAccount 的 imagePullSecrets 字段统一配置,省事多了。
4.3 编码与解码:别被 Base64 骗了
很多人以为 Secret 里的数据是加密的,其实不是。Base64 只是一种编码方式,不是加密算法。随便找个在线工具就能解码。
举个例子:
# 编码
echo -n "my-password" | base64
# 输出:bXktcGFzc3dvcmQ=
# 解码
echo -n "bXktcGFzc3dvcmQ=" | base64 --decode
# 输出:my-password
看到了吧?解码后就是明文。所以千万别把 Secret 的 YAML 文件提交到公开的 Git 仓库里。
警告:Base64 编码的 Secret 数据在 etcd 中也是以明文存储的。如果你对安全性有更高要求,建议开启 etcd 加密,或者使用外部密钥管理服务(如 HashiCorp Vault、AWS KMS)。
我个人习惯在开发环境用 K8s 原生 Secret,生产环境则用外部密钥管理方案。这样既保证了开发效率,又兼顾了生产安全。
4.4 实际操作中的注意事项
最后分享几个我在实战中总结的经验:
- 大小限制:单个 Secret 最大 1MB。不是 K8s 的限制,而是 etcd 的限制。如果你的配置数据超过这个值,考虑用 ConfigMap 或者挂载外部存储。
- 更新策略:修改 Secret 后,已经运行的 Pod 不会自动更新。需要手动重启 Pod,或者用一些工具(如 Reloader)来自动监听并触发滚动更新。
- 审计日志:Secret 的读取操作会被记录到审计日志中。如果你发现有人频繁读取某个 Secret,那就要警惕了——可能有人在尝试窃取敏感信息。
嗯,关于 Secret 的基础知识就聊到这里。下一节我们会深入讨论如何安全地管理 Secret,包括加密存储、访问控制等进阶话题。