ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Kubernetes高级特性面试指南:从Pod调度到nginx部署实战

Kubernetes高级特性面试指南:从Pod调度到nginx部署实战 1. 面试官问“高级特性”时到底在考什么——先摸清出题逻辑我在做技术面试官的时候发现一个现象大部分候选人简历上都写着“精通Kubernetes”但一问到Pod调度策略、驱逐机制、控制器工作原理这类问题时回答往往停留在“用过”“见过”的层面。Kubernetes高级特性的面试题表面考的是知识点实际上考的是两件事第一你有没有在真实环境里踩过坑第二你能不能把控制面组件之间的协作关系讲清楚。先说一个最容易被忽略的事实Kubernetes本身不是一个容器运行时它是一个容器编排平台。你在面试里说的每一个“高级特性”本质上都是在回答一个问题——你怎么让一组容器在一个几百台机器的集群里按照你期望的方式运行、通信、扩容、自愈。所以我不建议死记硬背面试题答案而是先建立一个坐标系调度、弹性、高可用、网络、存储、安全这六个维度基本覆盖了K8s高级特性的全部考点。这篇内容我会结合“部署nginx”这个最经典的实战场景把散落在各个知识点里的逻辑串起来顺便把我这些年整理面试题时沉淀下来的一些出题思路和答题技巧一并放进去。无论你是准备跳槽的候选人还是要组织团队面试的Leader应该都能从这里捞到点东西。另外一个建议不要指望一口气把下面所有东西都记住。Kubernetes的面试题有一个特点题目和题目之间有很强的关联性。比如面试官问你“Pod是怎么被调度到节点上的”如果你能把调度器、kubelet、资源请求、亲和性、污点这几个概念串成一个完整的链路这一题就能带出七八个高分点。这也是我下面这套拆解方式的出发点。2. 调度与资源管理Pod从创建到落地的完整决策链2.1 调度器到底在干嘛从Pending到Running中间发生了什么很多人一上来就被“高级特性”四个字带偏觉得K8s面试肯定要考什么Operator、Webhook、自定义控制器。但实际上调度这一块才是区分初中级和高级的分水岭。你去面试的时候面试官问你“Pod创建之后调度器做了什么”如果你只能回答“选个合适的节点”那基本就告别高级岗了。一个Pod从创建到运行链路大概是这样的你提交的YAML经过API Server的准入控制Admission Control之后被写入etcd接着调度器通过List-Watch机制感知到这个新的Pod对象然后开始为它寻找合适的节点。注意这里的“合适”不是随便选的而是一个两阶段的过程先过滤Filtering再打分Scoring。过滤阶段调度器会把不满足条件的节点全部排除。比如节点资源不够、端口冲突、不满足节点亲和性或污点容忍等这些都是硬约束。打分阶段则是在剩余节点里按一系列优先级策略算分比如资源余量、镜像是否已存在、节点亲和性匹配度等最后选出得分最高的节点。这也是为什么有时候你的Pod会被调度到一台看起来负载很高的机器上——因为综合评分最高。这里我要补充一个面试里特别爱考的细节调度器只是决定Pod放到哪个节点真正把Pod跑起来的是kubelet。调度器把Pod的NodeName字段写进去然后kubelet通过List-Watch发现这个Pod被分配给自己了才开始拉镜像、创建容器。很多候选人会把调度器说成“把Pod放到机器上的人”这个概念是不准确的——调度器只写了一个binding剩下的事全归kubelet管。2.2 资源请求与限制requests和limits的博弈关于资源面试题万年不变的问题就是“requests和limits有什么区别如果不设置会怎样”。这个问题看似基础但它牵出的陷阱特别多。requests是调度依据limits是运行限制。调度器只看requests不看limits——这一点几乎是必考的点。你设置Pod的limits很大、requests很小调度器依然会按requests去匹配节点资源也就是说这个Pod有潜力爆掉节点的实际负载却因为requests很低而被塞到一台资源紧张的机器上这就是Node压力问题的源头之一。还有一个高频场景状态工作负载Deployment、StatefulSet允许设置limits不设置requests但这样会产生一个后果——Pod的QoS等级会被标记为Burstable而且如果节点资源耗尽这类Pod优先被驱逐。所以生产环境里我一般建议requests和limits都显式声明而且最好不要拍脑袋填而是结合应用的真实内存画像来定。你可以先用不加limits的方式跑一两周配合监控看容器实际用量再回填合理的requests和limits。这就是Kubernetes官方一直提倡的“基于实际使用量配置资源”的思路。QoS等级这块面试官如果追问你要能说清楚三类Guaranteed每个容器都设置了相等的requests和limits、Burstable至少有一个容器设置了requests或limits但不满足Guaranteed条件、BestEffort完全不设置任何requests和limits。它们的区别不只是名字驱逐优先级从低到高是Guaranteed、Burstable、BestEffort。这也就解释了为什么有的人会碰到一种诡异现象明明自己的Pod没出问题却被系统杀掉了——大概率是节点内存紧张时BestEffort和Burstable先被优先驱逐。2.3 亲和性、污点与容忍把Pod“钉”在合适的节点上高级特性面试题里亲和性和污点这一组概念出现的频率非常高而且经常放在一起考。我给一个比较容易理解的说法亲和性是Pod主动去挑节点污点是节点主动拒绝Pod容忍是Pod戴了一个头盔去扛住拒绝。节点亲和性nodeAffinity有两种requiredDuringScheduling和preferredDuringScheduling。前者是硬性条件调度器找不到符合的节点就不调度后者是软性偏好加分项找不到也无所谓。Pod间亲和性podAffinity和反亲和性podAntiAffinity则用来表达“我想和谁待在一起”或者“我不想和谁待在一起”典型场景是保证同一个应用的多个副本尽量分散到不同节点避免单节点故障带走所有副本。污点Taint和容忍Toleration这边大家最熟悉的就是kubectl taint nodes node1 keyvalue:NoSchedule。这里面有一个很容易踩的坑添加了污点之后已经运行在该节点上的Pod不会被立刻驱逐只有NoExecute类型的污点才会对已存在的Pod生效。很多初学者以为打上NoSchedule污点就能清空节点结果节点上的Pod还在优雅运行然后他们就在面试现场翻车了。另外要注意master节点初始化之后自带一个node-role.kubernetes.io/master:NoSchedule的污点所以普通Pod不会调度到master上。你如果在一个单节点集群上创建Pod发现一直在Pending第一个排查点就是这个。2.4 横向扩缩容HPA其实比你想的更简单也更复杂弹性伸缩是K8s最吸引人的能力之一也是面试题里几乎必考的一类。HPAHorizontalPodAutoscaler的原理并不难Metrics Server持续采集Pod的CPU、内存等指标HPA Controller按照你设定的目标值计算期望副本数然后调整Deployment或StatefulSet的副本数。计算公式是期望副本数 ceil(当前副本数 x 当前指标值 / 目标指标值)。举个例子你设置目标CPU使用率是50%当前有4个副本实际使用率是100%那期望副本数就是4x100%/50%8。但面试题往往不会只考这个公式而是会追问两个进阶点。第一个是扩容和缩容的速率控制HPA默认的扩容是允许尽快扩容的容忍3-5分钟的指标延迟但缩容有一个冷却时间默认5分钟防止指标抖动导致副本数反复横跳。第二个是自定义指标CPU和内存指标只能反映资源压力如果你的应用是消息队列消费者更合理的扩缩容依据是队列长度。这种场景需要配合Prometheus Adapter或KEDA来实现自定义指标HPA。说实话HPA在生产里的坑比原理复杂得多。最典型的就是Java应用在启动初期CPU飙升HPA误判为负载高而触发扩容还没来得及复用又缩掉了。解决思路有两个一是给HPA配上 stabilization窗口二是用带缓冲的指标比如队列深度代替瞬时CPU。面试的时候如果能聊到这一层面试官基本会认为你是有线上经验的人。3. 高可用与自愈Pod明明挂了系统是怎么“装作无事发生”的3.1 探针的三个层级存活、就绪、启动Kubernetes的自愈能力全指望探针Probe这也是面试里的高频考点。探针有三个livenessProbe存活探针、readinessProbe就绪探针、startupProbe启动探针。很多人只记得前两个但startupProbe是K8s 1.16引入的专门解决“启动慢的应用被liveness误杀”的问题。三者的区别要能用一句话讲清楚liveness决定“要不要杀掉重启”readiness决定“要不要放流量进来”startup决定“要不要开始其他探针计时”。我最想提醒的是liveness和readiness的误用问题。有些同学图省事把readinessProbe和livenessProbe配成一样的探针结果应用一出现瞬时过载readiness失败的同时liveness也失败Pod直接被杀掉重启而不是暂时摘除流量。正确做法是liveness的阈值要比readiness宽松得多——比如readiness可以用3秒间隔、失败3次就摘流量而liveness可以放到15秒间隔、失败5次才重启。这样应用在抖动的时候只是暂时不接流量而不是动不动被重启。还有一个踩坑点探针执行的命令是写在容器里的如果容器里没有curl、wget这些工具你用HTTP探针或TCP探针完全没问题但用exec探针执行shell命令就会失败。这是一个在面试里可以反客为主的细节——你主动提出“我的镜像里没有bash所以我用HTTP探针”面试官会立刻对你的实战经验有印象。3.2 控制器模式Deployment、ReplicaSet、StatefulSet的分工逻辑高可用这个话题绕不开控制器。面试官问你“Deployment怎么实现滚动更新的”你要是只回答“先起新Pod、再删旧Pod”那是不够的。准确的回答是Deployment创建了一个ReplicaSetReplicaSet负责维持期望的副本数滚动更新时Deployment会创建新的ReplicaSet并逐步扩容同时缩容旧的ReplicaSet。这里有一个特别经典的追问**滚动更新过程中Pod版本不一致流量怎么处理**答案是这取决于readinessProbe的配合。新Pod的readiness探针通过后才会被加入Service的Endpoints否则就算新Pod已经Running流量还是打到旧Pod上。也就是说滚动更新真正决定一个副本是否“可用”的核心是ready状态而不是Running状态。StatefulSet和Deployment的区别也是必考项。StatefulSet给每个Pod一个稳定的网络标识如pod-0、pod-1、稳定的存储每个Pod绑定独立的PVC并且Pod的启停顺序是严格有序的。面试里常考的“为什么StatefulSet是顺序部署的”答案是它要保证分布式应用如etcd、ZooKeeper在启动时能按角色顺序加入集群避免脑裂或写入冲突。3.3 PodDisruptionBudget与节点维护优雅驱逐的最后一道保险高级一点的面试题会问我要对节点做重启维护怎么保证存量Pod不出现长时间不可用这个问题考的就是PDBPodDisruptionBudget。PDB的典型写法是给某个应用设置minAvailable: 2意思是自愿驱逐voluntary disruption过程中至少保持2个副本可用。注意PDB只对自愿驱逐生效——比如你执行kubectl drain、节点污点变更、滚动更新这类操作。节点宕机、Pod崩溃这种非自愿情况PDB是管不着的。所以“PDB保证了我的服务永远不挂”这种说法是一个典型的理解误区。实操层面kubectl drain之前最好先确认PDB已配置否则当节点只有一份副本且没设置PDB时drain会一直阻塞这是好事或者把Pod强制驱逐掉如果加了--force这是坏事。我自己踩过一次坑在某环境里没设置PDB直接drain了一台承载单副本关键服务的节点结果业务中断了十几秒。从那之后我养成了一个习惯任何有状态的或者单副本的应用必须配置PDB再考虑节点维护。3.4 多副本部署就够了吗Pod反亲和性的真实价值很多面试题会绕一大圈问“怎么保证高可用”。最常见的老实答案是“部署多个副本”。这个答案本身没问题但高级的回答必须带上反亲和性。如果多个副本没有任何调度约束是有可能挤在同一台物理机上的。一旦那台机器宕了你的多副本策略形同虚设。解决办法就是podAntiAffinity让同一个应用的不同副本尽量不落在同一个节点。但这里有个性能代价要说清楚反亲和性会显著降低调度成功率尤其是在小集群或节点数量有限的场景里。而且如果你用的是requiredDuringScheduling级别的反亲和性节点不够时Pod会一直Pending。所以生产里我通常用preferredDuringScheduling级别的软反亲和性配合节点数量的监控既能做基本的高可用分散又不会把调度逼进死胡同。面试的时候如果能主动区分硬反亲和和软反亲和各自的适用场景十分加分。4. Service与Ingress从“部署nginx”到“访问nginx”的完整链路4.1 一道看似简单的部署题nginx在你的集群里怎么跑起来“Kubernetes 部署nginx”这个热搜词背后对应的其实是一道复合题一个nginx应用从无到有、从内到外被访问涉及到的K8s知识点覆盖了Workload、Service、Ingress、ConfigMap、存储等多个层面。先按最简单的方式走一遍创建一个Deployment运行nginx镜像副本数设为3然后创建一个ClusterIP类型的Service暴露80端口。此时集群内部可以通过服务名:端口访问nginx。但如果要在集群外部访问就需要NodePort或者Ingress。这里有一个面试高频陷阱为什么ClusterIP的Service在集群外访问不了因为ClusterIP是一个虚拟IP只在集群内部的网络命名空间里有效。面试官真正想听到的是“Service的底层实现是iptables/IPVS规则”如果你能进一步说明NodePort就是在每个节点上开了一个端口把流量转发到ClusterIP再转发到Pod里的容器端口那基本就是满分答案。4.2 Service的类型选择ClusterIP、NodePort、LoadBalancer怎么选Service类型的选择是面试常见题也直接关系到nginx部署的实战效果类型访问方式适用场景缺点ClusterIP集群内部虚拟IP内部服务间调用外部不可直接访问NodePort每个节点的IP端口临时对外暴露端口范围有限多服务容易混乱LoadBalancer云厂商负载均衡器云环境对外暴露每个Service一个LB成本高ExternalNameDNS别名访问集群外部服务只做DNS映射无代理转发实战里我推荐的做法是nginx作为边缘入口不直接用NodePort暴露而是先创建一个ClusterIP的Service再用Ingress把域名路由到它。这样做的原因是NodePort直接暴露会占用节点端口而且没有TLS终止、路径路由这些能力。Ingress才是生产环境下的标准入口方案。还有一个常被忽略的点LoadBalancer类型的Service在裸金属集群bare metal里其实是无法自动创建云负载均衡器的需要用MetalLB这类方案来补充实现。如果你在IDC机房面试提到这一点会非常亮眼。4.3 Ingress Controller和Ingress资源别再傻傻分不清几乎所有K8s学习者都经历过一个困惑我创建了Ingress为什么访问不了域名原因非常简单——Ingress只是一份配置规则真正干活的是Ingress Controller。集群默认不会安装Ingress Controller你需要自己部署一个比如nginx-ingress-controller或traefik。这个区分是面试题的大热门。Ingress资源本身只是一系列规则某个域名的某个路径转发到哪个Service的哪个端口。Ingress Controller则是一个常驻Pod它不断读取这些规则并把它们翻译成Nginx或Traefik等的配置然后热加载。流量链路是外部请求 → Ingress Controller作为反向代理入口→ Service → Pod。我在这里强烈建议在练习环境里至少亲手部署一次ingress-nginx。等你看到那个ingress-nginx-controller的Pod创建出来、ConfigMap里自动生成的配置、以及访问日志里的转发记录时“Ingress资源”和“Ingress Controller”就再也不会搞混了。4.4 部署nginx的进阶姿势ConfigMap注入与优雅停机如果你只是把nginx用Deployment拉起、Service暴露这个练习只能算入门。想在部署nginx这个场景里体现你对高级特性的掌握至少还要加上三件事。第一用ConfigMap管理nginx.conf。nginx的配置天然适合文件注入你可以把Nginx的日志格式、gzip开关、代理参数写进ConfigMap里挂载到容器而不是把配置打进镜像。这样做的好处是修改配置后只需要重启或reload不需要重新构建镜像。第二处理好优雅停机。K8s删除Pod时会给容器发送SIGTERM信号但是nginx默认的master进程收到SIGTERM后会直接退出不等待当前连接处理完。你需要给nginx配置nginx -g daemon off;配合stop_signal: SIGQUITnginx的优雅退出信号或者在preStop钩子脚本里执行nginx -s quit。这个细节是我当年被折腾了一个晚上的地方也是面试时能讲出“生命周期钩子”加分项的绝佳素材。第三加一份readinessProbe。nginx的readiness探针建议用HTTP请求/healthz并且你需要在nginx配置里专门暴露这个location。探针的意义在于流量只打到健康副本上滚动更新时新旧副本平滑切换。否则你在滚动更新时可能会遇到短暂的502。4.5 面试必问题Pod访问Service的域名是怎么解析的如果面试官问“Service的DNS名称怎么用”你需要引出CoreDNS。Kubernetes集群里每个Service都会被COREDNS注册一个A记录格式是service-name.namespace.svc.cluster.local。同一命名空间下可以直接用Service名访问跨命名空间就要带命名空间名前缀。这个知识点本身不难但延伸出来的排查题特别多。比如在Pod里ping Service的ClusterIP不通是不是Service有问题这种题要看情况。ClusterIP是iptables/IPVS转发规则不是实际存在的网卡ping很可能被DROP掉但TCP请求是正常的。因此排查Service问题你应该用curl或者nc而不是ping。还有一道衍生题Pod的/etc/resolv.conf里的search domain是怎么影响DNS解析的。这个文件里默认带了一串search列表包含.namespace.svc.cluster.local、.svc.cluster.local、.cluster.local等所以你在Pod里访问myservice时系统会先试myservice.default.svc.cluster.local找到就直接返回结果。理解了这一点你就明白为什么有些人把Service当成域名写在配置里也能通——不是巧合是DNS search机制在起作用。5. 存储与持久化PV/PVC/StorageClass在面试中的正确打开方式5.1 从emptyDir到PV/PVC为什么要绕这么大一圈nginx本身是无状态的但你部署一个nginx无非是两种情况要么前面挂了缓存目录、网页静态文件要么后面接业务容器。不管哪种一旦涉及数据持久化存储的体系就绕不开了。K8s存储的抽象层次容易把人绕晕PVPersistentVolume是集群里的存储资源PVCPersistentVolumeClaim是使用方发起的资源请求StorageClass负责动态供给存储。用生活化的类比来解释PV是仓库里已有的货架PVC是你要租一个货架的申请单StorageClass则是接到申请单后现做货架的供货商。面试最常见的题是“静态PV和动态PVC有什么区别”。静态供给是管理员预先创建好一批PVPVC按条件去匹配动态供给是PVC创建时直接指定storageClassName由StorageClass的后端插件比如NFS Provisioner、云盘插件自动创建PV。生产环境几乎都会用动态供给因为你不可能预知每个应用需要多大空间。5.2 PVC的容量与访问模式你以为申请了就一定有空间吗关于PVC面试里有两个坑值得说出来。第一个是容量扩容早期PVC一旦创建容量就不能改。后来引入了allowVolumeExpansion但前提是StorageClass支持、存储后端支持在线扩容。而且云盘扩容的步骤往往是“改PVC继续fdisk、resize2fs”等多步操作并不是K8s改一个字段就好。第二个是回收策略PV被释放后是保留Retain、回收Recycle已废弃还是删除Delete。如果选择RetainPVC删除后数据还在但PV状态变成Released这时候你需要手动清理并重置PV的状态才能复用。访问模式也是一个高频考点。ReadWriteOnceRWO基本对应块存储只能被一个节点挂载ReadOnlyManyROX和ReadWriteManyRWX需要共享文件系统比如NFS或CephFS。你有没有想过这样一个场景Deployment有3个副本挂同一个PVC结果有一个副本Pending了。原因大概率就是这个PVC是RWO的只能在一个节点上挂载而三个副本里的两个被调度到了别的节点。这种题在面试里出现过的概率极高因为它是真实生产环境里确实会发生的问题。5.3 一个实战案例给nginx挂载持久化静态页面话题回到nginx。如果要把nginx的静态页面目录挂到持久卷上推荐的做法是部署一个NFS服务或者用云厂商的NAS然后创建StorageClass指向NFS Provisioner。之后写一个PVC再把Deployment里的nginx容器通过volumeMounts挂载这个PVC。这是整个链路里最容易卡壳的地方——PVC和容器目录的挂载关系一定要理清楚。PVC是一个“盘”volumeMounts只是把这个盘挂到容器里的某个路径。如果nfs服务器上对应的目录是空的那nginx容器里的/usr/share/nginx/html目录就会显示空内容覆盖掉镜像里的默认页面而不是镜像里的index.html。很多人挂载后页面404就是被这个“空目录覆盖”坑了。正确做法是先用一个initContainer把页面文件拷贝到挂载目录里再把nginx容器正常启动。或者在NFS服务器端预先放入初始文件。这个细节在面试中讲出来能证明你确实实操过而不是只看过文档。5.4 有状态应用的存储StatefulSet为什么需要VolumeClaimTemplate如果你面试的是偏后台或中间件方向的岗位StatefulSet绑定存储这题基本逃不掉。StatefulSet里的VolumeClaimTemplate相当于一个PVC模板每次创建Pod副本时系统自动为它生成一个独立的PVC。这意味着pod-0绑定的数据卷和pod-1绑定的数据卷物理上是两块独立的盘即使Pod被删掉重建新Pod还是会绑定原来那个PVC数据不丢。这个机制让状StatefulSet天然适合跑数据库、消息队列这类有状态服务。面试官如果问你“StatefulSet和Deployment最根本的区别是什么”除了启动顺序、网络标识之外你还要提这一点Deployment的Pod共享同一个PVC是可以的虽然受限于访问模式但一般不会为副本生成独立存储模板StatefulSet则是用VolumeClaimTemplate来保证每个副本有独立且稳定的存储这是两者在设计哲学上的根本差异。6. 安全与多租户RBAC、Namespace、NetworkPolicy是送分题还是送命题6.1 RBAC为什么大部分集群的安全事故都出在权限上Kubernetes的安全体系分散在好几个层但面试题里最高频的是RBAC。RBACRole-Based Access Control的核心对象有四个Role、ClusterRole、RoleBinding、ClusterRoleBinding。面试常考的一个点是Role和ClusterRole的区别——Role作用范围是某个NamespaceClusterRole作用于整个集群。但面试题目真正的杀招是组合拳能不能跨Namespace授权答案是RoleBinding只能绑定同Namespace下的Role如果你想在多个Namespace复用一组权限只能创建ClusterRole然后用RoleBinding在不同Namespace分别绑定它。那ClusterRoleBinding和RoleBinding绑定ClusterRole有什么区别前者让权限真正变成集群级后者让权限只作用于某个Namespace。实战里我最想补充的一点是不要为了省事把cluster-admin直接绑给应用服务账号。我见过太多因为调试方便用cluster-admin跑业务的例子出了问题之后根本没有审计追责的依据。正确做法是创建一个最小权限的ServiceAccount只授权它需要调用的资源操作比如读取Pod列表、查看日志、创建Job。然后通过kubectl auth can-i --list --assystem:serviceaccount:default:xxx来验证权限是否符合预期。这个小工具在面试时提到会让面试官觉得你对待权限是认真的。6.2 NetworkPolicy默认不隔离才是最大的安全漏洞Kubernetes的网络隔离是一个很容易被忽略的高级特性。默认情况下集群的网络是“全通”的——任何一个Pod都能访问其他Pod和所有Service。除非你显式创建NetworkPolicy否则你的nginx可以被任何命名空间的Pod访问。NetworkPolicy的难点在于它的“白名单”逻辑一旦创建了NetworkPolicy它就只允许符合规则的流量其余全部拒绝。这个“一旦创建就默认拒绝”的机制是新手最容易踩的坑。如果你给nginx加了一条只允许来自ingress-nginx命名空间流量的策略那么同命名空间里其他应用直接访问nginx——比如执行kubectl exec进到别的Pod里curl一下——也会被拒绝因为它的源地址不在允许列表里。生产环境的NetworkPolicy要特别小心两端都要考虑入口ingress和出口egress。如果要限制nginx只能访问数据库Service出口规则也得同时写上。很多人在面试里只会说入口规则很少提出口规则所以我每次听到有人能把egress也纳入讲述都会在心里默默加分。另外要记住NetworkPolicy要真正起作用依赖底层CNI插件的支持。Calico、Cilium这些都支持但是Flannel不支持NetworkPolicy。你如果在用了Flannel的集群里创建NetworkPolicy会发现根本没有效果——这个是架构选型层面的坑。6.3 多租户隔离Namespace的成本比你想的高多个团队共用集群时最基础的隔离单位是Namespace。ResourceQuota和LimitRange这两个资源就是为多租户准备的。ResourceQuota限制整个Namespace的总体资源上限比如CPU、内存、PVC数量、Service数量。LimitRange限制单个Pod或容器能在Namespace里申请的资源范围比如强制每个容器必须设置requests。这两个资源的目标很明确防止某个团队把一个共享集群的资源吃干榨净。但坑在于LimitRange设置“默认requests/limits”的行为只对新创建的Pod生效不回去改老Pod。如果你新增了一个LimitRange集群里已有的Pod依然保持裸奔状态除非重建。这算一个小知识点但面试题往往就是通过这类细节来区分“文档党”和“实战党”。6.4 镜像安全与准入控制你的nginx镜像来自哪里关于容器镜像安全面试的切入点通常是“你怎么保证线上跑的镜像是可信的”。常见答案有使用私有镜像仓库、镜像签名、扫描漏洞、避免latest标签。走到高级层面面试官会追问“准入控制Admission Control”。K8s的Pod创建请求会经过多个准入控制插件的检查比如NamespaceLifecycle、LimitRanger、ResourceQuota、PodSecurity等等。有的插件是内置默认开启的有的则需要自己部署。比如如果你想强制所有Pod不能以root用户运行可以借助Pod Security Standards或者部署OPA/Gatekeeper这类策略引擎在请求还投递到etcd之前就把不合规的Pod挡在外面。这里有一个思维转变值得在面试中体现K8s的安全不是某一个组件负责的而是一整条链条——镜像仓库供应链→ 准入控制器策略拦截→ RBAC权限管控→ NetworkPolicy网络隔离→ Pod Security运行时约束。如果你能按这个维度组织回答基本就能把安全相关的面试题串成一个体系。7. 一套nginx实战把所有高级特性串起来7.1 从零开始的高可用nginx部署、调度、自愈、访问现在我们把所有知识点收拢到一个具体的实操路径里按下面这几步在集群里部署一个生产级可用的nginx。假设你已经有一个K8s集群单节点也可以但最好有两个以上节点。第一步创建命名空间kubectl create namespace web。生产环境里我始终坚持用命名空间把环境或应用区分开不要什么都怼到default里。第二步配置资源清单。Deployment中副本设3个镜像使用固定版本比如nginx:1.25.3而不是latest。给每个容器设置requests为100m CPU加128Mi内存limits为500m CPU加256Mi内存并且加上livenessProbe和readinessProbe。这里用HTTP探针路径指向nginx自带的/healthz需要提前在ConfigMap里配置。调度方面用preferredDuringScheduling的podAntiAffinity让3个副本尽量分散到不同节点。第三步创建ServiceClusterIP类型暴露80端口再创建Ingress规则把nginx.example.local路由到刚才的Service。这套配置跑起来之后你会在kubectl get pods -o wide里看到3个副本分布在尽量不同的节点上kubectl get ingress能看到规则正常生成浏览器或curl也能通过域名访问到nginx页面。这个流程看上去简单但里面包含的Requests/Limits、探针、反亲和性、Service、Ingress正好覆盖了前面讲的大半知识点。7.2 模拟故障删掉一个Pod看K8s怎么“自我救赎”高可用特性的验证不能停留在“配置写了就完事”。我建议你亲自做一次故障演练kubectl delete pod nginx-pod-name——这里如果是Deployment管理的Pod控制器会立刻重新创建一个新Pod这正是ReplicaSet维持期望副本数的作用。再进阶一步kubectl scale deployment nginx --replicas5观察副本数变化然后kubectl autoscale deployment nginx --cpu-percent50 --min3 --max10给nginx配置HPA然后通过压测工具比如ab或hey打一波流量再看HPA是否自动扩容。这个过程特别直观你先执行kubectl top pods确认Metrics Server正常工作然后观察kubectl get hpa -w里副本数在压力下被拉上去。看到它真的扩容那一刻你对HPA的理解会比背十道面试题都有用。如果你再把节点维护也演练一遍就会触及PDB。没有PDB的Deployment其实还好——因为3副本分布在多个节点drain一个节点后控制器会把Pod补到其他节点但如果你drain的是单副本Pod所在节点又没有PDB那么这个Pod会被强制删除如果控制器的容忍度高通常也会重建。真正崩溃的场景是没有控制器管理的裸Pod比如用kubectl run直接创建drain之后它不会自动重建服务就真的断了。所以裸Pod在生产里是大忌。7.3 滚动更新和回滚的不传之秘nginx部署完最终绕不开“发版本”。把镜像从nginx:1.25.3改成nginx:1.26.0执行kubectl set image deployment/nginx nginxnginx:1.26.0或者直接改YAML后kubectl applyDeployment会触发滚动更新。那“滚动更新失败了”怎么回滚面试常考。kubectl rollout undo deployment/nginx会回到上一个版本。但如果已经连续发布过多个版本kubectl rollout history deployment/nginx可以查看历次变更记录然后--to-revision指定回滚到某个版本。这里有一个细节很多人没注意到Deployment默认的spec.revisionHistoryLimit是10意思是只保留10个历史版本超出的会被清理。这解释了为什么有时候执行rollout history发现只有最近几条——不是K8s丢了而是历史被清理了。这也意味着如果你需要长期保留更久的发布记录需要显式提高revisionHistoryLimit。7.4 这组实战里隐藏的面试加分项我想给你列一下上面这套nginx实战里每一个步骤对应的可以“主动拿分”的知识点写Deployment时设置requests/limits → 延伸出QoS等级和驱逐优先级。配置探针时区分liveness和readiness → 延伸出滚动更新时流量切换的细节。加podAntiAffinity → 延伸出多副本高可用的调度约束。创建ServiceIngress → 延伸出Service底层实现iptables/IPVS、Ingress Controller原理。配HPA → 延伸出扩缩容公式、冷却窗口、自定义指标。执行rollout undo → 延伸出ReplicaSet版本控制、revisionHistoryLimit。ConfigMap管理nginx配置 → 延伸出配置热加载和优雅重载。每条链路都能再多延展出一层这就是面试里所谓“举一反三”的来源。掌握知识点只是第一步把知识点串成一条“因为……所以……”的链条才是高级工程师和初级工程师的分界。8. 面试答题的心智模型与常见翻车现场8.1 不要背答案要背“推导链”我筛选候选人这些年最失望的不是答不上来的而是把面试当背书现场。问“HPA怎么工作”他能背出公式问“HPA扩出来的实例不够怎么办”他就开始沉默了。原因很简单他背了结论但没有建立起推导逻辑。一个高效的学习方法是把每个知识点变成“我怎么解决这个问题的”。不要问“K8s的Service有哪些类型”要问“如果我的服务想被外部访问有哪些方案各有什么代价”。前者是背书后者是工程决策。面试官想听到的永远是你做出决策的过程为什么选Ingress而不是NodePort为什么给这个Pod配3个副本而不是5个为什么用StatefulSet而不是Deployment。这些“为什么”背后都有推导链你平时多问自己几次面试时就能条件反射。8.2 几个高频翻车现场这些坑我真的见过我总结了几个现实中高频出现的错误答案分享给你作为“避雷清单”。第一个把“Pod崩溃了自动重启”归功于K8s自愈。实际上Pod崩溃后是否重启由restartPolicy和Pod的管理控制器决定。如果你是裸Pod且restartPolicyNever它不会自愈。真正自愈的是Deployment/StatefulSet这套控制器体系。回答时千万不要说“K8s检测到Pod挂掉就重新拉起”正确的说法是“控制器的Reconcile循环不断对比期望状态和实际状态发现不一致就修正”。第二个“Service的ClusterIP是DNS解析出来的”。这是概念混淆。Service提供了一个虚拟IPPod访问Service时请求先经过DNS解析获得ClusterIP然后流量被iptables/IPVS规则转发到后端的Pod IP。这里面DNS做的只是把Service名解析成ClusterIP并没有帮助负载均衡。负载均衡完全交给iptables/IPVS规则去做。第三个把探针认为是“监控工具”。探针不是监控工具它们的任务是配合K8s生命周期管理决定容器是否健康。监控是Prometheus那套的职责。两者层次不同如果你在面试里把CloudWatch/Prometheus和探针混为一谈会立刻暴露基本概念的漏洞。8.3 从面试题到真实排障怎么证明你“真的用过”面试最后面试官往往会让你讲一个线上排障案例。这几乎是决定胜败的环节。我建议你准备两个真实经历但关键不是讲你怎么看日志、怎么分析监控而是讲清楚你在解决问题的过程中和哪些K8s概念发生了交互。比如你以前处理过一个“Pod长时间Pending”的线上问题第一反应是kubectl describe pod看Events发现是调度失败继续查发现是节点资源不足requests太高、或者 nodeSelector 匹配不到任何节点、或者有污点但没加容忍。这样一个排障过程就把调度器、资源请求、节点选择、Taint/Toleration四个知识点串起来了同时证明了你遇到过、思考过、解决了。再比如你遇到过“Service偶尔502”的问题检查后端Pod都正常但再深入看发现是readinessProbe配置得太宽松导致Pod在重启的瞬间仍被认为ready而被暴露到Endpoints里流量持续打过来了。这种Case能让面试官看到你对“可用性”“探针”“Service转发”之间关系理解的意义所在。8.4 我个人沉淀下来的几条学习建议如果要在最后给点可操作的建议我会推荐这几件事。首先一定要自己动手把集群搭一遍。无论你用minikube、kind还是云厂商的托管集群至少要亲手经历一次从创建集群到发布应用的全流程。很多知识点在你亲手操作过一遍之后就不再是文档里抽象的名词了。其次多看集群事件Events和kubectl describe的输出。真实环境几乎每个异常都有Events线索比如FailedScheduling、BackOff、Unhealthy、Evicted。面试时你的回答会不自觉地用上这些具体的事件类型这是“实战经验”最直接的证据。第三养成先写“期望状态”再写“实现步骤”的习惯。K8s面试的核心就是声明式哲学你告诉系统要什么而不是怎么达到。这个思维模式听起来很简单但我面试过很多人聊到Deep Dive就会发现他们的没有真正理解“声明式”和“命令式”的区别。你在思考任何K8s问题时先问自己“系统里哪个对象在维持期望状态”这个问题能帮你理清绝大多数控制器相关的面试题。最后讲一句我这些年总结出来的经验Kubernetes的面试题目千变万化绕来绕去无非就是资源配置怎么定、流量怎么进、数据怎么存、权限怎么管、故障怎么处理。你把一条nginx从部署到被外部访问、再到扩容和故障演练的完整链路亲手跑通把每条链路里的每一个“为什么”想明白再去面试比刷两百道题有用得多。
返回列表