面试 · 对比辨析型
2. 对比题#
考察对两个相似概念的区分能力,每题含对比表格 + 关键差异说明 + 适用场景推荐。
题目 1:Pod vs Container#
问题: Pod 和 Container 在 K8s 中分别处于什么层次?两者的关系是什么?
参考答案:
| 维度 | Pod | Container |
|---|---|---|
| 层次 | K8s 最小调度/部署单元 | 容器运行时单元 |
| 包含关系 | 可以包含 1+ 个容器 | 被包含在 Pod 内 |
| IP 地址 | 每个 Pod 有独立 IP | 无独立 IP,共享 Pod IP |
| 网络 | 独立的网络命名空间 | 共享 Pod 网络命名空间,通过 localhost 通信 |
| 生命周期 | 由 K8s Controller 管理 | 由 Pod 内的容器运行时管理 |
| 存储 | 定义共享 Volume | 挂载 Pod 定义的 Volume |
关键差异: Pod 提供了比容器更高层级的抽象——Pod 内多容器共享网络和存储,适合需要紧密协作的容器组(如主容器 + sidecar)。K8s 以 Pod 而非容器为调度单元,解决了容器组需要共同调度、共享资源的场景。Pod 也是探针(Probe)、资源限制(QoS)、调度约束的应用层。
适用场景推荐: 单容器场景依然需要 Pod 包裹(K8s 不能直接调度裸容器);多容器协作场景(日志 sidecar、Service Mesh sidecar、Init Container)是 Pod 设计的核心价值。
题目 2:Deployment vs StatefulSet#
问题: Deployment 和 StatefulSet 的核心区别是什么?何时应该选择 StatefulSet?
参考答案:
| 维度 | Deployment | StatefulSet |
|---|---|---|
| Pod 命名 | 随机后缀(如 myapp-5d8f9c-abc12) | 固定序号(如 mysql-0, mysql-1) |
| 启停顺序 | 并行,无顺序保证 | 有序启停(0→N-1 启动,N-1→0 终止) |
| 网络身份 | 无固定 DNS | 配合 Headless Service 获得固定 DNS |
| 存储 | 共享 PVC(所有 Pod 用相同存储) | 独立 PVC(volumeClaimTemplates 为每个 Pod 创建独占 PVC) |
| 扩缩容 | 任意顺序 | 有序(扩容从最大序号开始,缩容从最大序号结束) |
| 更新策略 | RollingUpdate(逐个替换) | RollingUpdate(逆序滚动)或 OnDelete |
| 适用场景 | 无状态服务(Web、API) | 有状态服务(数据库、消息队列) |
关键差异: StatefulSet 保证了 Pod 的"稳定性"——即使 Pod 被重新调度到其他节点,其名称、存储(重新绑定同一 PVC)和 DNS 名称不变。Deployment 的 Pod 是完全等价的,任意替换不影响服务。
适用场景推荐: 需要固定网络身份的服务(Kafka broker 需要持久化的 Broker ID 和地址)、需要独占存储的数据库(MySQL 主从、MongoDB 副本集)、需要有序扩缩容的集群(Etcd 集群)应使用 StatefulSet。普通无状态 API/Web 服务使用 Deployment。
题目 3:ClusterIP vs NodePort vs LoadBalancer#
问题: 三种 Service 类型的区别、访问方式及生产选型建议。
参考答案:
| 维度 | ClusterIP | NodePort | LoadBalancer |
|---|---|---|---|
| 访问范围 | 仅集群内部 | 集群外(通过节点 IP) | 集群外(通过云 LB) |
| IP 分配 | 分配虚拟 ClusterIP | 分配 ClusterIP + 每个节点端口 | 分配 ClusterIP + 外部 LB IP |
| 实现原理 | kube-proxy iptables/ipvs DNAT | 在每个节点开端口转发到 ClusterIP | 云厂商创建 LB → NodePort |
| 端口范围 | 任意 | 30000-32767 | 由 LB 决定 |
| 运维复杂度 | 极低 | 中(需管理端口、配合外部 LB) | 低(云厂商托管) |
| 成本 | 无 | 无额外成本 | 按 LB 计费 |
关键差异: NodePort 是 LoadBalancer 的基础(LoadBalancer 内部包含 NodePort 机制)。三者存在包含/递进关系。
适用场景推荐:
- ClusterIP:集群内微服务间通信(主要场景,占 90% 以上)
- NodePort:快速测试外部访问(生产不推荐,端口管理混乱、安全性差)
- LoadBalancer:生产环境对外暴露服务(配合云厂商 NLB/ALB,支持 TLS 终止、健康检查)
- 对外暴露标准做法:Ingress(单入口多服务路由)或 LoadBalancer + ExternalDNS
Service 的职责与四种类型(含 ExternalName、Headless)见概念篇 题2;"为何要有 ClusterIP 这层间接、而非直连 Pod"见设计理念篇 题4。本题聚焦三种类型的横向对比。
题目 4:Ingress vs Service#
问题: Ingress 和 Service 有什么区别?何时用 Ingress 替代直接暴露 Service?
参考答案:
| 维度 | Service | Ingress |
|---|---|---|
| 工作层次 | L4(TCP/UDP),ClusterIP 在 L3/L4 | L7(HTTP/HTTPS),支持 Host/Path 路由 |
| 路由能力 | 仅 Port 级别路由 | Host + Path 级别路由,支持多域名、多路径 |
| 负载均衡 | 基于连接的四层均衡(iptables/IPVS) | 基于请求的七层均衡(Nginx/Traefik) |
| TLS | NodePort 模式可配,但管理复杂 | 原生 TLS 终止,证书集中管理 |
| 高级功能 | 无 | 限流、重写、认证、跨域、金丝雀发布 |
| 成本 | 一个 Service 一个 IP(ClusterIP) | 一个 Ingress 代理多个 Service,节省 IP 和 LB 成本 |
关键差异: Service 是 L4 流量入口,只做端口转发不做内容检查。Ingress 是 L7 入口,根据 HTTP 请求的 Host 头和 URL Path 路由到不同 Service,还能提供 TLS 终止、重写、限流等高级中间件能力。
适用场景推荐:
- Service:集群内部微服务间通信、非 HTTP 协议(gRPC、TCP 代理)
- Ingress:对外暴露 HTTP 应用、需要 SSL/TLS 终止、需要基于路径/域名的多服务路由
- 两者配合使用:外部流量 → Ingress Controller → Service → Pod
题目 5:ConfigMap vs Secret#
问题: ConfigMap 和 Secret 的区别是什么?为什么不能把敏感数据放在 ConfigMap 中?
参考答案:
| 维度 | ConfigMap | Secret |
|---|---|---|
| 设计目的 | 非敏感配置数据 | 敏感数据(密码、Token、密钥) |
| 存储方式 | 明文存储于 etcd | 默认 base64 编码(非加密),可启用 etcd 加密 |
| 大小限制 | 1 MiB(etcd 限制 ~1.5 MiB) | 1 MiB |
| 挂载方式 | 环境变量 / Volume 挂载 / subPath | 环境变量 / Volume 挂载(tmpfs 内存文件系统) |
| RBAC 管控 | 一般宽松 | 应严格限制 |
| GitOps 友好度 | 可直接入 Git | 不应明文入 Git,需配合 SOPS/Sealed Secrets/Vault |
关键差异:
- Secret 以 Volume 挂载时通过 tmpfs 存储在内存中,不落磁盘
- Secret 应配合 etcd 加密、RBAC 严格管控、外部密钥管理(Vault/ESO)使用
- ConfigMap 可直接入 Git 做版本管理,Secret 必须加密后才能入 Git
适用场景推荐:
- ConfigMap:应用配置(端口、日志级别、Feature Flag)、启动参数、Nginx/Apache 配置
- Secret:数据库密码、API Key、TLS 私钥、镜像仓库认证凭据、OAuth Client Secret
题目 6:PV vs PVC#
问题: PV 和 PVC 各自的职责是什么?为什么需要分成两个对象?
参考答案:
| 维度 | PV | PVC |
|---|---|---|
| 角色 | 存储资源(供给方) | 存储申请(消费方) |
| 创建者 | 集群管理员或 StorageClass 动态创建 | 应用开发者/用户 |
| 范围 | 集群级别资源 | Namespace 级别资源 |
| 内容 | 描述实际存储:容量、接入模式、后端存储类型/ID | 声明需求:容量、访问模式、StorageClass |
| 生命周期 | 独立于任何 Pod,PVC 删除后按策略处理 | 与 Pod 关联,Pod 删除不影响 PVC |
| 绑定关系 | 与 PVC 一对一绑定(一个 PV 只能绑定一个 PVC) | 绑定到一个匹配的 PV |
为什么分两层: K8s 将"存储供应"和"存储消费"解耦,遵循关注点分离原则。集群管理员负责定义可用的存储资源(PV/StorageClass),开发者只需声明存储需求(PVC)而无需关心底层存储的实现细节。这种模式使得开发者不需要知道 NFS 服务器地址、云磁盘 ID 等底层信息。
适用场景推荐: 理解这个分层模型后,PVC Pending 的排查思路就是:先看 StorageClass 是否存在和正确 → provisioner 是否健康 → 底层存储系统是否可用。
题目 7:emptyDir vs hostPath vs PVC#
问题: 三种存储卷类型的区别及各自适用场景。
参考答案:
| 维度 | emptyDir | hostPath | PVC |
|---|---|---|---|
| 数据生命周期 | 与 Pod 同生命周期(Pod 删除数据丢失) | 与 Node 同生命周期 | 独立于 Pod(Pod 删除数据保留) |
| 存储位置 | Node 的临时目录(或内存 medium: Memory) | Node 上指定路径 | 独立存储系统(云盘/NFS/本地 PV) |
| 跨 Pod 共享 | 同一 Pod 内多容器共享 | 可跨 Pod(同 Node) | 可跨 Pod(同一 Node 或跨 Node 视存储类型) |
| 跨 Node 迁移 | Pod 迁移后数据丢失 | Pod 迁移后数据留在旧 Node | Pod 迁移到任何 Node 数据跟随 |
| 安全性 | 较低(节点磁盘满影响) | 低(需特权,可访问节点文件) | 高 |
适用场景推荐:
- emptyDir:临时缓存、同 Pod 内容器间共享数据、
medium: Memory用做高性能临时存储(如 AI 推理的临时张量缓存) - hostPath:Log agent 读宿主机日志、监控 agent 访问宿主机指标(Docker socket/proc 文件系统);生产环境慎用,Pod 需绑定到特定节点
- PVC:数据库数据文件、用户上传文件、模型文件等需要持久化的数据
题目 8:Liveness Probe vs Readiness Probe vs Startup Probe#
问题: 三种探针的功能区别、失败后果及配置要点。
参考答案:
| 维度 | Startup Probe | Readiness Probe | Liveness Probe |
|---|---|---|---|
| 目的 | 判断应用是否完成启动 | 判断应用是否可以接收流量 | 判断应用是否需要被重启 |
| 失败后果 | 继续等待(不会触发重启) | 从 Service Endpoint 摘除 Pod | kubelet 重启容器 |
| 执行时机 | 仅在启动期间执行,成功后不再执行 | 贯穿 Pod 整个生命周期 | 贯穿 Pod 整个生命周期 |
| 配置重点 | failureThreshold × periodSeconds ≥ 最大启动时间 | 可检查下游依赖(DB/缓存是否就绪) | 只检查进程本身,不要检查外部依赖 |
| 典型检查 | 端口监听、初始化完成标志 | 连接池就绪、缓存预热完成 | HTTP /healthz 返回 200、进程心跳 |
关键差异:
- Startup Probe 解决了"慢启动应用被 Liveness 误杀"的问题。没有 Startup Probe 时只能用很长的
initialDelaySeconds,但每次重启后都要等这么久。 - Readiness 失败不会重启 Pod,只是停止向该 Pod 转发流量。这允许 Pod 在出现问题(如下游依赖不可用)时自我隔离。
- Liveness 不要检查数据库或 Redis 等外部依赖——如果外部系统故障,Liveness 失败会导致所有 Pod 被不断重启,引发雪崩。
适用场景推荐:
- 慢启动应用(JVM/Go 大依赖初始化):三者都配
- 快速启动应用:只配 Readiness + Liveness,initialDelaySeconds 5-10s
- 批处理/Worker:可能只配 Liveness
题目 9:RWO vs RWX vs ROX#
问题: 三种存储访问模式的含义及其对 Pod 调度的影响。
参考答案:
| 模式 | 全称 | 含义 | 典型存储类型 | 限制 |
|---|---|---|---|---|
| RWO | ReadWriteOnce | 单节点读写 | 云磁盘(EBS/Azure Disk)、本地磁盘 | PV 只能被单一 Node 上的 Pod 挂载 |
| ROX | ReadOnlyMany | 多节点只读 | NFS、CephFS、EFS | 所有 Node 上的 Pod 只能以只读方式挂载 |
| RWX | ReadWriteMany | 多节点读写 | NFS、CephFS、EFS、GlusterFS | 多个 Node 上的 Pod 可以同时读写同一卷 |
关键差异:
- RWO 是最常见的模式(块存储类),如果 Deployment 有多个副本且分布在多个 Node 上,每个 Pod 需要各自的 PV/PVC
- ROX 适合需要多 Pod 共享只读数据的场景(如静态资源、配置文件)
- RWX 架构最灵活但存储系统要求高(需要支持并发写入的文件系统),成本通常高于 RWO
适用场景推荐:
- RWO:数据库数据卷、普通应用持久化
- ROX:静态资源 CDN 缓存层、共享配置目录
- RWX:多个 Pod 需要同时写同一文件系统的场景(如共享上传目录)
题目 10:Role vs ClusterRole#
问题: Role 和 ClusterRole 的区别是什么?什么场景下必须使用 ClusterRole?
参考答案:
| 维度 | Role | ClusterRole |
|---|---|---|
| 作用范围 | 单个 Namespace | 全集群(所有 Namespace) |
| 可授权的资源 | Namespace 级资源(Pod、Service、Deployment 等) | 集群级资源(Node、PV、Namespace 本身) + Namespace 级资源 |
| 典型用例 | 给监控 SA 在本 Namespace 读 Pod | 给 admin 在任意 Namespace 读写所有资源 |
必须使用 ClusterRole 的场景:
- 访问集群级资源:Node、PersistentVolume、Namespace、StorageClass、CRD
- 访问非资源 URL:
/healthz、/metrics、/api/* - 需要在所有 Namespace 中操作资源(如日志采集器需要读所有 Namespace 的 Pod)
- 在某个 Namespace 中通过 RoleBinding 引用 ClusterRole 来复用其规则定义(授权范围会被降级到该 Namespace)——这一"复用但降权"机制的完整说明见题目 11
适用场景推荐:
- Role:团队 A 在
team-aNamespace 内管理自己的 Deployment - ClusterRole:集群管理员管理所有 Namespace;监控系统读取全集群 Pod 状态
- 经验法则:如果操作范围不超过单个 Namespace,优先使用 Role
题目 11:RoleBinding vs ClusterRoleBinding#
问题: RoleBinding 和 ClusterRoleBinding 的差异以及交叉使用场景。
参考答案:
| 维度 | RoleBinding | ClusterRoleBinding |
|---|---|---|
| 作用范围 | 限定在某个 Namespace | 全集群 |
| 可引用的 Role 类型 | 只能引用 Role | 只能引用 ClusterRole |
| 但... | 可以引用 ClusterRole!(权限降级到该 Namespace) | 不能引用 Role |
| 典型场景 | 给某个 Namespace 内的 SA 授权 | 给集群管理员或系统组件全局授权 |
交叉使用场景(重要):
RoleBinding 可以引用 ClusterRole,这是复用 ClusterRole 定义、但限制权限范围的重要手段。例如:定义 ClusterRole pod-reader(对所有 Namespace 读 Pod),在 team-a Namespace 创建 RoleBinding 引用该 ClusterRole,效果是只允许在 team-a 内读 Pod,而非所有 Namespace。
适用场景推荐:
- RoleBinding + Role:团队内权限(如只在自己 Namespace 运行)
- ClusterRoleBinding + ClusterRole:集群管理员、系统组件的全局权限
- RoleBinding + ClusterRole:复用通用权限定义但限制范围(最常用的模式)
本题是"RoleBinding 引用 ClusterRole"机制的单一出处;其"为何要分 Role/ClusterRole 两级、这层复用降权为何精妙"的设计动因见设计理念篇 题5。
题目 12:Request vs Limit#
问题: CPU/内存的 requests 和 limits 在调度、运行时和驱逐中的不同作用。
参考答案:
| 维度 | Request | Limit |
|---|---|---|
| 作用阶段 | 调度阶段(决定 Pod 放在哪个 Node) | 运行阶段(限制 Pod 实际使用量) |
| 对 Scheduler | 用于计算 Node 剩余可分配资源 | 不影响调度决策 |
| 对 Kubelet | 保证最低资源 | 不允许超过上限 |
| 超限后果 | 无直接后果 | CPU:throttling(降速);Memory:OOMKilled(被杀) |
| QoS 影响 | 决定 QoS 等级的关键参数 | 仅 memory limits 影响 QoS |
| 设置建议 | 必须设置,基于 P95 实际用量 | CPU 可不设(避免 throttling),Memory 必须设 |
关键差异:
- CPU:超过 request 不触发 throttle,超过 limit 才 throttle。很多团队选择不设 CPU limits 以避免 CFS 带宽控制导致的 P99 延迟飙升
- Memory:超过 request 不会被立即杀死(只要节点有足够内存),超过 limit 会触发 OOM Killer。Memory 的 limits 必须设置
- 调度:Scheduler 只看 requests,Node 上所有 Pod 的 requests 总和不能超过 Node 的 Allocatable
适用场景推荐:
- Requests:基于长期监控的 P95 用量 * 1.3
- CPU Limits:通常不设(Perf敏感服务);批处理可设
- Memory Limits:必须设(request * 1.5~2),防止内存泄漏影响整个节点
题目 13:HPA vs VPA#
问题: HPA 和 VPA 的不同扩缩维度、适用场景及能否共存。
参考答案:
| 维度 | HPA (Horizontal) | VPA (Vertical) |
|---|---|---|
| 扩缩维度 | 水平(改变 Pod 副本数) | 垂直(改变 Pod 的 requests/limits) |
| 触发方式 | 指标超阈值 | 历史用量分析 + 推荐值 |
| 是否需要重启 | 不需要(创建/删除 Pod) | Auto 模式需要重启 Pod |
| 响应速度 | 分钟级 | 小时级(推荐模式不重启) |
| 适用场景 | 无状态服务、流量波动的 API | 资源配置不合理的服务、内存泄漏分析 |
| 核心指标 | CPU/内存利用率、自定义指标 | 长期资源用量趋势 |
能否共存: HPA 和 VPA 不要同时用相同的资源指标(如都管理 CPU),会导致两者冲突。但可以分工——VPA 只调 memory requests/limits(controlledResources: ["memory"]),HPA 按 CPU 或 QPS 扩缩副本数。
适用场景推荐:
- HPA:应对流量波动(Web 服务、API 网关)
- VPA Off 模式:分析生产资源使用,给出 requests 建议值(最安全的用法)
- VPA + HPA:VPA 管 memory(Off/Initial 模式),HPA 管 CPU 副本扩缩
- 注意:VPA Auto 模式会重启 Pod,生产环境不推荐直接使用
题目 14:iptables vs IPVS(kube-proxy 模式)#
问题: kube-proxy 的 iptables 和 IPVS 两种转发模式在性能和规模上有何差异?
参考答案:
| 维度 | iptables 模式 | IPVS 模式 | nftables 模式 |
|---|---|---|---|
| 规则结构 | 链式规则表,每条链多条规则 | 内核级哈希表 | nftables map/verdict(内核态) |
| 查找复杂度 | O(n),规则越多越慢 | O(1),常数时间 | 接近 O(1)(基于 map) |
| 大规模集群性能 | 500+ Service 时新连接延迟显著升高 | 几乎不受 Service 数量影响 | 规则同步和查找都远优于 iptables |
| 负载均衡算法 | 随机(statistic probability) | rr/lc/sh/dh/sed/nq 等多种 | 目前仅随机(能力向 iptables 看齐) |
| Kubernetes 状态 | 默认模式 | 需配置 mode: ipvs | 1.33 GA,仍非默认,需 mode: nftables |
| 连接跟踪 | 大量 conntrack 条目 | 更少的 conntrack 依赖 | 依赖 conntrack |
| 调试工具 | iptables -t nat -L -n -v | ipvsadm -Ln | nft list ruleset |
关键差异: 在 1000 个 Service 的场景下,iptables 模式会产生数万条规则,每个新连接的 SYN 包需要遍历这些规则直到命中,导致数毫秒到数百毫秒的延迟;更痛的是规则全量同步慢。IPVS 用哈希查找直接定位后端;nftables 则用现代内核框架从根子上解决 iptables 的 O(n) 与同步慢问题,定位是"iptables 的官方现代替代",长期看会成为默认。(各模式的完整定义、以及 userspace 模式于 1.26 移除的来龙去脉见概念篇 题14;转发链路机制见原理篇 题2。)
适用场景推荐:
- iptables:小集群(<200 Service)、需要成熟稳定和熟悉的调试手段
- IPVS:中大型集群(200+ Service)、需要多种 LB 算法、对连接延迟敏感
- nftables:内核/发行版够新、愿意跟进新特性,想要 iptables 的兼容语义但更好的规模表现
- 终极方案:Cilium(eBPF 替代 kube-proxy),完全在内核处理,延迟可降至微秒级
题目 15:Flannel vs Calico vs Cilium(CNI)#
问题: 三种主流 CNI 插件的架构差异和选型建议。
参考答案:
| 维度 | Flannel | Calico | Cilium |
|---|---|---|---|
| 网络模型 | Overlay(VXLAN/host-gw) | Overlay(IPIP/VXLAN)或 Underlay(BGP) | Overlay(VXLAN)或 eBPF 直连路由 |
| 数据平面 | Linux 内核 VXLAN 模块 | iptables / eBPF | eBPF(XDP/TC hook) |
| 性能 | 一般(封包开销约 30%) | BGP 模式几乎无损耗,IPIP 有封包开销 | 最优,内核级处理 |
| NetworkPolicy | 不支持 | L3/L4 支持(iptables/eBPF) | L3/L4/L7 支持(HTTP Path/Method) |
| 可观测性 | 有限 | calicoctl + Prometheus | Hubble(L7 实时流量观测) |
| 复杂度 | 极低 | 中等 | 较高(需理解 eBPF) |
| 内核要求 | 无特殊要求 | 无特殊要求 | 内核 >= 5.10(建议 5.15+) |
适用场景推荐:
- Flannel:简单场景、学习环境、不需要 NetworkPolicy 的小集群
- Calico:混合云/私有云场景需要 BGP 对等、稳定性优先的中大型集群
- Cilium:追求性能天花板、需要 L7 NetworkPolicy 和 Hubble 可观测性、新集群
- 托管 K8s(EKS/ACK):通常使用厂商 CNI(AWS VPC CNI/Terway),不要替换
题目 16:Helm vs Kustomize#
问题: Helm 和 Kustomize 两种配置管理工具的设计理念和使用场景差异。
参考答案:
| 维度 | Helm | Kustomize |
|---|---|---|
| 设计理念 | 模板引擎 + 包管理 | 无模板、基于 Base + Overlay 的声明式补丁 |
| 工作方式 | Go template 替换变量 + values.yaml | 纯 YAML patch/overlay,无变量替换 |
| 包管理 | 支持(Helm Repository、OCI) | 不支持(需借助 Kustomize components 或 Git submodules) |
| Release 管理 | 有(helm install/upgrade/rollback) | 无(依赖 Kubernetes apply 机制) |
| 多环境管理 | values 文件(values-prod.yaml) | Overlay 目录(base/ + overlays/production/) |
| 复杂度 | 中等(需学习 Go template 语法) | 低(纯 YAML + 少量 kustomization.yaml 配置) |
| 社区 | CNCF Graduated,生态最成熟 | K8s 内置(kubectl apply -k) |
适用场景推荐:
- Helm:安装第三方软件(Prometheus、Ingress Controller、数据库)、复杂部署需要条件判断和循环
- Kustomize:自有应用的多环境管理、需要 patch 第三方配置的场景、GitOps 友好
- 混合使用:用 Helm 安装基础设施,用 Kustomize 管理自有应用配置
题目 17:ArgoCD vs FluxCD#
问题: 两种主流 GitOps 工具的架构差异和选型建议。
参考答案:
| 维度 | ArgoCD | FluxCD |
|---|---|---|
| 架构 | Server-first(集中式 API Server + Web UI) | Controller-first(五个解耦的 CRD Controller) |
| Helm 支持 | helm template 模式(不创建真实 release) | 真实 Helm install/upgrade(真 release) |
| 多集群 | 中心化(主集群控制所有集群) | 联邦式(每集群自治,通过 Git 仓库协调) |
| 多租户 | AppProject + 自有 RBAC 层 | K8s 原生 RBAC + ServiceAccount impersonation |
| UI | 原生 Web UI(拓扑图、diff、一键回滚) | 无原生 UI(Grafana/Weave GitOps 补充) |
| 同步粒度 | 全局 resync 周期(所有 Application 共享) | 每个 Kustomization/HelmRelease 独立 interval |
| 批量部署 | ApplicationSet(PR generator 等丰富能力) | Git 目录结构 + substituteFrom 变量注入 |
| Secret 管理 | Sealed Secrets/ESO(社区方案) | 原生 SOPS 集成 |
适用场景推荐:
- ArgoCD:中小规模集群、需要 Web UI 给开发团队自助查看部署状态、强依赖 ApplicationSet + PR preview 环境
- FluxCD:大规模跨云多集群(联邦式更安全)、重度 Helm 用户(真 release、rollback)、平台工程团队嵌入 IDP
题目 18:vCluster vs Capsule vs HNC(多租户)#
问题: 三种 K8s 多租户方案的隔离模型和各自优势。
参考答案:
| 维度 | vCluster | Capsule | HNC |
|---|---|---|---|
| 核心思路 | 在宿主 Namespace 内运行完整虚拟 K8s 集群 | 在现有集群叠加 Tenant CRD + Webhook 策略 | Namespace 层级继承(树形结构) |
| API Server 隔离 | 完全独立(k3s/k8s API) | 共享(通过 Webhook 限制) | 共享 |
| CRD 隔离 | 完全隔离,租户可安装自己的 CRD | 共享,可能冲突 | 共享 |
| RBAC 模型 | 虚拟集群内完全自主 | Capsule Webhook + K8s RBAC | 父 Namespace RBAC 传播到子 Namespace |
| 网络隔离 | 宿主层手动配置 NetworkPolicy | 自动注入 NetworkPolicy | NetworkPolicy 传播继承 |
| 资源开销 | 每租户 ~200m CPU + 256Mi(虚拟控制面) | 极轻量(Controller + Webhook) | 极轻量 |
| 运营复杂度 | 高(需管理每租户的控制面) | 中 | 低 |
| CNCF 阶段 | Sandbox | Sandbox | k8s-sigs(Google 内部大量使用) |
适用场景推荐:
- vCluster:SaaS 平台多客户强隔离、客户需要自定义 CRD、不同客户可能需要不同 K8s 版本
- Capsule:企业内部平台多个业务团队共享集群、需要集中管控镜像仓库/IngressClass/StorageClass
- HNC:开发环境 Namespace 层级管理、项目树形结构(org → team → project → branch)
题目 19:Istio vs Cilium vs Linkerd(Service Mesh)#
问题: 三种 Service Mesh 方案的架构、性能和适用场景对比。
参考答案:
| 维度 | Istio | Cilium Service Mesh | Linkerd |
|---|---|---|---|
| 数据平面 | Envoy sidecar(用户态代理,每 Pod 一个) | eBPF 内核(L4)+ 按需 Envoy(L7) | linkerd2-proxy(Rust 微代理 sidecar) |
| 无 sidecar 模式 | Ambient Mode(Istio 1.24 GA,1.22 仅 Beta;ztunnel + Waypoint) | 原生 eBPF 无 sidecar | 不支持 |
| P99 延迟增加 | sidecar: +8ms;Ambient L4: +3ms | eBPF L4: +1ms;Envoy L7: +4ms | +2ms |
| Sidecar 内存 | 50-100 MB(Envoy) | ~5 MB 内核(L4)或共享 50-80 MB/节点(L7) | 10-20 MB |
| L7 能力 | HTTP/gRPC/TCP(丰富) | HTTP/gRPC(需启用 Envoy) | HTTP/1.1、HTTP/2、gRPC |
| 可观测性 | Kiali + Jaeger/Zipkin | Hubble(eBPF 内核采集,零开销) | Linkerd Viz + tap 命令 |
| 安装复杂度 | 高(profile、IstioOperator CRD) | 中(需一定 eBPF 知识) | 最低(linkerd check 引导式安装) |
| 生态成熟度 | 最成熟(CNCF Graduated) | 快速追赶,eBPF 前沿 | 成熟(CNCF Graduated) |
适用场景推荐:
- Istio:大规模组织有专职 SRE、需要完整 L7 控制(金丝雀/WASM 扩展/多集群)、已用 Envoy 生态
- Cilium SM:已用 Cilium CNI 的团队、性能敏感(低延迟/高吞吐)、需要 CNI+SM 一体化
- Linkerd:小团队、90% 需求是 mTLS + 基础可观测、追求运维最简体验
题目 20:PSP vs PSA(Pod 安全策略演进)#
问题: PSP 为什么被废弃?PSA 如何替代它?
参考答案:
| 维度 | PSP (PodSecurityPolicy) | PSA (Pod Security Admission) |
|---|---|---|
| 引入/废弃时间 | v1.0 引入 → v1.21 废弃 → v1.25 移除 | v1.23 Beta → v1.25 GA |
| 作用机制 | Admission Controller + 集群级 Policy 对象 | 内置 Admission Webhook + Namespace 标签 |
| 使用复杂度 | 高(需创建 Policy + RBAC 绑定 + Admission Controller 启用) | 低(Namespace 打标签即可:enforce/audit/warn 三个模式) |
| 配置粒度 | 细粒度(sysctl、capabilities、volume 类型等数十个字段) | 三个预设级别:Baseline / Restricted / Privileged |
| 可扩展性 | 自定义策略灵活 | 预设级别不可扩展,复杂场景需配合 OPA/Kyverno |
| 审计能力 | 弱 | 原生支持 audit + warn 模式 |
关键差异: PSP 的问题在于使用门槛极高——创建 PSP 后还需要为 ServiceAccount 绑定 USE 权限,且 PSP 是集群级别的,需要 RBAC 来控制谁可以触发 PSP。PSA 采用 Namespace 标签方式,运维体验大幅简化:kubectl label ns production pod-security.kubernetes.io/enforce=restricted。
适用场景推荐:
- PSA:标准安全需求(禁止特权容器、非 root 运行、只读根文件系统)——三档预设覆盖 90% 场景
- OPA/Kyverno:PSA 预设不够的复杂场景(如限制镜像来源、限制 Ingress Host、注入 sidecar 策略)
题目 21:Sidecar 模式 vs Ambient 模式#
问题: Service Mesh 中 Sidecar 模式和 Ambient 模式的架构差异及各自优劣。
参考答案:
| 维度 | Sidecar 模式 | Ambient 模式 |
|---|---|---|
| 数据平面位置 | 每个 Pod 注入一个 sidecar proxy(Envoy/Rust proxy) | 节点级 ztunnel(L4)+ 按需 Waypoint Proxy(L7) |
| 资源开销 | 每 Pod 50-100 MB 内存(线性增长) | 每节点共享 ztunnel(20-40 MB),Waypoint 按需启动 |
| 升级方式 | 需滚动重启所有 Pod | 升级节点组件即可,Pod 无需重启 |
| 调试路径 | 简单(sidecar 就在 Pod 内) | 复杂(流量经过节点级组件 + Waypoint) |
| 流量拦截 | iptables/istio-init 重定向 | eBPF/zc 在节点级拦截 |
| L4 mTLS | Sidecar 之间 mTLS | ztunnel 之间 mTLS(节点到节点) |
| 成熟度 | 多年生产验证 | Istio 1.24 GA(1.22 Beta),仍在快速演进 |
补充:K8s 原生 Sidecar(1.33 GA)改善了 Sidecar 模式的老痛点。 过去 Envoy sidecar 是普通容器,存在两大顺序问题:启动时业务容器可能早于 sidecar 就绪而丢流量;关停时 sidecar 可能先于业务容器退出,导致业务最后的请求发不出去("代理先死"问题)。原生 sidecar 把它声明为 restartPolicy: Always 的 initContainer,由 kubelet 保证它先于业务容器启动、后于业务容器终止,正是这类问题的解法。这属于 K8s 层面的能力,与选不选 Ambient 是两码事。
适用场景推荐:
- Sidecar:成熟稳定、调试方便、中小规模集群(1000 Pod 以下)
- Ambient:大规模集群降低 sidecar 内存总开销、需要对 Pod 透明(不注入 sidecar 容器)、不需要重启 Pod 即可升级 mesh
题目 22:etcd 与其他分布式 KV 存储#
问题: etcd 相比 Redis、ZooKeeper、Consul 有哪些独特的设计优势?
参考答案:
| 维度 | etcd | ZooKeeper | Consul | Redis (Cluster) |
|---|---|---|---|---|
| 一致性协议 | Raft | ZAB(类 Multi-Paxos) | Raft | 异步主从(非强一致性) |
| 数据模型 | KV + Lease + Watch | 树形 ZNode + Watch | KV + Service Catalog | KV(多种数据结构) |
| Watch 机制 | 原生高效(HTTP/2 stream,复用连接) | 一次性(触发后需重新注册,易丢失事件) | Long Polling | 不支持原生 Watch(需 pub/sub 替代) |
| 社区 | CNCF,K8s 核心依赖 | Apache 项目(Kafka 也依赖它) | HashiCorp | 广泛使用 |
| 开源协议 | Apache 2.0 | Apache 2.0 | BSL(Business Source License,2023 变更) | BSD |
| 适用场景 | K8s 集群状态、分布式锁、配置中心 | Kafka 元数据 / Dubbo 注册中心 / HBase | 服务发现 + KV 存储 + 健康检查 | 缓存、消息队列(非强一致性场景) |
关键差异: etcd 的核心优势是 Watch 机制的持久性和高效性(基于 HTTP/2 Server-Sent Stream),K8s 所有 Controller 都依赖这个 Watch 机制来监听资源变化。ZooKeeper 的 Watch 是一次性的(触发后需重新注册),在事件密集场景下容易丢失事件。Redis 并非强一致性系统(异步复制可能导致数据丢失),不适合作为分布式协调存储。
题目 23:Docker vs containerd#
问题: K8s 中 Docker 和 containerd 的角色差异,以及 K8s 为什么移除 Docker 支持。
参考答案:
| 维度 | Docker | containerd |
|---|---|---|
| 定位 | 完整的容器管理平台(CLI + API + 构建 + 运行) | 专精容器运行时(只负责镜像拉取和容器生命周期) |
| CRI 兼容 | 需要 dockershim 适配层(K8s 1.24 移除) | 原生 CRI 插件,无需适配 |
| 功能范围 | docker build / push / run / compose / swarm | 仅容器运行时,不负责镜像构建 |
| 进程模型 | dockerd(守护进程)+ containerd + runc | containerd + runc(少一层 daemon) |
| 内存占用 | 较高(dockerd 额外占用 ~100 MB) | 更低(减少一层 daemon) |
| K8s 状态 | 1.24 后不再支持 | 默认运行时(kubeadm 默认) |
K8s 移除 Docker 支持的原因: K8s v1.24 废弃 dockershim,原因是 Docker 不符合 CRI(Container Runtime Interface)规范,需要通过 dockershim 适配层转换。维护这一适配层增加了复杂度且不是必需的——containerd 已经是 CRI 兼容的,且 Docker 内部也使用 containerd。
迁移影响: 对用户几乎透明——容器镜像标准(OCI)不变,Dockerfile 和构建流程不变。唯一的改变是节点上不再用 docker 命令排障,改用 crictl(CRI 层通用)或 nerdctl(containerd 原生、命令行仿 docker)进行调试。
厘清一句常被说错的话: 不是"K8s 不再支持 Docker 镜像",而是"K8s 不再把 Docker Engine 当作节点运行时"。当前主流的 CRI 运行时是 containerd(kubeadm/多数云厂商默认)和 CRI-O(Red Hat OpenShift 系默认,更精简、专为 K8s 而生);二者都用 runc/crun 作为底层 OCI runtime。Docker 本身仍可用来构建镜像。
题目 24:Overlay vs Underlay 网络#
问题: 两种跨节点网络模型的原理、性能差异和适用场景。
参考答案:
| 维度 | Overlay(覆盖网络) | Underlay(底层路由网络) |
|---|---|---|
| 工作原理 | 在 IP 包外再封装一层(VXLAN/IPIP),通过隧道传输 | 直接修改路由表或 BGP 通告 Pod CIDR |
| 封包开销 | 有(VXLAN 50 字节,IPIP 20 字节) | 无 |
| MTU 影响 | 需减小 MTU(VXLAN -50) | 无影响 |
| 网络依赖 | 仅需节点间 IP 可通(L3 连通即可) | 需要网络设备支持(同一 L2 域或 BGP 对等) |
| 调试复杂度 | 中(需理解隧道封装) | 高(需理解路由协议和 BGP) |
| 典型 CNI | Flannel VXLAN、Calico IPIP | Calico BGP、Cilium Direct Routing |
| 性能 | 一般(30% 封包开销) | 高(接近原生性能) |
适用场景推荐:
- Overlay:跨云/跨数据中心(网络不连续)、学习/测试环境、基础设施不提供路由互通能力
- Underlay:性能敏感场景(高频交易、AI 推理延迟敏感)、同一数据中心内(网络设备支持 BGP)、私有云
题目 25:声明式 vs 命令式#
问题: 声明式 API 和命令式 API 的核心差异,以及 K8s 为什么选择声明式。
参考答案:
| 维度 | 声明式(Declarative) | 命令式(Imperative) |
|---|---|---|
| 使用方式 | 描述"期望状态"(YAML 文件),系统自动达到该状态 | 发出"操作指令"(CLI 命令),执行单步操作 |
| 幂等性 | 天然幂等(多次 apply 同一文件结果相同) | 不一定(如 kubectl scale --replicas=5 与 --replicas=8 行为不同) |
| 可审计 | 强(YAML 文件可入 Git 版本管理) | 弱(操作历史依赖审计日志) |
| 自愈能力 | 强(控制器持续调谐,实际状态收敛到期望状态) | 弱(执行一次即结束,无后续调谐) |
| 大规模管理 | 容易(Git 仓库 + CI/CD = GitOps) | 困难(手动操作/脚本编排) |
| 示例 | kubectl apply -f deploy.yaml | kubectl run nginx --image=nginx |
K8s 选择声明式的原因(概要): 持续调谐带来自愈能力、配置可版本化(IaC/GitOps)、把"如何达成目标"的复杂性封装进控制器。这几点设计动因(另含水平触发的可靠性、幂等性)以及"若改用命令式的后果"详见设计理念篇 题2;本题聚焦声明式与命令式的逐项对比。
题目 26:Gateway API vs Ingress#
问题: Gateway API 相比 Ingress 解决了什么问题?两者的角色模型和能力差异是什么?现在该用哪个?
参考答案:
| 维度 | Ingress | Gateway API |
|---|---|---|
| API 状态 | 已冻结/维护模式,不再加新功能 | 官方继任者,持续演进(v1.0 已 GA,此后按 channel 迭代) |
| 协议支持 | 基本只有 HTTP/HTTPS | HTTP/HTTPS/TCP/UDP/gRPC/TLS(可扩展) |
| 角色模型 | 单一对象,路由 + 基础设施混在一起 | 角色分离:GatewayClass(厂商/平台)、Gateway(集群运维,管监听器/端口/证书)、HTTPRoute 等(应用开发者,管路由)——权责清晰、天然多租户 |
| 高级流量能力 | 靠各家 Controller 的 annotation 硬塞(不可移植) | 流量拆分/权重、Header 匹配与改写、跨 Namespace 路由等写进标准 API 字段,跨实现可移植 |
| 跨 Namespace | 不支持(Ingress 只能引本 Namespace 的 Service) | 支持(ReferenceGrant 授权跨 Namespace 引用,安全可控) |
| 可移植性 | 差(换 Controller 要重写一堆 annotation) | 强(标准字段,Istio/Envoy Gateway/Cilium/NGINX 等统一实现) |
关键差异: Ingress 最大的问题是表达力不足 + 靠 annotation 打补丁——想做金丝雀、限流、复杂改写只能写厂商私有 annotation,换个 Controller 就得推倒重来。Gateway API 用面向角色的多对象模型把"平台/运维/开发"权责分层,并把高级流量能力标准化为可移植的 API 字段。
现在该用哪个:
- 存量、简单的 HTTP 七层路由,Ingress 够用可继续维护
- 新项目、需要 TCP/UDP/gRPC、需要标准化流量拆分/多租户/跨 Namespace,直接上 Gateway API
- 迁移可借助官方
ingress2gateway工具转换存量 Ingress 配置
题目 27:HPA vs KEDA#
问题: 原生 HPA 有哪些能力边界?KEDA 补齐了什么?两者是替代还是配合关系?
参考答案:
| 维度 | 原生 HPA | KEDA (Kubernetes Event-Driven Autoscaling) |
|---|---|---|
| 扩缩依据 | CPU/内存、Custom/External Metrics(需自建 adapter) | 60+ 内置 Scaler(Kafka lag、RabbitMQ 队列、Prometheus 查询、云消息队列、cron 等),开箱即用 |
| 缩容到 0 | 不能(minReplicas 最小为 1) | 能(0↔1 由 KEDA 激活,1↔N 交给它内部创建的 HPA) |
| 事件驱动 | 弱(本质是周期性拉指标) | 强(面向消息/队列积压等事件源) |
| 实现关系 | 独立控制器 | 构建在 HPA 之上——KEDA 把外部事件源转成 External Metrics,再驱动一个自动创建的 HPA |
| 典型场景 | 常驻在线服务按 CPU/QPS 弹性 | 消费型/批处理 Worker、消息队列消费者、闲时缩到 0 省成本 |
关键差异: 原生 HPA 面向"常驻服务按利用率弹性",两个硬伤是接第三方指标要自己搭 metrics adapter、且缩不到 0。KEDA 用大量现成 Scaler 解决了前者,用"激活层 + 自动生成 HPA"解决了后者——闲时把消费者缩到 0、有消息进来再拉起,非常适合成本敏感的异步工作负载。
替代还是配合: 是配合,不是替代。KEDA 底层就是 HPA,只是替你把"事件源 → 指标 → HPA"这条链接好了。顺带补齐三者定位:HPA 改副本数(水平)、VPA 改单 Pod 的 requests/limits(垂直)、KEDA 让 HPA 能事件驱动并缩容到 0。