Appearance
配置、存储与有状态服务
这篇笔记聚焦 Kubernetes 里最容易“概念知道一点,但真正上线就踩坑”的一条主线:
- 配置应该怎么管理
- 敏感信息应该放在哪里
- 存储为什么会比无状态服务复杂很多
- 为什么有状态服务在 Kubernetes 上更难
1. 为什么配置管理会成为单独的话题
在容器化环境里,一个镜像往往会在多个环境复用:
- 开发环境
- 测试环境
- 预发环境
- 生产环境
如果把所有配置直接写死在镜像里,就会出现:
- 镜像和环境强耦合
- 环境切换笨重
- 配置变更需要重新构建镜像
这就是为什么 Kubernetes 里要单独强调配置对象。
2. ConfigMap 是什么
ConfigMap 可以理解成 用于保存普通配置的一种 Kubernetes 对象。
它解决的是 把应用配置从镜像里拆出来,变成可独立管理的外部配置。
常见内容包括:
- 应用参数
- 配置文件片段
- 环境变量值
- 非敏感的开关项
3. Secret 是什么
Secret 可以理解成 用于保存敏感配置的一种 Kubernetes 对象。
典型场景包括:
- 数据库密码
- API Token
- 证书材料
- Access Key
这里要注意一个常见误解:
Secret 不是“绝对安全保险箱”的同义词。
更贴近它定位的说法是:Kubernetes 中专门区分敏感信息的一类配置对象。
它能帮助你不要把敏感信息混在普通配置里,但仍然需要配合权限控制、加密和最小暴露原则。
4. 配置通常怎么注入到容器里
常见方式包括:
- 作为环境变量注入
- 作为文件挂载到容器目录
例如:
yaml
env:
- name: APP_ENV
valueFrom:
configMapKeyRef:
name: app-config
key: APP_ENV这段配置表达的是:把 ConfigMap 中的某个键值,注入成容器里的环境变量。
5. 为什么存储会让 Kubernetes 变复杂
因为容器和 Pod 更偏“可替换的运行实例”,而状态数据则要求:
- 不能轻易丢
- 不能随便跟着实例一起消失
- 有时还要求稳定身份和有序恢复
所以一旦进入数据库、消息队列、搜索引擎这类场景,问题就会从“把服务跑起来”变成:数据放哪、实例换了以后数据怎么跟过去、网络身份是否稳定、重建顺序怎么保证。
6. Volume、PersistentVolume、PersistentVolumeClaim 是什么
6.1 Volume
Volume 可以理解成 Pod 可以挂载和使用的一块存储。
它解决的是 容器之间如何共享一块存储,以及某些数据不只放在容器层里。
6.2 PersistentVolume
PersistentVolume,常缩写成 PV,可以理解成 集群里一块可被工作负载声明使用的持久化存储资源。
6.3 PersistentVolumeClaim
PersistentVolumeClaim,常缩写成 PVC,可以理解成 应用对持久化存储提出的一份使用申请。
把这组关系记住:
PV:集群里可提供的存储资源PVC:应用发起的存储申请
7. StatefulSet 为什么对有状态服务很重要
StatefulSet 可以理解成 专门用于管理有状态工作负载的一类控制器。
它适合:
- 需要稳定网络身份
- 需要稳定存储绑定
- 需要有序创建和删除
这正是很多数据库、中间件、副本集场景关心的能力。
它和 Deployment 的差别,不只是对象名字不同,而是:Deployment 更偏无状态副本管理,StatefulSet 更偏有状态实例管理。
8. 为什么说 Kubernetes 天然更适合无状态应用
因为无状态应用通常更符合 Kubernetes 的默认假设:
- 实例可以被替换
- 实例 IP 可以变化
- 副本之间没有强身份差异
而有状态服务往往要求:
- 稳定实例身份
- 稳定数据绑定
- 更谨慎的恢复顺序
所以 Kubernetes 不是不能跑有状态服务,而是:有状态服务在网络、存储和运维复杂度上要求更高。
9. 工程上最常见的几个误区
9.1 误区一:把所有配置都打进镜像
这样会让镜像失去环境复用价值。
9.2 误区二:用了 Secret 就代表敏感信息已经绝对安全
不是。
仍然要继续考虑:
- 权限控制
- 加密方式
- 配置暴露范围
- 审计和轮换
9.3 误区三:把有状态服务当成 Deployment 那样随便替换
对于数据库或中间件,这样做很容易引发数据和恢复顺序问题。
10. 一句话总结
配置、存储与有状态服务这条主线,本质上是在解决:
应用配置如何从镜像中解耦,状态数据如何稳定持久化,以及那些不能被随意替换的实例在 Kubernetes 上应该如何被管理。