上节课学习了ConfigMap
,了解了ConfigMap
这个资源对象是K8S
当中非常重要的一个对象,ConfigMap
一般情况下是用来存储一些非安全的配置信息,如果涉及到一些安全相关的数据的话用ConfigMap
就不适合了,因为ConfigMap
是明文存储的,如果需要加密存储,就需要用到另外一个资源对象了:Secret
,Secret
用来保存敏感信息,例如密码、API 密钥、TLS 证书等等,将这些信息放在Secret
中比放在Pod
的定义中或者docker
镜像中来说更加安全和灵活。
Secret
Secret 是 Kubernetes 中用于管理敏感信息(如密码、API 密钥、TLS 证书等)的核心资源。其设计目标是避免敏感数据硬编码到 Pod 或镜像中,提升安全性与可维护性。
一、Secret 的核心特性
-
数据安全
- Base64 编码存储:Secret 中的数据默认以 Base64 编码形式保存于 etcd 中,但需注意这并非加密,仅提供基础防护。
- 动态注入:支持通过环境变量或文件挂载方式注入到 Pod 中,无需重启容器即可更新(需重新创建 Pod)。
- 类型化支持:预定义多种类型适配不同场景,例如:
- **
Opaque
**:通用键值对存储(如用户名、密码)。 - **
kubernetes.io/tls
**:存储 HTTPS 证书和私钥。 - **
kubernetes.io/dockerconfigjson
**:私有镜像仓库认证信息。
- **
二、Secret 的创建与使用
1. 创建方式
-
命令行创建:
# 通用类型(键值对)
kubectl create secret generic my-secret --from-literal=username=root --from-literal=password=password
# TLS 证书类型
kubectl create secret tls my-tls-secret --cert=path/to/cert.pem --key=path/to/key.pem
-
YAML 文件定义:
apiVersion: v1
kind: Secret
metadata:
name: db-secret
data:
username: cm9vdA== # "root" 的 Base64 编码
password: cGFzc3dvcmQ= # "password" 的 Base64 编码
2.挂载方式
-
环境变量注入:
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
-
文件挂载:
volumes:
- name: secret-volume
secret:
secretName: db-secret
containers:
- volumeMounts:
- name: secret-volume
mountPath: "/etc/secrets"
3. 数据查看与验证
-
查看 Secret 详情:
kubectl get secret my-secret -o yaml # 显示编码后的数据
# kubectl get secret my-secret -o yaml
apiVersion: v1
data:
password: cGFzc3dvcmQ=
username: cm9vdA==
kind: Secret
metadata:
creationTimestamp: "2025-04-02T03:24:44Z"
name: my-secret
namespace: default
resourceVersion: "224361"
uid: be74cf70-d200-40de-b064-d3b99340f83f
type: Opaque
echo "cm9vdA==" | base64 -d # 解码示例
# echo "cm9vdA==" | base64 -d
root
三、举例说明
1.常规案例
1.创建secret
# cat secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: db-secret
data:
username: cm9vdA== # "root" 的 Base64 编码
password: cGFzc3dvcmQ= # "password" 的 Base64 编码
2. 创建deployment.yaml
# cat deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp-deployment-secret
labels:
app: webapp
spec:
replicas: 3
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: m.daocloud.io/docker.io/nginx
# 方式一:环境变量注入
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-secret
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
# 方式二:文件挂载
volumeMounts:
- name: secret-volume
mountPath: "/etc/db-credentials"
readOnly: true
volumes:
- name: secret-volume
secret:
secretName: db-secret
3.应用并验证
通过下图可以看出来,两种方式的secret都使用成功
①② 应用2个yaml文件
③ 查看pod
④ 进入任意一个pod
⑤⑥ 查看通过环境变量方式挂载secret 显示 用户密码
⑦⑧ 查看通过文件方式挂载secret 显示 现在用户密码
2.登录私有仓库的案例
上面举例说明了secret的使用,下面再举例一个用的最多的,也就是通过secret登录自己的私有仓库下载镜像
1. 创建 Docker Hub 认证 Secret
#方式1, 通过kubectl create 创建一个secret
kubectl create secret docker-registry dockerhub-secret \
--docker-server=https://index.docker.io/v1/ \
--docker-username=your-username \
--docker-password=your-password \
--docker-email=your-email@example.com
#方式2,通过yaml文件创建
apiVersion: v1
kind: Secret
metadata:
name: dockerhub-secret
namespace: default
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: eyJhdXRocyI6eyJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOnsidXNlcm5hbWUiOiJ5b3VyLXVzZXJuYW1lIiwicGFzc3dvcmQiOiJ5b3VyLXBhc3N3b3JkIiwiZW1haWwiOiJ5b3VyLWVtYWlsQGV4YW1wbGUuY29tIiwiYXV0aCI6ImVXOTFjaTExYzJWeWJtRnRaVHA1YjNWeUxYQmhjM04zYjNKayJ9fX0=
上面方式2 .dockerconfigjson后面一大截可能看起来会不知道什么意思,其实解码后能知道,是一串json键值对,包含方式1里面的仓库地址,用户密码等信息
#解码
# echo "eyJhdXRocyI6eyJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOnsidXNlcm5hbWUiOiJ5b3VyLXVzZXJuYW1lIiwicGFzc3dvcmQiOiJ5b3VyLXBhc3N3b3JkIiwiZW1haWwiOiJ5b3VyLWVtYWlsQGV4YW1wbGUuY29tIiwiYXV0aCI6ImVXOTFjaTExYzJWeWJtRnRaVHA1YjNWeUxYQmhjM04zYjNKayJ9fX0=" |base64 -d
{"auths":{"https://index.docker.io/v1/":{"username":"your-username","password":"your-password","email":"your-email@example.com","auth":"eW91ci11c2VybmFtZTp5b3VyLXBhc3N3b3Jk"}}}
2.创建deployment来使用这个secret
imagePullSecrets: # 关键配置:声明拉取镜像的凭证
- name: dockerhub-secret # 必须与 Secret 名称一致
apiVersion: apps/v1
kind: Deployment
metadata:
name: private-image-deployment
spec:
replicas: 2
selector:
matchLabels:
app: private-app
template:
metadata:
labels:
app: private-app
spec:
containers:
- name: app-container
image: your-dockerhub-username/private-image:latest # 私有镜像地址
ports:
- containerPort: 8080
imagePullSecrets: # 关键配置:声明拉取镜像的凭证
- name: dockerhub-secret # 必须与 Secret 名称一致
3.验证
由于这里的用户信息都是为了举例填写的,会登录失败,所以结果会拉取失败,大家在日常使用中修改为自己的仓库地址信息即可。
四、常见问题与解决方案
-
Secret 更新后未生效
- 原因:已运行的 Pod 不会自动同步 Secret 变更。
- 解决:重建 Pod 或使用支持热加载的应用框架(如 Nginx Reload)。
-
Base64 编码错误
- 注意点:使用
echo -n
避免换行符干扰编码结果。 - 验证命令:
kubectl get secret <name> -o jsonpath='{.data}' | jq .
检查数据完整性。
- 注意点:使用
-
Secret 挂载权限问题
- 设置文件权限:在 Volume 挂载时指定
defaultMode
参数限制文件访问权限。
- 设置文件权限:在 Volume 挂载时指定
五、与 ConfigMap 的对比
维度 | Secret | ConfigMap |
---|---|---|
数据安全 | Base64 编码 | 明文存储 |
适用场景 | 密码、密钥、证书等 | 配置文件、环境变量等 |
加密支持 | 需配合 KMS 或 Vault | 无原生加密 |
存储限制 | 1MB | 1MB |