聊容器和K8s面试题这件事我最大的感受就是很多人把它当成“背诵清单”来准备结果一到现场背得越顺越容易露馅。过去几年我既以候选人身份参加过容器方向的岗位面试也坐在面试官那侧看过不少候选人——简历上写着熟悉Docker与K8s问到底层原理就开始含糊。其实面试官想确认的从来不是你能不能背出“Pod是什么”而是你有没有真正理解这套体系在解决什么问题线上出故障时知不知道从哪里入手。这篇文章把我整理过、也在实战中验证过的Docker与K8s面试基础题按“考察逻辑—Docker底层—K8s核心—场景排查—备战经验”这条主线串起来每道题都给出原理分析和回答思路。适合正在准备开发、运维、SRE方向面试的同学也适合刚接触容器编排、想系统建立认知框架的读者。1. 面试考察逻辑从命令记忆到体系认知1.1 为什么Docker与K8s总被放在一起问很多候选人会单独准备Docker题和K8s题但面试官几乎总是把两者串起来问。原因在于它们本来就是一套递进关系Docker解决的是“如何把应用和它的运行环境一起打包、隔离、运行”的问题K8s解决的是“如何管理成百上千个容器让它们调度、扩容、恢复、互访都自动化”的问题。没有DockerK8s的Pod失去了最常用的容器运行时没有K8sDocker只能解决单机上的问题。所以面试时从“容器是怎么跑起来的”追问到“集群是怎么调度这些容器的”是一条非常自然的提问路径。这种提问方式也决定了准备方向只刷命令不行只背概念也不够。我见过不少候选人能把docker run的参数倒背如流但问他“为什么一个镜像能在两台机器上跑出一致的环境这个过程强依赖什么底层机制”就卡住了。面试官的潜台词其实是你不仅要会用还要能解释为什么。1.2 面试官判断候选人水平的三个层次把Docker与K8s相关的问题拉通看面试官通常用三个层次来判断候选人水平。第一层是“会操作”。能写出Dockerfile能跑通docker build和docker run能用kubectl apply部署一个Deployment能用kubectl logs看日志。这是基础门槛但光有这层远远不够因为操作是可以短时间突击的。第二层是“懂原理”。知道镜像分层是怎么回事知道Pod为什么是最小调度单位知道Service的流量转发依赖什么机制知道调度器按什么顺序选节点。到了这一层回答同一个问题时就能给出“为什么”而不是只报“是什么”。第三层是“能排障”。这层最拉分。比如遇到CrashLoopBackOff候选人能不能沿着“看状态—查日志—看事件—看资源—看配置”这条路径快速定位遇到两个服务互访不通能不能想到先分离网络问题和服务问题。面试里最常见的场景题本质上都是在考这一层。建议大家在准备时对每道题都问自己一句这道题对应哪个层次如果只在第一层就补原理如果原理清楚了就找几个故障场景练手。2. Docker高频面试题镜像、容器、网络与存储的底层原理2.1 镜像分层机制为什么基础镜像只需要拉取一次Docker最常见的面试题之一就是“解释Docker镜像的分层机制”。很多人能说出“镜像由多层组成”但说不清分层到底带来了什么。这里关键要提到两个机制联合文件系统和写时复制。Docker镜像不是一个大块文件而是由一组只读层叠加而成。每一层对应Dockerfile里的一条指令结果。比如基础镜像是一层apt install装依赖产生一层复制代码进去又产生一层。运行时Docker把所有这些只读层和一个可写的容器层联合挂载起来形成容器内部看到的完整文件系统。这套做法的直接收益是磁盘节省和构建加速多个镜像如果共享同一个基础镜像层物理上只需要存一份拉取时也只需要拉取本地没有的层。面试官通常还会追问“那容器里修改文件会发生什么”这就是写时复制机制的用武之地——修改不会动到底层只读文件而是在最上层的可写层里复制出一份再改所以容器之间互不影响。回答这道题时建议补一句实际经验因为镜像层可以复用所以Dockerfile里指令顺序会影响镜像构建缓存命中率。越不容易变化的指令越应该往前放比如先装系统依赖、再复制业务代码这样改了代码只重建最后一层构建速度会明显提升。这一句往往能让面试官觉得你是真的构建过镜像而不是只看过文档。2.2 Dockerfile的关键指令与多阶段构建面试中经常让你现场写一个Dockerfile或者问你某条指令的作用。这里有几个高频考点。COPY和ADD的区别是必问的。COPY只负责把文件复制进镜像ADD除了复制文件还支持解压压缩包、支持从URL拉取文件。但官方的实践建议是优先用COPY因为ADD的自动解压和URL拉取行为容易产生不可预期的副作用也会让镜像构建过程更难排查。面试时能说出“能用COPY就不用ADD需要解压场景再考虑ADD”说明你踩过坑。CMD和ENTRYPOINT的区别也是经典题。CMD提供容器启动时的默认命令和参数但它会被docker run后面追加的命令覆盖ENTRYPOINT定义容器的主进程入口不容易被覆盖通常配合CMD给ENTRYPOINT传默认参数。一个常见的组合用法是ENTRYPOINT写启动脚本CMD写参数默认值。多阶段构建是提高印象分的关键点。比如一个Java应用或者Go应用构建环境和运行环境对依赖的需求完全不同。多阶段构建允许你在一个临时镜像里完成编译、打包然后把产物复制到精简的运行镜像里最终镜像只保留运行时依赖。这类题目回答好了能同时体现你对镜像体积、安全性和可维护性的理解。面试中让写一个最小可用Dockerfile时可以参考这个思路# 第一阶段构建 FROM golang:1.22 AS builder WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . RUN CGO_ENABLED0 go build -o myapp # 第二阶段运行 FROM alpine:3.20 RUN adduser -D appuser USER appuser COPY --frombuilder /app/myapp /usr/local/bin/myapp EXPOSE 8080 ENTRYPOINT [myapp]这里有几个面试官想听到的细节第二阶段的USER appuser是为了避免以root运行容器COPY --frombuilder体现了多阶段构建go mod download单独放在COPY .之前是为了利用层缓存。能把这几点讲出来比单纯写一个能跑的Dockerfile得分高得多。2.3 容器网络模式bridge、host、none、container怎么选Docker网络题的难度通常介于“背模式”和“讲原理”之间。Docker默认的bridge网络会在宿主机上创建一个虚拟网桥默认网段通常是172.17.0.0/16每个容器通过虚拟网卡接入这个网桥容器之间靠网桥转发通信。当你在docker run -p 8080:80时Docker实际是通过宿主机上的端口映射规则把宿主机8080端口收到的流量转发到容器的80端口。这里能提到iptables的DNAT规则说明你真研究过。host模式直接让容器共享宿主机的网络命名空间没有端口映射这一层性能好但容器之间端口隔离要靠应用自己保证。none模式就是没有网络通常用于特殊场景比如只需要本地回环、完全不想暴露网络的容器。container模式让容器共享另一个容器的网络命名空间在K8s的Pod设计里能见到类似思想。回答这类题时我建议加一个选择维度如果你在意隔离性和多容器共存选bridge如果追求极致的网络性能且不担心端口冲突可以选host如果容器要作为网络代理角色共享入口考虑container模式。跨主机通信方向上面试官可能会顺带问“Docker原生怎么做跨主机容器通信”。早期Docker的跨主机方案依赖宿主机路由或overlay网络能力有限这也是为什么K8s要引入完整的容器网络接口规范。可以这样回答容器网络接口CNI把网络配置从运行时里抽出来由插件负责给Pod分配IP、配置网络规则常见的实现有基于overlay的、基于路由的、基于三层网络的几种思路。回答到CNI这一层面试官就知道你不是只玩过单机Docker。2.4 数据卷与存储容器删除后数据去哪了“容器里写入的文件容器删除后还在不在”是道送分题也是陷阱题。容器层是临时层容器删除后容器层里的数据也随之消失。如果要持久化必须挂载数据卷或绑定宿主机目录。Docker提供三种主要方式绑定挂载、命名卷和临时卷。绑定挂载是把宿主机某个路径直接挂到容器里适合开发和调试因为宿主机改文件容器里立刻能看到但这种方式对宿主机路径有强依赖可移植性差。命名卷由Docker管理存放位置对使用者透明适合生产环境持久化数据备份和迁移也更方便。临时卷随容器生命周期创建删除一般用来保存临时缓存或日志缓冲。实际面试时这道题经常会结合权限来问比如“为什么容器里写入挂载目录会报权限错误”。这是因为命名卷首次挂载时Docker会把镜像里对应目录的文件属主和权限复制到卷里如果宿主机和容器对UID/GID的约定不一致就可能出现“明明能读写却报Permission denied”。解决思路通常是在Dockerfile里显式指定运行用户或者用卷初始化容器修正属主关系。能说出这个坑说明你真的在服务器上部署过而不只是在本机跑过hello world。3. Kubernetes核心概念面试精讲Pod、控制器、网络与存储3.1 为什么K8s的最小调度单位是Pod而不是容器这是K8s面试的第一道分水岭题。正确思路是K8s把Pod作为调度的最小单位是因为很多应用场景下多个容器需要共享网络和存储把它们绑定成同一个调度单元才能保证它们一定被调度到同一节点上。具体来说一个Pod里的多个容器共享同一个网络命名空间也就说它们共享IP、共享端口空间可以通过localhost互相访问同时它们可以共享同一个数据卷。这种设计支撑了经典的边车模式主业务容器负责处理流量边车容器负责收集日志、做流量代理或者同步配置两个容器共享一个Pod生命周期和存储挂载。这道题还有个隐藏考点实现这种“共享网络命名空间”的底层角色是Pod里的基础容器通常叫pause容器。K8s创建Pod时会先启动一个pause容器它只负责持有网络命名空间和各种Linux命名空间然后业务容器启动时加入这个命名空间。所以面试时如果能补充一句“Pod里的网络命名空间由基础设施容器维持业务容器是加入者”会显得非常扎实。3.2 工作负载控制器选择Deployment、StatefulSet、DaemonSet、Job面试官喜欢给场景让候选人选控制器这比直接问“Deployment是什么”更有区分度。Deployment是最常用的无状态负载控制器适合处理“副本无差别、顺序无所谓、随便替换”的服务比如Web后端、API服务。它支持声明式更新、滚动升级、回滚和副本扩缩。StatefulSet适合有稳定网络标识、稳定存储和有序部署的应用典型例子是数据库、消息队列这类有状态服务每个副本有独立的网络身份和独立的持久化存储声明。DaemonSet确保每个节点上恰好运行一个Pod典型的用途是日志收集、监控采集这类需要覆盖所有节点的代理型组件。Job和CronJob则对应一次性任务和定时任务。面试中还经常追问“Deployment是如何做到滚动更新不中断业务的”。核心机制是ReplicaSetDeployment创建一个新的ReplicaSet把Pod副本从旧ReplicaSet逐步迁移到新ReplicaSet同时配合就绪探针判断新Pod是否真正可以接收流量。更新过程中如果发现问题kubectl rollout undo可以快速回滚到上一个版本。这里如果能提到“就绪探针通过才继续滚动否则滚动暂停”就说到点子上了。探针这块也是高频考点。存活探针决定容器需不需要重启就绪探针决定Pod能否被纳入Service的负载均衡启动探针用于慢启动应用。有一道经典的陷阱题“一个应用启动需要一分钟就绪探针设置的初始延迟是10秒会发生什么”答案是容器会被反复重启因为存活探针可能也判定失败。对这种慢启动应用正确做法是配置启动探针让它先等应用启动完成再启用存活探针。3.3 Service与流量入口服务发现到底怎么实现的K8s里Pod的IP是动态的直接用它做服务发现不现实Service抽象就是为解决这个问题。Service提供一组稳定的虚拟IP和DNS名称把流量负载均衡到背后一组由标签选择器选中的Pod上。Service的四种类型是必背内容ClusterIP只在集群内部可达是最常用的默认类型NodePort会在每个节点上开放一个固定端口把端口流量转发到ServiceLoadBalancer通常在云环境里自动创建负载均衡器把外部流量导入集群ExternalName则是返回一个外部DNS别名本质上不转发流量。回答时最好加一句使用场景的区分集群内部互访用ClusterIP简单外部接入可以用NodePort生产环境有云负载均衡就用LoadBalancer再往上一层做域名和路由转发就用Ingress。面试官大概率会追问流量转发细节Service的负载均衡是怎么实现的。这里要提到kube-proxy。早期版本默认使用iptables模式通过为每个Service建立一组iptables规则实现随机转发性能要求高时可以用IPVS模式它在内核态用更高效的哈希表做负载均衡。只要提到这个演进面试官就能确认你看过相关材料而不是只背了四类Service的名字。Ingress也值得详细说。Ingress不是一种Service类型它是一组路由规则真正干活的是Ingress控制器。控制器的角色是把规则转换成实际的反向代理配置比如基于域名或URL路径把请求转发给不同Service。回答时最加分的点是Ingress负责的是“HTTP层路由”Service负责的是“四层负载均衡”两者配合使用。3.4 ConfigMap与Secret配置和敏感信息怎么管K8s把配置从镜像中剥离出来思路和镜像分层的“关注点分离”一脉相承。ConfigMap用来保存非敏感配置比如配置文件内容、环境变量值、命令行参数。Secret用于保存敏感信息比如密码、Token、证书。两者的常见使用方式有两种作为环境变量注入Pod或者挂载成文件。面试时要注意几个细节。第一ConfigMap和Secret的名字必须是合法的DNS子域名因为它们是命名空间级资源。第二如果以环境变量方式注入Pod创建后修改ConfigMap不会自动更新环境变量因为环境变量只在容器启动时读取一次但如果以文件方式挂载默认情况下ConfigMap内容更新后挂载文件会同步更新应用是否感知要看应用自己的重载逻辑。第三Secret虽然在API里的存储形态做过加密相关的增强但更安全的实践是结合外部密钥管理系统避免把明文密钥写进YAML文件。有个常见的配置管理陷阱也值得提把整个配置文件做成一个ConfigMapvolumeMounts挂载目录时会覆盖掉镜像里该目录的全部内容包括其他不在ConfigMap里的文件。如果只想覆盖单个文件需要用subPath指定挂载子路径。这个坑我见过不止一次面试时主动讲出来效果非常好。3.5 PV与PVC存储是怎么和Pod解耦的有状态应用的存储是K8s面试里容易深度聊的模块。PV是集群层面的存储资源抽象PVC是应用对存储的请求声明。应用不直接关心底层存储在哪里、是什么类型只需要在PVC里声明“我要多少容量、什么访问模式”系统负责把PVC和满足条件的PV绑定。StorageClass则实现动态供给PV不用预先手动创建PVC提交后由StorageClass对应的存储插件按需创建PV。生命周期这块有个常见的状态链路问题PV会经历Available、Bound、Released等阶段。面试时容易被问到“删除PVC后PV去哪了”。答案取决于回收策略Retain表示PV保留管理员需要手动清理才能复用Delete表示自动删除底层存储资源Recycle已经不再推荐。还有一个经典追问“为什么Pod删了PVC还在”因为PVC是独立资源Pod只是使用它的消费者删除Pod不影响PVC。反过来如果删掉PVC正在使用它的Pod会受影响。访问模式也建议提前整理ReadWriteOnce表示单节点读写ReadOnlyMany表示多节点只读ReadWriteMany表示多节点读写。实际选型时块存储通常只支持单节点读写共享文件存储支持多节点读写。面试时用“数据库单点写一般用ReadWriteOnce日志汇聚多个Pod需要同时写一般用ReadWriteMany”来举例比干背模式清楚得多。3.6 调度器、资源限制与自动伸缩调度相关的问题越来越常考因为大部分生产故障都跟资源有关。基础问题是“调度器选节点的过程”。简化的流程是调度器先过滤掉不满足条件的节点比如资源不够、标签不匹配、端口冲突的节点会被过滤掉然后在剩余节点里根据打分策略排序选最优节点。Pod里的nodeSelector、节点亲和性、污点和容忍都是会影响过滤和打分的关键机制。污点的作用方向值得重点理解污点是打在节点上的容忍是声明在Pod上的Pod能容忍这个污点才可以被调度到该节点。这类规则的记忆方式可以用一个类比节点设置了“禁止入内”的标记Pod需要出示对应“通行证”才能进来。资源限制requests和limits是必问的。requests是调度依据和保障值limits是上限约束。调度器看的是requests而不是limits因为只有requests才是K8s承诺给Pod的资源量。如果节点上所有Pod的requests总和超过节点容量就会出现调度不上的情况。CPU是可压缩资源达到limits会被限流内存是不可压缩资源超过limits会触发OOM甚至可能把Pod杀掉。自动伸缩这块HPA是高频题。HPA根据工作负载控制器的Pod副本数进行扩缩最常用的指标是CPU使用率也支持自定义指标。回答时有一个常见误区要避开HPA不直接作用于Pod而是调整Deployment这类控制器的副本数由控制器完成Pod的创建和删除。配合这一点的最佳实践是单副本的Deployment配置HPA没有任何意义因为伸缩的最小单位是副本不是Pod里的容器资源。4. 面试中最常见的场景题与排查思路4.1 镜像一直拉不下来怎么办场景题里必有一道“部署时镜像拉取失败你怎么排查”。面试官想听的不是一句“网络问题”而是你完整的排查顺序。第一步确认事件本身。用kubectl describe pod查看Pod事件区分是拉取超时、认证失败、镜像不存在还是仓库拒绝了请求。第二步确认镜像地址是否正确特别是tag是否存在很多人把latest之外的tag写错过。第三步确认认证信息私有仓库需要提前创建镜像拉取凭据并且要在正确的命名空间下创建和使用。第四步确认节点上的容器运行时能否正常访问仓库可以在节点手动拉一次镜像排除运行时配置问题。最后再考虑网络连通、DNS解析这类基础设施因素。面试时能把“先看事件、再验地址、再查认证、再查运行时、最后查网络”的路径完整说出来就已经具备合格排查者的样子。反过来一上来就断言是网络问题面试官基本不会给过。4.2 Pod一直处于Pending状态怎么定位Pending状态表示Pod没有被成功调度到节点上。面试官考这道题是想确认你是否理解调度器的判定逻辑。最直接的排查命令是kubectl describe pod调度失败的原因会写在事件里常见的有几种。资源不足是最常见的原因节点上没有足够的CPU或内存满足Pod的requests事件里会显示有节点因为Insufficient cpu或Insufficient memory被过滤。另一个常见原因是节点选择器或亲和性不匹配Pod要求的标签在集群里没有任何节点满足。还有一种是污点和容忍问题所有可用节点都有污点而Pod没有对应的容忍自然调度不动。再往下查可能是PVC没有绑定成功调度器发现Pod依赖的存储不存在也不会继续调度。到这里还能延伸一个让人印象深刻的点如果Pod一直Pending且事件里什么提示都没有可以检查是否有非预期的调度约束比如集群里是否打了维护类污点导致节点都不可调度。这需要实际运维过才讲得出来。4.3 CrashLoopBackOff反复重启怎么处理CrashLoopBackOff是面试和实战中出现频率最高的故障之一意思是容器反复启动、崩溃、重启而且重启间隔在逐步拉长。这类题最能区分候选人的排查思路。标准路径是第一步看kubectl logs看容器崩溃前打印的最后日志大多数情况下原因会直接暴露比如程序因为配置错误直接退出、端口被占用、连不上数据库。第二步看kubectl describe pod重点关注容器最后一次退出的原因码和退出信号如果是被OOM杀死事件里会明确写出来。第三步检查探针配置有可能应用本身没挂但存活探针配置过严导致K8s主动杀掉了容器。第四步检查资源限制如果内存limits设置过小进程刚启动就被OOM Kill也会出现反复重启。这道题有一个很隐蔽的场景值得主动说出来如果容器日志里什么都没有程序就异常退出了说明进程可能是在启动早期崩溃这时候要考虑用临时调试容器或者修改启动命令把进程停在崩溃前再进去查看环境。这个技巧来自真实的排障经验面试官听到通常会眼前一亮。4.4 集群内两个服务访问不通怎么排查这道题考的是网络分层思维。我一般按四层来回答先确认目标服务是否存在再确认Service和后端Pod的关系再查网络转发最后查应用层。第一步确认目标Service存在且处于正常状态kubectl get svc和kubectl get endpoints是核心命令。Endpoints尤其关键如果Service的标签选择器没匹配到任何PodEndpoints列表就是空的流量发出去没有后端接收这经常是源码里标签写错导致的。第二步确认Pod是否Ready如果就绪探针挂了Pod不会进入Service的后端列表。第三步再考虑网络层比如从源Pod里直接访问目标Service的ClusterIP和端口看通不通如果不通可能涉及网络策略或者节点层面的防火墙规则。第四步确认目标应用本身是否正常监听端口用kubectl exec进入源Pod用命令行工具直接请求目标Pod IP区分Service层问题还是应用层问题。这道题回答得好能同时体现你对K8s对象模型和网络栈的理解属于场景题里的高分题。4.5 节点NotReady怎么处理节点故障题通常在更资深的面试环节出现。节点NotReady意味着kubelet的心跳上报中断或者集群控制面无法从节点获取健康信息。排查顺序一般是先看节点对象的事件确认最近有没有内存压力、磁盘压力或PID压力再到节点上看kubelet服务状态和日志再检查节点负载和系统资源比如磁盘写满就会让kubelet无法正常工作。这里有一个值得强调的经验很多节点NotReady的根因不是容器组件坏了而是宿主机层面的问题比如磁盘空间不足、Docker/containerd运行时僵死、系统负载过高。面试时如果把排查视角主动从“集群内部”扩展到“宿主机层面”说明你真的处理过生产环境节点故障。5. 备战建议与真实排障心得5.1 面试表达常见的三类扣分项我坐在面试官那侧时发现候选人回答容器题主要有三个通病。第一类是只背术语不给验证。比如一说Service就说“提供稳定的访问入口”但问到kube-proxy具体怎么转发、NodePort范围默认是多少就答不上来。术语是思考的起点不是思考的终点建议每个关键词都能配上一句“它解决什么问题、由什么组件实现、常见配置是什么”。第二类是只讲命令不讲场景。kubectl get pods谁都会用但面试官更希望你说出“什么情况下你会用kubectl describe而不是kubectl get”。比如排查故障时要看事件和详情get只能看状态describe才能看到最近事件。这种对命令适用场景的理解比命令本身更值钱。第三类是Answer里缺“然后呢”。比如提到探针不说探针失败会触发什么动作提到HPA不说它调整的是副本数提到PVC不说删除后底层存储的行为。每一层概念都要能往下再追问一级追不动的地方就是你复习时要补充的地方。5.2 我建议的复习路径与动手实践如果时间只有一个星期我建议按这个顺序来而不是拿着面试题列表从头刷到尾。前三天在本地跑一套最小环境手动用Dockerfile构建镜像修改它看层缓存变化再分别用bridge和host模式跑容器体会网络差异。中间两天搭一个单节点的K8s集群依次部署Deployment、Service、Ingress故意写错标签选择器观察Endpoints为空的现象。最后两天集中做故障演练把探针初始延迟改小制造CrashLoopBackOff把内存limits调低触发OOM给节点加污点观察Pod调度状态。这套路径的关键不是“做过”而是“做过之后能讲出因果链”。比如你亲手把镜像从2G优化到200M面试时聊多阶段构建就能非常自然地讲出“构建层和运行层分离”的收益你亲手见过OOM Kill事件聊limits时就不再是背概念。面试官不傻你有没有亲手折腾过从你例子里讲到的细节就能听出来。5.3 最后分享一个面试中的小技巧回答任何一道Docker或K8s题我都建议用“是什么—为什么—怎么做—踩过什么坑”这个四段式结构。面试官问“什么是Pod”不要停在定义上接着说为什么设计成多容器共享资源再讲实际部署时我在Pod里加边车容器做了什么最后补一句“如果两个容器必须一起调度把它们放进同一个Pod”。这套结构天然帮你避开空泛回答也让面试官有往下追问的抓手。我个人在实际参与面试的经验里发现最能拉分的往往不是某道难题的完美答案而是你展示出的“可被追问的深度”。容器和K8s的面试基础题看起来很多但它们的底层逻辑高度收敛镜像解决一致性编排解决自动化网络解决连通存储解决持久。把这四条主线吃透再配合真实的动手记录面试时你会发现自己不需要死记硬背也能把每个问题回答得有条理、有细节。