很多准备面试的朋友一看到 Docker 和 Kubernetes 的题就头大,原因不外乎两点:一是知识点太散,镜像、容器、网络、存储、编排、调度、服务发现,每个方向都能单独拎出来出一套卷子;二是光背概念没用,面试官现在都会顺着一个点往下挖,比如先问“Pod 里几个容器”,再问“sidecar 怎么通信”,接着问“Pod 重建后 IP 变了怎么办”,一套组合拳下来,死记硬背的答案根本顶不住。
这份 Docker 和 K8s 面试题总结,走的是“原理 + 场景 + 排查”的路子。直接背题解决不了问题,但把每个高频问题背后的原理和现场回答的思路搞清楚,面试时就能顺着自己的知识体系往深处聊。内容分成 Docker 基础、K8s 核心、网络存储、调度器、场景排查几个大块,每道题都标注了面试官想考察的能力方向,方便针对性复习。
说明:因为内容量比较大,这一篇先把 Docker 部分的大部分高频题和 K8s 的入门核心题写完,网络、调度器、存储以及更底层的 etcd 机制部分留在下一章。所有题目都是我在真实面试中遇到过的,或者是同行交流中公认的高频题,不是按文档目录硬凑的。
1. 先说清楚这套面试题怎么用
刷面试题最忌讳的就是“背答案”。容器这块技术栈有个特点,面试官几乎不问纯记忆性的问题,比如“Docker 有哪几种网络模式”,而是给你一个场景:“我用默认配置跑了一个 MySQL 容器,结果外部连不上,怎么排查?”你要在脑子里把网络模式、端口映射、防火墙、容器内监听地址这几个环节串起来,才能把这个问题答完整。
这套题的用法,我建议分三步:
- 先自己答一遍。拿到一道题,不要马上去看解析,先用两分钟时间口头回答。卡住的地方,就是你知识体系里的缺口。
- 对照解析找“为什么”。解析里不只有一个结论,还有这个结论产生的原因。比如“容器内进程 PID 和宿主机 PID 不同,是因为 PID namespace 隔离”,理解了 namespace 这一层,很多题都能顺势展开。
- 追问自己一层。每个重点题后面我都留了“延伸考点”,这些是面试官最常往深处挖的方向,提前准备好,现场就不会脑子空白。
提示:面试时如果遇到没准备过的题,千万不要慌。多数面试官想知道的是你的排查思路,而不是标准答案。把“我平时遇到这种问题会先看什么日志、再算什么数据”讲清楚,比硬憋一个不确定的结论有效得多。
2. Docker 高频题:从底层原理到日常运维
2.1 镜像、容器、仓库的区别,为什么面试官要先问这个
这道题看起来简单,但答得好的人真不多。大部分人会背“镜像是模板,容器是实例,仓库是存放镜像的地方”,但这个回答只触及了表面。
我一般会从联合文件系统这个点切入,接着说镜像层的内容,然后说容器启动时在上面加了一层可写层,这个结构直接决定了镜像构建和容器运行的很多行为:
- 镜像是一堆只读层堆起来的。每一层对应 Dockerfile 里的一条指令,层与层之间共享,所以多个镜像可以共用一个基础层,这也就是为什么本地磁盘上镜像占了几个 GB,但实际不少层都是去重的。
- 容器启动的时候,会在镜像层之上再加一个可写层。你对容器里文件的修改,都发生在这个可写层。一旦容器删除,这个可写层也就没了,所以容器里的数据默认不持久化。
- 仓库是镜像分发的中转站。Docker Hub 是公开仓库,企业内部一般用私有仓库,比如 Harbor 或者 Registry,负责镜像的推送、拉取和权限管理。
这个回答等于把镜像层、容器可写层、仓库分发三个知识点都带出来了,面试官顺着就能问“怎么减少镜像体积”“容器数据怎么持久化”“私有仓库怎么搭”,回答的空间很大。
2.2 Docker 的网络模式:bridge、host、none、container 的选型逻辑
Docker 网络这块,我面试的时候十次有八次会被问到。先背清楚默认的 bridge 模式:创建容器的时候,如果不指定网络,就会接到名为docker0的 Linux 网桥上,拿到一个172.17.x.x的 IP,这个 IP 是容器自己的,宿主机访问不到,外部更访问不到。要让宿主机或者外部访问容器里的服务,必须在启动时用-p做端口映射。
这个-p映射的底层逻辑是 iptables 的 DNAT 规则。Docker 是在宿主机上通过端口代理的方式,把宿主机某个端口收到的流量转发到容器 IP 的对应端口。理解这个机制后,常见的排障思路就清楚了:如果-p 3306:3306没用,先检查宿主机防火墙是否放行 3306,再检查容器内 MySQL 是否监听在 127.0.0.1 而不是0.0.0.0,然后检查容器 IP 是否变化导致 DNAT 规则指向了失效地址。
host 模式和 bridge 模式最大的区别是:容器不拥有独立的网络 namespace,直接复用宿主机的网络栈。这种模式下容器没有自己的 IP,端口直接占用宿主机的端口。优点是网络效率高,没有 NAT 转发;缺点是隔离性差,端口冲突要靠人管,适合对网络性能要求高的场景,比如一些压测工具。
container 模式用得更少一些,大意是让新容器和某个已存在的容器共享同一个网络 namespace。这个模式的价值在于,两个容器可以通过 localhost 直接通信,不需要走网络转发。比如监控容器和业务容器放在同一个网络命名空间里,监控进程直接连127.0.0.1:xxxx就能抓到业务进程的监控数据。
实际做题的时候,无非是掌握两个要点:
- bridge 是默认隔离方案,生产环境里最常见的用法是创建一个自定义 bridge 网络,让多个容器通过容器名互相访问。
- 端口映射依赖 iptables/ipvs 规则,排查外部访问不通时,路径是“防火墙规则 -> 端口监听 -> 路由规则”。
2.3 Docker 存储:Volume、Bind Mount、tmpfs 怎么选
面试里问到容器数据持久化,我见过不少回答都是“用 volume 挂载,数据放宿主机”,然后就没了。其实这里藏着一个关键考点:
Docker 容器删除后,容器内产生的所有数据都会消失,因为可写层跟着容器一起没了。所以需要把需要持久化的目录挂载出来,挂载方式主要有三种:
Volume(数据卷)由 Docker 管理,存放路径在
/var/lib/docker/volumes/下。这种方式的好处是数据不受容器生命周期影响,多个容器可以共享同一个 volume。生产环境里做数据库容器、文件服务容器,一般用这种方式。Bind Mount(绑定挂载)直接把宿主机的某个目录或者文件挂载到容器里。比如把宿主机
/data/mysql挂到容器/var/lib/mysql。缺点是路径写死,迁移性差,但优点是方便查看和备份,而且宿主机上可以直接改文件。开发环境调试配置用 bind mount 非常顺手,-v /home/user/app:/app就可以做到宿主机改代码、容器里直接生效。tmpfs(内存文件系统)数据只存在内存里,容器停止时数据清空。适合存放临时文件、缓存类数据,不会落盘,性能高。
这里还有一个容易踩的坑,就是权限问题。用 bind mount 挂载宿主机目录的时候,如果宿主机的目录权限是root,而容器内部进程是以uid=1000的身份运行的,启动容器后就会遇到 "Permission denied"。解决办法是在启动时用--user指定 uid,或者把宿主机目录的属主改成对应 uid。
2.4 容器资源限制:为什么限制 CPU 和内存要一起做
面试官问“怎么限制容器的资源使用”,你可以直接甩出--cpus--memory这些参数,但如果只说到参数层面,就还差得远。这里是常考的一个底层机制:
docker run --memory=2g --cpus=2限制的是容器最多能用 2GB 内存和 2 个 CPU。但不限制的话,一个失控的容器很可能把宿主机整个拖垮。比如容器的内存申请超出限制,触发 OOM,Docker 会直接把容器杀掉,这个行为由内核 OOM Killer 完成,很多时候看着像进程突然没了,真凶其实是 OOM。
CPU 限制相对温和一些,限制的是 CPU 时间片,容器只能在分配的额度里轮转,不会杀掉进程。所以触发器不同:内存超限直接杀,CPU 超限只是慢。
另外,很多新手不知道还有一个隐含层:Docker 的容器资源限制是基于 Cgroups 实现的。--cpu-shares是相对权重,--cpus是绝对限制(换算成 CPU 调度周期中的配额)。面试时把这层原理点出来,基本就能把候选人分层了:
- 基础回答:
docker run --memory 2g --cpus 2 - 进阶回答:说明 Cgroups 在 Linux 内核里通过 CFS 调度器分配 CPU 配额,通过 memory cgroup 记录并限制内存使用量,超出后触发 OOM Killer。
2.5 Dockerfile 优化与镜像安全:面试里最常被追问的细节
Dockerfile 相关的题看起来像送分题,实际上最容易暴露实践经验。这里有几个高频考点:
考点一:RUN、CMD、ENTRYPOINT的区别
RUN是构建镜像时执行的命令,每执行一次就会生成一个新的镜像层。CMD是容器启动时的默认命令,可以被docker run后面的命令覆盖。ENTRYPOINT也是启动命令,但一般作为容器的主进程固定下来,优先用ENTRYPOINT执行主程序,把变参交给CMD。
比如镜像里写:
ENTRYPOINT ["nginx", "-g"] CMD ["daemon off;"]运行时如果执行docker run 镜像名 -v,实际执行的是nginx -g -v,而CMD里的默认参数会被覆盖。这个组合方式理解透了,才能在设计镜像启动逻辑时不迷路。
考点二:怎么减小镜像体积
- 使用更小的基础镜像,比如
alpine,它基于 musl libc,体积只有几 MB。 - 合并 RUN 命令,减少镜像层数。比如用
&&连接多个命令,减少中间层。 - 删除构建过程中的临时文件,比如 apt 缓存、
.pyc文件。
还有一个细节:构建镜像时使用多阶段构建(multi-stage build)。比如编译 Go 程序的时候,第一阶段用golang镜像编译出二进制,第二阶段用alpine镜像把二进制 copy 进去,最终镜像里只保留了运行环境,编译器源码全都不在,这样镜像体积能缩小十倍不止。
考点三:镜像安全
镜像里最好以非 root 用户运行进程。Dockerfile 里用USER指令指定,基础镜像里没有这个用户就先useradd创建一个。以 root 身份运行容器,相当于把宿主机的 root 权限暴露给了容器进程,一旦容器被入侵,攻击者可以直接操作宿主机。这个安全观点现在几乎是必问点,回答时最好顺手说一句:K8s 里对应的安全上下文配置是securityContext.runAsNonRoot: true,这样面试官就会知道你 Docker 和 K8s 是一套知识体系。
2.6 Docker Compose 与 Docker 命令实战:常规但高频
Compose 相关的题不会单独出很多,但往往作为“你平时怎么管理容器”这个问题的延展。面试时我会遇到这种问题:“你们的环境里有十几个服务,怎么管理的?”这时候如果只回答“一个个 docker run”就露怯了。
Compose 的核心价值是把一个服务的完整配置声明在一个 YAML 文件里,然后一条docker-compose up -d全部启动。里面需要掌握的关键配置项:
services:服务的定义,一个服务对应一个镜像加上它的配置。environment:环境变量,用来传配置。depends_on:服务依赖顺序,比如先启动数据库再启动应用。networks:定义服务间的通信网络。volumes:持久化数据。
被问到“Compose 和 K8s 有什么区别”时,核心答案是:Compose 解决的是单机多容器编排的问题,K8s 解决的是跨多台服务器的容器编排和调度的问题。两者不在同一个维度。
3. K8s 核心概念:Pod、控制器与服务发现
3.1 为什么 Pod 是最小调度单元而不是容器
这道题几乎是 K8s 面试的必答题,而且对理解整个 K8s 设计哲学极其关键。先背结论:Pod 是 K8s 调度和资源分配的最小单元,但 Pod 里可以包含一个或多个容器。
面试官想探的点是 Pod 这个概念为什么存在。我一般会从业务通信和资源管理的角度拆:
- 共享网络命名空间。Pod 里的容器共享同一个网络命名空间,也就是说它们共享 IP 和端口空间,可以通过 localhost 互相访问。这解决了同组容器的本地通信问题。比如日志采集容器和业务容器放在一个 Pod 里,日志采集可以直接读业务容器写在共享卷里的日志文件,不需要走网络。
- 共享存储卷。Pod 可以挂载多个 volume,Pod 里的容器都能访问这些 volume,适合做文件交换和共享配置的场景。
- 生命周期绑定。Pod 是整体调度的,里面的容器要么一起调度到同一台 Node 上,要么一起被重新调度。这保证了依赖关系紧密的容器不会被拆到两台机器上。
从这些设计点出发,很容易延展到sidecar 模式。业务容器负责主要功能,辅助容器负责日志收集、流量治理、配置同步这些“边车”功能,两者在同一个 Pod 里共生。面试官如果追问“sidecar 和跨 Pod 通信有什么区别”,你就应该想到这就是“共享网络和存储 vs 通过网络访问”的区别。
3.2 控制器怎么选:Deployment、StatefulSet、DaemonSet、Job
面试中经常会有这种开放式场景题:“现在要部署一个 MySQL 主从复制,用 Deployment 行不行?”,如果回答“行”,面试官就知道你还没理解控制器的适用场景。这里我整理一个高频对照表,直接背下来就能应付大多数题目:
| 控制器 | 适用场景 | 选它而不是 Deployment 的原因 |
|---|---|---|
| Deployment | 无状态服务(Web 应用、API 服务) | 支持滚动更新、回滚、声明式伸缩,每个 Pod 都是可互换的 |
| StatefulSet | 有状态服务(数据库、消息队列、Redis 集群) | 为每个 Pod 提供稳定的网络标识和稳定的存储,Pod 编号有序 |
| DaemonSet | 集群级组件(日志采集、监控 Agent、网络插件) | 保证每个 Node 上恰好运行一个副本 |
| Job / CronJob | 一次性任务、定时任务(批处理、数据清理) | 执行完成后 Pod 自然结束,不会像 Deployment 那样保持运行 |
理解了这张表,还要能讲清楚 StatefulSet 的三个核心能力,才算是真正拿下这道题:
- 稳定的网络 ID。StatefulSet 里的 Pod 名字和 hostname 是有序且固定的,比如
mysql-0、mysql-1、mysql-2,配合 headless service,可以直接通过 Pod 名解析到稳定的 DNS 地址,这个能力对有状态的分布式系统(比如 master 节点相互发现)很关键。 - 稳定的存储绑定。每个 Pod 会绑定一个专属的 PVC,Pod 重建后,存储卷还能恢复挂载到新 Pod 上,数据不丢。
- 有序部署和收缩。StatefulSet 可以配置按顺序创建和删除 Pod,从
mysql-0开始,先启动 master,再启动 slave,这个顺序在很多分布式系统里有硬性要求。
3.3 Service:为什么 Pod 一旦重建 IP 就变,流量却不丢
这个问题对用过一段时间 K8s 的人来说肯定有体感。Pod 是“临时”的,滚动更新、故障重启、扩缩容的时候,Pod 会被杀掉重建,IP 完全变样。那么客户端怎么访问?
答案是Service。Service 在逻辑上是一个稳定的访问入口,它有一个固定 IP(ClusterIP)和一个固定 DNS 名。Service 后面用 selector 关联一组 Pod,Pod 的 IP 变化时,Service 会自动感知并更新 Endpoint 列表。
所以访问流程是:
- 客户端访问
Service 的 ClusterIP:端口。 - K8s 通过 kube-proxy 或者 ipvs 规则,把请求转发到后端的某个 Pod IP。
- Pod 挂了重建后,controller(比如 Deployment)会自动创建新 Pod,新 Pod 注册到 Endpoint 里,Service 的转发目标也随之更新。
这道题里容易漏掉的知识点是 Service 的几种类型:
- ClusterIP:只能在集群内部访问,默认类型。
- NodePort:在 ClusterIP 基础上,在每一台 Node 上开放一个特定端口,外部通过
任意NodeIP:NodePort访问。 - LoadBalancer:由云平台负载均衡器承载,把外部流量引入集群,一般是 NodePort 的上层封装,云厂商实现了对应的 controller 之后才会生效。
3.4 Ingress:外部流量进入集群的最佳入口
面试时问“Service 已经能把流量转发给 Pod 了,为什么还需要 Ingress”,大多数候选人答不到点子上。
一个集群里如果有五六个服务,每个服务都用 NodePort 暴露,那么外部访问就要记住一堆端口号,而且端口容易冲突,管理混乱。Ingress 的作用是在七层(HTTP/HTTPS)做路由分发,让外部请求按域名或者 URL 路径,转发到对应的 Service。
常见的 Ingress 规则长这样:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: app-ingress spec: rules: - host: api.example.com http: paths: - path: /v1 pathType: Prefix backend: service: name: api-service port: number: 80 - path: /web pathType: Prefix backend: service: name: web-service port: number: 80面试官一定会追问的是 Ingress 真正干活的是谁。答案是Ingress Controller。Ingress 只是一个资源对象,它本身不转发任何流量,真正在集群里跑着一个负载均衡器(比如 Nginx Ingress Controller 或者 Traefik),Ingress Controller 监听 Ingress 资源的变化,然后动态生成 Nginx 配置并重载。链路总结为:
外部请求 -> Ingress Controller(七层负载均衡) -> Service -> Pod
这道题答全,就同时展示了你在服务发现和流量治理两个方向的知识储备。
4. K8s 控制器与控制循环:理解声明式运维的本质
4.1 提一个“无用”的问题:Deployment 是怎么做到规模不变的
这个问题在面试里表面上看很简单,实际上背后是 K8s 最核心的声明式 API 和控制器模式。很多新人知道 Deployment 只管写replicas: 3,但完全不知道这个期望状态是谁在维护。
我在面试时最喜欢用这个问题来区分候选人到底是用过 K8s,还是只看了文档:
假设你设置replicas: 3,然后有人手动执行kubectl delete pod删掉了其中一个 Pod。过几秒钟,你会发现一个新的 Pod 被创建了出来。谁干的?
这不是 Deployment 干的,而是运行在控制平面里的Deployment Controller干的。Deployment Controller 内部有一个循环,大致流程是:
- 从 etcd 里读取当前状态(现在有几个 Pod 存活)。
- 从用户期望的声明里读取期望状态(应该有 3 个 Pod)。
- 对比差异,发现当前状态少于期望状态。
- 通过 API Server 创建缺少的 Pod,让集群状态向期望状态靠近。
这个循环被称为控制循环(control loop),也是 K8s 整个系统工作的核心哲学。每当实际状态和期望状态不一致,控制器就会介入修正。面试时如果能把这个闭环讲出来,再举例说明“打补丁式的运维与声明式运维的区别”,这道题基本就能拿到满分。
这个设计直接决定了 Kubernetes 的一个重要特性:系统是自愈的。任何一个组件的删除、崩溃、异常,都会被对应的控制器修复到期望的状态,这也是 K8s 相比手工运维脚本的巨大优势。
4.2 探针到底在检查什么,说清楚就懂运维了
K8s 的存活探针(liveness probe)和就绪探针(readiness probe)是运维场景里最高频的题,但很多人背了参数没搞懂使用场景的区别。我这样区分理解:
- 存活探针(livenessProbe):回答“这个容器是不是还活着”。如果探针失败,K8s 会杀掉并重启容器。典型用途是检测死锁。比如一个 Java 进程还在跑,但因为内存泄漏导致假死,存活探针的 HTTP 请求超时失败,K8s 就会把它杀掉重新拉起。
- 就绪探针(readinessProbe):回答“这个容器能不能接收流量”。如果探针失败,K8s 会把该 Pod 从 Service 的 Endpoint 列表里剔除,但不会杀掉容器。典型用途是服务启动慢的场景。比如应用启动时要加载缓存需要 30 秒,这段时间如果就绪探针没有通过,Service 就不会把流量转发过来,避免了用户请求打到还在加载的实例上。
再往深了走,还有启动探针(startupProbe),用于容器启动特别慢的场景,让 K8s 知道“这个容器正在启动,先别用存活性探针给我杀掉”。三个探针的使用场景捋清楚,基本上服务可用性相关的场景题都能答出个一二三来。
对应到定位思路,面试官如果问“线上有个 Pod 一直重启”,第一步一定是kubectl describe pod看探针配置,再查容器日志确认是存活探针失败了,还是进程本身就崩了。这里要记得区分:存活探针失败导致的频繁重启,和无探针时进程退出导致的 CrashLoopBackOff,排查路径完全不同。
5. 高频场景排查题:从命令到思路
面试到后期,基本都是场景题。面试官会给你一个模糊的现象,看你用工具和数据还原出问题根因。这里挑三个我遇到的最高频场景展开。
5.1 Pod 一直 Pending,一看就是集群资源不够了
很多人会直接说“集群没资源了,加节点就行”。但这个答案只蒙对了一半。
Pod 卡在 Pending 状态,意思是调度器(kube-scheduler)到目前为止,集群里没有找到合适的 Node 可以运行这个 Pod。造成这个结果的原因很多,常见的有:
- 节点资源不足:Pod 请求的 CPU/内存比集群里所有可用节点的剩余空间都大。
- 节点不满足亲和性规则:比如 Pod 写了
nodeSelector要求节点带某个 label,但集群里没有任何节点带这个 label。 - 缺乏 PVC 对应的存储:比如 Pod 引用了 PVC,但这个 PVC 一直 Pending(底层没有合适的 StorageClass),Pod 也就无法调度。
- 有污点没有容忍:节点上打了
taint,Pod 没有对应的toleration,调度器默认不会把 Pod 调度上去。
排查指令非常固定:
kubectl describe pod <pod-name>看 Events 部分,调度器会把拒绝原因写在里面,比如0/3 nodes are available: 1 Insufficient memory, 2 node(s) didn't match node selector。照着这个提示顺着看就行。
5.2 CrashLoopBackOff:容器反复重启的根本原因怎么找
CrashLoopBackOff 是 K8s 里最常见的故障现象之一。看到这个状态,表示容器启动后很快就退出,K8s 正在以指数退避的方式不断重启它。
出现 CrashLoopBackOff,原因多到数不清,但最常见的几类是:
- 启动命令错误:比如启动命令里路径写错,进程秒退。
- 配置文件错误:环境变量没传对,应用启动时读取配置报错。
- 缺少依赖:比如应用依赖数据库,但数据库还没有就绪,应用启动后连接失败直接退出。
- 存活探针失败:探针第一次探测就没通过,容器被 K8s 杀掉。
- 资源限制导致 OOM:容器内存限制设置太小,JVM 或者应用进程还没初始化完就被杀。
排查崩溃问题,一把钥匙就够了:
kubectl logs <pod-name> --previous--previous是查看上一次容器实例的日志,因为当前实例已经退出了,常规kubectl logs经常拉不到有效日志。然后再配合kubectl describe pod查看 Exit Code 和 OOMKilled 标志,基本能锁定 80% 的原因。
5.3 滚动更新卡住怎么定位
面试题里还有一道经典场景:发布新版本后,新老版本各占一半,半天都滚动不完。这道题的核心是滚动更新的机制。
Deployment 滚动更新不是一次性把旧 Pod 全删掉换成新 Pod,而是逐步替换。默认的maxSurge是 25%,maxUnavailable是 25%,意思是更新过程中,可以多出 25% 的 Pod,同时最多有 25% 的 Pod 不可用。如果新 Pod 一直处于不可用状态,滚动更新就会卡住。
卡住的原因主要有两个:
- 新 Pod 就绪探针一直不通过,导致新 Pod 无法进入可用状态,旧 Pod 就不会被继续删除。
- 资源不足,新 Pod 创建后卡 Pending,集群没有足够的资源容纳多余的
maxSurgePod。
排查手段是:
kubectl rollout status deployment/<name> kubectl describe deployment/<name>如果describe里显示新 ReplicaSet 一直等待 Pod 就绪,那就去看新 ReplicaSet 下 Pod 的状态和事件,继续绕回到上一节的排查思路。有一定经验的面试官,会在这个问题后面追加一句“那你觉得什么情况下滚动更新回滚最合适”,这时候可以引到发布暂停rollout pause、分批放量、以及金丝雀发布等发布运维策略。
6. 安全与多集群:面试里容易被忽视但很重要的方向
这一块内容在过去比较少出现在基础题里,但最近一年越来越常被问,因为云原生面试正在从“能不能跑起来”走向“跑起来之后怎么管好”。
6.1 容器以 root 运行的危害和最小权限原则
面试官说:“我在 K8s 里跑了一个容器,没有配置任何安全上下文,里面以 root 身份运行,有什么问题?”如果你的回答只是“不安全”,这个答案太单薄。好的回答链路是:
- 容器共享宿主内核。容器隔离的是用户态视图,内核是同一个。如果容器内进程是 root,内核里有些操作(比如加载内核模块、设置系统参数)就不能被 namespace 隔离住。一旦攻击者通过容器漏洞逃逸,拿到 root 权限,宿主就沦陷了。
- Linux capabilities 和 seccomp。容器默认允许的权限集合比传统系统进程大得多,最佳实践是给容器去掉不需要的 capabilities,追加
seccomp配置文件限制系统调用,有必要的话再加AppArmor/SELinux。 - 安全上下文。K8s 里可以在 Pod yaml 中配置:
securityContext: runAsNonRoot: true capabilities: drop: - ALL readOnlyRootFilesystem: true这个回答的价值在于你展示了从 Docker 到 K8s 的完整安全知识,而不是停留在“不要用 root”这种结论上。
6.2 多集群管理与备份迁移
从整个行业趋势看,Kubernetes 已经不单单是“在一个集群里跑容器”,跨国多集群、多区域容灾、云原生中间件迁移已经成为运维团队的日常。面试官如果问“你们现在如何管理多个集群”,通常是在探寻你有没有跨集群的运维能力。
核心答案围绕三点展开:
- 集群配置管理:用 GitOps 方式管理多个集群的资源配置,所有基础设施变更走仓库 + 审批流,每次变更可追溯。
- 应用编排与分发:负责运维的人更关注一套编排如何一键分发到多个集群,中间涉及 Helm Chart 打包、镜像版本控制、环境差异化配置。
- 备份与恢复:etcd 是集群状态的唯一真源。生产环境里必须周期性备份 etcd 快照,每套集群的备份机制都要提前演练。大部分“集群坏了数据丢了”的故障,都源于没有可用的 etcd 备份。
实际经验:我建议至少每半年做一次完整的恢复演练。只备份不演练等于没备份,因为快照文件损坏、版本兼容、恢复流程不熟练,都会在关键时刻掉链子。
7. 面试官视角下的答题策略与复习重点
最后一部分想直接给你一些非常实际的建议。刷题时很多人的误区是“觉得答上来就算会了”,但从面试官的角度,一道题答得好和答得差之间的分界线非常清楚:
- 不要只给结论,要给依据。比如“Service 网络不通”,不能说“可能是 kube-proxy 有问题”,要说“我先看 Service 的 Endpoint 列表,确认有没有可用的 Pod,再检查 kube-proxy 是否在运行,然后查看 node 上的 iptables/ipvs 规则”。给你的每个判断一个依据,面试官才有办法顺着你的思路继续下去。
- 把答案组织成递进关系。同一个问题,先答是什么,再答为什么,最后讲场景。如果时间紧,就优先讲为什么和场景。
- 诚实面对不会的题。千万不要硬编。可以这样回应:“这个细节我没有在生产环境验证过,但我了解大概的原理是……”。面试官并不要求候选人什么都会,但很介意候选人张嘴就来、把没验证过的东西说成实战经验。
以下是我的个人备查心得,也是我认为刷这套题最有效的方式:
- 先掌握“由外向内”的链路。所有 K8s 问题,都可以沿着“客户端访问 -> Ingress -> Service -> Endpoint -> Pod -> 容器 -> 镜像”这条链路去定位它属于哪一层。面试题看着千变万化,最后绝大多数都会落到这条链路的某一环。
- 把命令刻进肌肉记忆。
kubectl describe、kubectl logs --previous、kubectl get events、kubectl rollout status,这四个命令可以解决现场 90% 的 K8s 故障。不用怕被问“你刚才说的那个命令具体参数是什么”,用多了自然会。 - 练习用两分钟讲清一个组件。面试时会要求你回答得很精炼,不要一口气 5 分钟讲完。先用两分钟讲清核心原理,再等面试官追问细节点。
这份 Docker 和 K8s 面试题总结,我把容器基础的大部分内容已经覆盖到了。下一部分会继续补齐 K8s 的网络底层(CNI、Calico/Flannel)、存储体系(PV/PVC/StorageClass)、调度器原理(nodeSelector/Affinity/Taint/Toleration)、以及 etcd 的选主和 watch 机制。最后再提醒一遍,面试题只是引子,真正的底气和把控感,永远来自你亲手在一个真实环境里敲过的每一行命令。