Kubernetes中存放密码、令牌与证书等敏感信息的资源对象
Secret 用于存放密码、API Token、SSH 密钥、TLS 证书等敏感数据,用法与 ConfigMap 几乎一致,但独立成一种资源是为了施加更严格的管控:可以单独授权 RBAC、可以配合 etcd 静态加密、在 kubectl describe 中也不会直接展开内容。
需要特别强调的是:Secret 默认只是 base64 编码,不是加密。任何能读取该 Secret 的人都可以一条命令还原出明文。它的安全性来自访问控制(RBAC)与 etcd 加密配置,而不是编码本身。把 Secret 当成「加密过的 ConfigMap」是极其危险的误解。
Opaque 默认类型,任意键值对
kubernetes.io/service-account-token 服务账号令牌,由控制器自动创建
kubernetes.io/dockerconfigjson 私有镜像仓库的认证信息
kubernetes.io/tls TLS 证书与私钥,key 必须为 tls.crt 与 tls.key
kubernetes.io/basic-auth 用户名密码,key 为 username 与 password
kubernetes.io/ssh-auth SSH 私钥,key 为 ssh-privatekey
bootstrap.kubernetes.io/token 节点引导令牌
# 从字面量创建(值会自动 base64 编码)
kubectl create secret generic db-secret \
--from-literal=username=admin \
--from-literal=password='S3cr3t!'
# 从文件创建
kubectl create secret generic tls-secret --from-file=./cert.pem
# 从 env 文件创建
kubectl create secret generic app-secret --from-env-file=secret.env
# 创建 TLS 类型
kubectl create secret tls example-tls --cert=tls.crt --key=tls.key
# 创建镜像仓库认证
kubectl create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=admin \
--docker-password='S3cr3t!' \
--docker-email=admin@example.com
# 从已有 docker 配置创建
kubectl create secret generic regcred \
--from-file=.dockerconfigjson=$HOME/.docker/config.json \
--type=kubernetes.io/dockerconfigjson
kubectl get secret [名称] [选项]
kubectl describe secret [名称]
kubectl create secret [类型] [名称] [数据来源] [选项]
kubectl delete secret [名称]
Opaque 类型,data 中的值必须是 base64 编码:
apiVersion: v1
kind: Secret
metadata:
name: db-secret
namespace: default
type: Opaque
data:
username: YWRtaW4= # echo -n 'admin' | base64
password: UzNjcjN0IQ== # echo -n 'S3cr3t!' | base64
stringData 可以直接写明文,apiserver 会在写入时自动编码并合并进 data,但读取时不会显示出来:
apiVersion: v1
kind: Secret
metadata:
name: db-secret-plain
type: Opaque
stringData:
username: admin
password: "S3cr3t!"
TLS 证书类型:
apiVersion: v1
kind: Secret
metadata:
name: example-tls
type: kubernetes.io/tls
data:
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t...
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0t...
注入为环境变量:
apiVersion: v1
kind: Pod
metadata:
name: secret-env-demo
spec:
containers:
- name: app
image: busybox:1.36
command: ["sh", "-c", "sleep 3600"]
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-secret
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
envFrom:
- secretRef:
name: db-secret
optional: false
挂载为文件,适合证书与配置文件:
apiVersion: v1
kind: Pod
metadata:
name: secret-volume-demo
spec:
containers:
- name: app
image: nginx:1.27
volumeMounts:
- name: tls-volume
mountPath: /etc/nginx/certs
readOnly: true
volumes:
- name: tls-volume
secret:
secretName: example-tls
defaultMode: 0400 # 私钥建议收紧权限
items:
- key: tls.crt
path: server.crt
- key: tls.key
path: server.key
mode: 0400
拉取私有镜像时引用 imagePullSecrets,写在 spec.template.spec 下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
replicas: 2
selector:
matchLabels:
app: app
template:
metadata:
labels:
app: app
spec:
imagePullSecrets:
- name: regcred
containers:
- name: app
image: registry.example.com/team/app:1.0.0
envFrom:
- secretRef:
name: db-secret
# 查看列表(只显示 key 数量与大小,不显示内容)
kubectl get secret -A
kubectl describe secret db-secret
# 取出某个 key 并解码
kubectl get secret db-secret -o jsonpath='{.data.password}' | base64 -d
echo "UzNjcjN0IQ==" | base64 -d
# 一次性解码所有 key
kubectl get secret db-secret -o go-template='{{range $k,$v := .data}}{{$k}}={{$v|base64decode}}{{"\n"}}{{end}}'
# 转为可读的明文视图
kubectl view-secret db-secret # 需安装 view-secret 插件
Secret 默认以明文存放在 etcd 中,开启静态加密需要在 apiserver 上配置 EncryptionConfiguration,并用 --encryption-provider-config 指向该文件。配置完成后,已存在的 Secret 必须重写一遍才会真正加密:
head -c 32 /dev/urandom | base64 # 生成 aescbc 密钥
kubectl get secrets -A -o json | kubectl replace -f -
kubectl get secret -o jsonpath='{.data}' | base64 -d 即可还原明文,任何拥有读取权限(包括能创建 Pod 的人)都能拿到。真正的防护来自 RBAC 最小授权与 etcd 静态加密。imagePullSecrets 也一样,每个命名空间需要各建一份。kubectl exec env、崩溃日志、子进程继承等方式泄露。能挂载就优先挂载为文件。stringData 是只写的。用它写入的值会被合并进 data,但 kubectl get -o yaml 只会显示 data,看不到 stringData,不要以为数据丢了。kubectl create secret --dry-run=client -o yaml 输出的仍是 base64,纳入 Git 之前务必确认没有把明文密钥提交上去;生产环境应使用 SealedSecrets、External Secrets 或 SOPS 之类的方案。tls.crt 与 tls.key,写成 cert/key 不会被 Ingress 识别,证书不会生效且不报错。subPath 挂载的则不会,与 ConfigMap 行为一致。应用需要自行监听文件变化并重载。CreateContainerConfigError,排查时容易被误导。kubectl — Kubernetes集群管理工具configmap — 存放非敏感配置的同类资源service — 与之配合的ServiceAccount令牌来源namespace — Secret的作用域边界kubeadm — Kubernetes集群安装与生命周期管理工具