面试知识库
进阶

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 为空),走两阶段:

  1. Filter(预选 / Predicates): 逐节点过滤,淘汰不满足硬条件的——资源不足(CPU/内存)、不匹配 nodeSelector/亲和性、污点未容忍、端口冲突等。结果是”可行节点”集合。
  2. Score(优选 / Priorities): 对可行节点逐项打分(0~100)——资源最空闲优先、Pod 亲和/反亲和、镜像本地已存在、拓扑均衡等,加权汇总选最高分。
  3. 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 打分阶段(亲和性/均衡/镜像本地化)和抢占机制