应用代码和配置必须分离——这是十二要素应用的核心原则之一。Kubernetes 通过 ConfigMap 和 Secret 实现配置管理,通过 PV/PVC 体系实现存储管理。理解这些机制,是构建可移植、可维护的云原生应用的前提。
一、ConfigMap:配置管理
ConfigMap 将非敏感配置数据以键值对形式存储,Pod 通过环境变量或 Volume 挂载引用。
1.1 创建 ConfigMap
apiVersion: v1kind: ConfigMapmetadata: name: app-configdata: # 简单键值对 LOG_LEVEL: "info" MAX_CONNECTIONS: "100" # 完整配置文件 nginx.conf: | server { listen 80; location / { proxy_pass http://backend:8080; } }# 从文件创建 ConfigMapkubectl create configmap app-config --from-file=nginx.conf
# 从目录创建(目录中每个文件成为一个键)kubectl create configmap app-config --from-file=config/
# 从字面值创建kubectl create configmap app-config --from-literal=LOG_LEVEL=info1.2 Pod 引用 ConfigMap
方式一:环境变量
spec: containers: - name: my-app image: my-app:v1 envFrom: # 引用整个 ConfigMap - configMapRef: name: app-config env: # 引用单个键 - name: LOG_LEVEL valueFrom: configMapKeyRef: name: app-config key: LOG_LEVEL方式二:Volume 挂载
spec: containers: - name: my-app image: my-app:v1 volumeMounts: - name: config mountPath: /etc/nginx/nginx.conf subPath: nginx.conf # 挂载单个键,不覆盖目录 volumes: - name: config configMap: name: app-config通过 Volume 挂载的 ConfigMap 会自动更新——当 ConfigMap 内容变更时,Pod 内的文件会自动刷新(有延迟,通常 1-2 分钟)。通过环境变量引用的 ConfigMap 不会自动更新——需要重启 Pod 才能生效。
二、Secret:敏感信息管理
Secret 的数据以 Base64 编码存储。虽然 Base64 不是加密,但 Secret 与 ConfigMap 的分离使得 RBAC 可以对敏感信息施加更严格的访问控制。
2.1 Secret 类型
| 类型 | 用途 | 示例 |
|---|---|---|
Opaque | 通用键值对(默认) | 数据库密码、API Token |
kubernetes.io/tls | TLS 证书 | Ingress HTTPS |
kubernetes.io/dockerconfigjson | 镜像拉取凭证 | 私有镜像仓库 |
kubernetes.io/basic-auth | 基本认证 | 用户名密码 |
kubernetes.io/ssh-auth | SSH 认证 | SSH 密钥 |
2.2 创建与使用 Secret
# 创建通用 Secretkubectl create secret generic db-secret \ --from-literal=username=admin \ --from-literal=password='S3cur3P@ss!'
# 创建 TLS Secretkubectl create secret tls tls-secret \ --cert=cert.pem \ --key=key.pem
# 创建镜像拉取 Secretkubectl create secret docker-registry regcred \ --docker-server=registry.example.com \ --docker-username=user \ --docker-password=pass# Pod 引用 Secretspec: containers: - name: my-app image: my-app:v1 env: - name: DB_PASSWORD valueFrom: secretKeyRef: name: db-secret key: password imagePullSecrets: # 拉取私有镜像 - name: regcred2.3 Secret 安全最佳实践
| 实践 | 说明 |
|---|---|
| 启用 etcd 加密 | 配置 EncryptionConfiguration,Secret 在 etcd 中加密存储 |
| 使用外部密钥管理 | 通过 External Secrets Operator 对接 Vault/AWS Secrets Manager |
| 限制 RBAC | 只授予必要的 Secret 读取权限 |
| 避免明文提交 | 不要将 Secret YAML 提交到 Git,使用 Sealed Secrets 或 SOPS |
| 使用 ServiceAccount Token | Kubernetes 1.24+ 自动挂载短期 Token,取代长期 Secret |
默认情况下,Secret 在 etcd 中以 Base64 明文存储。任何有 etcd 访问权限的人都能读取 Secret 原文。生产环境必须启用 etcd 静态加密。
三、Volume:存储卷基础
Volume 将存储挂载到 Pod 中,其生命周期与 Pod 相同——Pod 删除时 Volume 也被清理(临时卷)。持久化存储需要 PV/PVC。
3.1 常见临时卷类型
| 类型 | 说明 | 适用场景 |
|---|---|---|
emptyDir | Pod 内共享的临时目录,Pod 删除即消失 | Sidecar 共享文件、缓存 |
hostPath | 挂载宿主机路径 | 调试、DaemonSet 访问节点文件 |
configMap | 挂载 ConfigMap 内容 | 配置文件 |
secret | 挂载 Secret 内容 | 证书、密钥 |
projected | 将多个源投射到同一目录 | 组合 ConfigMap + Secret |
spec: containers: - name: app image: my-app:v1 volumeMounts: - name: cache mountPath: /tmp/cache - name: config mountPath: /etc/config volumes: - name: cache emptyDir: # 临时目录 medium: Memory # 可选:使用内存(tmpfs) sizeLimit: 256Mi - name: config configMap: name: app-confighostPath 卷存在安全风险——Pod 可以读写宿主机文件。生产环境应避免使用 hostPath,或通过 Pod Security Policy 限制。
四、PV 与 PVC:持久化存储
PV(PersistentVolume)是集群级存储资源,PVC(PersistentVolumeClaim)是用户对存储的请求。PV 和 PVC 的分离使得存储管理员和应用开发者各司其职。
4.1 PV/PVC 绑定流程
4.2 PV 示例
apiVersion: v1kind: PersistentVolumemetadata: name: pv-nfs-1spec: capacity: storage: 50Gi accessModes: - ReadWriteMany # 多节点读写 persistentVolumeReclaimPolicy: Retain # 保留数据 nfs: server: nfs.example.com path: /data/share14.3 PVC 示例
apiVersion: v1kind: PersistentVolumeClaimmetadata: name: my-dataspec: accessModes: - ReadWriteOnce # 单节点读写 resources: requests: storage: 10Gi storageClassName: fast # 指定 StorageClass4.4 访问模式
| 模式 | 缩写 | 说明 | 典型后端 |
|---|---|---|---|
| ReadWriteOnce | RWO | 单节点读写 | AWS EBS、GCE PD、Ceph RBD |
| ReadOnlyMany | ROX | 多节点只读 | NFS、CephFS |
| ReadWriteMany | RWX | 多节点读写 | NFS、CephFS、GlusterFS |
| ReadWriteOncePod | RWOP | 单 Pod 独占读写 | 本地存储 |
4.5 回收策略
| 策略 | 说明 |
|---|---|
| Retain | PVC 删除后保留 PV 和数据,需手动清理 |
| Delete | PVC 删除后自动删除 PV 和后端存储 |
| Recycle | 已弃用,执行 rm -rf /volume/* 后重新可用 |
五、StorageClass:动态供给
StorageClass 定义存储”模板”,当 PVC 没有匹配的 PV 时,StorageClass 自动创建 PV。
apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: fastprovisioner: ebs.csi.aws.com # CSI 供给器parameters: type: gp3 # AWS EBS gp3 类型 iopsPerGB: "5000" throughput: "250"reclaimPolicy: DeletevolumeBindingMode: WaitForFirstConsumer # 延迟绑定allowVolumeExpansion: true # 允许扩容5.1 volumeBindingMode
| 模式 | 说明 | 适用场景 |
|---|---|---|
| Immediate | PVC 创建后立即供给 PV | 集群单区域 |
| WaitForFirstConsumer | 等 Pod 调度后再供给 PV | 多区域集群,确保 PV 与 Pod 同区域 |
WaitForFirstConsumer 解决了一个关键问题:如果集群跨多个可用区,Immediate 模式可能在 Zone A 创建 PV,但 Pod 被调度到 Zone B——跨区域挂载会失败。WaitForFirstConsumer 等 Pod 调度结果确定后,再在 Pod 所在区域创建 PV。
5.2 存储扩容
# 扩容 PVCkubectl patch pvc my-data -p '{"spec":{"resources":{"requests":{"storage":"20Gi"}}}}'
# 查看扩容状态kubectl get pvc my-data# NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE# my-data Bound pv-xxx 20Gi RWO fast 5m存储扩容需要 StorageClass 设置 allowVolumeExpansion: true。部分存储后端(如 AWS EBS)只支持扩容不支持缩容。
六、Pod 中使用 PVC
apiVersion: apps/v1kind: Deploymentmetadata: name: mysqlspec: selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers: - name: mysql image: mysql:8.0 env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: db-secret key: password volumeMounts: - name: mysql-data mountPath: /var/lib/mysql - name: config mountPath: /etc/mysql/conf.d volumes: - name: mysql-data persistentVolumeClaim: claimName: mysql-pvc # 引用 PVC - name: config configMap: name: mysql-config # 引用 ConfigMap总结
| 概念 | 核心要点 |
|---|---|
| ConfigMap | 非敏感配置,环境变量或 Volume 挂载,Volume 方式自动更新 |
| Secret | 敏感信息,Base64 编码(非加密),需启用 etcd 加密 |
| emptyDir | Pod 内临时共享目录,Pod 删除即消失 |
| hostPath | 宿主机路径挂载,安全风险高,生产环境慎用 |
| PV | 集群级存储资源,独立于 Pod 生命周期 |
| PVC | 用户对存储的请求,绑定到 PV |
| StorageClass | 存储模板,支持动态供给和扩容 |
| WaitForFirstConsumer | 延迟绑定,确保 PV 与 Pod 同区域 |
下一章将深入 Kubernetes 调度框架——调度算法的扩展点机制和自定义调度器开发。
支持与分享
如果这篇文章对你有帮助,欢迎支持作者或分享给更多人
部分信息可能已经过时






