mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
1247 字
4 分钟
Kubernetes 配置与存储:ConfigMap、Secret 与 PV/PVC
2023-08-11

应用代码和配置必须分离——这是十二要素应用的核心原则之一。Kubernetes 通过 ConfigMap 和 Secret 实现配置管理,通过 PV/PVC 体系实现存储管理。理解这些机制,是构建可移植、可维护的云原生应用的前提。

一、ConfigMap:配置管理#

ConfigMap 将非敏感配置数据以键值对形式存储,Pod 通过环境变量或 Volume 挂载引用。

1.1 创建 ConfigMap#

apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
# 简单键值对
LOG_LEVEL: "info"
MAX_CONNECTIONS: "100"
# 完整配置文件
nginx.conf: |
server {
listen 80;
location / {
proxy_pass http://backend:8080;
}
}
# 从文件创建 ConfigMap
kubectl 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=info

1.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
Note

通过 Volume 挂载的 ConfigMap 会自动更新——当 ConfigMap 内容变更时,Pod 内的文件会自动刷新(有延迟,通常 1-2 分钟)。通过环境变量引用的 ConfigMap 不会自动更新——需要重启 Pod 才能生效。

二、Secret:敏感信息管理#

Secret 的数据以 Base64 编码存储。虽然 Base64 不是加密,但 Secret 与 ConfigMap 的分离使得 RBAC 可以对敏感信息施加更严格的访问控制。

2.1 Secret 类型#

类型用途示例
Opaque通用键值对(默认)数据库密码、API Token
kubernetes.io/tlsTLS 证书Ingress HTTPS
kubernetes.io/dockerconfigjson镜像拉取凭证私有镜像仓库
kubernetes.io/basic-auth基本认证用户名密码
kubernetes.io/ssh-authSSH 认证SSH 密钥

2.2 创建与使用 Secret#

# 创建通用 Secret
kubectl create secret generic db-secret \
--from-literal=username=admin \
--from-literal=password='S3cur3P@ss!'
# 创建 TLS Secret
kubectl create secret tls tls-secret \
--cert=cert.pem \
--key=key.pem
# 创建镜像拉取 Secret
kubectl create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=user \
--docker-password=pass
# Pod 引用 Secret
spec:
containers:
- name: my-app
image: my-app:v1
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
imagePullSecrets: # 拉取私有镜像
- name: regcred

2.3 Secret 安全最佳实践#

实践说明
启用 etcd 加密配置 EncryptionConfiguration,Secret 在 etcd 中加密存储
使用外部密钥管理通过 External Secrets Operator 对接 Vault/AWS Secrets Manager
限制 RBAC只授予必要的 Secret 读取权限
避免明文提交不要将 Secret YAML 提交到 Git,使用 Sealed Secrets 或 SOPS
使用 ServiceAccount TokenKubernetes 1.24+ 自动挂载短期 Token,取代长期 Secret
Warning

默认情况下,Secret 在 etcd 中以 Base64 明文存储。任何有 etcd 访问权限的人都能读取 Secret 原文。生产环境必须启用 etcd 静态加密。

三、Volume:存储卷基础#

Volume 将存储挂载到 Pod 中,其生命周期与 Pod 相同——Pod 删除时 Volume 也被清理(临时卷)。持久化存储需要 PV/PVC。

3.1 常见临时卷类型#

类型说明适用场景
emptyDirPod 内共享的临时目录,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-config
Warning

hostPath 卷存在安全风险——Pod 可以读写宿主机文件。生产环境应避免使用 hostPath,或通过 Pod Security Policy 限制。

四、PV 与 PVC:持久化存储#

PV(PersistentVolume)是集群级存储资源,PVC(PersistentVolumeClaim)是用户对存储的请求。PV 和 PVC 的分离使得存储管理员和应用开发者各司其职。

4.1 PV/PVC 绑定流程#

flowchart TB DEV["开发者提交 PVC<br/>请求 10Gi 存储"] --> BIND{"存在匹配 PV?"} BIND -->|"是"| BOUND["PVC 绑定到 PV<br/>状态: Bound"] BIND -->|"否"| SC{"有 StorageClass?"} SC -->|"是"| PROV["StorageClass<br/>动态供给 PV"] PROV --> BOUND SC -->|"否"| PENDING["PVC 状态: Pending<br/>等待管理员创建 PV"] BOUND --> POD["Pod 挂载 PVC<br/>使用存储"] style DEV fill:#e3f2fd,stroke:#1565c0 style BOUND fill:#c8e6c9,stroke:#2e7d32 style PENDING fill:#ffcdd2,stroke:#c62828

4.2 PV 示例#

apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs-1
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteMany # 多节点读写
persistentVolumeReclaimPolicy: Retain # 保留数据
nfs:
server: nfs.example.com
path: /data/share1

4.3 PVC 示例#

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-data
spec:
accessModes:
- ReadWriteOnce # 单节点读写
resources:
requests:
storage: 10Gi
storageClassName: fast # 指定 StorageClass

4.4 访问模式#

模式缩写说明典型后端
ReadWriteOnceRWO单节点读写AWS EBS、GCE PD、Ceph RBD
ReadOnlyManyROX多节点只读NFS、CephFS
ReadWriteManyRWX多节点读写NFS、CephFS、GlusterFS
ReadWriteOncePodRWOP单 Pod 独占读写本地存储

4.5 回收策略#

策略说明
RetainPVC 删除后保留 PV 和数据,需手动清理
DeletePVC 删除后自动删除 PV 和后端存储
Recycle已弃用,执行 rm -rf /volume/* 后重新可用

五、StorageClass:动态供给#

StorageClass 定义存储”模板”,当 PVC 没有匹配的 PV 时,StorageClass 自动创建 PV。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
provisioner: ebs.csi.aws.com # CSI 供给器
parameters:
type: gp3 # AWS EBS gp3 类型
iopsPerGB: "5000"
throughput: "250"
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer # 延迟绑定
allowVolumeExpansion: true # 允许扩容

5.1 volumeBindingMode#

模式说明适用场景
ImmediatePVC 创建后立即供给 PV集群单区域
WaitForFirstConsumer等 Pod 调度后再供给 PV多区域集群,确保 PV 与 Pod 同区域

WaitForFirstConsumer 解决了一个关键问题:如果集群跨多个可用区,Immediate 模式可能在 Zone A 创建 PV,但 Pod 被调度到 Zone B——跨区域挂载会失败。WaitForFirstConsumer 等 Pod 调度结果确定后,再在 Pod 所在区域创建 PV。

5.2 存储扩容#

# 扩容 PVC
kubectl 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
Note

存储扩容需要 StorageClass 设置 allowVolumeExpansion: true。部分存储后端(如 AWS EBS)只支持扩容不支持缩容。

六、Pod 中使用 PVC#

apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
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 加密
emptyDirPod 内临时共享目录,Pod 删除即消失
hostPath宿主机路径挂载,安全风险高,生产环境慎用
PV集群级存储资源,独立于 Pod 生命周期
PVC用户对存储的请求,绑定到 PV
StorageClass存储模板,支持动态供给和扩容
WaitForFirstConsumer延迟绑定,确保 PV 与 Pod 同区域

下一章将深入 Kubernetes 调度框架——调度算法的扩展点机制和自定义调度器开发。

支持与分享

如果这篇文章对你有帮助,欢迎支持作者或分享给更多人

Kubernetes 配置与存储:ConfigMap、Secret 与 PV/PVC
https://blog.souloss.com/posts/kubernetes/k8s-config-storage/
作者
Souloss
发布于
2023-08-11
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时