找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

3163

积分

1

好友

425

主题
发表于 昨天 03:47 | 查看: 1| 回复: 0

最近临近春节,工作节奏忙碌,很难静下心来写东西。不过我还是想尽量记录一些思考,也算是对这个不同寻常时期的一个注脚。

学习 Kubernetes 的人,迟早会经历三个灵魂拷问:

第一问:我明明把 Pod 修好了,为什么又坏了?
第二问:为什么我手动改的配置,总是莫名其妙消失?
第三问:Kubernetes 到底听谁的?

如果你已经了解过它的基本理念,你应该知道:

  • Kubernetes 的设计哲学不依赖于人的持续干预(声明式与自动化)
  • 它要的是规则,不是一次性的命令
  • 它会通过控制循环,不断将偏离的现实拉回期望状态

但这里有个更扎心的问题:

你辛辛苦苦改的配置,为什么在 K8s 眼里“不算数”?

今天我们就来深入聊聊这件事。

一、一个似曾相识的运维夜晚

想象一下这个场景:
凌晨三点。
Pod 挂了。
你睡眼惺忪,咖啡已经凉透,但还是凭借着肌肉记忆敲下命令:

kubectl exec -it my-pod -- /bin/bash

进入容器,修改配置,重启相关进程。
看着服务恢复,你在工作群里留下一句:“已修复。”
然后便疲惫地趴在桌上睡着了。

早上九点,电话铃声刺耳地响起。
“服务怎么又挂了?”
你愣住了。明明昨晚日志显示修复成功,配置也确实改过了。
直到同事问了一句:“你是进 Pod 里面改的吧?”
你沉默了两秒。
对方回了一句,语气平静却像一盆冷水:
“那等于没修。”

那一刻,你可能开始自我怀疑:是不是我技术不行?是不是 Kubernetes 有 Bug?是不是这系统在针对我?
但事实只有一个:

你昨晚做的那一切,从 Kubernetes 的角度看——从未发生过。

二、Kubernetes 不讲“人情”,只认“合同”

在传统的运维世界里,你的操作会被系统“默认承认”。
你改了配置文件,服务就按新配置跑;你重启了进程,它就会以新的状态运行。

但 Kubernetes 的世界观截然不同。它只承认一种东西:

写进规则里的事实。

你没有写进去,没有留下可验证、可复现、可追溯的痕迹,那么无论你多么努力,都只是无法被采信的“现场口供”。而 Kubernetes,从来不相信口供。

三、YAML 在 Kubernetes 中的真实身份

很多教程会告诉你:“YAML 是 Kubernetes 的配置文件。”
这句话在技术层面没错,但在认知层面却可能引入一个危险的误解:让人以为 YAML 只是“多种配置方式之一”。

然而在 Kubernetes 的语境下,YAML 的真实身份是:

唯一具有法律效力的、对系统期望状态的正式描述。

你在 YAML 里写的不是建议,也不是临时性的偏好。
你不是在说“我觉得可以这样”或“先这么改着试试”,而是在宣告:

我规定,系统必须长成这个样子。

Kubernetes 的角色不是一个会体谅你辛苦的助手,而是一个严格、死板、毫无弹性的执行者。它不会问你为什么,不会理解你的加班,更不会因为你昨晚没合眼而网开一面。
它只做一件事:

把现实世界,一次又一次、坚定不移地拉回到 YAML 所描述的样子。

四、Pod 会重建,节点会更换,但 YAML 永存

这是理解 Kubernetes 运维模式的一个关键转折点
在传统运维思维里:

  • 物理服务器或虚拟机是核心资产
  • 上面运行的服务是核心业务
  • 运维人员的记忆和经验是隐形的核心依赖

而在 Kubernetes 的设计中:

  • Pod 是临时的,生命期短暂
  • 容器是一次性的,用完即弃
  • 节点(Node)是可被替换的耗材
    唯一被系统视为“长期事实”和“真理来源”的,只有 YAML 文件。

你可以把 Kubernetes 世界里的实体分为两类:

会消失的:

  • Pod(今天的“张三”,明天重建可能就是“李四”)
  • 容器(像一次性餐盒,用完即弃)
  • 进程(随时可能被重启)
  • 节点(机器故障或升级时说换就换)

不会消失的:

  • YAML 中定义的期望状态

这就解释了那个很“反直觉”的现象:你费尽心思在容器内部调试了半天,结果节点一次重启,所有修改荡然无存。这不是 Kubernetes 冷血,而是它从一开始就没打算记住你的任何手工操作
就像你在沙滩上刻字,海浪一来,字迹就消失了。不是海浪故意和你作对,而是沙滩本身就不是用来铭刻永久碑文的地方

五、为什么 Kubernetes 必须“只认 YAML”?

还记得控制循环(Control Loop)的核心逻辑吗?
观察现实 -> 对比期望 -> 执行纠偏

这里引出一个根本性问题:

如果没有一个稳定、可重复、不受临时操作干扰的“期望来源”,控制循环拿什么作为对比的基准?

答案只能是:

一份不依赖于任何特定人员、不会被临机操作搞乱的、文本化的声明。
也就是 YAML。

把 Kubernetes 想象成一个严谨的法庭:

  • (手动改 Pod):法官大人,他昨天答应还我钱,真的!
  • Kubernetes(法官):有白纸黑字、双方签字的借款合同吗?
  • :这个……当时是口头说的……
  • Kubernetes:口头承诺无效,不予采纳。下一个案子。

YAML 就是那份具有法律效力的合同。你可以有一万次口头承诺,但只要没写进合同,在法律上就等于从未发生

你通过 kubectl exec 现场修改 Pod:

  • 不可追溯(谁改的?什么时候改的?)
  • 不可复现(下次出问题还能一模一样地改吗?)
  • 不可验证(改得对不对?有没有引入副作用?)
  • 不可持久(Pod 一重建,修改就灰飞烟灭)

从系统工程和可靠性的角度看,这种“运维”方式是灾难性的。 Kubernetes 正是为了避免这种灾难,才设计成了这个“只认白纸黑字”的系统。

六、Kubernetes 世界里的“合法”操作路径

理解了上述核心,很多之前觉得“别扭”的 Kubernetes 设计,瞬间就顺理成章了。
在 Kubernetes 的世界里,只有下面这条路径是“合法”且被系统承认的

修改 YAML 文件
    ↓
通过 kubectl apply 提交给 API Server
    ↓
相应的 Controller 感知到期望状态变化
    ↓
控制循环开始工作
    ↓
驱动现实世界(Pod、配置等)向新的期望状态对齐

而不是我们熟悉但不可靠的路径:

发现服务有问题
    ↓
SSH/exec 进入环境
    ↓
手动修改配置、重启服务
    ↓
祈祷它别再出问题

对比一下两种方式:

操作方式 是否持久? Pod 重建后 K8s 承认吗? 能否方便回滚?
kubectl exec 手动改 ❌ 否 修改丢失 ❌ 不承认 ❌ 几乎不能
改 YAML 后 apply ✅ 是 配置仍在 承认 可以

用一句话总结这种思维的转变:

你不是在“操作”一个系统,你是在“修订”管理这个系统的法律条文。

七、kubectl exec:临时止血工具,而非根治方案

说句大实话:kubectl execKubernetes 世界里,其定位是临时诊断与止血工具,绝不是最终的治疗方案

它可以:

  • ✅ 帮你快速定位问题根因
  • ✅ 验证你的故障假设
  • ✅ 在紧急救火时实现快速止血

但它永远不应该成为你的问题解决方案

为什么?
因为它提供了一种虚假的掌控感。你以为修复了问题,实际上只是给一个随时可能“死亡并重生”的 Pod 化了个妆。几天后,这个 Pod 因为调度、更新或故障而重建,新生的 Pod 又是“素颜”,你之前的所有“化妆”痕迹丝毫未留。

一个类比:
kubectl exec 就像你在租住的房子里钉了个钉子挂画。某天,房东(Kubernetes)来检查或维护,直接把这面墙重新粉刷了一遍。你的钉子?不好意思,它从未在租赁合同里存在过。
想要合法地挂画?正确做法是去修改你的“租赁合同”(YAML),让房东书面同意你可以在指定位置钉钉子。

一个真实的故事:
运维工程师小明发现线上 MySQL 的 max_connections 设置过低,导致连接数不足。
他的操作是:

  1. kubectl exec 进入 MySQL Pod。
  2. 修改 /etc/mysql/my.cnf 配置文件。
  3. 重启 MySQL 服务。
  4. 连接数恢复正常,安心下班。

一周后,因节点维护,Pod 被驱逐并重建。
新建的 Pod 加载的是原始的、未修改的 my.cnf 配置。
早高峰来临,数据库连接数瞬间被打满,整个系统瘫痪。
老板在群里质问:“这配置谁改的?怎么又回去了?!”

正确的声明式做法应该是:

  1. 创建一个 ConfigMap,包含正确的 my.cnf 配置。
  2. 修改 Deployment 的 YAML,将 Pod 挂载的配置文件指向这个 ConfigMap。
  3. 执行 kubectl apply -f deployment.yaml
  4. Kubernetes 会自动滚动更新 Pod,新 Pod 会加载正确的配置。

这样,无论节点重启、Pod 重建还是版本回滚,你的配置都永远是预期中的样子。因为它被写进了 YAML——那份 Kubernetes 唯一承认的“法律条文”里。

八、记住这一句就够了

在 Kubernetes 的世界里,任何未写入 YAML(或通过其 API 声明)的修改,在系统眼中都等同于从未发生。

所有这类修改,都只是系统运行过程中短暂的幻觉,随着 Pod 的生命周期结束而湮灭。

收尾

传统运维模式下,你的工作是:“哪里坏了修哪里。”
而在掌握了 Kubernetes 的声明式哲学后,你的工作应转变为:“定义规则,让系统自动地、持续地按规则运行。”

打一个比方:

  • 以前的你:是村里的赤脚医生,头疼医头,脚疼医脚。
  • 现在的你:是卫生部的官员,负责制定《医疗规范》和《诊疗流程》,让全国的医院都按标准执行。

以前你治疗的是单个病人,现在你定义的是保障全民健康的规则。

所以,下次当你下意识地想敲 kubectl exec 进去手动修改时,先问问自己:

“我此刻是在紧急救火,还是在制定长期有效的规则?”

救火时,可以使用 exec 快速探查和临时处理。
但若要制定规则,请务必去修改 YAML。这正是云原生时代运维工程师思维转变的核心,也是保障系统长期稳定运行的基石。更多关于云原生运维的实践与探讨,欢迎访问云栈社区,那里有丰富的实战经验和技术文档分享。

思考题

假设线上一个服务的 Pod,需要临时将其日志级别从 INFO 调整为 DEBUG,以便排查一个偶发问题。通过修改 YAML 并触发滚动更新需要10分钟,而你只需要看5分钟 DEBUG 日志就能定位问题。

你会怎么办?
A.kubectl exec 进入 Pod 修改日志配置,排查完再改回来。
B. 老老实实改 YAML,等待10分钟的滚动更新完成。
C. 有没有更优雅的第三种办法?

我的答案:
这种情况,使用 kubectl exec 是可以接受的,但你必须非常清醒地认识到

  • ✅ 这是临时性、诊断性的操作,绝非最终解决方案。
  • ✅ 排查完毕后,应立即将配置恢复,或者将正确的配置正式更新到 YAML 中。
  • ⚠️ 要清楚风险:如果 Pod 在你排查的这5分钟内发生了重启,你的临时修改会全部丢失。

更优雅、更“Kubernetes”的办法:
使用 kubectl set envkubectl patch 命令,临时修改 Deployment 的环境变量(假设应用通过环境变量控制日志级别),触发一次快速的、受控的 Pod 滚动更新。排查完毕后,使用 kubectl rollout undo 一键回滚。

# 临时将日志级别改为 DEBUG,触发滚动更新
kubectl set env deployment/my-app LOG_LEVEL=DEBUG

# 观察日志,排查问题...

# 排查完毕后,回滚到上一个版本
kubectl rollout undo deployment/my-app

这种方式的好处是,你的修改是“合法”的(通过 Kubernetes API 修改了期望状态),记录在案,并且可以瞬间回滚,完美契合声明式运维的理念。




上一篇:AWS控制台供应链攻击漏洞分析:CodeBreach如何威胁云安全
下一篇:告别滚动监听:IntersectionObserver 在现代前端懒加载中的实战指南
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-2-7 07:44 , Processed in 0.314574 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表