K8s 高频面试题分批梳理计划
Summary
按 Java 后端 / 高级后端 / 架构岗 面试视角,把 Kubernetes 高频题拆成 7 轮讲解。每题按固定结构回答:一句话结论、核心原理、流程图、常见追问、面试表达,重点覆盖基础概念、调度、网络、存储、发布、故障排查和架构落地。
Key Topics
- 第一轮:K8s 基础核心
- Kubernetes 是什么,解决什么问题
- Master/Worker 架构
- Pod、Node、Namespace、Label、Annotation
- Deployment、ReplicaSet、StatefulSet、DaemonSet、Job/CronJob
- Service、Ingress、ConfigMap、Secret
- 第二轮:Pod 生命周期与调度
- Pod 创建流程
- kube-apiserver、scheduler、controller-manager、kubelet 分工
- 调度流程
- 资源 requests/limits
- QoS 分类
- 探针:liveness/readiness/startup
- Pod 重启策略
- 第三轮:K8s 网络
- Service 四种类型
- ClusterIP、NodePort、LoadBalancer、ExternalName
- kube-proxy 原理:iptables/IPVS
- Pod 间通信
- Service 负载均衡原理
- Ingress 和 Ingress Controller
- CNI 是什么
- CoreDNS 解析流程
- 第四轮:存储与配置
- Volume、PV、PVC、StorageClass
- 静态供给和动态供给
- StatefulSet 稳定身份和稳定存储
- ConfigMap 和 Secret 区别
- Secret 安全注意点
- 数据库是否适合跑在 K8s
- 第五轮:发布、扩缩容与高可用
- Deployment 滚动更新
- maxSurge / maxUnavailable
- 蓝绿发布、金丝雀发布、灰度发布
- HPA、VPA、Cluster Autoscaler
- PodDisruptionBudget
- 多副本服务如何保证高可用
- 如何优雅停机
- 第六轮:故障排查
- Pod 一直 Pending 怎么排查
- Pod CrashLoopBackOff 怎么排查
- ImagePullBackOff 怎么排查
- Service 访问不通怎么排查
- Ingress 访问 502/504 怎么排查
- 节点 NotReady 怎么排查
- CPU/内存飙高怎么定位
- 常用 kubectl 命令
- 第七轮:架构与生产实践
- K8s 中如何部署 Java 微服务
- 网关、服务发现、配置中心如何落地
- K8s 和 Spring Cloud 的关系
- 日志、监控、链路追踪方案
- 权限 RBAC
- 多环境、多集群、命名空间隔离
- K8s 生产环境最佳实践
Answer Format
每一轮输出保持统一:
- 面试结论:先给 30 秒答案。
- 底层机制:讲清楚组件怎么协作。
- 流程图:用文本图表示请求或资源流转。
- 常见追问:补充面试官可能继续问的问题。
- 标准表达:给一段可以直接用于面试的回答。
Test / Acceptance Criteria
完成后应覆盖:
- K8s 八股基础题
- Pod、Service、Ingress、调度、存储核心原理
- 生产发布和高可用实践
- 常见线上故障排查
- 高级后端/架构岗表达方式
Assumptions
默认面向 Java 后端 / 高级后端 / 架构岗。不绑定某个特定 K8s 小版本,回答以通用生产实践为主,避免陷入过细版本差异。
Implement plan
17:44
下面开始 第一轮:K8s 基础核心。这一轮先把 Kubernetes 的对象模型和整体架构讲清楚,后面调度、网络、存储、发布都是建立在这些概念上。
1. Kubernetes 是什么,解决什么问题?
面试结论:
Kubernetes 是一个容器编排平台,用来管理容器化应用的部署、调度、扩缩容、服务发现、故障自愈和滚动发布。它解决的是大规模容器应用“怎么部署、怎么运行、怎么发现、怎么恢复”的问题。
传统部署的问题:
1 | 手工部署困难 机器资源利用率低 服务扩缩容麻烦 实例挂了需要人工恢复 发布回滚复杂 服务地址变化后发现困难 |
K8s 解决:
1 | 自动调度:把 Pod 放到合适 Node 自动拉起:实例挂了自动重建 服务发现:Service 提供稳定访问入口 弹性扩缩容:按副本数或指标扩容 滚动发布:平滑升级和回滚 配置管理:ConfigMap / Secret 资源隔离:Namespace / ResourceQuota |
标准表达:
K8s 本质是一个声明式的容器编排系统。用户描述期望状态,比如我要 3 个副本,K8s 控制器不断把实际状态调整到期望状态。它不是简单运行 Docker,而是提供了调度、自愈、服务发现、发布、扩缩容等完整平台能力。
2. Master / Worker 架构
现在更准确叫:
1 | Control Plane:控制平面 Worker Node:工作节点 |
面试里很多人仍然说 Master/Worker,可以兼容回答。
整体架构:
1 | 用户 / kubectl / CI/CD | v kube-apiserver | v etcd <---- controller-manager | v scheduler | v Worker Node ├── kubelet ├── kube-proxy └── container runtime |
Control Plane 组件:
| 组件 | 作用 |
|---|---|
| kube-apiserver | K8s 统一入口,所有资源操作都经过它 |
| etcd | 保存集群状态和资源对象 |
| scheduler | 负责给未调度 Pod 选择 Node |
| controller-manager | 负责控制器逻辑,让实际状态接近期望状态 |
Worker Node 组件:
| 组件 | 作用 |
|---|---|
| kubelet | 节点代理,负责 Pod 生命周期管理 |
| kube-proxy | 维护 Service 转发规则 |
| container runtime | 真正运行容器,比如 containerd |
标准表达:
K8s 是典型的控制面和数据面分离。控制面负责资源声明、调度和状态协调;工作节点负责真正运行 Pod。apiserver 是入口,etcd 是状态存储,scheduler 做调度,controller-manager 做控制循环,kubelet 在节点上负责把 Pod 真正拉起来。
3. Pod 是什么?
面试结论:
Pod 是 K8s 中最小的调度和部署单位,一个 Pod 里可以包含一个或多个容器,这些容器共享网络命名空间和存储卷。
不要说“容器是 K8s 最小单位”,准确是:
1 | K8s 最小调度单位是 Pod 容器运行在 Pod 里面 |
Pod 内部特点:
1 | 共享 IP 共享端口空间 共享 Volume 生命周期绑定 |
图示:
1 | Pod ├── Container A ├── Container B ├── shared network namespace └── shared volume |
为什么不直接调度容器?
因为有些容器天然需要强绑定,比如业务容器 + sidecar 日志采集、业务容器 + service mesh proxy,它们需要部署在同一台机器、共享网络和生命周期。
标准表达:
Pod 是对一组紧密相关容器的封装。K8s 不直接调度单个容器,而是调度 Pod。一个 Pod 内的容器共享网络和存储,适合业务容器和 Sidecar 这种强耦合场景。
4. Node、Namespace、Label、Annotation
Node
Node 是 K8s 的工作节点,可以是物理机或虚拟机,Pod 最终运行在 Node 上。
1 | Cluster ├── Node 1 │ ├── Pod A │ └── Pod B └── Node 2 ├── Pod C └── Pod D |
Namespace
Namespace 是逻辑隔离空间,用于区分环境、团队或业务。
常见用法:
1 | dev test staging prod team-a team-b |
注意:
Namespace 不是强安全边界,真正权限隔离还要配合 RBAC、NetworkPolicy、ResourceQuota。
Label
Label 是资源标签,用于选择和分组资源。
例如:
1 | labels: app: order-service env: prod version: v1 |
Service 通过 Label 找 Pod:
1 | Service selector: app=order-service 匹配 Pod: app=order-service |
Annotation
Annotation 是资源注解,用来存储非选择性元数据。
常见用途:
1 | Ingress 配置 监控采集配置 发布信息 构建版本 运维备注 |
Label 和 Annotation 区别:
| 对比 | Label | Annotation |
|---|---|---|
| 是否用于选择 | 是 | 否 |
| 典型用途 | 筛选、分组、关联 | 存元数据、配置 |
| 是否参与 selector | 参与 | 不参与 |
标准表达:
Label 是给 K8s 控制器和 Service 用来选择资源的,Annotation 更偏扩展元数据。能用于筛选和关联的放 Label,说明性或组件扩展配置放 Annotation。
5. Deployment、ReplicaSet、StatefulSet、DaemonSet、Job
这几个是面试高频,核心是:不同工作负载类型解决不同部署场景。
Deployment
面试结论:
Deployment 用来部署无状态服务,支持副本管理、滚动更新和回滚,是最常用的工作负载对象。
典型场景:
1 | Java 微服务 Web 服务 API 服务 无状态业务应用 |
关系:
1 | Deployment | v ReplicaSet | v Pod 副本 |
Deployment 负责:
1 | 声明副本数 滚动更新 版本回滚 维护 ReplicaSet |
ReplicaSet
面试结论:
ReplicaSet 负责保证指定数量的 Pod 副本一直存在,但通常不直接使用,而是由 Deployment 管理。
比如期望 3 个副本:
1 | 期望:3 实际:2 ReplicaSet 创建 1 个 期望:3 实际:4 ReplicaSet 删除 1 个 |
StatefulSet
面试结论:
StatefulSet 用于有状态服务,提供稳定的网络标识、稳定存储和有序部署/删除。
适合:
1 | MySQL Redis Cluster Kafka ZooKeeper Elasticsearch |
特点:
1 | Pod 名字稳定:mysql-0、mysql-1、mysql-2 网络身份稳定 PVC 稳定绑定 启动和删除有顺序 |
Deployment 的 Pod 名字通常随机:
1 | order-service-7d9c8f9d8c-x92ab |
StatefulSet 的 Pod 名字稳定:
1 | mysql-0 mysql-1 mysql-2 |
DaemonSet
面试结论:
DaemonSet 保证每个 Node 上运行一个 Pod,适合节点级 Agent。
典型场景:
1 | 日志采集:Fluent Bit / Filebeat 监控 Agent:Node Exporter 网络插件:CNI Agent 存储插件:CSI Node Plugin |
图示:
1 | Node 1 -> Agent Pod Node 2 -> Agent Pod Node 3 -> Agent Pod |
Job / CronJob
Job
Job 用于一次性任务,确保任务成功完成。
场景:
1 | 数据修复 批处理 一次性脚本 离线计算 |
CronJob
CronJob 用于定时任务,类似 Linux crontab。
场景:
1 | 每天凌晨生成报表 定时清理数据 周期性同步任务 |
标准表达:
Deployment 适合无状态服务,StatefulSet 适合有状态服务,DaemonSet 适合每个节点都要跑的 Agent,Job/CronJob 适合一次性或定时任务。ReplicaSet 是副本控制器,通常由 Deployment 间接管理。
6. Service 是什么?
面试结论:
Service 为一组 Pod 提供稳定访问入口和负载均衡。因为 Pod IP 会变化,不能让调用方直接依赖 Pod IP。
为什么需要 Service?
1 | Pod 会重建 Pod IP 会变化 副本数量会变化 调用方需要稳定入口 |
Service 通过 Label Selector 找 Pod:
1 | Service selector: app=order-service | v Pod A: app=order-service Pod B: app=order-service Pod C: app=order-service |
访问链路:
1 | Client | v Service ClusterIP | v Pod A / Pod B / Pod C |
Service 提供:
1 | 稳定虚拟 IP 服务发现 负载均衡 屏蔽 Pod 变化 |
标准表达:
Pod 是易变的,Service 是稳定的。Service 通过 selector 关联一组 Pod,对外提供固定访问地址,并把流量负载均衡到后端 Pod。
7. Ingress 是什么?
面试结论:
Ingress 是 K8s 中管理七层 HTTP/HTTPS 入口流量的资源对象,真正转发流量的是 Ingress Controller。
不要混:
1 | Ingress:规则 Ingress Controller:执行规则的组件 |
例如:
1 | api.example.com/order -> order-service api.example.com/user -> user-service |
链路:
1 | 外部用户 | v LoadBalancer / NodePort | v Ingress Controller | v Service | v Pod |
Ingress 能做:
1 | 域名路由 路径路由 HTTPS 证书 七层转发 部分灰度能力 |
常见 Ingress Controller:
1 | Nginx Ingress Controller Traefik HAProxy Ingress Kong APISIX Envoy Gateway |
标准表达:
Service 主要解决集群内部服务发现和四层访问,Ingress 解决 HTTP/HTTPS 七层入口路由。Ingress 只是声明规则,必须有 Ingress Controller 才能真正生效。
8. ConfigMap 和 Secret
ConfigMap
面试结论:
ConfigMap 用来管理非敏感配置,把配置和镜像解耦。
适合放:
1 | 配置文件 环境变量 开关参数 应用配置项 |
使用方式:
1 | 环境变量注入 |
Secret
面试结论:
Secret 用来保存敏感信息,比如密码、Token、证书,但默认只是 Base64 编码,不等于天然加密。
适合放:
1 | 数据库密码 API Token TLS 证书 镜像仓库凭证 |
重要提醒:
1 | Base64 不是加密 需要开启 etcd 加密 需要配合 RBAC 控制访问 生产环境可接 Vault / KMS |
ConfigMap vs Secret:
| 对比 | ConfigMap | Secret |
|---|---|---|
| 数据类型 | 普通配置 | 敏感配置 |
| 默认编码 | 明文 | Base64 |
| 典型内容 | application.yml | password/token/cert |
| 权限要求 | 普通 | 更严格 |
标准表达:
ConfigMap 管普通配置,Secret 管敏感配置。两者都能通过环境变量或 Volume 注入到 Pod,但 Secret 默认只是 Base64 编码,生产环境还要配合 RBAC、etcd 加密和外部密钥系统。
9. 第一轮总图
1 | Kubernetes Cluster | ├── Control Plane │ ├── kube-apiserver │ ├── etcd │ ├── scheduler │ └── controller-manager | └── Worker Nodes ├── kubelet ├── kube-proxy ├── container runtime └── Pods ├── Deployment 管理无状态 Pod ├── StatefulSet 管理有状态 Pod ├── DaemonSet 管理节点 Agent └── Job/CronJob 管理任务 |
访问关系:
1 | 外部用户 | v Ingress Controller | v Service | v Pod |
配置关系:
1 | ConfigMap / Secret | v Pod |
10. 面试官常见追问
1 | 1. Pod 和容器有什么区别? 2. Deployment 和 ReplicaSet 什么关系? 3. Deployment 和 StatefulSet 区别? 4. Service 为什么需要 selector? 5. Service 和 Ingress 区别? 6. ConfigMap 修改后 Pod 会自动更新吗? 7. Secret 是不是安全的? 8. DaemonSet 适合什么场景? 9. Namespace 能不能实现强隔离? 10. K8s 为什么是声明式系统? |
第一轮标准总结:
K8s 是声明式容器编排平台,核心是用户提交期望状态,控制器不断协调实际状态。Pod 是最小调度单位,Deployment 管无状态服务,StatefulSet 管有状态服务,DaemonSet 管节点级 Agent,Job/CronJob 管任务。Service 解决 Pod 易变带来的稳定访问问题,Ingress 解决 HTTP/HTTPS 七层入口流量。ConfigMap 和 Secret 用于配置解耦,但 Secret 生产上还要配合权限和加密机制。
下一轮继续讲:Pod 生命周期与调度:Pod 创建流程、apiserver/scheduler/controller/kubelet 分工、requests/limits、QoS、探针、重启策略。
17:45
继续讲
17:47
继续,下面是 第二轮:Pod 生命周期与调度。这一轮是 K8s 面试核心中的核心,很多故障排查题都绕不开它。
1. Pod 创建完整流程
面试结论:
Pod 创建不是 kubelet 直接启动容器,而是用户提交资源到 apiserver,控制器创建 Pod,scheduler 选择 Node,kubelet 监听到属于自己的 Pod 后,调用容器运行时拉镜像并启动容器。
流程图:
1 | kubectl / CI-CD | v kube-apiserver | v etcd 保存期望状态 | v controller-manager 创建 Pod | v scheduler 选择 Node | v kubelet 监听到 Pod | v container runtime 拉镜像、启动容器 | v Pod Running |
标准表达:
K8s 是声明式系统,用户提交的是期望状态。apiserver 负责接收请求并写入 etcd,controller 负责创建和维护资源,scheduler 负责给 Pod 绑定 Node,kubelet 在目标节点上真正执行容器启动。
2. 核心组件分工
| 组件 | 作用 |
|---|---|
| kube-apiserver | 集群统一入口,所有资源读写都经过它 |
| etcd | 存储集群状态 |
| controller-manager | 控制循环,确保实际状态接近期望状态 |
| scheduler | 给未绑定 Node 的 Pod 选择节点 |
| kubelet | 节点代理,负责 Pod 生命周期 |
| container runtime | 真正运行容器,如 containerd |
可以这样记:
1 | apiserver:入口 etcd:数据库 controller:调谐器 scheduler:调度员 kubelet:节点执行者 runtime:容器执行器 |
3. Scheduler 调度流程
面试结论:
调度分两步:先过滤掉不满足条件的节点,再对剩余节点打分,选择分数最高的 Node 绑定 Pod。
流程:
1 | 待调度 Pod | v Filter 过滤 | | 排除资源不足、亲和性不匹配、污点不可容忍的节点 v Score 打分 | | 根据资源均衡、亲和性、拓扑分布等评分 v Bind 绑定 | v Pod 被分配到某个 Node |
常见影响因素:
1 | CPU / Memory requests nodeSelector nodeAffinity / podAffinity / podAntiAffinity taints / tolerations PV 绑定关系 拓扑分布约束 |
标准表达:
Scheduler 不负责启动 Pod,它只负责选择节点并写回绑定结果。真正启动容器的是目标 Node 上的 kubelet。
4. requests 和 limits
面试结论:
requests 是调度依据,表示容器最少需要多少资源;limits 是运行时上限,表示容器最多能用多少资源。
| 配置 | 含义 | 影响 |
|---|---|---|
| requests.cpu | 最低 CPU 需求 | 影响调度 |
| requests.memory | 最低内存需求 | 影响调度 |
| limits.cpu | CPU 使用上限 | 超过会被限流 |
| limits.memory | 内存使用上限 | 超过可能 OOMKilled |
重点区别:
1 | CPU 超 limit:通常被 throttle,变慢 Memory 超 limit:可能被 OOMKilled,容器重启 |
例子:
1 | resources: requests: cpu: "500m" memory: "512Mi" limits: cpu: "1" memory: "1Gi" |
标准表达:
requests 决定 Pod 能不能被调度到某个节点,limits 决定容器运行时最多能使用多少资源。CPU 超限一般是被限速,内存超限更危险,可能直接被 OOMKilled。
5. QoS 分类
面试结论:
K8s 根据 requests 和 limits 把 Pod 分成 Guaranteed、Burstable、BestEffort 三类,节点资源紧张时,BestEffort 最容易被驱逐,Guaranteed 最稳定。
| QoS | 条件 | 稳定性 |
|---|---|---|
| Guaranteed | 每个容器 CPU/Memory 都设置 request=limit | 最高 |
| Burstable | 设置了部分 request/limit,但不完全相等 | 中等 |
| BestEffort | 没有设置 request/limit | 最低 |
驱逐优先级大致是:
1 | BestEffort -> Burstable -> Guaranteed |
标准表达:
生产服务一般不要裸跑 BestEffort,至少要设置 requests。核心服务可以考虑 Guaranteed,但资源利用率会低一些;大部分业务服务通常是 Burstable,在稳定性和资源利用率之间平衡。
6. 探针:liveness、readiness、startup
面试结论:
liveness 判断容器是否需要重启,readiness 判断 Pod 能不能接流量,startup 判断应用是否启动完成,避免慢启动应用被 liveness 误杀。
| 探针 | 作用 | 失败后果 |
|---|---|---|
| livenessProbe | 判断应用是否活着 | 失败会重启容器 |
| readinessProbe | 判断是否可以接流量 | 失败会从 Service Endpoints 摘除 |
| startupProbe | 判断启动是否完成 | 成功前禁用其他探针 |
典型链路:
1 | Pod 启动 | v startupProbe 通过 | v readinessProbe 通过 -> 加入 Service 流量 | v livenessProbe 持续检测 -> 失败则重启 |
标准表达:
readiness 影响流量,liveness 影响重启。不能用 liveness 代替 readiness,否则应用只是临时不可用也会被重启,反而扩大故障。
7. Pod 重启策略
Pod 的 restartPolicy 常见有:
1 | Always OnFailure Never |
不同工作负载常见选择:
1 | Deployment:通常 Always Job:通常 OnFailure 或 Never 普通长期服务:Always 一次性任务:OnFailure / Never |
常见状态:
1 | CrashLoopBackOff:容器反复启动失败 ImagePullBackOff:镜像拉取失败 Pending:还没调度或资源不满足 Running:Pod 已运行 Completed:任务执行完成 OOMKilled:内存超限被杀 |
标准表达:
Deployment 管理的是长期运行服务,所以容器异常退出会被持续拉起。Job 更关注任务是否成功完成,所以通常使用 OnFailure。
8. 常见追问
1 | 1. Pod Pending 一般是什么原因? 2. requests 和 limits 哪个影响调度? 3. CPU 超限和内存超限有什么区别? 4. readiness 和 liveness 区别? 5. 为什么需要 startupProbe? 6. Scheduler 会不会启动容器? 7. OOMKilled 是谁杀的? 8. QoS 有什么用? |
第二轮总结:
Pod 从创建到运行,核心链路是 apiserver 接收声明、etcd 保存状态、controller 创建资源、scheduler 选择节点、kubelet 启动容器。调度主要看 requests、节点资源、亲和性、污点容忍等条件。生产中必须合理配置 requests/limits 和探针,readiness 控制接流量,liveness 控制重启,startup 保护慢启动应用。资源配置还会影响 QoS,进而影响节点压力下的驱逐优先级。
下一轮讲 K8s 网络:Service 类型、kube-proxy、Pod 间通信、Ingress、CNI、CoreDNS。
17:47
继续回答
17:52
继续,下面是 第三轮:K8s 网络。这一轮非常高频,而且是 K8s 里最容易“懂概念但讲不透”的部分。抓住三条线就稳:Pod 怎么通信、Service 怎么转发、Ingress 怎么进来。
1. K8s 网络模型
面试结论:
Kubernetes 网络模型要求每个 Pod 都有独立 IP,Pod 之间默认可以直接通信,不需要 NAT。真正实现这个网络模型的是 CNI 网络插件。
K8s 网络基本原则:
1 | 1. 每个 Pod 有自己的 IP |
图示:
1 | Node 1 Node 2 |
注意:
K8s 定义网络模型,CNI 插件负责实现,比如 Flannel、Calico、Cilium。
标准表达:
K8s 自身不直接实现 Pod 网络,而是定义了 Pod 间可达的网络模型,具体由 CNI 插件实现。Service 解决的是 Pod IP 变化和多副本负载均衡问题。
2. CNI 是什么?
面试结论:
CNI 是容器网络接口规范,K8s 通过 CNI 插件为 Pod 分配 IP、创建网络设备、配置路由和网络策略。
Pod 创建时网络大致流程:
1 | kubelet 创建 Pod Sandbox |
常见 CNI:
1 | Flannel:简单,常用 VXLAN Calico:支持 BGP 和 NetworkPolicy Cilium:基于 eBPF,性能和可观测性强 Weave:较早的容器网络方案 |
标准表达:
CNI 负责让 Pod 接入集群网络。K8s 通过 kubelet 调用 CNI 插件,完成 IP 分配、网卡创建和路由配置。不同 CNI 的差异主要在跨节点通信方式、网络策略和性能能力上。
3. Pod 间通信
同一个 Pod 内容器通信
同一个 Pod 内多个容器共享网络命名空间:
1 | Container A -> localhost -> Container B |
图示:
1 | Pod ├── Container A : localhost:8080 └── Container B : localhost:9000 |
同 Node 不同 Pod 通信
通常通过 veth pair 和 Linux bridge 或 eBPF 转发:
1 | Pod A | veth | bridge / eBPF | veth | Pod B |
跨 Node Pod 通信
由 CNI 实现,常见方式:
1 | VXLAN 隧道 BGP 路由 云厂商 VPC 路由 eBPF 转发 |
图示:
1 | Pod A | Node 1 | CNI 网络 | Node 2 | Pod B |
标准表达:
同 Pod 容器通过 localhost 通信;同节点 Pod 通常通过 veth 和 bridge/eBPF 通信;跨节点 Pod 通信由 CNI 插件通过隧道、路由或 eBPF 实现。
4. Service 是什么?为什么需要?
面试结论:
Service 给一组动态变化的 Pod 提供稳定访问入口和负载均衡。因为 Pod 会重建,Pod IP 不稳定,调用方不能直接依赖 Pod IP。
Service 通过 selector 选择 Pod:
1 | selector: app: order-service |
匹配:
1 | Pod A app=order-service Pod B app=order-service Pod C app=order-service |
访问链路:
1 | Client | v Service ClusterIP | v Pod A / Pod B / Pod C |
Service 后端实际由 EndpointSlice 维护:
1 | Service | v EndpointSlice | v Pod IP 列表 |
标准表达:
Service 是一层稳定抽象,屏蔽了 Pod IP 和副本变化。调用方访问 Service,K8s 根据后端 Endpoints 把流量转发到真实 Pod。
5. Service 四种类型
ClusterIP
面试结论:
ClusterIP 是默认类型,只能在集群内部访问。
1 | Pod -> ClusterIP Service -> Pod |
适合:
1 | 微服务内部调用 内部数据库代理 内部缓存服务 |
NodePort
面试结论:
NodePort 会在每个 Node 上开放一个端口,外部可以通过 NodeIP:NodePort 访问服务。
1 | 外部用户 -> NodeIP:NodePort -> Service -> Pod |
缺点:
1 | 端口范围有限 暴露方式粗糙 生产通常不直接给用户用 |
LoadBalancer
面试结论:
LoadBalancer 通常依赖云厂商负载均衡,为 Service 创建外部 LB。
1 | 外部用户 -> 云 LB -> Node/Pod -> Service -> Pod |
适合:
1 | 云上服务对外暴露 |
ExternalName
面试结论:
ExternalName 把 Service 映射到外部 DNS 名称,不创建 ClusterIP。
例如:
1 | mysql-external.default.svc.cluster.local -> mysql.company.com |
适合:
1 | 集群内用 Service 名访问外部服务 |
标准表达:
ClusterIP 用于集群内部访问,NodePort 把服务暴露到节点端口,LoadBalancer 依赖云 LB 对外暴露,ExternalName 用 DNS 别名指向外部服务。
6. kube-proxy 原理:iptables / IPVS
面试结论:
kube-proxy 负责在节点上维护 Service 转发规则,把访问 Service VIP 的流量转发到后端 Pod。实现模式常见有 iptables 和 IPVS。
iptables 模式
特点:
1 | 基于 iptables 规则做 DNAT 规则多时维护和匹配成本较高 随机负载均衡 |
链路:
1 | 访问 ClusterIP:Port | v iptables 规则匹配 | v DNAT 到某个 PodIP:Port |
IPVS 模式
特点:
1 | 基于 Linux IPVS 适合大规模 Service 支持更多负载均衡算法 性能更稳定 |
算法:
1 | rr:轮询 lc:最少连接 sh:源地址哈希 |
链路:
1 | 访问 ClusterIP | v IPVS 虚拟服务 | v 真实 Pod 后端 |
标准表达:
kube-proxy 不直接转发每个包,而是在每个节点维护内核转发规则。iptables 模式通过 DNAT 实现,IPVS 模式通过内核 LVS 能力实现,规模大时 IPVS 通常更稳定。
7. Service 负载均衡流程
假设访问:
1 | order-service.default.svc.cluster.local |
流程:
1 | 1. CoreDNS 解析 Service DNS 到 ClusterIP |
图示:
1 | Client Pod |
注意:
ClusterIP 是虚拟 IP,不是真实绑定在某个 Pod 上。
标准表达:
Service 的访问通常先经过 DNS 解析拿到 ClusterIP,然后由节点上的 kube-proxy 规则把流量转发到后端 Pod。真正承载请求的是 Pod,不是 ClusterIP 本身。
8. Ingress 和 Ingress Controller
面试结论:
Ingress 是七层入口规则,Ingress Controller 是真正实现规则的网关组件。没有 Controller,Ingress 资源本身不会转发流量。
例子:
1 | api.example.com/order -> order-service api.example.com/user -> user-service |
链路:
1 | 外部用户 | v LB / NodePort | v Ingress Controller | v Service | v Pod |
Ingress 能力:
1 | 域名路由 路径路由 TLS 终止 HTTP header 路由 部分灰度发布 |
常见 Controller:
1 | Nginx Ingress Traefik Kong APISIX Envoy |
Service 和 Ingress 区别:
| 对比 | Service | Ingress |
|---|---|---|
| 层级 | 四层为主 | 七层 HTTP/HTTPS |
| 作用 | 集群内服务发现和负载均衡 | 外部 HTTP 入口 |
| 路由能力 | 基于端口 | 基于域名、路径、Header |
| 是否需 Controller | kube-proxy 支撑 | 需要 Ingress Controller |
标准表达:
Service 解决服务稳定访问,Ingress 解决外部 HTTP 流量怎么进入集群。Ingress 是规则,Ingress Controller 才是执行者。
9. CoreDNS 解析流程
面试结论:
CoreDNS 是 K8s 集群内的 DNS 服务,负责把 Service 名称解析成 ClusterIP,把 Headless Service 解析成 Pod IP。
常见域名:
1 | service.namespace.svc.cluster.local |
例如:
1 | order-service.default.svc.cluster.local |
简写访问:
1 | order-service order-service.default |
解析流程:
1 | Pod 访问 order-service | v Pod 内 /etc/resolv.conf 指向 CoreDNS | v CoreDNS 查询 K8s API | v 返回 Service ClusterIP |
图示:
1 | Pod | | DNS query v CoreDNS | | watch Service / EndpointSlice v 返回 ClusterIP 或 Pod IP |
Headless Service:
1 | clusterIP: None |
解析结果:
1 | 普通 Service -> ClusterIP Headless Service -> 后端 Pod IP 列表 |
适合:
1 | StatefulSet 数据库集群 需要直接访问具体 Pod 的场景 |
标准表达:
CoreDNS 通过监听 K8s Service 和 Endpoint 信息,为集群内服务提供 DNS 解析。普通 Service 解析到 ClusterIP,Headless Service 直接解析到 Pod IP,常用于 StatefulSet。
10. NetworkPolicy 是什么?
面试结论:
NetworkPolicy 是 K8s 的网络访问控制策略,用来限制 Pod 之间或 Pod 与外部之间的流量。
默认情况下:
1 | Pod 之间通常互通 |
加 NetworkPolicy 后可以限制:
1 | 哪些 Pod 可以访问我 我可以访问哪些 Pod 允许哪些端口 |
注意:
NetworkPolicy 需要 CNI 插件支持,比如 Calico、Cilium。不是所有 CNI 都完整支持。
典型场景:
1 | 只允许 gateway 访问业务服务 只允许业务服务访问数据库 不同 namespace 之间隔离 |
标准表达:
K8s 默认网络比较开放,NetworkPolicy 用于做东西向流量隔离。但它依赖 CNI 实现,生产上需要确认网络插件是否支持。
11. 常见追问
1 | 1. Pod IP 和 Service IP 有什么区别? 2. ClusterIP 是真实 IP 吗? 3. kube-proxy 是不是转发所有流量? 4. iptables 和 IPVS 模式区别? 5. Ingress 和 Service 区别? 6. 为什么有了 Service 还需要 Ingress? 7. CoreDNS 怎么解析 Service? 8. Headless Service 有什么用? 9. CNI 负责什么? 10. NetworkPolicy 为什么不生效? |
第三轮总结:
K8s 网络可以分三层理解:Pod 网络由 CNI 实现,保证 Pod 间可通信;Service 通过 ClusterIP 和 kube-proxy 为动态 Pod 提供稳定访问和负载均衡;Ingress 通过 Ingress Controller 管理外部 HTTP/HTTPS 入口。CoreDNS 提供服务名解析,NetworkPolicy 提供网络隔离能力。面试时要特别强调:Ingress 是规则,Controller 才执行;Service IP 是虚拟入口,真实流量最终到 Pod。
下一轮讲 存储与配置:Volume、PV/PVC/StorageClass、StatefulSet 稳定存储、ConfigMap/Secret、数据库是否适合跑在 K8s。
17:52
继续回答
18:01
继续,下面是 第四轮:K8s 存储与配置。这一轮的关键是讲清楚:Pod 是短暂的,数据和配置要独立出来。K8s 里很多存储题,都是围绕这句话展开的。
1. Volume 是什么?
面试结论:
Volume 是 Pod 级别的存储抽象,用来让容器共享数据或持久化数据。它的生命周期通常和 Pod 绑定,但具体是否持久取决于 Volume 类型。
为什么需要 Volume?
1 | 容器文件系统是临时的 容器重启可能丢数据 同一个 Pod 内多个容器需要共享文件 配置、证书、日志等需要挂载进容器 |
常见 Volume 类型:
1 | emptyDir hostPath configMap secret persistentVolumeClaim |
emptyDir
1 | Pod 创建时创建 Pod 删除时删除 Pod 内容器可共享 |
适合:
1 | 临时缓存 中间文件 sidecar 共享目录 |
hostPath
1 | 挂载宿主机目录 |
风险:
1 | 和节点强绑定 安全风险高 可移植性差 |
生产要慎用。它像一根直通宿主机的小管子,方便,但也容易把边界捅穿。
标准表达:
Volume 是 Pod 对存储的抽象,解决容器文件临时性和多容器共享问题。但普通 Volume 不一定持久,真正的持久化通常要用 PV/PVC。
2. PV、PVC、StorageClass
面试结论:
PV 是集群里的存储资源,PVC 是用户对存储资源的申请,StorageClass 定义动态创建存储的类型和参数。
三者关系:
1 | Pod -> PVC -> PV -> 真实存储 |
图示:
1 | Pod | | 挂载 v PVC:我要 20Gi,可读写 | | 绑定 v PV:实际存储卷 | v 云盘 / NFS / Ceph / NAS / 本地盘 |
PV
PersistentVolume,集群级存储资源。
包含:
1 | 容量 访问模式 回收策略 存储后端 |
PVC
PersistentVolumeClaim,用户对存储的声明。
比如:
1 | 我要 20Gi 我要 ReadWriteOnce 我要 fast-ssd 类型 |
StorageClass
定义动态供给存储的模板。
例如:
1 | 使用 SSD 使用某个云盘类型 删除 PVC 后是否删除真实云盘 文件系统类型 |
标准表达:
PV 是实际存储资源,PVC 是应用对存储的申请,StorageClass 负责动态创建 PV。这样应用不需要关心底层是云盘、NFS 还是 Ceph,只声明自己需要什么容量和访问模式。
3. 静态供给和动态供给
静态供给
管理员提前创建 PV:
1 | 管理员创建 PV 用户创建 PVC PVC 匹配并绑定 PV Pod 使用 PVC |
适合:
1 | 固定存储资源 手工管理存储 特殊存储后端 |
动态供给
用户只创建 PVC,K8s 根据 StorageClass 自动创建 PV:
1 | 用户创建 PVC StorageClass 调用 provisioner 自动创建真实存储和 PV PVC 绑定 PV Pod 使用 PVC |
图示:
1 | PVC | | 指定 storageClassName v StorageClass | v CSI Provisioner | v 自动创建云盘 / 存储卷 |
标准表达:
静态供给是管理员先准备 PV,动态供给是用户提交 PVC 后由 StorageClass 和 CSI 自动创建 PV。生产上云环境更常用动态供给,运维成本低。
4. 访问模式 AccessModes
常见访问模式:
1 | ReadWriteOnce,RWO ReadOnlyMany,ROX ReadWriteMany,RWX |
含义:
| 模式 | 含义 | 常见存储 |
|---|---|---|
| RWO | 单节点读写 | 云盘、块存储 |
| ROX | 多节点只读 | 共享存储 |
| RWX | 多节点读写 | NFS、CephFS、NAS |
注意:
RWO 不是只能被一个 Pod 挂载,而是通常只能被一个 Node 以读写方式挂载。
面试标准表达:
多副本应用如果多个 Pod 分布在不同 Node,并且都要读写同一份数据,不能随便用普通云盘 RWO,需要 RWX 类型存储,或者从架构上避免多个副本共享写同一块盘。
5. 回收策略 ReclaimPolicy
PV 回收策略:
1 | Retain |
Retain
1 | PVC 删除后,PV 和真实数据保留 需要人工处理 |
适合:
1 | 重要数据 数据库数据 防止误删 |
Delete
1 | PVC 删除后,PV 和底层存储一起删除 |
适合:
1 | 临时环境 可重建数据 自动化资源管理 |
标准表达:
生产核心数据通常更谨慎,使用 Retain 或配套快照备份;临时环境可以使用 Delete 降低清理成本。
6. StatefulSet 稳定身份和稳定存储
面试结论:
StatefulSet 适合有状态服务,因为它提供稳定 Pod 名称、稳定网络身份、稳定 PVC,并按顺序创建和删除 Pod。
Deployment 的 Pod:
1 | order-service-7f9d88c4c-xa12p order-service-7f9d88c4c-kp82m |
名字随机,重建会变。
StatefulSet 的 Pod:
1 | mysql-0 mysql-1 mysql-2 |
名字稳定。
配合 Headless Service:
1 | mysql-0.mysql.default.svc.cluster.local mysql-1.mysql.default.svc.cluster.local mysql-2.mysql.default.svc.cluster.local |
PVC 也稳定:
1 | data-mysql-0 data-mysql-1 data-mysql-2 |
图示:
1 | mysql-0 -> pvc-data-mysql-0 mysql-1 -> pvc-data-mysql-1 mysql-2 -> pvc-data-mysql-2 |
Pod 重建后:
1 | mysql-0 仍然挂回 pvc-data-mysql-0 |
标准表达:
StatefulSet 的关键不是“能跑数据库”这么简单,而是它保证每个副本有稳定身份和稳定存储。Pod 重建后名字不变、DNS 不变、PVC 也不变,这对主从复制、集群成员发现很重要。
7. ConfigMap 和 Secret 区别
面试结论:
ConfigMap 存普通配置,Secret 存敏感配置。两者都可以通过环境变量或 Volume 挂载到 Pod,但 Secret 默认只是 Base64 编码,不等于加密。
对比:
| 项目 | ConfigMap | Secret |
|---|---|---|
| 内容 | 普通配置 | 密码、Token、证书 |
| 安全性 | 普通 | 更敏感 |
| 默认存储 | 明文 | Base64 |
| 使用方式 | env / volume | env / volume |
| 典型例子 | application.yml | DB password |
使用方式:
1 | 1. 环境变量 2. 挂载成文件 3. 命令行参数 |
重要区别:
1 | 环境变量注入:ConfigMap 更新后,容器内环境变量不会自动更新 Volume 挂载:ConfigMap 更新后,文件内容可自动更新,但应用不一定自动 reload |
标准表达:
ConfigMap/Secret 解决镜像和配置解耦,但更新配置不等于应用自动生效。很多 Java 应用仍然需要重启或接入动态配置中心。
8. Secret 安全注意点
面试容易被问:“Secret 安全吗?”
标准答案别说“安全”,要说“相对管理敏感信息,但默认不够”。
Secret 默认问题:
1 | 1. Base64 只是编码,不是加密 2. 有权限读取 Secret 的人可以解码 3. 如果 etcd 未加密,Secret 可能明文落盘 4. 环境变量形式可能被进程信息或日志暴露 |
生产建议:
1 | 1. 开启 etcd encryption at rest 2. 使用 RBAC 限制 Secret 访问 3. 使用 namespace 隔离 4. 避免把 Secret 打进镜像 5. 避免日志打印敏感信息 6. 对接 Vault / KMS / External Secrets 7. 证书和密码定期轮换 |
标准表达:
K8s Secret 是敏感配置管理对象,但默认 Base64 不等于加密。生产环境要配合 RBAC、etcd 静态加密、外部 KMS/Vault 和密钥轮换,才能算比较完整的安全方案。
9. 数据库适不适合跑在 K8s?
这是架构岗高频场景题。
面试结论:
数据库可以跑在 K8s,但要谨慎。无状态服务天然适合 K8s,有状态数据库对存储、网络、故障恢复、备份和运维能力要求更高。生产中核心数据库是否上 K8s,要看团队的存储和运维成熟度。
适合的情况:
1 | 测试环境数据库 开发环境数据库 中间件集群 云原生数据库 Operator 成熟 团队有存储和备份能力 |
不适合贸然上的情况:
1 | 核心交易数据库 强一致和低延迟要求高 存储插件不成熟 没有备份恢复演练 团队缺乏 K8s 有状态服务经验 |
如果要跑,需要重点考虑:
1 | 1. StatefulSet 稳定身份 2. 高性能持久化存储 3. 数据备份和恢复 4. 主从切换 5. 反亲和性,避免副本同节点 6. PDB,避免维护时同时驱逐 7. 资源隔离 8. 监控告警 9. Operator 自动化运维 |
标准表达:
K8s 可以承载数据库,但数据库不是只要 StatefulSet 加 PVC 就万事大吉。真正难点在数据安全、存储性能、故障恢复、备份、主从切换和运维自动化。如果团队没有成熟 Operator 和存储能力,核心数据库更建议使用云数据库或专门数据库集群。
10. 常见追问
1 | 1. Volume 和 PV/PVC 区别? 2. PVC 一直 Pending 是什么原因? 3. StorageClass 有什么作用? 4. RWO、ROX、RWX 区别? 5. StatefulSet 为什么适合有状态服务? 6. Headless Service 和 StatefulSet 什么关系? 7. ConfigMap 更新后应用会自动生效吗? 8. Secret 是不是加密的? 9. hostPath 为什么生产慎用? 10. 数据库能不能跑在 K8s? |
第四轮总结:
K8s 中 Pod 是易变的,所以数据和配置不能依赖容器本地文件系统。临时数据可以用 emptyDir,持久数据要通过 PVC 绑定 PV,动态存储由 StorageClass 和 CSI 提供。StatefulSet 通过稳定名称、稳定网络身份和稳定 PVC 支撑有状态服务。ConfigMap 管普通配置,Secret 管敏感配置,但生产 Secret 还要配合 RBAC、etcd 加密和外部密钥系统。数据库可以跑在 K8s,但核心数据库要看存储、备份、故障恢复和运维能力是否成熟。
下一轮讲 发布、扩缩容与高可用:Deployment 滚动更新、maxSurge/maxUnavailable、蓝绿/金丝雀/HPA/PDB/优雅停机。
18:01
继续回答
18:21
继续,下面是 第五轮:K8s 发布、扩缩容与高可用。这一轮偏生产实践,面试里很容易从“Deployment 怎么更新”一路追到“怎么做到不停机发布”。
1. Deployment 滚动更新
面试结论:
Deployment 默认使用滚动更新,通过创建新的 ReplicaSet、逐步增加新 Pod、逐步减少旧 Pod,实现应用平滑升级和可回滚。
流程:
1 | Deployment v1 | | 修改镜像版本 v 创建 ReplicaSet v2 | | 新 Pod Ready 后 v 逐步减少 ReplicaSet v1 Pod | v 全部切到 v2 |
常用命令:
1 | kubectl rollout status deployment/order-service kubectl rollout history deployment/order-service kubectl rollout undo deployment/order-service |
标准表达:
Deployment 不直接替换 Pod,而是通过新旧 ReplicaSet 的副本数变化完成滚动更新。新版本异常时,可以回滚到历史 ReplicaSet。
2. maxSurge 和 maxUnavailable
面试结论:
maxSurge 控制更新过程中最多额外创建多少 Pod,maxUnavailable 控制最多允许多少 Pod 不可用。它们共同决定发布速度和可用性。
例子:
1 | strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 0 |
假设期望副本数是 3:
1 | maxSurge=1:更新时最多可以有 4 个 Pod maxUnavailable=0:更新过程中至少保证 3 个可用 |
更安全:
1 | maxSurge: 1 maxUnavailable: 0 |
更快但风险更高:
1 | maxSurge: 50% maxUnavailable: 50% |
标准表达:
核心服务发布时我一般倾向于 maxUnavailable=0,保证更新期间可用副本不减少;maxSurge 允许临时多起一些新 Pod,用资源换平滑发布。
3. 蓝绿发布、金丝雀发布、灰度发布
蓝绿发布
同时维护蓝、绿两套环境,一套对外服务,一套准备新版本,验证通过后一次性切流。
1 | 用户流量 -> Blue v1 Green v2 部署完成 验证通过 用户流量 -> Green v2 |
优点:
1 | 切换快 回滚快 环境隔离清晰 |
缺点:
1 | 资源成本高 一次性切流风险较大 |
金丝雀发布
先让少量流量进入新版本,观察稳定后逐步扩大比例。
1 | 95% -> v1 5% -> v2 80% -> v1 20% -> v2 0% -> v1 100%-> v2 |
实现方式:
1 | Ingress 权重 Service Mesh:Istio/Linkerd 网关灰度规则 两个 Deployment 按副本比例粗粒度分流 |
灰度发布
按用户、地域、Header、Cookie、租户等规则让特定流量进入新版本。
例子:
1 | 内部用户 -> v2 北京用户 -> v2 Header version=beta -> v2 普通用户 -> v1 |
标准表达:
蓝绿强调两套环境快速切换,金丝雀强调按流量比例逐步放量,灰度强调按用户或规则定向放量。生产中更推荐网关或 Service Mesh 做精细流量治理。
4. HPA、VPA、Cluster Autoscaler
HPA:Horizontal Pod Autoscaler
HPA 横向扩缩 Pod 副本数,适合根据 CPU、内存或自定义指标扩容。
1 | CPU 升高 | v HPA 增加 Pod 副本 |
常见指标:
1 | CPU 利用率 内存利用率 QPS 队列堆积 自定义业务指标 |
注意:
1 | HPA 基于 CPU 时,Pod 必须设置 requests.cpu |
VPA:Vertical Pod Autoscaler
VPA 纵向调整 Pod 的 requests/limits,适合给应用推荐或自动调整资源规格。
注意:
1 | VPA 自动调整通常会重建 Pod |
Cluster Autoscaler
Cluster Autoscaler 扩缩 Node。当 Pod 因资源不足 Pending 时扩容节点;节点长期空闲时缩容。
1 | Pod Pending |
标准表达:
HPA 扩 Pod,VPA 调单个 Pod 资源规格,Cluster Autoscaler 扩 Node。线上常见组合是 HPA + Cluster Autoscaler:业务压力上来先扩 Pod,节点不够再扩机器。
5. PodDisruptionBudget,PDB
面试结论:
PDB 用来限制自愿中断时最多可以同时不可用多少 Pod,防止节点维护、升级、驱逐时把服务副本一次性赶下线。
例子:
1 | apiVersion: policy/v1 kind: PodDisruptionBudget spec: minAvailable: 2 selector: matchLabels: app: order-service |
含义:
1 | order-service 至少保持 2 个 Pod 可用 |
PDB 能管:
1 | kubectl drain 节点维护 集群升级 主动驱逐 |
PDB 管不了:
1 | 节点宕机 机器断电 Pod 自己崩溃 OOMKilled |
标准表达:
PDB 不是高可用的全部,它只能约束自愿中断。真正的高可用还要靠多副本、跨节点分布、探针、资源配置和故障恢复。
6. 多副本服务如何保证高可用?
面试结论:
多副本只是高可用的基础,不等于天然高可用。还要保证副本分散、流量只打到 Ready Pod、发布不中断、节点故障可恢复。
关键手段:
1 | 1. Deployment 多副本 2. readinessProbe 控制是否接流量 3. livenessProbe 异常自愈 4. Pod 反亲和 / topologySpreadConstraints 5. PDB 防止维护时同时驱逐 6. requests/limits 保证调度和隔离 7. HPA 应对流量波动 8. 多可用区部署 |
副本分散示意:
1 | Node A -> order Pod 1 Node B -> order Pod 2 Node C -> order Pod 3 |
不要变成:
1 | Node A -> order Pod 1 / 2 / 3 Node B -> 空 Node C -> 空 |
标准表达:
高可用不是把 replicas 设成 3 就结束了,还要保证 Pod 跨节点甚至跨可用区分布,并且通过 readiness、PDB 和滚动更新策略保证发布和维护期间服务可用。
7. 如何优雅停机?
面试结论:
优雅停机的核心是:先从流量入口摘除,再停止接收新请求,最后等待存量请求处理完成后退出。
K8s 删除 Pod 流程:
1 | 1. Pod 被标记 Terminating 2. readiness 变为不可用,Service 不再转发新流量 3. 执行 preStop hook 4. kubelet 向容器发送 SIGTERM 5. 应用开始优雅关闭 6. 等待 terminationGracePeriodSeconds 7. 超时后 SIGKILL 强杀 |
建议配置:
1 | terminationGracePeriodSeconds: 60 lifecycle: preStop: exec: command: ["sh", "-c", "sleep 10"] |
Java 服务要做:
1 | 收到 SIGTERM 后停止接收新请求 等待线程池任务完成 关闭 HTTP server 关闭 MQ consumer 关闭 DB/Redis 连接池 提交或回滚事务 |
Spring Boot 可以配:
1 | server: shutdown: graceful spring: lifecycle: timeout-per-shutdown-phase: 30s |
标准表达:
优雅停机不能只依赖 K8s,应用本身也要处理 SIGTERM。readiness 负责摘流,preStop 给网关和 Endpoints 更新留缓冲,应用负责处理完存量请求再退出。
8. 常见追问
1 | 1. Deployment 滚动更新底层怎么做? 2. maxSurge 和 maxUnavailable 怎么配置? 3. 蓝绿和金丝雀区别? 4. HPA 扩容依据是什么? 5. HPA 和 Cluster Autoscaler 谁先触发? 6. VPA 为什么可能导致 Pod 重启? 7. PDB 能不能防止节点宕机? 8. replicas=3 是否一定高可用? 9. 如何做到 Java 服务不停机发布? 10. readiness 和优雅停机有什么关系? |
第五轮总结:
K8s 发布和高可用的核心是“控制变化”。Deployment 通过新旧 ReplicaSet 做滚动更新,maxSurge/maxUnavailable 控制发布过程中的容量和可用性。HPA 扩 Pod,Cluster Autoscaler 扩 Node,PDB 约束自愿中断。真正的高可用不仅是多副本,还包括跨节点分布、探针、资源隔离、优雅停机和灰度发布能力。生产 Java 服务要特别重视 readiness 摘流和 SIGTERM 优雅关闭,否则滚动更新也可能造成请求失败。
下一轮讲 K8s 故障排查:Pending、CrashLoopBackOff、ImagePullBackOff、Service 不通、Ingress 502/504、Node NotReady 和常用 kubectl 命令。
18:21
继续回答
20:27
继续,下面是 第六轮:K8s 故障排查。这一轮非常实战,面试官会特别看你是不是只会背对象,还是能真正把线上问题拆开定位。
1. 排查总思路
面试结论:
K8s 故障排查要按资源链路分层看:Pod 状态、事件、日志、资源、网络、Service/Endpoint、Ingress、Node。先看 describe 和 events,再看 logs 和指标。
常用顺序:
1 | kubectl get kubectl describe kubectl logs kubectl exec kubectl get events kubectl top |
基本命令:
1 | kubectl get pod -n <ns> -o wide |
标准表达:
我排查 K8s 问题一般先看 Pod 当前状态和事件,判断是调度、镜像、启动、运行还是探针问题;再看日志和资源指标;如果是访问问题,再看 Service、Endpoints、Ingress 和网络策略。
2. Pod 一直 Pending 怎么排查?
面试结论:
Pod Pending 表示还没有成功调度或启动,常见原因是资源不足、调度约束不满足、PVC 未绑定、节点污点不可容忍。
排查命令:
1 | kubectl describe pod <pod> -n <ns> |
常见原因:
1 | 1. CPU / Memory requests 太大,节点资源不足 2. nodeSelector / nodeAffinity 匹配不到节点 3. taints 没有对应 tolerations 4. PVC Pending,存储没有绑定 5. 节点 NotReady 6. 配额 ResourceQuota 不足 |
典型事件:
1 | 0/5 nodes are available: insufficient cpu 0/5 nodes are available: node(s) had taint pod has unbound immediate PersistentVolumeClaims |
标准表达:
Pending 先看 describe 里的 Events。调度失败通常会明确告诉你是资源不足、污点、亲和性还是 PVC 未绑定。不要先看业务日志,因为 Pod 可能根本没启动。
3. CrashLoopBackOff 怎么排查?
面试结论:
CrashLoopBackOff 表示容器启动后反复崩溃,K8s 正在退避重启。重点看容器日志、上一次日志、退出码、探针和配置。
排查命令:
1 | kubectl logs <pod> -n <ns> kubectl logs <pod> -n <ns> --previous kubectl describe pod <pod> -n <ns> |
常见原因:
1 | 1. 应用启动异常 2. 配置文件错误 3. 环境变量缺失 4. 端口冲突 5. 依赖服务不可用 6. livenessProbe 配置错误导致反复杀容器 7. JVM 参数或内存配置不合理 |
看退出码:
1 | Exit Code 1:应用异常退出 Exit Code 137:通常是被 SIGKILL,常见 OOMKilled Exit Code 143:收到 SIGTERM,正常终止或被终止 |
Java 常见:
1 | 配置中心连不上 数据库连不上启动失败 内存太小导致 OOM 启动慢被 livenessProbe 杀掉 |
标准表达:
CrashLoopBackOff 要看 previous logs,因为当前容器可能已经重启了。还要看 describe 里的 Last State 和 Exit Code,判断是应用异常、OOMKilled 还是探针误杀。
4. ImagePullBackOff 怎么排查?
面试结论:
ImagePullBackOff 表示镜像拉取失败,常见原因是镜像地址错误、tag 不存在、仓库权限不足、网络不通或镜像仓库限流。
排查命令:
1 | kubectl describe pod <pod> -n <ns> |
常见事件:
1 | ErrImagePull ImagePullBackOff manifest unknown unauthorized i/o timeout |
原因对应:
1 | manifest unknown:镜像 tag 不存在 unauthorized:镜像仓库认证失败 i/o timeout:网络或仓库不可达 not found:镜像路径错误 |
解决:
1 | 1. 确认 image 地址和 tag 2. 确认 imagePullSecret 3. 确认节点能访问镜像仓库 4. 检查私有仓库账号权限 5. 检查镜像是否推送成功 |
标准表达:
ImagePullBackOff 基本看 describe 事件就能定位大方向。tag 不存在、认证失败、网络超时的错误信息很直观,优先从镜像名、tag、imagePullSecret 和节点网络查。
5. OOMKilled 怎么排查?
面试结论:
OOMKilled 表示容器内存超过 limit,被内核或 kubelet 杀掉。排查重点是内存 limit、应用内存曲线、JVM 参数和是否有内存泄漏。
排查命令:
1 | kubectl describe pod <pod> -n <ns> kubectl top pod <pod> -n <ns> kubectl logs <pod> -n <ns> --previous |
看状态:
1 | Last State: Terminated Reason: OOMKilled Exit Code: 137 |
Java 特别注意:
1 | 容器 memory limit = 1Gi JVM -Xmx 设置太大 堆外内存、线程栈、Metaspace 也要占内存 |
建议:
1 | 1. 合理设置 requests/limits 2. JVM 使用容器感知参数 3. Xmx 不要接近容器 limit 4. 监控 heap、direct memory、metaspace、线程数 5. dump 分析内存泄漏 |
标准表达:
Java 容器 OOM 不能只看 Xmx,容器内存还包括堆外内存、Metaspace、线程栈和 Native 内存。Xmx 设置太接近 limit,很容易被 OOMKilled。
6. Service 访问不通怎么排查?
面试结论:
Service 不通要按 Service -> EndpointSlice -> Pod -> 端口 -> 网络策略逐层排查。很多问题不是 Service 本身,而是 selector 没匹配到 Pod 或 Pod 没 Ready。
排查命令:
1 | kubectl get svc -n <ns> kubectl describe svc <svc> -n <ns> kubectl get endpoints <svc> -n <ns> kubectl get endpointslice -n <ns> kubectl get pod -n <ns> --show-labels |
排查点:
1 | 1. Service selector 是否匹配 Pod label 2. Endpoints 是否为空 3. targetPort 是否写错 4. Pod 是否 Ready 5. 容器端口是否真正监听 6. NetworkPolicy 是否拦截 7. kube-proxy 是否异常 8. CoreDNS 是否解析异常 |
进入临时 Pod 测试:
1 | kubectl run debug --image=busybox:1.36 -it --rm -- sh wget -qO- http://order-service:8080 nslookup order-service |
标准表达:
Service 不通先看 Endpoints。如果 Endpoints 为空,通常是 selector 不匹配或 Pod 未 Ready。如果 Endpoints 正常,再查端口、DNS、网络策略和 kube-proxy。
7. Ingress 访问 502/504 怎么排查?
面试结论:
Ingress 502/504 要从 Ingress Controller 视角看:路由规则是否匹配、Service 是否可达、Endpoints 是否为空、上游是否超时或连接失败。
排查命令:
1 | kubectl describe ingress <ing> -n <ns> kubectl get ingress -n <ns> kubectl logs <ingress-controller-pod> -n <ingress-ns> kubectl get svc,endpoints -n <ns> |
502 常见原因:
1 | 1. Service 后端无可用 Pod 2. targetPort 错误 3. Pod 端口未监听 4. 上游连接被拒绝 5. 协议不匹配,比如 HTTP/HTTPS 搞反 |
504 常见原因:
1 | 1. 后端接口处理太慢 2. Ingress 超时配置过短 3. 后端连接池耗尽 4. 网络不通或丢包 |
标准表达:
502 更偏上游不可达或响应异常,504 更偏上游响应超时。排查时先看 Ingress Controller 日志,再看 Service 和 Endpoints,最后进 Pod 内部验证服务端口和接口耗时。
8. Node NotReady 怎么排查?
面试结论:
Node NotReady 通常是 kubelet 异常、容器运行时异常、节点资源压力、网络插件异常或节点和 apiserver 通信失败。
排查命令:
1 | kubectl get nodes kubectl describe node <node> |
节点上排查:
1 | systemctl status kubelet journalctl -u kubelet -f systemctl status containerd df -h free -h top |
常见原因:
1 | 1. kubelet 挂了 |
Node Conditions:
1 | MemoryPressure DiskPressure PIDPressure NetworkUnavailable Ready |
标准表达:
Node NotReady 先看 describe node 的 Conditions 和 Events,再上节点看 kubelet、containerd、磁盘、内存和网络。很多 NotReady 是节点资源压力或 kubelet/container runtime 异常导致的。
9. CPU / 内存飙高怎么定位?
面试结论:
先用 kubectl top 定位 Pod,再结合应用日志、JVM 指标、线程栈和容器资源限制判断是业务流量、死循环、GC、内存泄漏还是资源配置问题。
命令:
1 | kubectl top pod -n <ns> kubectl top pod -n <ns> --containers kubectl top node |
Java CPU 高:
1 | kubectl exec -it <pod> -n <ns> -- sh top -H jstack <pid> |
内存高:
1 | jcmd <pid> VM.native_memory jmap -dump jstat -gc <pid> 1000 |
注意:
生产容器里不一定有这些工具,需要 debug 镜像或临时诊断容器。
标准表达:
K8s 层面只能先定位哪个 Pod、哪个容器资源异常,真正原因要结合应用层指标。Java 服务 CPU 高通常要看线程栈,内存高要区分堆、堆外、Metaspace 和线程栈。
10. 常用 kubectl 命令清单
1 | # 查看资源 kubectl get pod -n <ns> -o wide kubectl get deploy,rs,pod -n <ns> kubectl get svc,ingress,endpoints -n <ns> # 详情和事件 kubectl describe pod <pod> -n <ns> kubectl get events -n <ns> --sort-by=.lastTimestamp # 日志 kubectl logs <pod> -n <ns> kubectl logs <pod> -n <ns> -c <container> kubectl logs <pod> -n <ns> --previous kubectl logs -f deployment/<deploy> -n <ns> # 进入容器 kubectl exec -it <pod> -n <ns> -- sh # 资源指标 kubectl top pod -n <ns> kubectl top node # 发布回滚 kubectl rollout status deploy/<deploy> -n <ns> kubectl rollout history deploy/<deploy> -n <ns> kubectl rollout undo deploy/<deploy> -n <ns> # 临时调试 kubectl run debug --image=busybox:1.36 -it --rm -- sh |
11. 常见追问
1 | 1. Pending 和 CrashLoopBackOff 区别? 2. CrashLoopBackOff 为什么要看 --previous? 3. ImagePullBackOff 常见原因? 4. OOMKilled 和 JVM OOM 区别? 5. Service Endpoints 为空说明什么? 6. Ingress 502 和 504 区别? 7. Node NotReady 常见原因? 8. Pod Running 但服务不通怎么排查? 9. readiness 失败会发生什么? 10. CPU 高怎么定位到具体线程? |
第六轮总结:
K8s 排查要按层次来:Pod Pending 看调度和资源,CrashLoopBackOff 看日志和退出码,ImagePullBackOff 看镜像和仓库权限,OOMKilled 看内存 limit 和应用内存,Service 不通先看 Endpoints,Ingress 502/504 看 Controller 日志和上游 Service,Node NotReady 看 kubelet、containerd、资源压力和网络。核心方法是先用事件定位方向,再用日志、指标和链路逐层验证。
下一轮讲最后一部分:架构与生产实践:Java 微服务如何部署到 K8s、网关/服务发现/配置中心、K8s 和 Spring Cloud、日志监控链路追踪、RBAC、多环境多集群最佳实践。
下面进入 第七轮:K8s 架构与生产实践。这一轮更贴近高级后端/架构岗:不是只问 K8s 对象,而是问你怎么把业务系统真实跑稳。
1. K8s 中如何部署 Java 微服务?
面试结论:
Java 微服务部署到 K8s,一般用 Deployment 管无状态服务,用 Service 暴露稳定入口,用 ConfigMap/Secret 管配置,用 probes 做健康检查,用 requests/limits 做资源隔离,用 HPA 做弹性扩缩容。
典型结构:
1 | Deployment | v Pod | ├── Java Container ├── ConfigMap ├── Secret ├── readinessProbe ├── livenessProbe └── resources requests/limits | v Service | v Ingress / Gateway |
Java 服务重点配置:
1 | 1. 镜像尽量小,启动命令明确 2. 设置 JVM 容器感知参数 3. 配置 requests/limits 4. 配置 readiness/liveness/startupProbe 5. 支持 SIGTERM 优雅停机 6. 日志输出到 stdout/stderr 7. 配置通过 ConfigMap/Secret 或配置中心注入 |
标准表达:
Java 微服务上 K8s,不是把 jar 放进镜像就结束了。要配合资源限制、健康探针、优雅停机、日志标准输出、配置解耦和弹性扩缩容,才能符合生产要求。
2. 网关、服务发现、配置中心如何落地?
网关
常见入口:
1 | 外部流量 -> Ingress Controller / API Gateway -> Service -> Pod |
可选组件:
1 | Nginx Ingress Spring Cloud Gateway Kong APISIX Envoy Istio Gateway |
一般建议:
1 | 南北向入口:Ingress / API Gateway 东西向服务治理:Service / Service Mesh |
服务发现
K8s 内建服务发现:
1 | Service Name -> CoreDNS -> ClusterIP -> Pod |
例如:
1 | http://order-service.default.svc.cluster.local:8080 |
Spring Cloud 迁移到 K8s 后:
1 | 可以逐步减少 Eureka/Nacos 注册发现依赖 |
配置中心
配置来源可以有三类:
1 | ConfigMap/Secret |
取舍:
1 | 少量静态配置:ConfigMap |
标准表达:
K8s 自带 Service 和 CoreDNS,可以承担基础服务发现;ConfigMap/Secret 适合环境级配置,但复杂动态配置仍然可以保留 Nacos/Apollo。网关层一般用 Ingress 或 API Gateway 统一入口,再通过 Service 转发到后端 Pod。
3. K8s 和 Spring Cloud 的关系
面试结论:
K8s 和 Spring Cloud 有能力重叠,但层次不同。K8s 偏基础设施编排,Spring Cloud 偏应用层微服务治理。
能力对比:
| 能力 | K8s | Spring Cloud |
|---|---|---|
| 服务部署 | Deployment | 不负责 |
| 服务发现 | Service + DNS | Eureka/Nacos |
| 负载均衡 | Service/kube-proxy | Ribbon/Spring Cloud LoadBalancer |
| 配置管理 | ConfigMap/Secret | Nacos/Apollo/Config |
| 网关 | Ingress/Gateway | Spring Cloud Gateway |
| 熔断限流 | 基础能力弱 | Sentinel/Resilience4j |
| 弹性扩缩容 | HPA | 不负责 |
| 发布回滚 | Deployment | 不负责 |
迁移思路:
1 | 部署、弹性、服务发现逐步交给 K8s 动态配置、限流熔断、业务治理可保留 Spring Cloud 生态 |
标准表达:
K8s 不是 Spring Cloud 的简单替代。K8s 管容器、调度、服务发现和弹性;Spring Cloud 管应用层网关、配置、熔断、限流等。实际落地通常是两者结合,再逐步减少重复能力。
4. 日志、监控、链路追踪
日志
推荐方式:
1 | 应用日志输出 stdout/stderr 节点 DaemonSet 采集日志 发送到 Elasticsearch / Loki / Kafka |
常见组件:
1 | Fluent Bit Filebeat Vector Logstash Loki Elasticsearch |
链路:
1 | Pod stdout | v Node 日志文件 | v DaemonSet 日志采集器 | v 日志系统 |
监控
常见方案:
1 | Prometheus + Grafana |
采集:
1 | Node Exporter:节点指标 |
核心指标:
1 | Pod CPU/Memory |
链路追踪
常见方案:
1 | OpenTelemetry |
关注:
1 | traceId |
标准表达:
K8s 生产可观测性至少要有日志、指标、链路三件套。日志用于查具体错误,指标用于发现趋势和告警,链路追踪用于定位跨服务调用慢在哪一段。
5. RBAC 权限控制
面试结论:
RBAC 是 K8s 的权限控制机制,通过 Role/ClusterRole 定义权限,通过 RoleBinding/ClusterRoleBinding 把权限绑定给用户、组或 ServiceAccount。
核心对象:
1 | Role:namespace 级权限 |
图示:
1 | ServiceAccount/User |
最佳实践:
1 | 最小权限原则 |
标准表达:
RBAC 的关键是最小权限。Role 定义能做什么,Binding 定义谁能做。生产上要避免业务服务使用默认 ServiceAccount 或过大权限。
6. 多环境、多集群、命名空间隔离
多环境
常见方式:
1 | dev namespace |
或者:
1 | 不同环境不同集群 |
推荐:
1 | 生产和非生产尽量不同集群 同集群内用 namespace 做逻辑隔离 |
Namespace 隔离要配合
1 | RBAC ResourceQuota LimitRange NetworkPolicy 独立 Ingress 域名 独立 Secret |
ResourceQuota 示例能力:
1 | 限制 namespace 总 CPU/内存 限制 Pod 数量 限制 PVC 数量 |
LimitRange:
1 | 给未设置 requests/limits 的 Pod 设置默认值 限制单个 Pod 最大资源 |
标准表达:
Namespace 是逻辑隔离,不是完整安全隔离。生产上要配合 RBAC、ResourceQuota、NetworkPolicy 和独立发布权限。关键业务或生产环境最好独立集群。
7. K8s 生产最佳实践
应用层:
1 | 无状态服务用 Deployment 有状态服务谨慎使用 StatefulSet 日志输出 stdout 支持优雅停机 提供健康检查接口 配置和镜像解耦 |
资源层:
1 | 必须配置 requests/limits 核心服务避免 BestEffort 合理设置 HPA 设置 PDB 使用反亲和或拓扑分布 |
发布层:
1 | 滚动更新配置 maxSurge/maxUnavailable readiness 通过后再接流量 发布失败及时回滚 灰度发布优先走网关/Service Mesh |
安全层:
1 | 镜像漏洞扫描 非 root 用户运行容器 限制容器特权 Secret 加密和权限控制 RBAC 最小权限 NetworkPolicy 隔离 |
可观测性:
1 | 日志采集 Prometheus 指标 链路追踪 告警规则 审计日志 |
标准表达:
生产 K8s 的核心不是资源能跑起来,而是可发布、可扩容、可观测、可恢复、可治理。应用要适配容器生命周期,平台要做好权限、资源、网络、安全和监控。
8. 架构面试综合回答模板
如果面试官问:“你们 Java 微服务怎么落地 K8s?”
可以这样答:
我们一般用 Deployment 部署无状态 Java 服务,通过 Service 提供稳定访问入口,外部流量走 Ingress 或 API Gateway。配置通过 ConfigMap/Secret 注入,动态业务配置保留 Nacos/Apollo。服务发现优先使用 K8s Service 和 CoreDNS,应用层限流熔断可以继续使用 Sentinel 或 Resilience4j。
生产上每个服务都要配置 requests/limits、readiness/liveness/startupProbe,并支持 SIGTERM 优雅停机。发布使用 Deployment 滚动更新,核心服务设置 maxUnavailable=0,并配合 PDB、反亲和和 HPA 保证可用性。日志输出到 stdout,由 DaemonSet 采集到日志系统,指标用 Prometheus/Grafana,链路追踪用 OpenTelemetry 或 SkyWalking。
权限上使用 RBAC 和独立 ServiceAccount,环境隔离通过 namespace 或独立集群实现,核心生产环境会配 ResourceQuota、NetworkPolicy、镜像扫描和 Secret 加密。整体目标是让服务不仅能跑,还要能稳定发布、快速排查和安全治理。
9. 常见追问
1 | 1. K8s 能不能替代 Spring Cloud? 2. Java 服务上 K8s 要注意什么? 3. ConfigMap 和 Nacos 怎么取舍? 4. 服务发现用 K8s Service 还是注册中心? 5. 如何做日志采集? 6. Prometheus 采集哪些指标? 7. RBAC 怎么设计? 8. Namespace 是不是强隔离? 9. 生产环境为什么要 requests/limits? 10. 如何做到不停机发布? |
第七轮总结:
K8s 生产实践的核心是把应用、平台和治理能力结合起来。Java 微服务用 Deployment/Service/Ingress 跑起来只是第一步,真正要考虑的是配置管理、服务发现、滚动发布、弹性扩缩容、优雅停机、日志监控链路追踪、RBAC 权限、安全策略和多环境隔离。高级面试里要体现一点:K8s 是基础设施平台,不是业务治理银弹,很多能力仍然需要和网关、配置中心、Service Mesh、监控体系、DevOps 流程一起落地。
20:37
回答k8s所有的常见追问的问题
20:54
下面给你一版 K8s 常见追问速答版,适合面试前快速过一遍。每题都是“能直接说出口”的标准回答。
一、基础核心追问
1. Pod 和容器有什么区别?
容器是实际运行进程的环境,Pod 是 K8s 最小调度单位,一个 Pod 可以包含一个或多个容器,Pod 内容器共享网络和 Volume。
2. Deployment 和 ReplicaSet 什么关系?
Deployment 管理 ReplicaSet,ReplicaSet 管理 Pod 副本。平时直接使用 Deployment,因为它支持滚动更新和回滚。
3. Deployment 和 StatefulSet 区别?
Deployment 适合无状态服务,Pod 名称和存储不稳定;StatefulSet 适合有状态服务,提供稳定名称、稳定网络身份和稳定 PVC。
4. Service 为什么需要 selector?
Service 通过 selector 匹配一组 Pod Label,从而把流量转发给这些 Pod。没有 selector,Service 不知道后端是谁。
5. Service 和 Ingress 区别?
Service 解决集群内稳定访问和负载均衡,Ingress 解决外部 HTTP/HTTPS 七层入口路由。
6. ConfigMap 修改后 Pod 会自动更新吗?
如果以环境变量注入,不会自动更新;如果以 Volume 挂载,文件内容可能更新,但应用不一定自动 reload。
7. Secret 是不是安全的?
Secret 默认只是 Base64 编码,不是加密。生产要配合 RBAC、etcd 加密、KMS/Vault 和权限控制。
8. DaemonSet 适合什么场景?
适合每个 Node 都要运行一个实例的场景,比如日志采集、监控 Agent、CNI 插件、存储插件。
9. Namespace 能不能实现强隔离?
Namespace 是逻辑隔离,不是强安全隔离。强隔离还要配合 RBAC、NetworkPolicy、ResourceQuota,甚至独立集群。
10. K8s 为什么是声明式系统?
用户声明期望状态,比如副本数为 3,K8s 控制器持续对比实际状态并自动调谐到期望状态。
二、Pod 生命周期与调度
1. Pod Pending 一般是什么原因?
常见是资源不足、PVC 未绑定、节点污点不可容忍、亲和性不满足、Node NotReady 或 ResourceQuota 不足。
2. requests 和 limits 哪个影响调度?
requests 影响调度,scheduler 根据 requests 判断节点资源是否足够;limits 是运行时资源上限。
3. CPU 超限和内存超限有什么区别?
CPU 超 limit 通常被限流,表现为变慢;内存超 limit 可能被 OOMKilled,容器会被杀掉重启。
4. readiness 和 liveness 区别?
readiness 判断 Pod 能不能接流量,失败会从 Service 后端摘除;liveness 判断容器是否存活,失败会重启容器。
5. 为什么需要 startupProbe?
用于保护启动慢的应用,在 startupProbe 成功前不会执行 liveness,避免应用还没启动完就被误杀。
6. Scheduler 会不会启动容器?
不会。Scheduler 只负责给 Pod 选择 Node,真正启动容器的是目标节点上的 kubelet。
7. OOMKilled 是谁杀的?
通常是容器内存超过 cgroup limit 后,被内核 OOM killer 杀掉,K8s 再根据重启策略拉起容器。
8. QoS 有什么用?
QoS 影响节点资源紧张时的驱逐优先级,BestEffort 最容易被驱逐,Guaranteed 最稳定。
三、K8s 网络
1. Pod IP 和 Service IP 有什么区别?
Pod IP 是具体 Pod 的真实地址,会变化;Service IP 是稳定虚拟入口,用来负载均衡到后端 Pod。
2. ClusterIP 是真实 IP 吗?
ClusterIP 是虚拟 IP,不对应某个真实网卡,流量由 kube-proxy 的 iptables/IPVS 规则转发到 Pod。
3. kube-proxy 是不是转发所有流量?
不是。kube-proxy 主要维护 Service 转发规则,真正数据转发由内核规则完成。
4. iptables 和 IPVS 模式区别?
iptables 基于规则链 DNAT,规模大时规则多;IPVS 基于内核 LVS,支持更多负载算法,大规模场景更稳定。
5. Ingress 和 Service 区别?
Service 是服务访问抽象,偏四层;Ingress 是 HTTP/HTTPS 入口规则,偏七层,需要 Ingress Controller 执行。
6. 为什么有了 Service 还需要 Ingress?
Service 解决集群内访问,Ingress 解决外部域名、路径、HTTPS、七层路由等入口能力。
7. CoreDNS 怎么解析 Service?
CoreDNS 监听 K8s Service 和 EndpointSlice,把 service.namespace.svc.cluster.local 解析成 ClusterIP。
8. Headless Service 有什么用?
Headless Service 不分配 ClusterIP,DNS 直接返回后端 Pod IP,常用于 StatefulSet 和需要访问具体 Pod 的场景。
9. CNI 负责什么?
CNI 负责给 Pod 分配 IP、创建网络设备、配置路由和网络策略,实现 Pod 间通信。
10. NetworkPolicy 为什么不生效?
常见原因是 CNI 不支持 NetworkPolicy、selector 写错、namespace 选错、策略方向 ingress/egress 配错。
四、存储与配置
1. Volume 和 PV/PVC 区别?
Volume 是 Pod 内挂载抽象;PV 是集群存储资源;PVC 是应用对存储资源的申请。
2. PVC 一直 Pending 是什么原因?
可能没有匹配 PV、StorageClass 不存在、动态 provisioner 异常、容量/访问模式不匹配。
3. StorageClass 有什么作用?
StorageClass 定义动态存储供给模板,PVC 可以通过它自动创建对应 PV 和底层存储。
4. RWO、ROX、RWX 区别?
RWO 单节点读写,ROX 多节点只读,RWX 多节点读写。多副本共享写通常需要 RWX 存储。
5. StatefulSet 为什么适合有状态服务?
因为它提供稳定 Pod 名称、稳定 DNS、稳定 PVC,以及有序启动和删除。
6. Headless Service 和 StatefulSet 什么关系?
Headless Service 给 StatefulSet 每个 Pod 提供稳定 DNS,比如 mysql-0.mysql.default.svc.cluster.local。
7. ConfigMap 更新后应用会自动生效吗?
环境变量不会自动变;Volume 文件可能更新,但 Java 应用通常仍需要 reload 机制或重启。
8. Secret 是不是加密的?
默认不是加密,只是 Base64 编码;需要开启 etcd 静态加密并配合 RBAC/KMS。
9. hostPath 为什么生产慎用?
hostPath 绑定宿主机路径,可移植性差,安全风险高,Pod 调度到其他节点可能无法使用同样数据。
10. 数据库能不能跑在 K8s?
可以,但要谨慎。核心难点是存储性能、备份恢复、主从切换、故障处理和 Operator 运维能力。
五、发布、扩缩容、高可用
1. Deployment 滚动更新底层怎么做?
Deployment 创建新的 ReplicaSet,逐步增加新 Pod,减少旧 Pod,直到全部切换到新版本。
2. maxSurge 和 maxUnavailable 怎么配置?
核心服务常用 maxUnavailable=0 保证可用副本不减少,maxSurge=1 或百分比允许临时多起 Pod。
3. 蓝绿和金丝雀区别?
蓝绿是两套环境一次性切流,回滚快但资源成本高;金丝雀是小流量逐步放量,风险更低。
4. HPA 扩容依据是什么?
可以基于 CPU、内存、自定义指标或外部指标;CPU HPA 依赖 Pod 的 requests.cpu。
5. HPA 和 Cluster Autoscaler 谁先触发?
HPA 先扩 Pod;如果节点资源不够导致 Pod Pending,Cluster Autoscaler 再扩 Node。
6. VPA 为什么可能导致 Pod 重启?
因为 VPA 调整 requests/limits 通常需要重建 Pod,运行中的容器资源规格不能总是原地修改。
7. PDB 能不能防止节点宕机?
不能。PDB 只能约束自愿中断,比如 drain、升级,不能阻止机器故障、断电、OOM。
8. replicas=3 是否一定高可用?
不一定。如果 3 个 Pod 都在同一 Node 或同一可用区,节点故障仍会全挂,需要反亲和和拓扑分布。
9. 如何做到 Java 服务不停机发布?
配置 readiness 摘流、滚动更新、maxUnavailable=0、优雅停机、SIGTERM 处理、preStop 缓冲和合理探针。
10. readiness 和优雅停机有什么关系?
Pod 终止前 readiness 变失败,Service 不再转发新流量,应用再处理完存量请求后退出。
六、故障排查
1. Pending 和 CrashLoopBackOff 区别?
Pending 是 Pod 还没成功调度或启动;CrashLoopBackOff 是容器启动后反复崩溃。
2. CrashLoopBackOff 为什么看 –previous?
因为当前容器可能已经重启,崩溃原因在上一次容器日志里。
3. ImagePullBackOff 常见原因?
镜像地址错误、tag 不存在、私有仓库认证失败、节点网络不通、镜像仓库限流。
4. OOMKilled 和 JVM OOM 区别?
OOMKilled 是容器超过 cgroup 内存限制被系统杀;JVM OOM 是 JVM 堆或元空间等内部内存不足抛异常。
5. Service Endpoints 为空说明什么?
通常是 selector 没匹配到 Pod,或者 Pod 没 Ready,也可能是命名空间或 Label 写错。
6. Ingress 502 和 504 区别?
502 偏上游不可达、连接失败或响应异常;504 偏上游响应超时。
7. Node NotReady 常见原因?
kubelet 异常、containerd 异常、磁盘满、内存压力、CNI 异常、节点到 apiserver 网络不通、证书问题。
8. Pod Running 但服务不通怎么排查?
看 readiness、容器端口监听、Service selector、Endpoints、targetPort、NetworkPolicy、CoreDNS 和 Ingress 日志。
9. readiness 失败会发生什么?
Pod 会从 Service Endpoints 中摘除,不再接收新流量,但容器不会因为 readiness 失败而自动重启。
10. CPU 高怎么定位到具体线程?
先 kubectl top 找 Pod,再进入容器用 top -H 找线程,转换线程 ID 后用 jstack 定位 Java 线程栈。
七、架构与生产实践
1. K8s 能不能替代 Spring Cloud?
不能简单替代。K8s 管部署、调度、服务发现、弹性;Spring Cloud 更偏应用层配置、熔断、限流、网关等治理。
2. Java 服务上 K8s 要注意什么?
注意 JVM 容器内存、requests/limits、探针、优雅停机、日志 stdout、配置解耦和 HPA 指标。
3. ConfigMap 和 Nacos 怎么取舍?
ConfigMap 适合环境级静态配置;Nacos/Apollo 适合动态业务配置和运行时热更新。
4. 服务发现用 K8s Service 还是注册中心?
集群内基础服务发现可以用 K8s Service/CoreDNS;复杂应用治理或跨集群场景可保留注册中心。
5. 如何做日志采集?
应用日志输出 stdout/stderr,由 DaemonSet 日志 Agent 如 Fluent Bit/Filebeat 采集到 ES、Loki 或 Kafka。
6. Prometheus 采集哪些指标?
采集 Node、Pod、容器、K8s 对象状态、应用业务指标、JVM 指标、接口耗时和错误率。
7. RBAC 怎么设计?
按最小权限原则,区分 namespace、角色和 ServiceAccount,避免默认账号和 cluster-admin 滥用。
8. Namespace 是不是强隔离?
不是。Namespace 是逻辑隔离,强隔离需要 RBAC、NetworkPolicy、ResourceQuota,生产关键环境最好独立集群。
9. 生产环境为什么要 requests/limits?
requests 保证调度和基础资源,limits 防止单个容器打爆节点;不配置会影响稳定性和 HPA/QoS。
10. 如何做到不停机发布?
依靠多副本、readiness、滚动更新、优雅停机、PDB、反亲和、灰度发布和快速回滚机制共同保证。
__END__