Kubernetes学习笔记03:配置、密钥和存储

发表于 2024-02-06 21:52 1566 字 8 min read

Spring AI学习笔记(四)工具调用和MCPSpring AI学习笔记(三)RAG从文档入库到回答Spring AI学习笔记(二)ChatClient从怎么调到怎么封装Spring AI学习笔记(一)它到底解决什么问题java新版本-java25学习笔记(四)用JFR和GC日志做一次体检java新版本-java25学习笔记(三)虚拟线程要和资源边界一起看java新版本-java25学习笔记(二)运行时基线先统一java新版本-java25学习笔记(一)LTS版本对比和学习路线主流AI Agent能力对比与工程选型我用Kiro做了个自己的工具站盘一盘虚拟线程我用Trae做了个AstrBot的AI角色扮演插件Python初学笔记(六)常用标准库先学这几个Python初学笔记(五)读写文件和处理异常Python初学笔记(四)函数让代码开始有结构Python初学笔记(三)条件、循环和推导式Python初学笔记(二)变量和基础类型比想象中重要Python初学笔记(一)先把环境和运行方式弄明白主流AI大模型能力对比Java 21和Spring Boot 3升级笔记(五)日志指标与可观测性Java 21和Spring Boot 3升级笔记(四)数据访问层适配Java 21和Spring Boot 3升级笔记(三)虚拟线程使用边界Java 21和Spring Boot 3升级笔记(二)Jakarta迁移要点Java 21和Spring Boot 3升级笔记(一)工程基线整理魔法値をどうやって我慢する?JPAのSpecification大改造!处理生僻字乱码:JPA框架对于Oracle的NVarchar2,NChar,NClob类型支持Redis Stream能不能当轻量消息队列用RocketMQ 5学习笔记:普通消息之外要看什么事件流不是换个消息队列这么简单Kubernetes学习笔记04:发布、排障和观测Kubernetes学习笔记03:配置、密钥和存储Kubernetes学习笔记02:Deployment、Service和IngressKubernetes学习笔记01:Pod和控制器mysql索引原理02--存储引擎索引的实现mysql索引原理01--索引的数据结构
この投稿は「日本語」では表示できません。元の投稿を表示しています。
  应用跑到 Kubernetes 以后,代码和镜像只是其中一部分。真正让服务能在不同环境运行起来的,还有配置、密钥和存储。   这三类东西很容易被混在一起。比如把数据库密码写进 ConfigMap,把上传文件放在容器本地目录,把所有配置都塞进环境变量。短期能跑,长期会很难维护。   这篇主要梳理...

前言

  应用跑到 Kubernetes 以后,代码和镜像只是其中一部分。真正让服务能在不同环境运行起来的,还有配置、密钥和存储。

  这三类东西很容易被混在一起。比如把数据库密码写进 ConfigMap,把上传文件放在容器本地目录,把所有配置都塞进环境变量。短期能跑,长期会很难维护。

  这篇主要梳理 ConfigMap、Secret、Volume、PersistentVolumeClaim 这些概念,重点不是背字段,而是分清它们各自应该解决什么问题。

镜像不要绑定环境

  容器镜像最好只包含应用和运行所需依赖,不要把测试环境、预发环境、生产环境的差异直接打进镜像。

同一个镜像,应该可以通过不同配置跑在不同环境里。

比如 Spring Boot 应用里,镜像只包含 jar 包和启动脚本。数据库地址、Redis 地址、日志级别、外部接口地址这些,应该由部署环境注入。

这样做有两个好处:

1.镜像可以在多个环境复用。 2.发布时更容易判断变更来自代码还是配置。

如果每个环境都重新打一个镜像,问题排查会变复杂。你以为线上和测试是同一份代码,实际镜像里可能已经混入了环境差异。

ConfigMap 放普通配置

  ConfigMap 适合放非敏感配置,比如开关、URL、日志级别、线程池大小。

可以用环境变量注入:

env:
  - name: LOG_LEVEL
    valueFrom:
      configMapKeyRef:
        name: order-config
        key: log-level

也可以把 ConfigMap 挂载成文件:

volumes:
  - name: app-config
    configMap:
      name: order-config
containers:
  - name: order-service
    volumeMounts:
      - name: app-config
        mountPath: /app/config

环境变量适合少量简单配置,文件挂载适合结构化配置,比如一段完整的 application.yaml

但要注意,配置更新不一定等于应用立即重新加载。很多应用启动时读取一次配置,后面不会自动感知变化。真实项目里要么重启 Pod,要么明确做动态配置机制,不要假设 ConfigMap 改了服务就一定生效。

Secret 放敏感信息

  Secret 用来放密码、token、证书这类敏感信息。

从使用方式上看,它和 ConfigMap 很像,也能作为环境变量或文件挂载。但语义完全不同。

比如数据库密码:

env:
  - name: DB_PASSWORD
    valueFrom:
      secretKeyRef:
        name: order-secret
        key: db-password

Secret 至少能让敏感信息和普通配置分开管理,也能配合集群权限控制。不要因为 Base64 看起来简单,就觉得 Secret 没意义。

当然,Secret 也不是终点。生产环境如果要求更高,通常还会接专门的密钥管理系统,由平台负责加密、轮换、审计和下发。

对业务开发来说,最基本的底线是:不要把密码写进镜像,不要提交到 Git,不要放进 ConfigMap。

容器本地目录不是持久存储

  容器里的文件系统是临时的。Pod 被删除后,容器本地写入的数据可能就没了。

这对无状态服务不是问题。日志可以输出到 stdout,由采集系统处理;临时文件可以放在临时目录;缓存可以重建。

但如果应用真的需要保存数据,比如用户上传文件、数据库数据、消息中间件数据,就不能依赖容器本地目录。

Kubernetes 用 Volume 把存储挂进 Pod。普通的 emptyDir 只和 Pod 生命周期绑定,Pod 删除后也会消失。需要真正持久化时,要用 PersistentVolume 和 PersistentVolumeClaim。

PVC 是应用要存储的声明

  PersistentVolumeClaim 可以理解为应用对存储资源的申请。

应用不用直接关心底层是云盘、NFS、Ceph 还是其他存储,只声明自己需要多大容量、什么访问模式、什么存储类。

一个简单 PVC:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: upload-data
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi

Deployment 里再挂载:

volumes:
  - name: upload-data
    persistentVolumeClaim:
      claimName: upload-data
containers:
  - name: file-service
    volumeMounts:
      - name: upload-data
        mountPath: /data/upload

这样 Pod 重建后,只要 PVC 仍然存在,数据就可以继续挂载回来。

有状态服务要谨慎上 k8s

  不是所有东西都适合一开始就搬进 Kubernetes。

无状态 Web 服务、后台 worker、网关、定时任务,通常比较适合。数据库、消息队列、搜索引擎这类有状态组件,要看团队是否真的具备存储、备份、恢复、升级和故障处理能力。

Kubernetes 可以跑有状态服务,但它不会替你理解 MySQL 主从、Kafka ISR、Redis 持久化、Elasticsearch 分片这些业务组件自己的规则。

如果只是为了“全部容器化”,把数据库也贸然搬进去,风险会比收益大。

我的习惯是:业务应用先容器化,基础中间件优先使用成熟托管服务或已有运维体系。等团队对 k8s 存储、调度、备份和演练都有经验后,再考虑更复杂的有状态部署。

配置变更也要可追踪

  配置一旦进入 k8s,就不能再靠口口相传。

至少要知道:

1.谁改了配置。 2.改了什么 key。 3.什么时候发布到哪个环境。 4.哪些 Pod 使用了这份配置。 5.出问题时怎么回滚。

如果用 GitOps,这些配置通常会以 YAML 形式进入仓库,通过提交记录追踪。如果用平台控制台,也要有审计和版本记录。

配置问题很常见,而且经常比代码问题更隐蔽。把配置管理好,本质上也是在降低发布风险。

小结

  ConfigMap、Secret、PVC 看起来都是 YAML,但它们解决的是不同问题。

  ConfigMap 放普通配置,Secret 放敏感信息,PVC 声明持久化存储。镜像不要绑定环境,容器本地目录不要当持久存储,配置变更也要能追踪和回滚。

  Kubernetes 能提供统一的应用运行抽象,但不会自动替我们做好配置治理和数据治理。越是核心系统,越要把配置、密钥和存储边界分清楚。

気に入ったならばコメントを残してくださいね~

© 2019 - 2026 VincentHo @VincentHo
Powered by theme astro-koharu · Inspired by Shoka