Skip to content

Pod/Service/Ingress 深度解析

面试官:K8s 中 Pod 是什么?Container 和 Pod 有什么区别?

:Pod 是 K8s 中最小的调度单元,一个 Pod 可以包含一个或多个容器。同一个 Pod 中的容器共享网络命名空间(同一 IP)和存储卷,是紧密协作的逻辑整体。相比之下,单独的容器之间完全隔离,无法通过 localhost 直接通信。

面试官:Pod 中的多个容器如何通信?为什么需要 Pause 容器?

这个追问很关键,能说清 Pod 网络模型和 Pause 容器作用的候选人,才真正理解了 K8s 的设计哲学。


Q1:Pod 中为什么有 Pause 容器?它的作用是什么?必考

Section titled “Q1:Pod 中为什么有 Pause 容器?它的作用是什么?”

Pause 容器(Infra 容器)是每个 Pod 的基础设施

Pod 启动流程:
1. Kubelet 创建 Pod
└── 首先启动 Pause 容器(gcr.io/google_containers/pause-amd64:3.2)
├── 创建并持有 Network Namespace
├── 创建并持有 IPC Namespace
└── 分配 Pod IP(从节点网段)
2. 用户容器启动
├── Container A:加入 Pause 的 Network Namespace
│ └── 共享同一个 IP、网络栈
└── Container B:加入 Pause 的 Network Namespace
└── 通过 localhost:port 互相访问
3. 容器重启场景
├── 用户容器 A 崩溃重启
│ └── Pause 容器依然运行 → Pod IP 不变
└── 其他容器不受影响,继续通过原 IP 通信

Pause 容器的三大作用

作用原理实际意义
持有网络命名空间Pause 容器创建网络栈后不退出,生命周期与 Pod 相同Pod IP 恒定,容器重启不影响网络
持有 IPC 命名空间同一 Pod 的容器共享 System V IPC、POSIX 消息队列容器间可通过共享内存通信
作为僵尸进程回收者Pause 容器回收孤儿进程(reaper)避免容器内僵尸进程堆积

本质一句话:Pause 容器是 Pod 的”基础设施层”,通过持有命名空间确保 Pod 网络和 IPC 环境稳定,让业务容器来了又走而不影响整体网络拓扑。


Q2:Pod 的生命周期和三种探针的区别?必考

Section titled “Q2:Pod 的生命周期和三种探针的区别?”

Pod 状态机

Pod 生命周期状态流转:
Pending(等待调度)
├── 等待调度器分配节点
├── 镜像拉取中
└── 资源不足无法调度
Running(运行中)
├── 至少一个容器在运行
├── 可能包含正常容器 + Init 容器
└── 可能正在重启容器
┌──┴──┐
↓ ↓
Succeeded Failed
(Job 完成) (容器异常退出)
└── 所有容器成功退出 └── 至少一个容器以非 0 退出
└── 或被系统 OOM Kill
Unknown(节点通信故障)
└── Kubelet 无法上报状态

三种探针对比

探针类型检测目的失败后的动作典型配置场景
livenessProbe(存活探针)容器是否还在运行(死锁、死循环)重启容器(restartPolicy: Always/OnFailure)应用死锁检测、JVM 卡死
readinessProbe(就绪探针)容器是否准备好接受流量从 Service Endpoints 移除,不再接收新请求应用启动完成、依赖就绪检测
startupProbe(启动探针)慢启动应用是否完成启动阻止其他探针执行,直到启动成功大型应用初始化(数据库迁移、缓存预热)

探针配置实战

spec:
containers:
- name: app
image: myapp:1.0
# 启动探针:慢启动应用(如 Java 应用启动需 60s)
startupProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 10 # 启动后 10s 开始探测
periodSeconds: 5 # 每 5s 探测一次
failureThreshold: 30 # 允许失败 30 次(150s 内)
# 作用:禁用 liveness/readiness 直到启动完成,避免被误判为死锁
# 存活探针:检测死锁、线程池耗尽
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
periodSeconds: 10 # 每 10s 探测
failureThreshold: 3 # 连续失败 3 次 → 重启容器
successThreshold: 1
timeoutSeconds: 5
# 就绪探针:滚动更新时新 Pod 必须通过
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 20
periodSeconds: 5 # 每 5s 探测
failureThreshold: 3 # 失败 3 次 → 从 Service 摘除
successThreshold: 1 # 成功 1 次 → 加入 Service

探针执行时序

Pod 启动:
0s → 容器启动
10s → startupProbe 开始探测(liveness/readiness 被阻塞)
60s → startupProbe 成功(或 150s 后失败重启)
→ livenessProbe 和 readinessProbe 开始工作
80s → readinessProbe 成功 → Pod 加入 Service Endpoints
→ 开始接收流量
120s → livenessProbe 检测到死锁(连续失败 3 次)
→ 容器重启

Q3:Resource 的 Request 和 Limit 有什么区别?OOM Kill 的原理是什么?必考

Section titled “Q3:Resource 的 Request 和 Limit 有什么区别?OOM Kill 的原理是什么?”

Request vs Limit 对比

维度Request(请求)Limit(限制)
作用阶段调度阶段(Scheduler)运行阶段(Runtime)
用途节点资源分配依据容器资源使用上限
CPU 行为调度器保证节点剩余资源 ≥ Request超过 Limit → CPU 被限速(Throttle)
内存行为调度器保证节点剩余内存 ≥ Request超过 Limit → OOM Kill(容器被杀)
QoS 等级Request = Limit → GuaranteedRequest < Limit → Burstable

CPU Throttle 和 OOM Kill 原理

CPU 限速机制(CFS Quota):
容器配置:
request.cpu: 500m # 调度时保证分配 0.5 核
limit.cpu: 1000m # 运行时最多使用 1 核
CFS(Completely Fair Scheduler)实现:
1. 每 100ms(CFS 周期)为一个配额周期
2. 容器在 100ms 内最多使用 100ms × 1 核 = 100ms CPU 时间
3. 如果 50ms 内用完 100ms 配额:
容器在剩余 50ms 内被限速(Throttle),等待下一周期
性能影响:
- CPU 密集型应用(计算、加密)频繁被 Throttle → 延迟飙升
- 建议:limit ≈ 实际峰值使用量 × 1.5 倍冗余
内存 OOM Kill 机制:
容器配置:
request.memory: 512Mi
limit.memory: 1Gi
OOM 触发流程:
1. 容器内存使用接近 1Gi(如 900Mi)
2. 内核 OOM Killer 扫描进程树
3. 选择 OOM 分数最高的进程(通常是内存占用最大的)
4. 发送 SIGKILL 信号 → 容器被强制终止
OOM 分数计算:
oom_score = (进程内存占用 / 总内存) × 1000 + oom_score_adj
容器进程的 oom_score_adj 根据 Limit 自动调整
实战案例:
- JVM 堆内存设置 800Mi,但未限制 Metaspace、直接内存
- 容器总内存达到 1Gi → OOM Kill
- 解决:JVM 堆 + 非堆内存 ≤ 容器 Limit 的 80%

最佳实践配置

resources:
requests:
cpu: "500m" # 调度依据:节点剩余资源 ≥ 500m
memory: "512Mi" # 调度依据:节点剩余内存 ≥ 512Mi
limits:
cpu: "1000m" # 运行上限:最多使用 1 核
memory: "1Gi" # 运行上限:超过触发 OOM Kill
# Java 应用 JVM 参数(容器感知)
env:
- name: JAVA_OPTS
value: >
-XX:+UseContainerSupport
-XX:MaxRAMPercentage=75.0 # 堆内存 = Limit × 75%(留 25% 给非堆)
-XX:InitialRAMPercentage=50.0

本质一句话:Request 是调度器的承诺(保证最小资源),Limit 是运行时的红线(超过触发限速或 Kill),两者配合实现资源隔离和超额订阅。


Q4:Service 的四种类型及应用场景?必考

Section titled “Q4:Service 的四种类型及应用场景?”

四种 Service 类型对比

类型访问范围实现机制典型场景性能数据
ClusterIP(默认)集群内部虚拟 IP(VIP),iptables/ipvs 转发微服务间通信延迟 ~0.5ms(同节点)
NodePort集群外部(通过节点 IP)节点开放端口(30000-32767)开发测试环境、临时暴露延迟 ~1-2ms
LoadBalancer集群外部(云厂商 LB)自动创建云负载均衡器(AWS ALB/阿里云 SLB)生产环境对外暴露服务延迟 ~5-10ms(经过云 LB)
ExternalName集群内部访问外部服务CoreDNS CNAME 映射访问外部数据库、第三方 API无转发

配置示例与流量路径

# ClusterIP:集群内部访问
apiVersion: v1
kind: Service
metadata:
name: user-service
spec:
type: ClusterIP # 默认类型
selector:
app: user-service
ports:
- port: 80 # Service 端口
targetPort: 8080 # Pod 端口
ClusterIP 流量路径(iptables 模式):
Client Pod → ClusterIP:80
iptables DNAT(目标地址转换)
Pod IP:8080(随机选择)
直接到达 Pod(不经代理)
性能数据:
- 单节点 iptables 规则数:10,000 条 Service → iptables 延迟 ~1ms
- ipvs 模式(K8s 1.11+):支持 10万+ Service,延迟 <0.5ms
# NodePort:通过节点 IP + 端口访问
spec:
type: NodePort
ports:
- port: 80
targetPort: 8080
nodePort: 30080 # 每个节点的 30080 端口 → Service
NodePort 流量路径:
外部客户端 → Node1:30080
kube-proxy(监听 NodePort)
ClusterIP:80
Pod IP:8080
注意:即使访问 Node1,Pod 可能调度在 Node2(跨节点转发)
# LoadBalancer:云厂商负载均衡器(生产环境)
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8080
# 云厂商自动分配外部 IP(如 AWS ALB)
LoadBalancer 流量路径:
客户端 → 云 LB(公网 IP)
健康检查 → 只转发到健康节点
NodePort 或直接到 Pod(取决于云厂商实现)

Q5:Service 如何发现 Pod 并实现负载均衡?高频

Section titled “Q5:Service 如何发现 Pod 并实现负载均衡?”

服务发现完整流程

Service → Pod 的服务发现机制:
1. Service 定义 Label Selector
2. Endpoints Controller 监听 Pod 变化
└── 匹配 Label 的 Pod IP:Port 写入 Endpoints 对象
3. kube-proxy 监听 Endpoints 变化
└── 更新节点的 iptables/ipvs 规则
4. CoreDNS 解析 Service 名称
└── my-service.default.svc.cluster.local → ClusterIP

kube-proxy 的三种模式对比

模式实现原理性能连接数限制适用场景
userspace(已废弃)用户态代理,所有流量经过 kube-proxy 进程低(多次上下文切换)无限制早期 K8s(<1.2
iptables(默认)内核态 DNAT 规则,随机选择 Pod高(~0.5ms)规则数 O(n²),大集群慢中小集群(<5000 Service)
ipvs(推荐)内核态 LVS,支持多种调度算法极高(~0.1ms)哈希表 O(1),支持 10万+ Service大规模集群

iptables 模式的负载均衡实现

Terminal window
# 查看 iptables 规则(简化版)
iptables -t nat -L KUBE-SERVICES
# 规则示例:
Chain KUBE-SVC-XXX (user-service)
├── 33% probability KUBE-SEP-POD1 # Pod1 IP:8080
├── 33% probability KUBE-SEP-POD2 # Pod2 IP:8080
└── 34% probability KUBE-SEP-POD3 # Pod3 IP:8080

ipvs 模式的负载均衡算法

# kube-proxy 配置(ipvs 模式)
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs
ipvs:
scheduler: rr # 轮询(Round Robin)
# 可选算法:
# - lc: 最少连接(Least Connections)
# - dh: 目标哈希(Destination Hashing)
# - sh: 源地址哈希(Source Hashing)
# - sed: 最短期望延迟(Shortest Expected Delay)

CoreDNS 服务发现

Service 名称解析规则:
同命名空间:
http://user-service:80
└── 解析为 user-service.default.svc.cluster.local
跨命名空间:
http://user-service.prod:80
└── 解析为 user-service.prod.svc.cluster.local
完整 FQDN:
http://user-service.prod.svc.cluster.local:80
└── 格式:<service>.<namespace>.svc.cluster.local
性能数据:
- CoreDNS 单实例 QPS:~10,000+
- 缓存命中延迟:<1ms
- 缓存未命中延迟:~5-10ms(需查询上游 DNS)

Q6:Ingress 和 Service 的区别?为什么需要 Ingress?高频

Section titled “Q6:Ingress 和 Service 的区别?为什么需要 Ingress?”

四层 vs 七层负载均衡对比

Service(L4,传输层):
├── 基于 IP + 端口转发
├── 不理解 HTTP 协议
├── 无法按域名、路径、Header 路由
└── 每个服务需要一个 LoadBalancer(成本高)
Ingress(L7,应用层):
├── 基于 HTTP 协议(域名、路径、Header)
├── 支持路由规则:api.example.com/api/users → user-service
├── SSL 终止:在 Ingress 处理 HTTPS,后端用 HTTP
├── 多个服务共享一个入口 IP(节省 LoadBalancer 成本)
└── 需要安装 Ingress Controller(Nginx/Traefik/Istio Gateway)

Ingress 架构图

客户端请求(HTTPS)
云 LoadBalancer(AWS ALB / 阿里云 SLB)
Ingress Controller(Nginx Pod)
├── 解析域名:api.example.com
├── 卸载 SSL(HTTPS → HTTP)
├── 匹配路由规则:
│ ├── /api/users → user-service:80
│ ├── /api/orders → order-service:80
│ └── /admin → admin-service:80
└── 转发到对应 Service(ClusterIP)
Pod(HTTP)

Ingress 配置示例

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2 # URL 重写
nginx.ingress.kubernetes.io/ssl-redirect: "true" # HTTP 重定向到 HTTPS
spec:
ingressClassName: nginx # 指定 Ingress Controller
# TLS 配置(HTTPS)
tls:
- hosts:
- api.example.com
secretName: tls-secret # Kubernetes Secret 存储证书
# 路由规则
rules:
- host: api.example.com
http:
paths:
# 路径:/api/users/* → user-service
- path: /api/users(/|$)(.*)
pathType: Prefix
backend:
service:
name: user-service
port:
number: 80
# 路径:/api/orders/* → order-service
- path: /api/orders(/|$)(.*)
pathType: Prefix
backend:
service:
name: order-service
port:
number: 80

Ingress Controller 对比

Ingress Controller特点性能适用场景
Nginx Ingress成熟稳定、社区活跃、配置灵活QPS ~50,000(单实例)通用场景、K8s 官方推荐
Traefik原生云原生、自动服务发现、配置热更新QPS ~30,000微服务架构、动态配置
Istio GatewayService Mesh 集成、流量管理、可观测性QPS ~20,000(Sidecar 模式)服务网格、灰度发布
Kong基于 Nginx、API 网关特性(限流、认证)QPS ~40,000API 网关、企业级特性

本质一句话:Ingress 是 K8s 的”智能路由器”,用七层协议实现多服务共享入口、域名/路径路由、SSL 卸载,节省云 LoadBalancer 成本并提升灵活性。


Q7:如何基于 Ingress 实现金丝雀发布(灰度发布)?实战

Section titled “Q7:如何基于 Ingress 实现金丝雀发布(灰度发布)?”

金丝雀发布场景:将 10% 流量路由到新版本,观察无异常后逐步扩大比例。

方案一:基于权重(Nginx Ingress)

# 稳定版 Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-stable
spec:
rules:
- host: api.example.com
http:
paths:
- path: /
backend:
service:
name: app-service-stable
port:
number: 80
---
# 金丝雀 Ingress(新版本)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-canary
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10" # 10% 流量到金丝雀版本
spec:
rules:
- host: api.example.com
http:
paths:
- path: /
backend:
service:
name: app-service-canary
port:
number: 80

方案二:基于 Header(内部测试)

metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "X-Canary"
nginx.ingress.kubernetes.io/canary-by-header-value: "true"
# 请求头 X-Canary: true → 路由到金丝雀版本

灰度发布流程

灰度发布步骤(逐步放量):
1. 部署金丝雀版本(Deployment: app-canary)
└── replicas: 1(先起 1 个 Pod)
2. 创建金丝雀 Ingress(weight: 10%)
└── 监控错误率、延迟(Prometheus + Grafana)
3. 观察 30min 无异常 → weight: 30%
└── 继续监控
4. 观察 30min 无异常 → weight: 50%
└── 继续监控
5. 观察 30min 无异常 → weight: 100%
└── 全量切换
6. 删除旧版本 Deployment 和 Ingress

实战案例

场景:电商订单服务 v1.2.0 灰度发布
监控指标(Prometheus):
- 错误率:< 0.1%(正常)
- P95 延迟:< 200ms(正常)
- QPS:稳定在 5000
灰度过程:
10:00 → weight: 10%(金丝雀 QPS: 500)
10:30 → weight: 30%(金丝雀 QPS: 1500)
11:00 → weight: 50%(金丝雀 QPS: 2500)
11:30 → weight: 100%(全量切换)
12:00 → 删除旧版本
异常回滚:
如果金丝雀版本错误率 > 1%:
→ 立即 weight: 0%(切回稳定版)
→ 排查问题后重新灰度