目录

一、核心逻辑:从“过程式”到“声明式”的思维跃迁

1. 以前的你(过程式运维)

2. 现在的 K8s(声明式运维)

二、核心概念:都是为了解决具体“坑”才诞生的

1. Pod:不是容器,是“豌豆荚”

2. Deployment:真正的“管家”与“保命符”

3. Service:固定的“前台总机”

4. Ingress:集群的“大门保安”

5. ConfigMap & Secret:配置和密码的“外挂 U 盘”

6. Namespace:逻辑上的“隔断墙”

三、实战推演:一次故障是如何被“无感”修复的

🔴 如果是传统运维(Docker 单机/脚本模式)

🟢 如果用 K8s


很多人学 K8s(Kubernetes)被劝退,是因为教程一上来就甩名词:Pod、Service、Deployment、Ingress、ETCD……看着像天书,背了也忘。

它存在的唯一目的,就是把你从“登录服务器 -> 敲命令 -> 盯进程 -> 半夜报警起来重启”这种低级重复劳动中解放出来。

这篇文章不整虚的,咱们用大白话,把你以前运维遇到的破事,和 K8s 是怎么冷酷无情又高效地解决的,一次性捋清楚。

一、核心逻辑:从“过程式”到“声明式”的思维跃迁

1. 以前的你(过程式运维)

你要上线一个服务,脑子里全是步骤:

  1. 登录服务器 A。
  2. git pull 拉代码。
  3. mvn package 编译。
  4. docker run 启动容器。
  5. 写个 crontab 脚本,每分钟检查一次,挂了重启。
  6. 最痛苦的:如果服务器 A 硬件坏了,你得半夜爬起来,找新机器,重装环境,再手动迁移服务。

痛点:你在教计算机 “怎么做(How)”。只要中间一步出错,或者环境变了,整个链条就断了。

2. 现在的 K8s(声明式运维)

你不再管步骤,只给 K8s 一张 “愿望清单”(YAML 文件):

我要 3 个 Nginx 服务(镜像版本 v1.2),每个限制 1G 内存,对外暴露 80 端口。不管发生什么,给我死死保住这 3 个。

提交完单子,你的工作就结束了。剩下的全是 K8s 的死循环(Reconcile Loop):

观察:现在只有 2 个在跑?

行动:立马补上第 3 个。

观察:某台机器断电了?

行动:立马在别的机器上重新拉起这 3 个。

观察:流量大了?

行动:根据你定的规则(HPA),自动扩容到 10 个。

K8s 的唯一使命,就是不断对比 “现状” 和你的 “期望”,一旦不一致,它就自动动手修正,直到一致为止。你只管定义终点,路让它自己走。

二、核心概念:都是为了解决具体“坑”才诞生的

别死记硬背定义,看看这些概念是为了解决什么血泪教训才诞生的。

1. Pod:不是容器,是“豌豆荚”

误区:以为 K8s 直接跑 Docker 容器。真相:K8s 的最小调度单位不是容器,是 Pod

为什么要搞个 Pod?
想象一下,一个应用运行时,往往不光需要主程序(比如 Java Jar),还需要一个“侧车”(Sidecar,比如专门负责收集日志或同步配置的小工具)。这两个东西必须:

  • 绑定在一起,同生共死。
  • 共享网络 IP(不然主程序怎么把日志传给收集器?)。
  • 共享存储目录。

🗣️ 人话比喻

  • Docker 容器:像是独立的单人牢房,隔离太彻底,想协作得通过复杂的网络。
  • Pod:像是一个 豌豆荚。荚里面可以包一颗豆子(单容器),也可以包两颗(主程序 + 辅助程序)。
  • 关键点:Pod 里的所有容器,共用一个 IP,共用一套端口空间。它们之间可以通过 localhost 互相访问,就像在同一台机器上一样。

把 Pod 当作 一次性耗材。它随时可能被杀掉重建(节点维护、资源不足、版本更新)。绝对不要在 Pod 本地存重要数据,也不要指望它的 IP 永远不变。

2. Deployment:真正的“管家”与“保命符”

痛点:Pod 是“一次性”的,挂了就得换新的。那谁来负责“挂了就换”?难道还要人工盯着?

解决方案:Deployment。

你永远不会直接创建 Pod(除非调试),你永远创建的是 Deployment。
你跟 Deployment 说:“我要 3 个副本(replicas: 3)”。

Deployment 就像个 强迫症管家,时刻盯着集群:

“哎?怎么只有 2 个 Pod 活着?不行,立马再开一个!”

“哎?怎么有 4 个了?多了,杀掉一个!”

“老板说要升级版本?好,我先开一个新的,等它健康检查(Readiness Probe)通过了,再杀掉一个旧的。”(这就是 滚动更新,业务零中断)。

生产环境 严禁直接裸跑 Pod,必须套一层 Deployment(或者 StatefulSet)。它是你服务高可用的基石。

3. Service:固定的“前台总机”

痛点:Pod 的 IP 是动态的。今天 IP 是 10.0.0.5,明天它挂了,新来的 Pod IP 变成了 10.0.0.9。如果你的代码里写死了连接 10.0.0.5,明天系统必崩。

解决方案Service

Service 就是一个 永远不变的虚拟 IP(ClusterIP) 或 DNS 名。

  • 你创建一个 Service,通过标签选择器(Label Selector)绑定一组 Pod。
  • 外部程序(或其他 Pod)只访问 Service 的域名(如 order-svc.default.svc.cluster.local)。
  • Service 内部维护着一份“活着的 Pod 名单”(Endpoints)。请求来了,它自动转发给后面任意一个健康的 Pod。

服务间调用,永远用 Service 的域名,别用 IP;Service 默认做了负载均衡(轮询策略),不用你自己写代码做负载分发。

4. Ingress:集群的“大门保安”

痛点:Service 解决了内部访问,但外网用户怎么进来?给每个 Service 都配一个公网 IP(LoadBalancer)?太贵了,而且端口管理会乱套。

解决方案Ingress

Ingress 是集群的统一七层入口(通常是 Nginx 或 Traefik 控制器)。
你定个规则(Ingress Resource):

  • 访问 api.xxx.com -> 转给后端的 api-service (8080 端口)。
  • 访问 www.xxx.com -> 转给后端的 web-service (80 端口)。
  • 顺便还能处理 HTTPS 证书自动续签。

🗣️ 人话比喻:Ingress 就是 小区大门保安。外人进不来,得在门口登记,保安看你找谁(域名/路径),再把你指引到具体的楼栋(Service)。

5. ConfigMap & Secret:配置和密码的“外挂 U 盘”

痛点:以前改个数据库地址,得重新打包镜像,或者登录服务器改配置文件,太蠢。密码写在代码里更是安全大忌。

解决方案

  • ConfigMap:存普通配置(.properties, .yaml, 环境变量)。
  • Secret:存敏感信息(密码、密钥、Token),Base64 编码(注意:默认只是编码不是加密,生产环境需配合加密插件)。

用法:把它们像挂载 U 盘一样,挂载到 Pod 里的指定目录,或者注入为环境变量。

优势:想改配置?直接 kubectl edit configmap,Pod 重启(或应用热加载)就生效了,不用重新构建镜像。实现了 代码与配置分离。

6. Namespace:逻辑上的“隔断墙”

痛点:开发、测试、生产都在一个集群里,万一开发手滑把生产的库删了怎么办?或者开发跑个死循环把 CPU 占满,生产跑不动了怎么办?

解决方案Namespace

把一个物理集群,切分成多个逻辑空间(虚拟集群):

  • dev:给开发随便折腾。
  • test:给测试做集成。
  • prod:给生产,加严格的资源配额(ResourceQuota)和网络策略。

严禁所有东西都扔在 default 命名空间!那是新手村,生产环境必须按业务或环境划分 Namespace。

三、实战推演:一次故障是如何被“无感”修复的

光说概念没感觉,咱们模拟一次真实的服务器宕机,看看 K8s 是怎么操作的。

场景:你的订单服务跑了 3 个副本,分布在 3 台机器(Node)上。突然,2 号机器断电了

🔴 如果是传统运维(Docker 单机/脚本模式)

  1. 报警:半夜手机狂响,监控显示 2 号机器失联,订单接口大量 502。
  2. 起床:你迷迷糊糊爬起来,打开电脑,心跳加速。
  3. 止损:赶紧登录负载均衡器(如 F5 或 SLB),手动把 2 号机器摘除,不然用户请求全报错。
  4. 恢复
  • 找运维申请新机器(等半小时审批)。
  • 登录新机器,装 Docker,配环境,拉镜像。
  • 手动敲命令启动容器,配置日志路径。
  • 验证没问题,再加回负载均衡。
  1. 结果:折腾一小时,用户投诉一堆,第二天还要写事故报告,背锅。

🟢 如果用 K8s

  1. 检测(秒级):K8s 的控制节点(Controller Manager)通过心跳机制,在几十秒内发现 2 号机器 NotReady
  2. 判定:标记 2 号机器上的所有 Pod 为“未知”随后“终止”。
  3. 自愈(自动)
  • Deployment 控制器发现:“订单服务怎么只剩 2 个了?我的目标是 3 个啊!”
  • 它立刻下令:“在剩下的 1 号或 3 号机器上(只要资源够),马上再启动一个 Pod!”
  1. 调度:调度器(Scheduler)找到资源足够的机器,拉起新 Pod,拉取镜像,启动容器。
  2. 切换(无感)
  • Service 监听到旧 Pod 死了,新 Pod 活了(且通过了就绪探针),瞬间更新后端列表。
  • 流量自动切到新 Pod。
  1. 结果
  • 全程没人值班,你在睡觉。
  • 耗时可能只有 30-60 秒(取决于镜像大小和启动速度)。
  • 用户顶多觉得卡了一下,甚至完全没感觉(如果有重试机制)。
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐