K8s 劝退?那是你打开方式不对
目录
5. ConfigMap & Secret:配置和密码的“外挂 U 盘”
很多人学 K8s(Kubernetes)被劝退,是因为教程一上来就甩名词:Pod、Service、Deployment、Ingress、ETCD……看着像天书,背了也忘。
它存在的唯一目的,就是把你从“登录服务器 -> 敲命令 -> 盯进程 -> 半夜报警起来重启”这种低级重复劳动中解放出来。
这篇文章不整虚的,咱们用大白话,把你以前运维遇到的破事,和 K8s 是怎么冷酷无情又高效地解决的,一次性捋清楚。
一、核心逻辑:从“过程式”到“声明式”的思维跃迁
1. 以前的你(过程式运维)
你要上线一个服务,脑子里全是步骤:
- 登录服务器 A。
git pull拉代码。mvn package编译。docker run启动容器。- 写个
crontab脚本,每分钟检查一次,挂了重启。 - 最痛苦的:如果服务器 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 单机/脚本模式)
- 报警:半夜手机狂响,监控显示 2 号机器失联,订单接口大量 502。
- 起床:你迷迷糊糊爬起来,打开电脑,心跳加速。
- 止损:赶紧登录负载均衡器(如 F5 或 SLB),手动把 2 号机器摘除,不然用户请求全报错。
- 恢复:
- 找运维申请新机器(等半小时审批)。
- 登录新机器,装 Docker,配环境,拉镜像。
- 手动敲命令启动容器,配置日志路径。
- 验证没问题,再加回负载均衡。
- 结果:折腾一小时,用户投诉一堆,第二天还要写事故报告,背锅。
🟢 如果用 K8s
- 检测(秒级):K8s 的控制节点(Controller Manager)通过心跳机制,在几十秒内发现 2 号机器
NotReady。 - 判定:标记 2 号机器上的所有 Pod 为“未知”随后“终止”。
- 自愈(自动):
- Deployment 控制器发现:“订单服务怎么只剩 2 个了?我的目标是 3 个啊!”
- 它立刻下令:“在剩下的 1 号或 3 号机器上(只要资源够),马上再启动一个 Pod!”
- 调度:调度器(Scheduler)找到资源足够的机器,拉起新 Pod,拉取镜像,启动容器。
- 切换(无感):
- Service 监听到旧 Pod 死了,新 Pod 活了(且通过了就绪探针),瞬间更新后端列表。
- 流量自动切到新 Pod。
- 结果:
- 全程没人值班,你在睡觉。
- 耗时可能只有 30-60 秒(取决于镜像大小和启动速度)。
- 用户顶多觉得卡了一下,甚至完全没感觉(如果有重试机制)。
更多推荐


所有评论(0)