Skip to content

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):

  1. Pending:Pod 已被接受但容器尚未启动(正在调度或拉取镜像)
  2. Running:Pod 已绑定到节点,至少一个容器正在运行或正在启动
  3. Succeeded:Pod 中所有容器成功终止且不会重启
  4. Failed:Pod 中所有容器已终止,且至少一个容器以失败状态退出
  5. Unknown:无法获取 Pod 状态,通常是与 Node 通信失败

容器启动顺序控制:

  • initContainers:按定义顺序逐个执行,前一个成功完成后才启动下一个,全部完成后才启动主容器
  • 主容器之间并行启动,无严格顺序保证

容器终止顺序:

  • Pod 终止时,所有容器同时收到 SIGTERM 信号
  • 通过 preStop hook 可以在 SIGTERM 之前执行清理逻辑
  • terminationGracePeriodSeconds(默认 30s)超时后发送 SIGKILL 强制终止
  • 终止顺序与启动顺序相反:先启动的最后终止(网络层面),但信号是并行发出的

延伸思考: 如何确保应用优雅退出?如果 preStop hook 执行时间超过 terminationGracePeriodSeconds 会怎样?


3. Deployment、StatefulSet 和 DaemonSet 三种工作负载分别适用于什么场景?核心差异是什么? ​

难度: ⭐⭐

标准答案:

特性DeploymentStatefulSetDaemonSet
适用场景无状态应用(Web服务、API)有状态应用(数据库、ZK)节点级守护进程(日志采集、监控)
Pod 名称随机后缀(app-7d4f8b)有序编号(app-0, app-1)每节点一个(app-xxxx)
扩缩容随机创建/删除有序创建/删除(逆序)随节点增减自动调整
更新策略RollingUpdate/RecreateRollingUpdate/OnDeleteRollingUpdate/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 类型:

  1. ClusterIP(默认):分配一个集群内部虚拟 IP,仅在集群内可访问。通过 kube-proxy 维护的 iptables/IPVS 规则将流量负载均衡到后端 Pod。
  2. NodePort:在 ClusterIP 基础上,在每个节点上开放一个静态端口(30000-32767),外部可通过 <NodeIP>:<NodePort> 访问。
  3. LoadBalancer:在 NodePort 基础上,向云厂商请求一个外部负载均衡器(如 AWS ELB、GCP LB),流量经 LB → NodePort → Pod。
  4. 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 配置文件),实现流量转发

基于域名的虚拟主机路由示例:

yaml
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: 80

TLS 终止:

yaml
spec:
  tls:
  - hosts:
    - app1.example.com
    secretName: app1-tls-secret   # 包含 tls.crt 和 tls.key

Ingress Controller 在收到 HTTPS 请求后,使用 Secret 中的证书解密,再以 HTTP 转发给后端 Service,实现 TLS 卸载。

延伸思考: 如果后端 Service 需要端到端加密(即 Ingress 不解密),应该如何配置?多 Ingress Controller 共存时如何隔离?


6. ConfigMap 和 Secret 都用于配置管理,它们在使用方式和安全性上有何不同?Secret 的数据是否真正"安全"? ​

难度: ⭐⭐

标准答案:

使用方式对比:

方面ConfigMapSecret
数据类型非敏感配置(环境变量、配置文件)敏感数据(密码、证书、Token)
存储大小限制1 MiB1 MiB
数据编码明文存储Base64 编码存储
挂载方式环境变量 / 卷挂载环境变量 / 卷挂载
tmpfs 挂载磁盘存储可配置为 tmpfs(内存)

Secret 是否安全?

  • Base64 ≠ 加密:Base64 只是编码,任何人 kubectl get secret -o yaml 都能解码
  • etcd 中默认明文存储,需启用 EncryptionConfiguration 对 etcd 中的 Secret 加密
  • RBAC 可控制访问权限,但拥有权限的用户可直接读取
  • 挂载到 Pod 的 Secret 以 tmpfs 形式存在内存中,节点磁盘不会留存

安全增强措施:

  1. 启用 etcd 加密存储(EncryptionConfiguration)
  2. 配置严格的 RBAC 策略
  3. 使用外部密钥管理(Vault、AWS Secrets Manager)通过 CSI Driver 注入
  4. 启用 Audit 日志审计 Secret 访问
  5. 使用 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 → 自动绑定

动态供给工作流程:

  1. 用户创建 PVC,指定 storageClassName: fast-ssd 和 resources.requests.storage: 10Gi
  2. K8s 找到对应的 StorageClass,确认其 Provisioner(如 kubernetes.io/aws-ebs)
  3. Provisioner 调用云厂商 API 创建底层存储卷
  4. 自动创建对应的 PV 对象
  5. PVC 与 PV 自动绑定
  6. 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/内存扩缩容:

yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
spec:
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70   # CPU 使用率超过 70% 时扩容

HPA 基于自定义指标扩缩容:

yaml
  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 逻辑,无法表达"偏好"或"软约束"
yaml
spec:
  nodeSelector:
    disktype: ssd    # Pod 只调度到有 disktype=ssd 标签的节点

nodeAffinity:

  • nodeSelector 的增强版,支持更丰富的表达式
  • requiredDuringSchedulingIgnoredDuringExecution:硬约束,必须满足(等同于 nodeSelector)
  • preferredDuringSchedulingIgnoredDuringExecution:软约束,尽量满足但不保证
yaml
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)
bash
# 节点打污点
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 状态

bash
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 是否符合预期

第三步:查看容器日志

bash
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 批量查看

第四步:进入容器调试

bash
kubectl exec -it <pod-name> -c <container> -- /bin/sh    # 进入容器终端
kubectl debug <pod-name> -it --image=busybox             # 使用临时调试容器(Pod 无 shell 时)

第五步:集群事件排查

bash
kubectl get events -n <ns> --sort-by='.lastTimestamp'     # 按时间排序查看事件
kubectl get events --field-selector reason=FailedScheduling  # 过滤特定事件

第六步:节点级排查

bash
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 面试题