本章目录(点击跳转):
- 7.1 为什么要配置分离
- 7.2 ConfigMap 详解
- 7.2.1 创建 ConfigMap 的几种方式
- 7.2.2 使用方式一:环境变量
- 7.2.3 使用方式二:命令行参数
- 7.2.4 使用方式三:挂载为文件(配置文件整体更新场景)
- 7.2.5 修改配置后会发生什么(小白高频疑问)
- 7.3 Secret 详解
- 7.3.1 类型
- 7.3.2 创建与使用
- 7.3.3 实战:私有镜像仓库认证
- 7.3.4 Secret 使用注意事项
- 7.4 最佳实践清单
- 7.5 本章小结
本章目标:掌握 ConfigMap 和 Secret 的三种使用方式(环境变量、命令行参数、文件挂载),并学会镜像仓库认证等实战技巧。
7.1 为什么要配置分离
同一个应用镜像,在开发/测试/生产环境数据库地址、开关不同。如果把配置写死在镜像里:
- 每个环境要构建不同镜像;
- 改个配置就要重新发版;
- 密码进了镜像仓库,泄露风险极大。
K8s 的解法:ConfigMap 放普通配置,Secret 放敏感配置,都注入到 Pod 里,镜像保持一份。
7.2 ConfigMap 详解
7.2.1 创建 ConfigMap 的几种方式
# 方式一:字面量(演示用)
kubectl create configmap app-config \
--from-literal=db-host=mysql.default.svc \
--from-literal=db-port=3306 \
--from-literal=log-level=info
# 方式二:从文件(生产常用,一个文件 = 一个 key,内容是 value)
echo "server.port=8080" > app.properties
kubectl create configmap app-config --from-file=app.properties
# 方式三:从目录(目录下所有文件都进来)
kubectl create configmap nginx-conf --from-file=./conf/
# 方式四:YAML(推荐,可进版本管理)
# app-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
db-host: "mysql.default.svc"
db-port: "3306" # 注意:value 都是字符串
log-level: "info"
app.properties: | # 整个文件作为一个 key
server.port=8080
spring.datasource.url=jdbc:mysql://mysql:3306/mydb
kubectl apply -f app-config.yaml
kubectl get configmap app-config -o yaml
kubectl create configmap app-config --from-file=app.properties --dry-run=client -o yaml
# 最后一句:用 kubectl 生成 YAML,保存下来进 git,很实用
7.2.2 使用方式一:环境变量
apiVersion: v1
kind: Pod
metadata:
name: cm-env-demo
spec:
containers:
- name: app
image: busybox:1.36
command: ["sh", "-c", "echo db=$DB_HOST port=$DB_PORT; sleep 3600"]
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: db-host
- name: DB_PORT
valueFrom:
configMapKeyRef:
name: app-config
key: db-port
# 一次性引入整个 ConfigMap(每个 key 变一个环境变量)
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: log-level
envFrom: # 或者整体引入
- configMapRef:
name: app-config
kubectl apply -f - <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: cm-env-demo
spec:
containers:
- name: app
image: busybox:1.36
command: ["sh", "-c", "env | sort; sleep 3600"]
envFrom:
- configMapRef:
name: app-config
EOF
kubectl logs cm-env-demo
kubectl delete pod cm-env-demo
7.2.3 使用方式二:命令行参数
command: ["python", "app.py"]
args:
- "--db=$(DB_HOST):$(DB_PORT)" # 容器内支持 $(VAR) 插值(需先定义 env)
7.2.4 使用方式三:挂载为文件(配置文件整体更新场景)
apiVersion: v1
kind: Pod
metadata:
name: cm-file-demo
spec:
containers:
- name: app
image: busybox:1.36
command: ["sh", "-c", "cat /etc/app/app.properties; sleep 3600"]
volumeMounts:
- name: config
mountPath: /etc/app
volumes:
- name: config
configMap:
name: app-config
# 应用后查看
kubectl logs cm-file-demo
# 只挂单个 key 为单个文件:
# volumes:
# - name: config
# configMap:
# name: app-config
# items:
# - key: app.properties
# path: app.properties
7.2.5 修改配置后会发生什么(小白高频疑问)
- env 方式:ConfigMap 改了,Pod 里的环境变量不会自动变,需要重启 Pod 才生效(
kubectl rollout restart deployment xxx)。 - 文件挂载方式:K8s 会定期同步(默认 1 分钟内)更新文件内容,但应用自己要监听文件变化才会生效(比如 Spring Cloud、Nginx 的 reload 机制)。
# 修改 ConfigMap
kubectl edit configmap app-config
# 让 env 方式生效:重启工作负载
kubectl rollout restart deployment web
7.3 Secret 详解
7.3.1 类型
| 类型 | 用途 |
|---|---|
Opaque(默认) |
任意键值对 |
kubernetes.io/dockerconfigjson |
私有镜像仓库认证 |
kubernetes.io/tls |
TLS 证书(第 5 章用过) |
kubernetes.io/basic-auth / ssh-auth |
基础认证/SSH |
⚠️ Secret 默认只是 base64 编码,不是加密!base64 是编码不是加密,任何人拿到都能解码。生产要开启 etcd 静态加密(Encryption at Rest)并严格 RBAC。
7.3.2 创建与使用
# 创建
kubectl create secret generic db-secret \
--from-literal=username=root \
--from-literal=password='P@ssw0rd'
# 从文件
kubectl create secret generic tls-secret --from-file=ca.crt=./ca.crt
# 查看(注意输出是 base64)
kubectl get secret db-secret -o yaml
# 解码看明文
kubectl get secret db-secret -o jsonpath='{.data.password}' | base64 -d
# 使用(与 ConfigMap 几乎一样,只是 secretKeyRef)
apiVersion: v1
kind: Pod
metadata:
name: secret-demo
spec:
containers:
- name: app
image: busybox:1.36
command: ["sh", "-c", "echo user=$DB_USER pass=$DB_PASS; sleep 3600"]
env:
- name: DB_USER
valueFrom:
secretKeyRef:
name: db-secret
key: username
- name: DB_PASS
valueFrom:
secretKeyRef:
name: db-secret
key: password
kubectl apply -f secret-demo.yaml # 上面 YAML 存为 secret-demo.yaml
kubectl logs secret-demo
# 输出:user=root pass=P@ssw0rd
kubectl delete pod secret-demo
7.3.3 实战:私有镜像仓库认证
私有镜像拉不下来(ImagePullBackOff)时,多半要配 registry 凭证:
# 创建 dockerconfigjson 类型的 Secret
kubectl create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=admin \
--docker-password=secret \
--docker-email=admin@example.com
Pod 里引用:
spec:
imagePullSecrets:
- name: regcred
containers:
- name: app
image: registry.example.com/myapp:1.0
也可以把 imagePullSecret 写到 ServiceAccount 上,该 SA 的所有 Pod 自动带上。
7.3.4 Secret 使用注意事项
- Secret 只能被同命名空间的 Pod 引用(跨命名空间要复制或用工具同步)。
- 不要把 Secret 写进 git;YAML 里只引用名字,不写明文。
- 审计:
kubectl get secret -A能列出所有,RBAC 要管住(第 8 章)。
7.4 最佳实践清单
- 配置进 ConfigMap,敏感进 Secret,镜像里一个不留。
- 配置随应用一起进 git(ConfigMap 的 YAML 可以进 git;Secret 用 SealedSecret / SOPS / 云 KMS 等方案加密后管理)。
- 用
--dry-run=client -o yaml把 kubectl 生成的对象落成文件。 - 应用做好"配置变更"处理:文件挂载 + 监听变化 > 环境变量(改配置不用重启)。
- 每个环境一个 ConfigMap(
app-config-dev/app-config-prod),用不同的 Deployment 模板引用。
7.5 本章小结
- ConfigMap/Secret 三种注入方式:env、args 插值、文件挂载。
- env 方式改配置必须重启 Pod;文件方式有同步延迟且应用需支持热加载。
- Secret 是 base64 不是加密,生产要 etcd 加密 + 严格 RBAC。
- 私有镜像拉不动先查
imagePullSecrets。
下一章:命名空间与权限(RBAC)。
原文链接:第7章 配置与密钥,转载请注明来源!
