Kubernetes 面试题精选
生成时间:2026-06-06 21:40 | 共 10 题
1. 请描述 Kubernetes 的 Master 节点和 Worker 节点各自的核心组件及其职责
难度: ⭐
标准答案:
Master 节点核心组件:
- kube-apiserver:集群的统一入口,所有操作都通过 API Server 进行,负责认证、授权、准入控制和 API 注册发现。
- etcd:分布式键值存储,保存集群所有的持久化状态数据,是集群的"唯一真相来源"(Single Source of Truth)。
- kube-scheduler:负责 Pod 的调度,根据资源需求、亲和性、污点容忍等策略将 Pod 分配到合适的 Node。
- kube-controller-manager:运行各种控制器(Deployment Controller、ReplicaSet Controller、Node Controller 等),通过控制循环将集群实际状态向期望状态收敛。
Worker 节点核心组件:
- kubelet:节点代理,负责 Pod 的生命周期管理,包括容器启停、健康检查、卷挂载等,向 API Server 汇报节点和 Pod 状态。
- kube-proxy:维护节点上的网络规则(iptables/IPVS),实现 Service 的负载均衡和流量转发。
- 容器运行时(Container Runtime):如 containerd、CRI-O,负责实际拉取镜像和运行容器。
延伸思考: 如果 etcd 集群不可用,集群会发生什么?已运行的 Pod 会受影响吗?为什么?
2. Pod 的完整生命周期包含哪些阶段?Pod 中容器的启动顺序和终止顺序如何控制?
难度: ⭐⭐
标准答案:
Pod 生命周期阶段(Phase):
- Pending:Pod 已被接受但容器尚未启动(正在调度或拉取镜像)
- Running:Pod 已绑定到节点,至少一个容器正在运行或正在启动
- Succeeded:Pod 中所有容器成功终止且不会重启
- Failed:Pod 中所有容器已终止,且至少一个容器以失败状态退出
- Unknown:无法获取 Pod 状态,通常是与 Node 通信失败
容器启动顺序控制:
- initContainers:按定义顺序逐个执行,前一个成功完成后才启动下一个,全部完成后才启动主容器
- 主容器之间并行启动,无严格顺序保证
容器终止顺序:
- Pod 终止时,所有容器同时收到 SIGTERM 信号
- 通过
preStophook 可以在 SIGTERM 之前执行清理逻辑 terminationGracePeriodSeconds(默认 30s)超时后发送 SIGKILL 强制终止- 终止顺序与启动顺序相反:先启动的最后终止(网络层面),但信号是并行发出的
延伸思考: 如何确保应用优雅退出?如果 preStop hook 执行时间超过 terminationGracePeriodSeconds 会怎样?
3. Deployment、StatefulSet 和 DaemonSet 三种工作负载分别适用于什么场景?核心差异是什么?
难度: ⭐⭐
标准答案:
| 特性 | Deployment | StatefulSet | DaemonSet |
|---|---|---|---|
| 适用场景 | 无状态应用(Web服务、API) | 有状态应用(数据库、ZK) | 节点级守护进程(日志采集、监控) |
| Pod 名称 | 随机后缀(app-7d4f8b) | 有序编号(app-0, app-1) | 每节点一个(app-xxxx) |
| 扩缩容 | 随机创建/删除 | 有序创建/删除(逆序) | 随节点增减自动调整 |
| 更新策略 | RollingUpdate/Recreate | RollingUpdate/OnDelete | RollingUpdate/OnDelete |
| 存储 | 共享或无持久化 | 每个Pod独立PVC,PVC随Pod | 通常用HostPath或节点本地存储 |
| 网络标识 | 无稳定网络标识 | 稳定DNS:<pod-name>.<svc>.<ns>.svc.cluster.local | 无稳定标识 |
| 删除后PVC | 自动删除 | 默认保留(需手动清理) | 取决于存储类型 |
核心差异:
- Deployment 强调水平扩展和滚动更新,Pod 间完全等价可替换
- StatefulSet 提供有序部署、稳定网络标识和持久化存储绑定,Pod 不可随意替换
- DaemonSet 确保每个(或特定)节点恰好运行一个 Pod 副本
延伸思考: StatefulSet 的 Partition 更新策略在灰度发布中如何使用?当 StatefulSet Pod 被意外删除后重建,它的 DNS 记录和 PVC 会怎样?
4. Kubernetes 中 Service 有哪几种类型?ClusterIP、NodePort、LoadBalancer 和 ExternalName 分别如何工作?服务发现机制是怎样的?
难度: ⭐⭐
标准答案:
Service 类型:
- ClusterIP(默认):分配一个集群内部虚拟 IP,仅在集群内可访问。通过 kube-proxy 维护的 iptables/IPVS 规则将流量负载均衡到后端 Pod。
- NodePort:在 ClusterIP 基础上,在每个节点上开放一个静态端口(30000-32767),外部可通过
<NodeIP>:<NodePort>访问。 - LoadBalancer:在 NodePort 基础上,向云厂商请求一个外部负载均衡器(如 AWS ELB、GCP LB),流量经 LB → NodePort → Pod。
- ExternalName:不代理流量,仅返回 CNAME 记录,将 Service 映射到外部 DNS 名称(如
my.database.aws.com)。
服务发现机制:
- DNS 服务发现:CoreDNS 为每个 Service 创建 DNS 记录,格式为
<svc>.<ns>.svc.cluster.local,Pod 直接通过服务名访问 - 环境变量注入:Pod 启动时注入同命名空间下所有 Service 的 IP 和端口作为环境变量(如
REDIS_SERVICE_HOST=10.96.0.100),但只反映启动时已存在的 Service
延伸思考: Headless Service(ClusterIP: None)有什么用?它和普通 ClusterIP Service 在 DNS 解析上有什么区别?
5. Ingress 和 Ingress Controller 的关系是什么?如何实现基于域名的虚拟主机路由和 TLS 终止?
难度: ⭐⭐
标准答案:
关系:
- Ingress 是 K8s 的 API 资源对象,定义了从集群外部到内部 Service 的 HTTP/HTTPS 路由规则(相当于"配置文件")
- Ingress Controller 是实际运行的控制器(如 Nginx Ingress Controller、Traefik、Kong),监听 Ingress 资源变化并配置底层代理(如 Nginx 配置文件),实现流量转发
基于域名的虚拟主机路由示例:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-host
spec:
rules:
- host: app1.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app1-svc
port:
number: 80
- host: app2.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app2-svc
port:
number: 80TLS 终止:
spec:
tls:
- hosts:
- app1.example.com
secretName: app1-tls-secret # 包含 tls.crt 和 tls.keyIngress Controller 在收到 HTTPS 请求后,使用 Secret 中的证书解密,再以 HTTP 转发给后端 Service,实现 TLS 卸载。
延伸思考: 如果后端 Service 需要端到端加密(即 Ingress 不解密),应该如何配置?多 Ingress Controller 共存时如何隔离?
6. ConfigMap 和 Secret 都用于配置管理,它们在使用方式和安全性上有何不同?Secret 的数据是否真正"安全"?
难度: ⭐⭐
标准答案:
使用方式对比:
| 方面 | ConfigMap | Secret |
|---|---|---|
| 数据类型 | 非敏感配置(环境变量、配置文件) | 敏感数据(密码、证书、Token) |
| 存储大小限制 | 1 MiB | 1 MiB |
| 数据编码 | 明文存储 | Base64 编码存储 |
| 挂载方式 | 环境变量 / 卷挂载 | 环境变量 / 卷挂载 |
| tmpfs 挂载 | 磁盘存储 | 可配置为 tmpfs(内存) |
Secret 是否安全?
- Base64 ≠ 加密:Base64 只是编码,任何人
kubectl get secret -o yaml都能解码 - etcd 中默认明文存储,需启用 EncryptionConfiguration 对 etcd 中的 Secret 加密
- RBAC 可控制访问权限,但拥有权限的用户可直接读取
- 挂载到 Pod 的 Secret 以 tmpfs 形式存在内存中,节点磁盘不会留存
安全增强措施:
- 启用 etcd 加密存储(
EncryptionConfiguration) - 配置严格的 RBAC 策略
- 使用外部密钥管理(Vault、AWS Secrets Manager)通过 CSI Driver 注入
- 启用 Audit 日志审计 Secret 访问
- 使用
immutable: true防止 Secret 被意外修改
延伸思考: 为什么 Secret 的环境变量方式比卷挂载方式更不安全?immutable Secret 对集群性能有什么影响?
7. PV、PVC 和 StorageClass 三者的关系是什么?动态供给的工作流程是怎样的?
难度: ⭐⭐
标准答案:
三者关系:
- PV(PersistentVolume):集群级别的存储资源,由管理员预配置或动态创建,是存储的"物理实体"
- PVC(PersistentVolume Claim):命名空间级别的存储请求,用户声明需要的存储大小和访问模式,是存储的"消费申请"
- StorageClass:存储类定义,描述存储的"等级"和供给方式,将 PVC 与特定存储后端关联
绑定流程:
- 静态供给:管理员手动创建 PV → 用户创建 PVC → K8s 根据 capacity/accessMode 匹配绑定
- 动态供给:用户创建 PVC 并指定 StorageClass → StorageClass 调用 Provisioner 自动创建 PV → 自动绑定
动态供给工作流程:
- 用户创建 PVC,指定
storageClassName: fast-ssd和resources.requests.storage: 10Gi - K8s 找到对应的 StorageClass,确认其 Provisioner(如
kubernetes.io/aws-ebs) - Provisioner 调用云厂商 API 创建底层存储卷
- 自动创建对应的 PV 对象
- PVC 与 PV 自动绑定
- Pod 通过 PVC 使用该存储
回收策略(Reclaim Policy):
- Retain:删除 PVC 后 PV 保留,需手动清理
- Delete:删除 PVC 后自动删除 PV 和底层存储
- Recycle(已废弃):执行
rm -rf后重新可用
延伸思考: 当 PVC 请求的 StorageClass 不存在时会怎样?如何实现跨命名空间共享 PV?
8. HPA 和 VPA 的区别是什么?HPA 基于 CPU/内存和基于自定义指标扩缩容的配置有什么不同?
难度: ⭐⭐⭐
标准答案:
| 特性 | HPA(Horizontal Pod Autoscaler) | VPA(Vertical Pod Autoscaler) |
|---|---|---|
| 扩缩方式 | 增减 Pod 副本数 | 调整 Pod 的 CPU/内存请求和限制 |
| 适用场景 | 无状态应用、可水平扩展的服务 | 无法水平扩展的单体应用、JVM 类应用 |
| 实时性 | 秒级到分钟级响应 | 通常需要 Pod 重启才能生效 |
| 稳定性 | 较稳定,生产广泛使用 | 部分(Updater + Admission Controller)可生产使用 |
HPA 基于 CPU/内存扩缩容:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
spec:
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70 # CPU 使用率超过 70% 时扩容HPA 基于自定义指标扩缩容:
metrics:
- type: Pods
pods:
metric:
name: http_requests_per_second # 自定义指标名
target:
type: AverageValue
averageValue: 1000 # 每个 Pod 平均 1000 QPS关键差异:
- Resource 指标由 metrics-server 提供(CPU/内存)
- 自定义指标需部署 Prometheus Adapter(
custom.metrics.k8s.io)或外部指标适配器 - 外部指标(External)如 SQS 队列长度,使用
type: External
HPA 扩缩算法:desiredReplicas = ceil[currentReplicas × (currentMetric / desiredMetric)]
延伸思考: HPA 和 VPA 能否同时对同一个 Deployment 生效?为什么?HPA 的冷却期(cooldown)如何防止抖动?
9. Kubernetes 调度策略中,nodeSelector、nodeAffinity 和 taint/toleration 各自的使用场景和区别是什么?
难度: ⭐⭐⭐
标准答案:
nodeSelector:
- 最简单的调度约束,通过标签精确匹配节点
- 只支持
AND逻辑,无法表达"偏好"或"软约束"
spec:
nodeSelector:
disktype: ssd # Pod 只调度到有 disktype=ssd 标签的节点nodeAffinity:
- nodeSelector 的增强版,支持更丰富的表达式
- requiredDuringSchedulingIgnoredDuringExecution:硬约束,必须满足(等同于 nodeSelector)
- preferredDuringSchedulingIgnoredDuringExecution:软约束,尽量满足但不保证
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values: ["us-east-1a", "us-east-1b"]
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
preference:
matchExpressions:
- key: node-type
operator: In
values: ["high-mem"]taint / toleration:
- Taint 打在 Node 上,表示"排斥"效果;Toleration 写在 Pod 上,表示"容忍"该排斥
- 三个效果:
NoSchedule(不调度新 Pod)、PreferNoSchedule(尽量不调度)、NoExecute(驱逐已有 Pod)
# 节点打污点
kubectl taint nodes node1 dedicated=gpu:NoSchedule
# Pod 容忍污点
tolerations:
- key: "dedicated"
operator: "Equal"
value: "gpu"
effect: "NoSchedule"核心区别:
- nodeSelector/nodeAffinity:Pod 主动选择节点("我要去哪")
- taint/toleration:节点主动排斥 Pod("谁能来我这")
- 两者同时生效:Pod 必须同时满足亲和性条件且容忍节点污点才能调度
延伸思考: IgnoredDuringExecution 意味着什么?如果节点标签在 Pod 运行后改变了会怎样?NoExecute 污点的 tolerationSeconds 如何实现优雅驱逐?
10. 如何对运行中的 Pod 进行排障?请描述从 kubectl 命令到日志收集、事件排查的完整流程。
难度: ⭐⭐⭐
标准答案:
排障完整流程:
第一步:确认 Pod 状态
kubectl get pods -n <namespace> # 查看 Pod Phase 和 Ready 状态
kubectl describe pod <pod-name> -n <namespace> # 查看事件、状态、容器列表第二步:根据状态分类排查
| 状态 | 排查方向 | 命令 |
|---|---|---|
| Pending | 调度失败 | 查看 Events 中的 FailedScheduling 原因(资源不足/亲和性/污点) |
| ImagePullBackOff | 镜像拉取失败 | 检查镜像名、Tag、拉取凭证(imagePullSecrets) |
| CrashLoopBackOff | 容器启动后崩溃 | 查看容器日志和 Exit Code |
| OOMKilled | 内存溢出 | 检查 resources.limits.memory,调大或优化应用 |
| Completed | 正常退出 | 确认 restartPolicy 是否符合预期 |
第三步:查看容器日志
kubectl logs <pod-name> -c <container> -n <ns> # 当前容器日志
kubectl logs <pod-name> -c <container> --previous # 上一次崩溃的日志(关键!)
kubectl logs <pod-name> -c <container> --since=1h # 最近1小时日志
kubectl logs -l app=my-app --all-containers=true # 按 Label 批量查看第四步:进入容器调试
kubectl exec -it <pod-name> -c <container> -- /bin/sh # 进入容器终端
kubectl debug <pod-name> -it --image=busybox # 使用临时调试容器(Pod 无 shell 时)第五步:集群事件排查
kubectl get events -n <ns> --sort-by='.lastTimestamp' # 按时间排序查看事件
kubectl get events --field-selector reason=FailedScheduling # 过滤特定事件第六步:节点级排查
kubectl describe node <node-name> # 查看节点资源使用、条件(Ready/MemoryPressure)
kubectl top nodes # 实时资源使用
kubectl top pods -n <ns> # Pod 实时资源使用常见 Exit Code 含义:
0:正常退出1:应用错误137:被 SIGKILL 杀死(通常是 OOMKilled)139:段错误(SIGSEGV)143:被 SIGTERM 正常终止
延伸思考: 当 Pod 处于 CrashLoopBackOff 且日志没有任何输出时,如何排查?kubectl debug 的 ephemeral container 与普通 container 有什么区别?
End of Kubernetes 面试题