配置与存储
ConfigMap
ConfigMap 用于存储非敏感配置数据(键值对、配置文件)。
创建 ConfigMap
# 从字面量创建
kubectl create configmap app-config \
--from-literal=DB_HOST=mysql \
--from-literal=DB_PORT=3306
# 从文件创建
kubectl create configmap nginx-config \
--from-file=nginx.conf
# 从目录创建
kubectl create configmap configs \
--from-file=./config-dir/
configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DB_HOST: "mysql"
DB_PORT: "3306"
LOG_LEVEL: "info"
# 多行配置文件
app.properties: |
server.port=8080
spring.datasource.url=jdbc:mysql://mysql:3306/mydb
logging.level.root=INFO
使用 ConfigMap
pod-with-configmap.yaml
spec:
containers:
- name: app
image: myapp
# 方式 1:环境变量(单个)
env:
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: DB_HOST
# 方式 2:批量注入所有 key
envFrom:
- configMapRef:
name: app-config
# 方式 3:挂载为文件
volumeMounts:
- name: config-volume
mountPath: /etc/config
readOnly: true
volumes:
- name: config-volume
configMap:
name: app-config
items: # 可选:只挂载特定 key
- key: app.properties
path: application.properties
Secret
Secret 存储敏感信息(密码、Token、证书)。值以 Base64 编码存储。
创建 Secret
# 从字面量
kubectl create secret generic db-secret \
--from-literal=username=admin \
--from-literal=password='S3cret!'
# 从文件
kubectl create secret generic tls-secret \
--from-file=tls.crt --from-file=tls.key
# TLS 类型
kubectl create secret tls app-tls \
--cert=server.crt --key=server.key
secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
# data 中的值必须 Base64 编码
data:
username: YWRtaW4= # echo -n 'admin' | base64
password: UzNjcmV0IQ==
# 或使用 stringData(明文,K8s 自动编码)
stringData:
api-key: my-super-secret-key
使用 Secret
spec:
containers:
- name: app
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
volumeMounts:
- name: secret-volume
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secret-volume
secret:
secretName: db-secret
Secret 安全
K8s Secret 默认只是 Base64 编码,不是加密。需要额外措施:
- 启用 etcd 静态加密(EncryptionConfiguration)
- 使用 Sealed Secrets 或 External Secrets Operator
- 集成外部密钥管理(Vault、AWS Secrets Manager)
- 配置 RBAC 限制 Secret 访问权限
持久化存储
PV / PVC / StorageClass
| 概念 | 角色 | 说明 |
|---|---|---|
| PV | 管理员 | 集群级存储资源,预先创建 |
| PVC | 用户 | 存储请求声明(大小、模式) |
| StorageClass | 自动化 | 动态创建 PV,按需分配 |
PV(静态分配)
pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany # RWX:多节点读写
persistentVolumeReclaimPolicy: Retain # 回收策略
nfs:
server: 192.168.1.100
path: /exports/data
PVC
pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-data
spec:
accessModes:
- ReadWriteOnce # RWO:单节点读写
resources:
requests:
storage: 5Gi
storageClassName: standard # 指定 StorageClass
StorageClass(动态分配,推荐)
storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp3
fsType: ext4
reclaimPolicy: Delete
allowVolumeExpansion: true # 允许扩容
volumeBindingMode: WaitForFirstConsumer # 延迟绑定
在 Pod 中使用
spec:
containers:
- name: app
volumeMounts:
- name: data
mountPath: /app/data
volumes:
- name: data
persistentVolumeClaim:
claimName: app-data
访问模式
| 模式 | 缩写 | 说明 |
|---|---|---|
| ReadWriteOnce | RWO | 单节点读写 |
| ReadOnlyMany | ROX | 多节点只读 |
| ReadWriteMany | RWX | 多节点读写(NFS/Ceph) |
| ReadWriteOncePod | RWOP | 单 Pod 读写(K8s 1.22+) |
回收策略
| 策略 | 说明 |
|---|---|
| Retain | PVC 删除后 PV 保留数据,需手动清理 |
| Delete | PVC 删除后自动删除 PV 和底层存储 |
| Recycle | 已弃用 |
常见面试问题
Q1: ConfigMap 和 Secret 的区别?
答案:
| 维度 | ConfigMap | Secret |
|---|---|---|
| 用途 | 非敏感配置 | 敏感信息 |
| 存储 | 明文 | Base64 编码 |
| 大小限制 | 1 MiB | 1 MiB |
| 内存存储 | 否 | 可选 tmpfs(mountPath 挂载时) |
| RBAC | 通常宽松 | 应严格限制 |
两者使用方式相同:环境变量注入或卷挂载。
Q2: PV 和 PVC 如何实现存储解耦?
答案:
PV/PVC 模式将存储供给(管理员)和存储消费(开发者)分离:
- 管理员创建 PV(或配置 StorageClass 动态创建)
- 开发者创建 PVC 声明需要的存储大小和模式
- K8s 自动将 PVC 绑定到匹配的 PV
- Pod 通过 PVC 使用存储
开发者不需要关心底层存储是 NFS、Ceph 还是云盘。
Q3: K8s 配置更新时 Pod 会自动重启吗?
答案:
- 环境变量方式:ConfigMap/Secret 更新后,已运行的 Pod 不会自动更新。需要重启 Pod 或使用 Reloader
- 卷挂载方式:kubelet 会自动更新挂载的文件(延迟 ~1 分钟),但应用需要支持文件变更检测
- 推荐使用 Reloader 自动触发滚动更新