恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
Kubernetes核心概念与架构解析:从Pod到控制器与集群实践
首页
资讯中心
/
Kubernetes核心概念与架构解析:从Pod到控制器与集群实践
Kubernetes核心概念与架构解析:从Pod到控制器与集群实践
发布时间:2026/10/10 6:45:18
Kubernetes 这套东西我用了几年从最开始在本地跑个单节点玩玩到后来在真实环境里承载几十个服务最大的感受是真正让你上手的不是命令而是把“核心概念、架构组成、核心功能”这三件事想明白。很多初学者第一眼看到 K8s 的组件图满屏都是名词什么 etcd、kubelet、Pod、Service其实它们解决了运维世界里几个非常朴素的痛点服务怎么调度、怎么扩容、怎么自愈、怎么不被中断。这篇不打算给你抄文档而是用“深入浅出”的方式把 Kubernetes 的核心逻辑拆开讲清楚再配上我实际操作中踩过的坑和排查思路。适合两类人一是已经会启动容器但还没系统理解集群编排的开发者二是刚接触 K8s、想搭建第一套集群的运维新手。看完之后至少你能解释清楚一次kubectl apply后整个集群发生了什么Pod 出问题时知道往哪儿看。1. 为什么需要 Kubernetes先搞清楚它要解决什么问题很多教程一上来就讲架构结果读者一脸懵因为根本不知道这套复杂系统是为了应付什么局面才出现的。所以我先聊痛点。1.1 容器时代的最强“单机”与致命短板Docker 解决了环境一致性问题把代码、运行时、依赖打包成一个镜像开发环境里跑起来什么样生产环境跑起来基本也是什么样这已经是很大的进步。但容器本身跑在一台机器上这台机器有硬伤这台机器一旦硬件故障或宕机上面所有容器全部失效业务流量暴增时想扩展多个实例只能手动一台台去拉镜像、起容器发布新版本时如果没有滚动发布策略直接全部重启业务会中断多个容器之间如何互相发现如何分配流量单靠 docker run 的端口映射很快会陷入混乱。用个生活化类比Docker 是做集装箱的把货物标准化封装得很好。但一个港口每天要进进出出几万个集装箱如果靠人工去指挥每一箱放在哪里、什么时候装船、坏箱怎么替换整个港口就瘫痪了。所以港口需要一套管理系统Kubernetes 就是这套港口管理系统。1.2 Kubernetes 的答案声明式状态与持续协调Kubernetes 和传统运维脚本最大的不同是它的操作逻辑不是“命令式”的。传统方式是你告诉机器“启动这个容器”“杀掉那个进程”它是顺序执行的单次操作而 K8s 是“声明式”的你把期望状态写下来比如“我要 5 个副本”它自己会持续观察当前状态一旦发现只有 3 个就自动补到 5 个发现多了就自动缩掉。这个“观察-差异-调整”的循环就是控制器模式。整个 K8s 架构里充满了这种控制器每个控制器负责一类资源的调谐。这个理念非常重要理解了它后面所有功能都顺理成章。1.3 动手之前需要先储备的基础我不建议一点基础都没有就硬上 K8s实操前最好有几样底子Linux 基本操作常用命令、查看日志、权限概念容器基本概念Docker 的镜像、容器、网络、卷知道docker run背后的流程而不是光会敲命令YAML 语法K8s 所有资源定义基本都是 YAML缩进错了资源就创建不了网络基础IP、DNS、端口、TCP/UDP 至少要能聊明白。有人会觉得要学的太多其实只要容器概念到位后面这些可以在实践中边用边补。2. 核心概念把集群当作一个自管理的数据中心Kubernetes 的概念很多但核心就那么几个。我把它们分成五类按依赖顺序理解最容易记忆。2.1 节点与集群最外层的顶层抽象Kubernetes 把物理机或虚拟机抽象成节点。节点分两种角色控制节点负责管理整个集群工作节点负责跑实际业务负载。控制节点不承担业务流量它的任务是做决策比如该把 Pod 调度到哪、某个应用副本数够不够、服务暴露的端口怎么管理。工作节点就纯粹多了上面运行 kubelet 和容器运行时真正承载用户的容器。一个集群就是这些节点的总和它对外暴露一个统一的 API 入口。你在集群里操作资源时不需要关心具体落在哪台机器上只需要和集群交互。2.2 Pod调度的最小原子单位这是新手最容易卡住的点。有人问容器已经有隔离能力了为什么还要多包一层 Pod Pod 是 Kubernetes 调度和运行的最小单位一个 Pod 可以放一个或多个容器。同一个 Pod 里的容器共享同一个网络命名空间和存储卷也就是说它们共享 IP、共享端口空间可以通过 localhost 互相访问。什么时候一个 Pod 里放多个容器典型场景是边车模式比如业务容器旁边放一个日志采集容器专门负责把业务日志转发到日志系统或者放一个流量代理容器负责做连接注入。这些辅助容器和主容器需要贴近部署、共享生命周期放一起最合理。和直接单跑一个容器相比Pod 最大的特点是它的 IP 是临时的生命周期随时可能结束。这个“不确定性”直接催生了 Service 和控制器这两类资源的存在。2.3 控制器谁来保证“状态符合预期”既然 Pod 可能随时挂掉那谁来拉新的答案是控制器。不同业务形态用不同控制器Deployment最常用适合无状态应用比如 Web 服务、API 服务。它管理副本数支持滚动更新和回滚。StatefulSet适合有状态应用比如数据库、消息队列。它给每个副本一个稳定的网络标识并且规范了存储卷的挂载顺序。DaemonSet保证每个节点上都运行一个 Pod典型的场景是日志采集 Agent、监控节点 Agent。Job 和 CronJob处理一次性任务和定时任务比如数据清理、定时报表。理解方式可以很形象Deployment 是“维持数量”的管家StatefulSet 是“保持身份”的管家DaemonSet 是“覆盖全员”的管家。它们管的事不同但工作机制相似都是通过控制器循环让当前状态朝期望状态靠拢。2.4 Service 与 Ingress从 Pod IP 到稳定访问入口Pod 的 IP 会变那客户端怎么访问这就轮到 Service 登场。Service 是对一组 Pod 的抽象稳定入口。它通过 selector 按标签选择后端 Pod对外提供一个稳定的虚拟 IPClusterIP并自动负载均衡到这些 Pod。即使某个 Pod 挂了被重建只要标签不变Service 就不受影响。Service 有几种类型ClusterIP只在集群内部访问NodePort把服务端口映射到节点端口集群外可以通过节点 IP 访问LoadBalancer在云环境或裸金属环境对接负载均衡器。Ingress 再上一层处理的是七层 HTTP/HTTPS 路由。你可以用 Ingress 把请求按域名、按路径转发到不同 Service还能顺便做 TLS 证书终止。简单理解Service 负责集群内部的流量分发Ingress 负责外部进来的请求如何进入集群内部。2.5 配置与存储ConfigMap、Secret、PV/PVC应用跑起来离不开配置和存储K8s 对这两件事都做了抽象。ConfigMap 用来存配置文件Secret 用来存敏感信息比如数据库密码、令牌、证书。把配置从容器镜像里解耦出来好处是同一个镜像可以通过不同 ConfigMap 适配不同环境不需要重新构建镜像。Secret 比 ConfigMap 更安全存储时做了编码处理使用时会挂载成文件或环境变量。存储方面PersistentVolumePV是集群级别的存储资源PersistentVolumeClaimPVC是用户对存储的请求。这个设计把“存储资源提供方”和“存储资源使用方”分开了应用只需要声明要多大空间、什么访问模式至于底层是 NFS、分布式存储还是云盘由管理员决定。这样应用开发和存储运维互不干扰也是 K8s 很优雅的一个抽象。3. 架构组成控制平面与工作节点的协作概念看明白了再看架构组成就会顺畅很多。Kubernetes 整体分为控制平面和工作节点两大部分它们通过 API 交互形成一个“中央决策-边缘执行”的模型。3.1 控制平面组件各司其职控制平面有四个关键组件API Server 是集群的唯一入口所有命令kubectl、内部组件通信都要经过它。它负责认证、授权、准入控制然后把数据写到 etcd。你可以把 API Server 想象成整个集群的前台和后厨连接点。etcd 是集群的数据库保存所有资源对象的定义和实际状态。它是一个分布式键值存储为了保证一致性生产环境一般部署奇数个节点比如 3 个或 5 个。注意etcd 是整个集群的“真相来源”写坏了它就等于集群脑死亡所以必须做好备份。Scheduler 是调度的决策者负责决定一个新建的 Pod 放到哪个节点上。它通过评估节点资源、亲和性要求、污点容忍等条件挑出最合适的节点然后告诉 API Server。Controller Manager 是一组控制器的集合Deployment 的控制器、ReplicaSet 的控制器、Namespace 的控制器等都在里面。它们持续监控集群状态调用 API 让实际状态趋向期望状态。3.2 工作节点组件工作节点上的组件相对朴实kubelet 是节点的代理负责和容器运行时交互创建、启动、停止 Pod并把节点状态上报给 API Server。它是工作节点上最重要的进程。kube-proxy 负责维护节点上的网络规则实现 Service 的虚拟 IP 转发和负载均衡。它靠 iptables 或 IPVS 这类机制工作保证发往 Service 的流量能到达后端 Pod。容器运行时是真正运行容器的地方常见的有 containerd、CRI-O。kubelet 通过容器运行时接口和运行时通信并不直接调用 Docker CLI。3.3 一次 Pod 调度背后的完整链路理解这条链路排查问题会非常有底。从你敲下一行命令开始kubectl apply -f deployment.yaml这条命令行会先被 API Server 接收通过认证和准入控制后Deployment 对象被写入 etcd。接着 Controller Manager 里的 Deployment 控制器发现“期望副本数”和“当前实际 Pod 数”不一致就会创建 ReplicaSet 对象再由 ReplicaSet 控制器创建具体的 Pod 对象。Pod 对象创建后Scheduler 监听到这个未调度的 Pod它综合评估节点资源、污点、亲和性等选一个节点把调度结果写回 API Server。然后该节点的 kubelet 发现有一个新 Pod 被调度到自己身上就调用容器运行时开始拉镜像、创建容器。等容器运行起来kubelet 会回报状态给 API Server。最后如果这个 Pod 被某个 Service 选中kube-proxy 会更新网络规则让新 Pod 能收到流量。整个链路不算短但只要理解了以后碰到“应用起不来”“流量没过去”就有清晰排查方向。4. 核心功能为什么 Kubernetes 这么能打这章节回答一个问题K8s 凭什么叫容器编排平台我挑几个最核心的功能展开讲。4.1 声明式 API 与控制器模式这是整个 Kubernetes 的底层逻辑也是很多人在刚接触时比较容易忽略的。传统运维自动化是这样的写脚本说如果 A 情况发生就执行 B 操作。而 K8s 的逻辑是你告诉我目标状态我不停地让实际状态靠拢。这种模式最大的优点是可自愈。比如某节点宕机节点上的 Pod 全没了但 Deployment 控制器还在它看到当前实际副本数低于期望副本数就会在别的节点上重新创建 Pod。这个过程不需要人介入也不需要额外写“故障检测脚本”。K8s 把“维持状态”变成了基础设施的默认能力。4.2 自动伸缩HPA 与资源请求的配合自动伸缩是 K8s 比较吸引人的功能。Pod 水平自动伸缩器HPA可以根据 CPU 使用率、内存使用率等指标自动调整 Deployment 的副本数。但这个功能有一个前提你必须在 Pod 里配置资源请求。如果没写 requestsHPA 就不知道怎么判断负载因为调度器不知道该 Pod 的基础水位是什么。这是一个非常常见的配置疏漏很多人创建 Deployment 时不写 resources 段后面想配置自动伸缩发现完全不生效。资源请求分两种requests 是声明“最少要这么多”用于调度判断limits 是声明“最多能用这么多”用于限制运行时。不写 requests 会导致 Pod 可能被调度到资源已经很紧张的节点不写 limits 可能导致某个容器把宿主机内存吃完。4.3 滚动更新、自愈与故障转移发布新版本时K8s 默认采用滚动更新策略而不是一次性全部替换。在 Deployment 中可以通过maxSurge和maxUnavailable控制更新速率。maxUnavailable表示更新过程中最多允许多少个旧 Pod 不可用可以设置百分比或绝对数量。maxSurge表示更新过程中最多可以多启动多少个 Pod。这两个参数配合既能保证发布过程中服务不中断又能控制资源占用和发布并发度。自愈能力前面提过这里补充一个细节Pod 内部还分存活探针和就绪探针。存活探针探测失败K8s 会杀掉容器重启就绪探针探测失败Pod 不会从 Service 的负载池里摘除也就是暂时不接收流量。这是保障滚动更新时流量平滑切换的重要手段。只配存活探针不配就绪探针滚动更新时可能出现新 Pod 还没就绪就接收流量的问题。4.4 服务发现与负载均衡在集群内部服务之间互相访问主要靠 DNS。Kubernetes 内置 DNS 服务通常是 CoreDNS当你创建一个 Service 时会自动生成一条 DNS 记录域名格式一般像是服务名.命名空间.svc.cluster.local。应用之间只需要通过服务名就能访问不必关心实际 Pod IP。负载均衡由 kube-proxy 实现常用的模式是 iptables 和 IPVS。IPVS 的性能和算法种类比 iptables 更丰富支持轮询、最少连接等策略所以生产环境如果用纯软件负载很多人倾向开 IPVS 模式。当然外部流量进入集群后一般还会搭配云负载均衡器或 Ingress Controller 来统一入口。5. 实操在本地快速搭起一个可用的单节点环境理论讲多了容易飘实际操作一遍才能把前面说的概念钉在脑子里。我建议先在本地单节点环境中跑通不用一上来就上多节点集群。5.1 环境准备与安装工具选择本地学习工具我比较推荐这两个minikube功能完整跨平台支持好适合模拟接近生产环境的体验只是对机器配置要求稍高一些。k3s轻量级发行版安装快资源占用低适合笔记本或虚拟机。如果你是在低配机器上学习用 k3s 会舒服很多。我自己入门时用的 minikube但后来给一些测试环境装 k3s发现对于学习来说 k3s 更省心。如果只想概念验证一条命令就能起集群。装好后先确认节点状态kubectl get nodes如果状态是 Ready说明集群起来了。然后再看看所有组件的状态kubectl get pods -n kube-system这一步能看到控制平面相关的 Pod 都在运行例如 CoreDNS。这里给个经验本地环境如果卡在 Pulling 镜像不动大概率是网络拉取镜像慢可以配置镜像加速或者耐心等待。5.2 部署第一个 Nginx 并暴露访问光跑一个容器不够你至少要创建 Deployment 和 Service才能体现 K8s 的价值。先写一个最基础的 DeploymentapiVersion: apps/v1 kind: Deployment metadata: name: nginx-demo spec: replicas: 2 selector: matchLabels: app: nginx-demo template: metadata: labels: app: nginx-demo spec: containers: - name: nginx image: nginx:stable ports: - containerPort: 80应用它kubectl apply -f nginx-deployment.yaml然后创建 ServiceapiVersion: v1 kind: Service metadata: name: nginx-svc spec: selector: app: nginx-demo ports: - port: 80 targetPort: 80 type: ClusterIP执行kubectl apply -f nginx-service.yaml kubectl get svc这个 Service 分配了一个内部虚拟 IP你在集群内任意 Pod 里都能通过服务名nginx-svc访问它。如果想让本机直接访问可以把 Service 类型改成 NodePort它会映射一个节点端口然后通过localhost:节点端口访问。这里想强调一个排查重点Service 能不能把流量送到 Pod完全取决于 selector 和 Pod 的 label 是否匹配。如果 label 写错了Service 后端列表是空的流量进来就会被丢弃。5.3 执行一次滚动更新与回滚手动体验一次滚动更新能直观理解“期望状态”到底是什么。修改 nginx-demo 这个 Deployment 的镜像版本kubectl set image deployment/nginx-demo nginxnginx:alpine为了让过程看得到你可以在更新过程中开一个终端持续观察kubectl get pods -w你会看到 Pod 并不是全部一次性替换而是先起一个新的新的就绪了旧的才会逐步删除。默认情况就是典型的滚动策略这就是maxSurge和maxUnavailable在起作用。如果这次更新有问题比如镜像 tag 不存在导致拉取失败回滚的命令也很简单kubectl rollout undo deployment/nginx-demo再看状态就会发现 Pod 回到了上一个版本。实际生产中我建议养成发布前先查看当前 rollout 状态的习惯kubectl rollout status deployment/nginx-demo确认发布完成再继续下一步操作。5.4 配置资源限制与探针这一节比跑通一个应用更重要因为生产环境排查问题大多发生在资源限制和探针配置上。在 Deployment 中给容器加上 resourcesresources: requests: cpu: 100m memory: 128Mi limits: cpu: 500m memory: 256Mi注意100m是 100 毫核也就是 0.1 个 CPU 核心。这个值是调度和限制的依据如果节点的可用资源不够Pod 会一直等待调度。再配两个探针livenessProbe: httpGet: path: / port: 80 initialDelaySeconds: 3 periodSeconds: 5 readinessProbe: httpGet: path: / port: 80 initialDelaySeconds: 3 periodSeconds: 5配置好后你可以刻意把探针路径改成/wrong-path再观察 Pod会发生重启或就绪探针一直失败。通过这种方式你能直观了解 K8s 的“自愈”到底是怎么运作的。这套配置实操下来你就会理解为什么负载均衡、滚动更新和自愈都建立在“行为声明”之上K8s 不需要知道你的应用里面在干什么只需要知道它表现是否健康是否符合预期的资源模型。6. 常见问题与排查技巧实录最后把我在实际使用中踩过比较多的问题整理成速查表格碰到类似情况可以直接对着排查。6.1 Pod 一直处于 PendingPod 一直 Pending说明没有被调度到节点上。最常见的原因有三个节点资源不足剩余 CPU 或内存满足不了 requests存在节点污点而且 Pod 没有对应的容忍配置了 nodeSelector 或节点亲和性但没有节点满足标签条件。排查指令先是看事件kubectl describe pod pod-name事件里会明确写调度失败的原因比如Insufficient cpu或者0/1 nodes are available。如果是因为资源不足要么调大节点资源要么减小 Pod 的 requests或者清理节点上不需要的 Pod。6.2 CrashLoopBackOff这个状态说明 Pod 一直在启动然后崩溃反复循环。原因无非几类容器进程启动失败比如启动命令写错配置缺失比如环境变量没传、配置文件挂载路径不对启动后立刻崩溃没有常驻进程存活探针配置过严容器明明还活着但探针认为失败。排查看日志kubectl logs pod-name --previous这条命令看的是实例上一次异常的日志非常重要。有时当前容器日志是空的但上一次的日志能告诉你到底为什么挂。6.3 网络不通或 DNS 解析失败这类问题在集群里最让人头疼。我按经验把常见原因排个优先级Service selector 选不中后端 Pod导致后端为空Service 和 Pod 的端口定义不匹配流量到达 Pod 但它监听的不是这个端口CoreDNS 异常或网络插件问题导致服务域名无法解析集群网络插件本身配置错误比如 CNI 的 IP 段冲突。排查第一步先看 Service 后端kubectl get endpoints service-name如果 Endpoints 里没有 IP说明 selector 没选中 Pod如果有 IP就要进入 Pod 内部测试访问服务名kubectl exec -it pod-name -- curl http://service-name这样能快速定位问题发生在 Service 层还是 DNS 层。6.4 排查命令与使用思路速查常备以下命令能覆盖 90% 的排查场景kubectl get events --sort-by.lastTimestamp kubectl describe node node-name kubectl get pods -o wide kubectl logs pod-name -f kubectl exec -it pod-name -- sh kubectl top nodes kubectl top pods一个良好习惯是不要只看状态要看“事件”。很多问题事件里写得很明白只是平时没人留意。在实操层面我还总结出了几条铁律。Pod 状态异常先看日志和事件别急着重启Service 流量不通先看 Endpoints别猜网络插件更新失败先看 rollout status别直接手动改资源。按这个顺序排查大部分问题都能在十分钟内定位。Kubernetes 本身的理念想通之后再看日常操作就自然很多。它不是一个“容器启动工具”而是一个把数据中心里的调度、网络、存储、发布都抽象成统一资源模型的控制系统。我给新人的建议是不用急着背命令先把 Deployment、Service、Pod 这三者的关系在本地跑熟再把控制器的调谐逻辑想明白后面看 Tem StatefulSet、DaemonSet、各类 Operator 都会轻松很多。最后分享一个我自己的习惯每次学一个新的 K8s 资源我都会亲手写一份最小可运行的 YAML 跑一遍再故意改一个字段看会引发什么变化。这个“破坏性实验”的方法比单纯看文档理解深得多。比如把 Service selector 改错你才会真实记住“选择器决定后端”把探针路径改错你才会理解它的触发机制。K8s 的知识体系虽然大但核心就那么几条主线抓住之后剩下的都是往这个框架里填充细节。