当前位置: 首页 > news >正文

【Kubernetes01】—— K8s核心原理一文吃透:从架构到调度的完整拆解

【Kubernetes】—— K8s核心原理一文吃透:从架构到调度的完整拆解

你可能听过 Kubernetes 很多次,知道它能"编排容器",但真要说清楚它内部怎么运作的、为什么要这么设计、各个组件之间怎么配合——这些才是你真正需要理解的东西。这篇文章不讲怎么装 K8s(那是下一篇的事),而是把它的核心原理拆开来讲透。

一句话:看完这篇,你能画出 K8s 的架构图,讲清楚每个组件的职责,理解 Pod、Service、Deployment 这些核心对象背后的设计逻辑。


一、先搞明白:K8s 到底在解决什么问题

假设你有 10 个微服务,每个服务跑 3 个副本,总共 30 个容器。用 Docker 跑起来没问题,但接下来你要面对一连串头疼的事:

  • 容器挂了,谁来重启?
  • 要扩容,怎么把新容器均匀分到几台机器上?
  • 服务 A 要访问服务 B,B 的 IP 一直在变,怎么处理?
  • 滚动更新的时候,怎么保证不丢请求?
  • 某台机器宕机了,上面的容器怎么迁移?

这些问题,Docker Compose 解决不了(它只管单机),手动运维又太累。Kubernetes 就是来干这件事的:在集群层面,自动化地管理容器的生命周期、网络、存储、调度。

说直白点:Docker 管一个容器,K8s 管一群容器。

你手动要做的事K8s 帮你做的事
容器挂了手动重启自动检测并重启(自愈)
手动 SSH 到机器上部署声明式配置,一条命令部署到集群
手动分配容器到哪台机器调度器自动选择最优节点
手动配负载均衡Service 自动分发流量
手动做滚动更新Deployment 自动渐进式替换

二、架构全景:K8s 集群长什么样

一个 K8s 集群由两类节点组成:Control Plane(控制平面)Worker Node(工作节点)。控制平面是"大脑",工作节点是"手脚"。

┌─────────────────────────────────────────────────────┐ │ Control Plane │ │ ┌───────────┐ ┌───────────┐ ┌──────────┐ ┌──────┐ │ │ │ API Server│ │ Scheduler │ │Controller│ │ etcd │ │ │ │ │ │ │ │ Manager │ │ │ │ │ └─────┬─────┘ └─────┬─────┘ └────┬─────┘ └──┬───┘ │ │ └──────────────┴────────────┴──────────┘ │ └─────────────────────────┬───────────────────────────┘ │ ┌─────────────┼─────────────┐ ▼ ▼ ▼ ┌─────────────┐┌─────────────┐┌─────────────┐ │ Worker Node ││ Worker Node ││ Worker Node │ │ ┌─────────┐ ││ ┌─────────┐ ││ ┌─────────┐ │ │ │ kubelet │ ││ │ kubelet │ ││ │ kubelet │ │ │ └─────────┘ ││ └─────────┘ ││ └─────────┘ │ │ ┌─────────┐ ││ ┌─────────┐ ││ ┌─────────┐ │ │ │kube-proxy│ ││ │kube-proxy│ ││ │kube-proxy│ │ │ └─────────┘ ││ └─────────┘ ││ └─────────┘ │ │ ┌───┐ ┌───┐ ││ ┌───┐ ┌───┐ ││ ┌───┐ ┌───┐ │ │ │Pod│ │Pod│ ││ │Pod│ │Pod│ ││ │Pod│ │Pod│ │ │ └───┘ └───┘ ││ └───┘ └───┘ ││ └───┘ └───┘ │ └─────────────┘└─────────────┘└─────────────┘

Control Plane 四大组件

API Server——集群的"总前台"。所有操作(kubectl 命令、控制器的协调、kubelet 的上报)都必须经过它。它对外暴露 RESTful API,内部负责认证、授权、准入控制。你可以把它理解为集群的唯一入口。

etcd——集群的"数据库"。所有集群状态(节点信息、Pod 配置、Service 映射)都存在这里。它是一个分布式 KV 存储,用 Raft 协议保证一致性。K8s 集群挂了,90% 的情况先查 etcd。

Scheduler——集群的"调度员"。当一个新 Pod 需要创建时,Scheduler 根据资源需求、亲和性、污点容忍等规则,决定这个 Pod 跑在哪台 Node 上。它不做实际部署,只做决策,然后把结果写回 API Server。

Controller Manager——集群的"管家团"。里面跑着一堆控制器(Deployment Controller、Node Controller、Service Controller 等),每个控制器负责一种资源的"期望状态 → 实际状态"的持续对齐。比如 Deployment Controller 发现副本数少了,就会创建新 Pod。

Worker Node 三大件

kubelet——节点上的"代理人"。它跟 API Server 保持通信,接收 Pod 的调度指令,调用容器运行时(如 containerd)来创建和管理容器,同时上报节点和 Pod 的状态。

kube-proxy——节点上的"网络管家"。它维护节点上的网络规则(iptables 或 IPVS),确保 Service 的流量能正确转发到后端 Pod。没有它,Service 就是个空壳。

容器运行时——真正跑容器的地方。早期是 Docker,现在主流是 containerd 或 CRI-O。kubelet 通过 CRI(Container Runtime Interface)跟它交互。

本章小结

组件所在位置一句话职责
API ServerControl Plane所有操作的唯一入口
etcdControl Plane存储集群全部状态
SchedulerControl Plane决定 Pod 跑在哪台机器
Controller ManagerControl Plane持续对齐期望状态与实际状态
kubeletWorker Node执行 Pod 生命周期管理
kube-proxyWorker Node维护 Service 网络转发规则

三、核心对象拆解:Pod / Service / Deployment

这三个是 K8s 里出场率最高的对象。搞懂它们,你就搞懂了 K8s 80% 的日常操作。

3.1 Pod:最小调度单元

Pod 不是容器,它是一组容器的"包装盒"。一个 Pod 里的容器共享网络命名空间(互相可以用 localhost 访问)和存储卷。

为什么要有 Pod?因为有些场景下,两个容器必须"住在一起"。比如一个 Web 服务 + 一个日志收集 Sidecar,它们需要共享同一个网络栈。Pod 就是 K8s 对这种"亲密关系"的抽象。

🔴 重点:Pod 是"临时品"。它随时可能被销毁重建,IP 地址也会变。所以永远不要直接访问一个 Pod 的 IP——这就是 Service 存在的意义。

一个最小的 Pod 定义:

apiVersion:v1kind:Podmetadata:name:my-applabels:app:my-appspec:containers:-name:my-appimage:nginx:1.25ports:-containerPort:80

但实际项目中,你几乎不会直接创建 Pod。你会通过 Deployment 来管理它。

3.2 Deployment:Pod 的"管家"

Deployment 解决的是"我需要 3 个一样的 Pod 持续运行"这个问题。它声明你想要多少个副本,然后由 Deployment Controller 持续保证实际数量和期望一致。

你:"我要 3 个 nginx Pod" Deployment Controller:"收到,我盯着。少了一个我就补,多了一个我就删。"

Deployment 还管滚动更新。当你改了镜像版本,它会按策略逐步替换旧 Pod,而不是一刀切全部停掉。这就是生产环境能做到"零停机发布"的基础。

apiVersion:apps/v1kind:Deploymentmetadata:name:my-appspec:replicas:3# 期望 3 个副本selector:matchLabels:app:my-appstrategy:type:RollingUpdaterollingUpdate:maxSurge:1# 最多多出 1 个 PodmaxUnavailable:0# 最多允许 0 个不可用template:metadata:labels:app:my-appspec:containers:-name:my-appimage:nginx:1.25ports:-containerPort:80resources:requests:cpu:"100m"memory:"128Mi"limits:cpu:"250m"memory:"256Mi"

⚠️ 注意:resources字段不是可选的装饰。不写 requests,Scheduler 就无法合理分配资源;不写 limits,一个失控的容器可能把整台节点的内存吃光。生产环境必须写。

3.3 Service:稳定的访问入口

Pod 的 IP 会变,Service 给你一个固定的虚拟 IP(ClusterIP)和 DNS 名字。不管你后端 Pod 怎么漂移、怎么替换,访问 Service 的地址始终不变。

apiVersion:v1kind:Servicemetadata:name:my-servicespec:selector:app:my-app# 匹配标签为 app=my-app 的 Podports:-protocol:TCPport:80# Service 暴露的端口targetPort:80# 转发到 Pod 的端口

Service 有几种类型,用得最多的是这三种:

类型使用场景特点
ClusterIP(默认)集群内部互访只能在集群内访问
NodePort开发测试、简单暴露在每个节点上开一个端口
LoadBalancer生产环境对外暴露需要云厂商支持(AWS ALB 等)

坑就坑在这里:很多人以为 Service 是"负载均衡器",其实它只是一组 iptables/IPVS 规则。真正的流量转发是 kube-proxy 在每个节点上做的。Service 的 ClusterIP 甚至不是一个真实存在的网络接口——它是个"虚 IP",靠 DNAT 规则把流量转到后端 Pod。


四、Pod 的一生:从声明到运行

理解一个 Pod 从创建到运行的完整链路,你就能理解 K8s 各组件是怎么协作的。

你执行 kubectl apply │ ▼ API Server 收到请求,校验后写入 etcd │ ▼ Deployment Controller 检测到副本数不足 │ ▼ 创建 Pod 对象(此时 Pod 处于 Pending 状态) │ ▼ Scheduler 发现未调度的 Pod │ ▼ 根据资源、亲和性、污点等规则选择 Node │ ▼ 把调度结果写回 Pod 的 spec.nodeName 字段 │ ▼ 目标 Node 的 kubelet 检测到分配给自己的 Pod │ ▼ kubelet 调用 containerd 拉镜像、创建容器 │ ▼ 容器启动,Pod 状态变为 Running │ ▼ kubelet 持续上报 Pod 状态给 API Server

🔴重点:这条链路上任何一环出问题,Pod 都会卡在某个状态。排查问题的时候,沿着这条链路往下查,基本都能定位到原因。

常见卡住的状态:

  • Pending:最常见的原因是资源不足(CPU/Memory 不够)或者没有满足条件的 Node(污点、亲和性)。用kubectl describe pod <name>看 Events。
  • ImagePullBackOff:镜像拉不下来。检查镜像名是否正确、仓库是否需要认证、网络是否通畅。
  • CrashLoopBackOff:容器启动后立刻退出。用kubectl logs <pod-name>看容器日志。

五、调度机制:Pod 是怎么选 Node 的

Scheduler 不是随机分配的,它有两步:过滤(Filtering)打分(Scoring)

过滤阶段:把不满足条件的 Node 删掉。比如 Pod 需要 2 核 CPU,只有 1 核的 Node 直接出局;Pod 有 nodeSelector 要求,不匹配的 Node 直接出局。

打分阶段:在剩下的 Node 里按策略打分,选得分最高的。默认策略会优先选资源利用率较低的 Node,避免把所有 Pod 都堆在同一台机器上。

几个影响调度的关键机制:

机制作用使用场景
nodeSelector按标签选择 Node“这个 Pod 必须跑在 SSD 机器上”
nodeAffinity更灵活的 Node 选择“优先选 zone-a,实在没有就选 zone-b”
Pod Affinity跟其他 Pod 亲近或远离“Web 和缓存放同一台机器”
Taints & TolerationsNode 拒绝某些 Pod“这台机器是 GPU 专用,普通 Pod 不要来”
Resource Requests声明 Pod 需要多少资源Scheduler 据此判断 Node 是否够用

⚠️ 注意:如果你设了 requests 但不设 limits,Pod 可以"超卖"使用资源,极端情况下会触发 OOMKilled。如果你设了 limits 但不设 requests,Pod 默认 requests = limits,等于完全不超卖。根据业务特性选择合适的策略。


六、网络模型:K8s 的网络怎么通的

K8s 的网络模型有三条基本原则(这是官方硬性要求):

  1. 所有 Pod 可以不经过 NAT 直接互相访问
  2. 所有 Node 可以不经过 NAT 直接访问所有 Pod
  3. Pod 看到的自己的 IP 和别人看到的它的 IP 一样

为了实现这三条,需要一个CNI(Container Network Interface)插件。常见的有:

插件特点适用场景
Calico支持 NetworkPolicy,性能好生产环境首选
Flannel简单轻量小集群、学习环境
Cilium基于 eBPF,性能极强大规模集群、需要高级网络策略

实际用下来,Calico 的稳定性最好,Cilium 的性能最猛但学习曲线陡。如果你是入门阶段,Flannel 够用;上生产直接选 Calico。

Pod 网络解决的是"Pod 之间怎么通信"。Service 网络解决的是"怎么用固定地址访问一组 Pod"。两者配合,构成了 K8s 完整的网络体系。


七、声明式管理:K8s 的核心哲学

这是理解 K8s 最重要的一点,很多人忽略了。

K8s 采用声明式(Declarative)管理,而不是命令式(Imperative)。区别在哪?

  • 命令式:“创建 3 个 Pod,然后把第一个的镜像改成 v2,然后删掉第三个……”——你在告诉系统"怎么做"。
  • 声明式:“我要 3 个 nginx v2 Pod,资源限制是这样,网络配置是这样。”——你只告诉系统"要什么",系统自己想办法达到。

这就是为什么 K8s 里一切都是 YAML。你写好 YAML 描述"期望状态",apply 一下,K8s 自动计算当前状态和期望状态的差异,然后执行必要的操作。

这个理念贯穿了整个 K8s 设计:

  • Deployment:声明"我要 3 个副本",Controller 负责对齐
  • Service:声明"我要把流量分发到这些 Pod",kube-proxy 负责配规则
  • HPA:声明"CPU 超过 80% 就扩容",HPA Controller 负责调整副本数

说白了:你写的是"目标",K8s 是"执行者"。你不需要关心具体怎么达到目标,只需要定义目标本身。这就是 K8s 最大的设计优势。


八、常见误区:这些坑你大概率会踩

误区一:Pod 就是容器

Pod 是容器的"包装盒",不是容器本身。一个 Pod 里可以有多个容器(主容器 + Sidecar)。Pod 拥有独立的网络命名空间和存储卷,容器共享这些资源。

误区二:Service 是负载均衡器

Service 只是一组转发规则的"声明"。真正的流量转发由 kube-proxy 在每个节点上通过 iptables/IPVS 规则实现。如果你需要七层负载均衡(HTTP 路由、限流等),得用 Ingress 或 Gateway API。

误区三:kubectl apply 就是部署

apply 只是把 YAML 提交给 API Server。真正的"部署"发生在后面的一系列控制器协调过程中。apply 之后立刻 get pods 看不到东西是正常的——给 Scheduler 和 kubelet 一点时间。

误区四:namespace 是硬隔离

namespace 只是逻辑隔离,不是网络隔离。不同 namespace 的 Pod 默认可以互相访问。要实现网络隔离,必须配 NetworkPolicy(需要 CNI 插件支持)。

误区五:K8s 能自动处理所有故障

K8s 能处理的是"进程级别"的故障(Pod 挂了、容器 OOM 了)。但它处理不了"应用级别"的故障(你的代码有 Bug、数据库连接超时)。健康检查(livenessProbe 和 readinessProbe)能帮你覆盖一部分,但不是万能的。


九、小结:你真正需要记住的 7 件事

  1. Control Plane 是大脑:API Server 是入口,etcd 是数据库,Scheduler 管调度,Controller Manager 管对齐。Worker Node 是手脚,kubelet 执行,kube-proxy 管网络。
  2. Pod 是最小调度单元:不是容器,是容器的包装盒。Pod 是临时的,IP 会变。
  3. Deployment 管副本和更新:声明式地管理 Pod 的数量和版本,支持滚动更新。
  4. Service 提供稳定入口:给一组 Pod 一个固定地址,后端变了前端不变。
  5. 调度是过滤 + 打分:先排除不满足条件的 Node,再选最优的。
  6. 网络靠 CNI 插件:K8s 只定义网络模型,具体实现由插件完成。
  7. 声明式是核心哲学:告诉 K8s “要什么”,不要告诉它 “怎么做”。

参考资源

  • Kubernetes 官方文档 - 概念
  • Kubernetes 官方文档 - 教程
  • kubectl 官方文档
http://www.zskr.cn/news/1489927.html

相关文章:

  • 小程序毕设项目:基于Springboot+微信小程序的粤语文化传播平台的设计与开发 (源码+文档,讲解、调试运行,定制等)
  • MATLAB版蛙跳算法特征筛选工具包:含数据、分类器接口与完整运行示例
  • 用MATLAB复现经典圆柱绕流:手把手教你跑通POD模态分解(附完整代码与避坑指南)
  • 从FreeRTOS转向ThreadX:在STM32F103C8上体验微软开源RTOS的移植差异
  • SOLIDWORKS转CAD字体终极指南:TrueType vs SHX字体怎么选?看完这篇不再纠结
  • AI 聊天辅助为什么不应该替你自动发送消息?
  • 纯文科考生,有没有机会报考大数据类本科专业?
  • 别再死磕公式了!用MATLAB/Octave手把手教你搞定LMMSE信道估计里的自相关矩阵
  • python学习第十七天(自用)
  • 微软为 Windows 10、11 及 Server 安装镜像发布 Defender 更新
  • 从虚拟机到私有云:手把手教你用CentOS 7和OpenStack搭建个人开发测试环境
  • Qt安装后第一件事:手把手教你配置环境变量和创建Hello World项目(Win10 + Qt 5.12)
  • 为什么国内大学普遍把c语言作为程序设计的入门课程?
  • C# WinForm连接SQLite踩坑实录:从‘文件被占用’到性能调优,我都帮你解决了
  • 免费图片去水印工具推荐:2026年收藏与学习向实用教程
  • 明明插了麦克风却没声音?这些坑你踩了几个?
  • 告别配置混乱!用Apollo Profiles统一管理Spring Boot多环境配置(附Idea/Eclipse实战)
  • 基于 Windows + Ubuntu 练习 MuJoCo 模拟
  • 基础采集设备
  • Vim党福音:用Coc.nvim + Clangd搞定嵌入式开发,解决交叉编译链头文件索引的终极脚本
  • 高效空气过滤器哪家好 2026年市场选择指南 - 品牌排行榜
  • 鸿蒙原生 ArkTS:margin 溢出、Row 弹性分配与 alignItems 的交互
  • 鸿蒙6.0应用开发——网络状态管理
  • LeetCode 2161.根据给定数字划分数组:双指针(O(1)但非源地操作)
  • 电商物流避坑指南:这8个快递查询痛点,你遇到过几个?
  • 告别截图!MapChart遗传图谱高清导出与个性化样式进阶教程
  • 市面上正规的雾森系统厂家哪家可靠
  • 大模型应用专家,做好随时涨薪的准备吧~
  • STM32F4 CANopen SDO通信调试实录:我是如何用逻辑分析仪抓包解决数据帧错误的
  • 2026乐山油炸串串推荐 脆皮五花肉人气店 - 优质品牌商家