K8s架构与组件#
一句话答案#
K8s Master(API Server / etcd / Scheduler / Controller Manager)+ Node(kubelet / kube-proxy / 容器运行时)。
核心要点
Master(控制面): API Server(入口)/ etcd(状态存储)/ Scheduler(调度)/ Controller Manager(控制器)
Node(工作面): kubelet(Pod管理)/ kube-proxy(网络转发)/ 容器运行时(containerd)
核心对象层次: Pod → Deployment → Service → Ingress
声明式 reconcile 循环(控制器核心)#
心智模型: 你只声明”期望状态”(写进 etcd),控制器不停地把”实际状态”往期望状态拉平,这个闭环就是 reconcile(调谐)。
informer + list-watch 怎么感知变化:
- 控制器不轮询 API Server,而是建立 informer:先
List拉全量做基线,再Watch监听增量。 - Watch 底层是 etcd 的 watch +
resourceVersion:每个对象有版本号,watch 带上版本号只推送之后的变更事件(Add/Update/Delete),实现高效增量同步,避免全量轮询压垮 API Server。 - informer 本地维护一份缓存(Indexer),事件到来时把对象 key 丢进 work queue,worker 协程消费、执行 reconcile,处理失败可重新入队重试(带限速/退避)。
level-triggered 而非 edge-triggered(容错关键): reconcile 每次都读取”当前完整期望状态 vs 实际状态”做全量对比并修正,而不是只响应”某个变化事件”。即使中途漏掉一个事件、控制器重启、消息丢失,下次 reconcile 仍会基于最新状态纠偏 —— 这就是 K8s 自愈和最终一致的根本。Deployment 副本被删,控制器下一轮发现 actual<desired 就补齐。
Scheduler 两阶段调度#
Scheduler watch 到未绑定 Node 的 Pod(spec.nodeName 为空),走两阶段:
- Filter(预选 / Predicates): 逐节点过滤,淘汰不满足硬条件的——资源不足(CPU/内存)、不匹配 nodeSelector/亲和性、污点未容忍、端口冲突等。结果是”可行节点”集合。
- Score(优选 / Priorities): 对可行节点逐项打分(0~100)——资源最空闲优先、Pod 亲和/反亲和、镜像本地已存在、拓扑均衡等,加权汇总选最高分。
- Bind: 把选中 Node 写回 Pod 的
spec.nodeName(更新 etcd),kubelet watch 到后才真正拉起容器。
调度框架(Scheduling Framework): 把上述过程拆成 PreFilter/Filter/PreScore/Score/Reserve/Bind 等插件扩展点,自定义调度策略以插件形式注入,无需 fork 调度器。
抢占(Preemption): 高优先级 Pod 无节点可调度时,调度器可驱逐(evict)低优先级 Pod 腾出资源,让高优先级 Pod 先调度,被驱逐者重新排队。
面试回答(2分钟版)
K8s架构分为控制面和工作面两大部分。控制面也就是Master节点,核心有四个组件:API Server是整个集群的唯一入口,所有操作都通过它走RESTful接口;etcd是分布式KV存储,负责持久化集群状态,用Raft协议保证一致性;Scheduler负责将新建的Pod调度到合适的Node上,会综合考虑资源、亲和性等策略;Controller Manager运行各种控制器,持续对比期望状态和实际状态,比如Deployment Controller保证副本数正确。工作面是Node节点,kubelet负责管理Pod的生命周期,kube-proxy维护网络转发规则实现Service的负载均衡,容器运行时通常是containerd来真正启动容器。对象层次从小到大是Pod、Deployment、Service、Ingress。实际使用中,我们通过Deployment管理无状态应用的滚动更新和回滚,Service做服务发现和内部负载均衡,Ingress统一管理外部流量入口。理解这套声明式架构的关键是:你只需要告诉K8s你要什么状态,控制器会自动驱动集群达到目标状态。
追问与易错
追问方向:
- “etcd 挂了会怎样?”→ etcd 存储整个集群状态,挂了后无法创建/更新/删除资源,已运行的 Pod 不受影响但无法调度新 Pod;生产环境必须部署 3 或 5 节点 etcd 集群保证高可用
- “API Server 怎么做高可用?”→ 部署多个 API Server 实例,前面挂负载均衡器(如 HAProxy/Nginx);API Server 本身无状态,状态全在 etcd,所以水平扩展很简单
- “K8s 和 Spring Cloud 微服务治理有什么区别?”→ K8s 在基础设施层做服务发现(Service/DNS)和负载均衡(kube-proxy),Spring Cloud 在应用层做(Nacos/Ribbon);两者可配合使用,K8s 管部署编排,Spring Cloud 管应用级治理(熔断/限流/配置中心)
易错点:
- ❌ 以为控制器轮询 API Server——实际靠 informer 的 list-watch(基于 etcd watch + resourceVersion)做增量感知,轮询会压垮 API Server
- ❌ 分不清 level-triggered 和 edge-triggered——reconcile 是 level(每次全量对比纠偏),所以漏事件、重启都能自愈;edge(只响应变化)漏一个事件就永久错乱
- ❌ 说调度只是”挑资源够的节点”——漏了 Score 打分阶段(亲和性/均衡/镜像本地化)和抢占机制