一、基础概念类(必问,奠定面试基础)
1. 什么是Kubernetes(K8s)?它的核心作用是什么?
答案:
Kubernetes是一个开源的、用于管理容器化应用的容器编排平台,由Google基于Borg系统(Google内部的容器管理工具)开源而来,遵循Apache 2.0协议,核心定位是“自动化容器的部署、扩展和管理”。
核心作用:解决容器化应用的“运维复杂性”——当应用被容器化后,单容器部署易管理,但多容器、多节点(集群)部署时,会面临容器调度、负载均衡、故障自愈、滚动更新、资源管控等问题,K8s通过统一的调度和管理机制,将这些操作自动化,实现“容器集群的高效运维”,让开发者专注于应用开发,而非底层部署运维。
原理拓展:
K8s的设计理念是“以应用为中心”,而非“以机器为中心”,它将容器抽象为“Pod”(最小部署单元),通过声明式API(用户只需要定义“想要的状态”,K8s自动实现该状态),屏蔽底层节点差异,实现应用的跨节点、跨环境部署。其核心思想借鉴了Google Borg的“自愈、弹性、自动调度”三大特性,本质是一个“分布式系统的操作系统”,管理着集群中的计算、存储、网络等资源,为容器化应用提供全生命周期管理。
延伸考点: K8s与Docker的关系——Docker是“容器化工具”(负责打包应用和依赖),K8s是“容器编排工具”(负责管理大量Docker容器),二者协同工作:Docker负责“造容器”,K8s负责“管容器”;此外,K8s支持多种容器运行时(如containerd、CRI-O),Docker只是其中一种,目前K8s已弃用Docker作为默认运行时(推荐containerd),但仍兼容Docker容器。
2. K8s的核心组件有哪些?每个组件的作用是什么?(重中之重)
答案:
K8s集群分为控制平面(Control Plane) 和节点(Node) 两部分,各组件协同工作,实现集群的正常运行,核心组件如下(按重要性排序):
(1)控制平面组件(集群的“大脑”,负责决策和管理,通常部署在Master节点)
- kube-apiserver:核心入口,所有集群操作(如创建Pod、部署Service)都通过API Server进行,它提供RESTful API接口,负责接收用户请求、验证请求合法性、将请求转发给其他组件,同时作为集群中所有组件的通信枢纽(其他组件不直接通信,均通过API Server交互)。 原理:API Server是“单一入口”,采用“声明式API”,用户提交的是“期望状态”(如Pod的副本数),API Server将状态存储到etcd,再触发其他组件去实现该状态;同时提供权限控制(RBAC)、准入控制(Admission Controller)等功能,保障集群安全。
- etcd:分布式键值存储数据库,是K8s集群的“数据中心”,存储集群的所有核心数据(如Pod配置、Service配置、集群节点信息、权限信息等),所有组件的状态数据都通过API Server写入etcd,且etcd支持高可用部署(至少3个节点),保证数据的一致性和可靠性。 原理:etcd基于Raft一致性算法,实现分布式数据同步,确保集群中多个etcd节点的数据一致;它是K8s的“状态来源”,如果etcd数据丢失,集群将无法正常运行,因此生产环境必须做好etcd的数据备份。
- kube-controller-manager:控制器管理器,运行着多个“控制器”(Controller),每个控制器负责监控集群的一种资源状态,对比“期望状态”和“实际状态”,一旦出现差异,就触发“调谐”(Reconciliation),将实际状态拉回到期望状态(即“自愈能力”的核心)。 常见控制器:Node Controller(节点故障检测与自愈)、ReplicaSet Controller(维护Pod副本数)、Deployment Controller(管理Deployment,实现Pod的滚动更新)、Service Controller(维护Service与Pod的关联)、EndpointSlice Controller(管理服务端点)等。 原理:控制器采用“循环调谐”机制,不断查询API Server获取资源的实际状态,与etcd中存储的期望状态对比,差异触发调谐操作,直到两者一致。
- kube-scheduler:调度器,负责将“未调度的Pod”分配到合适的Node节点上,分配的核心依据是“调度策略”(资源需求、节点亲和性、污点/容忍度、亲和性/反亲和性等)。 原理:调度过程分为两个阶段——① 筛选(Filter):排除不符合Pod资源需求、有污点且Pod无对应容忍度的节点,得到“可调度节点列表”;② 打分(Score):对可调度节点进行打分(如资源剩余量、节点负载、距离等),选择得分最高的节点分配Pod;调度完成后,将Pod与Node的关联信息写入etcd,由Node节点的kubelet执行Pod的启动。
(2)Node节点组件(集群的“工作节点”,负责运行容器,部署在Worker节点)
- kubelet:Node节点的核心组件,运行在每个Node上,负责与控制平面的API Server通信,接收并执行控制平面下发的指令(如启动Pod、停止Pod、监控Pod运行状态),同时负责Pod与容器运行时的交互,确保Pod中的容器正常运行。 原理:kubelet定期向API Server上报Node节点的状态(资源使用情况、节点健康状态)和Pod的运行状态,同时监听etcd中Pod的配置变化,当Pod的期望状态发生变化时,kubelet通过容器运行时(如containerd)操作容器(启动、停止、重启);此外,kubelet还负责执行Pod的健康检查(存活探针、就绪探针),若Pod健康检查失败,会触发重启或删除操作。
- kube-proxy:网络代理,运行在每个Node上,负责维护集群的网络规则,实现Pod之间、Pod与外部网络的通信,核心作用是“Service的负载均衡”和“网络隔离”。 原理:kube-proxy有三种工作模式(重点):① userspace模式(废弃):通过用户空间的代理进程转发流量,性能较差;② iptables模式(主流):通过Linux iptables规则实现流量转发,性能较好,但不支持会话保持;③ ipvs模式(推荐,生产环境常用):基于Linux IPVS(IP虚拟服务器)实现流量转发,支持多种负载均衡算法(轮询、最少连接等),性能优于iptables,且支持会话保持。kube-proxy会监听API Server中Service和EndpointSlice的变化,实时更新节点上的网络规则,确保流量能正确转发到对应的Pod。
- 容器运行时(Container Runtime) :负责运行容器的软件,是kubelet操作容器的“底层工具”,K8s通过CRI(容器运行时接口)与容器运行时交互,支持多种运行时。 常见容器运行时:① containerd(目前K8s默认,轻量级、高性能,是Docker的核心组件拆分而来);② CRI-O(专门为K8s设计的轻量级运行时);③ Docker(需通过cri-dockerd适配CRI,目前已不推荐作为默认运行时)。 原理:kubelet通过CRI接口向容器运行时发送指令(如创建容器、删除容器),容器运行时负责容器的生命周期管理(镜像拉取、容器启动、资源限制等),底层依赖Linux的容器技术(namespace、cgroups)。
拓展考点: 控制平面高可用部署——生产环境中,控制平面不能单节点部署(单点故障),通常部署3个Master节点,etcd集群也部署3个节点,kube-apiserver通过负载均衡器(如Nginx、HAProxy)暴露入口,确保控制平面的高可用;Node节点可根据业务需求横向扩展,增加集群的计算能力。
3. K8s中的Pod是什么?Pod的核心特点是什么?
答案:
Pod是K8s集群中最小的部署单元,也是K8s调度的最小单位,它不是容器,而是一个“容器组”——一个Pod可以包含一个或多个容器(通常是一个主容器+多个Sidecar容器,如日志收集、监控容器),这些容器共享Pod的网络命名空间(IP地址、端口)、存储卷(Volume)和运行环境,相当于一个“逻辑主机”。
Pod的核心特点:
- 共享网络:Pod内所有容器共享同一个网络命名空间(net namespace),拥有相同的IP地址和端口范围,容器之间可以通过localhost直接通信,无需跨网络调用;Pod的IP地址是集群内唯一的,由K8s的网络插件(如Calico、Flannel)分配。
- 共享存储:Pod可以定义存储卷(Volume),Pod内的所有容器都可以挂载这个Volume,实现容器之间的数据共享;Volume的生命周期与Pod一致(Pod删除,Volume中的数据也会丢失,除非使用持久化存储,如PV/PVC)。
- 生命周期与容器一致:Pod本身没有自愈能力,当Pod内的主容器故障且无法重启时,Pod会被标记为失败状态,需要通过控制器(如ReplicaSet、Deployment)重新创建新的Pod;Pod一旦被调度到某个Node节点,除非被删除或Node节点故障,否则不会被重新调度到其他节点(除非使用Pod亲和性/反亲和性或节点污点等策略)。
- 原子部署:K8s调度时,会将整个Pod作为一个整体调度到某个Node节点,不会将Pod内的容器拆分到不同节点;部署、更新、删除时,也是以Pod为单位进行操作。
原理拓展:
Pod的底层实现依赖Linux的namespace和cgroups:① namespace(命名空间):通过网络命名空间(net)实现Pod内容器的网络共享,通过PID命名空间(pid)实现容器内进程的隔离,通过挂载命名空间(mnt)实现容器的挂载隔离;② cgroups(控制组):通过cgroups限制Pod的资源(CPU、内存、磁盘IO等),确保Pod不会占用过多宿主机资源,影响其他Pod或节点。
延伸考点: Pod的两种类型——① 自主式Pod(Independent Pod):直接创建的Pod,没有控制器管理,一旦Pod故障,不会自动重启或重建,适合临时测试场景;② 受控Pod(Managed Pod):由控制器(如Deployment、StatefulSet、DaemonSet)管理的Pod,控制器会确保Pod的副本数和运行状态,具备自愈、弹性伸缩、滚动更新等能力,是生产环境的主流方式。
二、核心工作机制类(高频进阶,考察底层理解)
1. K8s的Pod生命周期包含哪些阶段?常见的状态有哪些?
答案:
Pod的生命周期从“创建”到“删除”,分为多个阶段,每个阶段对应不同的状态,核心阶段和状态如下(按执行顺序):
(1)Pod生命周期阶段(重点):
- Pending(挂起) :Pod已被API Server创建,但是还未被调度器分配到具体的Node节点,或者Node节点上的kubelet还未开始启动Pod内的容器(可能是正在拉取镜像、等待资源分配等)。
- Running(运行中) :Pod已被调度到Node节点,kubelet已启动Pod内的所有容器,且至少有一个容器处于运行状态(或正在启动、重启中)。
- Succeeded(成功) :Pod内的所有容器都已正常终止,且不会再重启(通常用于一次性任务,如Job),任务完成后Pod会保持该状态。
- Failed(失败) :Pod内的所有容器都已终止,但至少有一个容器是异常终止的(退出码非0),此时Pod会保持该状态,需要排查容器故障。
- Unknown(未知) :API Server无法获取Pod的状态(可能是Node节点故障、网络通信异常等),无法判断Pod的实际运行状态。
(2)Pod内容器的状态(补充):
- Waiting(等待):容器正在等待某个条件满足(如镜像拉取、依赖的Volume挂载)。
- Running(运行中):容器正常运行。
- Terminated(终止):容器已终止(正常或异常)。
原理拓展:
Pod的生命周期中,会触发多个“钩子函数”(Hook),用于在Pod的不同阶段执行自定义操作:① PostStart(启动后钩子):Pod内的容器启动后立即执行,常用于初始化配置(如修改配置文件、注册服务);② PreStop(停止前钩子):Pod被删除前执行,常用于优雅关闭容器(如停止服务、保存数据),避免数据丢失。
此外,Pod的健康检查(探针)会影响其生命周期:① 存活探针(livenessProbe):检测容器是否“存活”,若探针失败,kubelet会重启容器;② 就绪探针(readinessProbe):检测容器是否“就绪”(可提供服务),若探针失败,Pod会被从Service的端点列表中移除,不再接收流量;③ 启动探针(startupProbe):检测容器是否“启动完成”,适用于启动时间较长的容器(如Java应用),启动探针失败前,存活探针和就绪探针不会执行。
延伸考点: 如何排查Pod处于Pending状态的原因?——常见原因:① 资源不足(Node节点CPU、内存不足,无法满足Pod的资源请求);② 镜像拉取失败(镜像地址错误、镜像不存在、私有镜像未配置密钥);③ 节点污点(Pod无对应容忍度,无法被调度到有污点的节点);④ 调度器故障(控制平面的kube-scheduler未正常运行)。
2. K8s中的Deployment、ReplicaSet、Pod三者的关系是什么?Deployment的核心作用是什么?
答案:
三者是“层级管理”关系,从上到下依次是:Deployment → ReplicaSet → Pod,层层递进,各自负责不同的功能,协同实现Pod的全生命周期管理。
具体关系:
- Pod:最底层,是实际运行容器的载体,无自愈、无伸缩能力,是被管理的对象。
- ReplicaSet(RS) :中间层,核心作用是“维护Pod的副本数”,确保集群中始终有指定数量的Pod在运行(自愈能力的核心)。当Pod故障、删除或Node节点故障时,ReplicaSet会自动创建新的Pod,维持副本数不变;ReplicaSet通过“标签选择器”(selector)关联Pod,只有标签匹配的Pod才会被其管理。
- Deployment(部署) :最上层,不直接管理Pod,而是管理ReplicaSet,通过控制ReplicaSet的数量和配置,实现Pod的“滚动更新”“回滚”“弹性伸缩”等高级功能。Deployment会创建一个或多个ReplicaSet(滚动更新时会创建新的ReplicaSet,逐步替换旧的ReplicaSet),通过ReplicaSet间接管理Pod。
Deployment的核心作用(生产环境最常用,面试必问):
- 副本管理:通过ReplicaSet维护Pod的副本数,确保Pod的高可用(如指定3个副本,即使1个Node故障,其他2个副本仍能正常提供服务)。
- 滚动更新(Rolling Update) :这是Deployment最核心的功能,用于实现应用的“无停机更新”。更新时,Deployment会创建一个新的ReplicaSet,逐步增加新ReplicaSet的Pod副本数,同时逐步减少旧ReplicaSet的Pod副本数,直到旧ReplicaSet的Pod全部被替换,新的Pod全部启动,整个过程不中断服务,避免更新导致的业务 downtime。
- 回滚(Rollback) :当更新失败(如新Pod启动失败、应用报错)时,Deployment可以快速回滚到上一个稳定版本,只需执行回滚命令,Deployment会重新激活旧的ReplicaSet,删除新的ReplicaSet,恢复到更新前的状态。
- 弹性伸缩(Horizontal Pod Autoscaler,HPA) :Deployment支持与HPA联动,根据集群的CPU利用率、内存利用率或自定义指标(如QPS、并发数),自动增加或减少Pod的副本数,实现资源的动态分配,避免资源浪费或服务过载。
原理拓展:
Deployment的滚动更新原理:Deployment通过“滚动更新策略”(strategy)控制更新过程,核心参数包括:① maxSurge(最大超出副本数):更新过程中,允许超出期望副本数的最大数量(如期望副本数3,maxSurge=1,则更新时最多有4个Pod运行);② maxUnavailable(最大不可用副本数):更新过程中,允许不可用的Pod最大数量(如maxUnavailable=0,则更新时不允许有Pod不可用,确保服务不中断)。更新时,新ReplicaSet的副本数从0开始增加,旧ReplicaSet的副本数从期望数开始减少,直到旧ReplicaSet副本数为0,更新完成。
延伸考点: Deployment与StatefulSet的区别——Deployment适用于“无状态应用”(如Web服务、API服务),Pod之间无差异,可随意替换,不依赖固定的网络标识和存储;StatefulSet适用于“有状态应用”(如数据库、Redis集群),Pod有固定的名称、网络标识(如hostname)和持久化存储,Pod之间有依赖关系,不能随意替换,删除后重建的Pod会保持原有的标识和存储。
3. K8s中的Service是什么?Service的核心作用是什么?常见的Service类型有哪些?
答案:
Service是K8s中用于“暴露Pod网络服务”的资源,核心作用是“解决Pod的IP不固定问题”——Pod的生命周期是短暂的(重启、重建、滚动更新时,Pod的IP会变化),如果直接通过Pod的IP访问服务,会导致服务不可用;Service通过“标签选择器”关联Pod,为Pod提供一个固定的集群内部IP(ClusterIP)和端口,无论Pod如何变化,只要标签匹配,Service就能转发流量到对应的Pod,实现服务的稳定访问。
Service的核心作用:
- 固定访问入口:为一组Pod提供固定的ClusterIP和端口,外部(集群内其他Pod或外部服务)通过Service的IP和端口访问Pod,无需关注Pod的IP变化。
- 负载均衡:将请求均匀分发到关联的多个Pod上,实现负载分担,提高服务的可用性和并发能力(由kube-proxy实现负载均衡)。
- 服务发现:集群内的Pod可以通过Service的名称(DNS解析)访问服务,无需记住Service的IP地址(K8s内置DNS插件,如CoreDNS,实现Service名称到ClusterIP的解析)。
常见的Service类型(重点,面试高频):
- ClusterIP(默认类型) :只能在集群内部访问,为Service分配一个集群内部唯一的IP(ClusterIP),无法被集群外部访问,适用于集群内部服务之间的通信(如后端API服务被前端Web服务访问)。 原理:kube-proxy在每个Node节点上配置iptables/ipvs规则,将访问ClusterIP:端口的流量,转发到关联的Pod的IP:端口,实现负载均衡。
- NodePort(节点端口) :在每个Node节点上开放一个固定的端口(NodePort,范围30000-32767),外部可以通过“NodeIP:NodePort”访问Service,进而访问Pod。适用于测试环境或小型应用,不推荐生产环境(端口范围有限,且需要暴露NodeIP)。 原理:外部请求访问NodeIP:NodePort,kube-proxy将流量转发到Service的ClusterIP:端口,再转发到Pod,本质是在ClusterIP的基础上,增加了一个节点端口的转发规则。
- LoadBalancer(负载均衡器) :适用于云环境(如阿里云、AWS、Google Cloud),会自动申请云厂商的负载均衡器(如阿里云SLB),外部流量通过负载均衡器访问Service,负载均衡器会将流量分发到集群内的Node节点,再由kube-proxy转发到Pod。适用于生产环境,实现外部流量的稳定接入。 原理:Service创建后,云厂商的控制器会监听Service的变化,自动创建负载均衡器,并将集群内所有Node的NodePort添加到负载均衡器的后端,外部流量先经过负载均衡器,再分发到Node节点,最后转发到Pod。
- ExternalName(外部名称) :将Service映射到一个外部域名(如www.baidu.com),集群内的Pod访问该Service时,会被解析到外部域名,适用于访问集群外部的服务(如外部数据库、第三方API)。 原理:通过CoreDNS将Service名称解析为指定的外部域名,无需kube-proxy参与转发,直接访问外部服务。
拓展考点:
① Service与Ingress的区别:Service只能实现“四层负载均衡”(基于TCP/UDP端口),无法实现域名路由、路径路由、SSL终止等功能;Ingress是“七层负载均衡”(基于HTTP/HTTPS),可以实现域名路由(一个域名对应多个Service)、路径路由(一个域名的不同路径对应不同Service)、SSL证书配置等功能,通常与LoadBalancer配合使用,实现外部流量的精细化管理。
② Service的会话保持:默认情况下,Service的负载均衡是无状态的(每次请求可能分发到不同的Pod),如果需要会话保持(同一客户端的请求始终分发到同一个Pod),可以使用ipvs模式的kube-proxy,并配置sessionAffinity: ClientIP(基于客户端IP的会话保持)。
三、资源管理与调度类(高频,考察实战能力)
1. K8s如何进行资源管理?Pod的资源请求(requests)和资源限制(limits)有什么区别?
答案:
K8s的资源管理核心是“对Pod的CPU、内存等资源进行限制和分配”,避免单个Pod占用过多资源,导致其他Pod或节点故障,同时确保Pod能获得足够的资源正常运行。K8s支持的核心资源包括CPU(单位:毫核,1核=1000毫核)、内存(单位:Mi、Gi),此外还支持磁盘IO、GPU等扩展资源。
Pod的资源请求(requests)和资源限制(limits)是资源管理的核心配置,二者区别如下:
- 资源请求(requests) :Pod启动时,向K8s请求的最小资源量,用于K8s调度器筛选节点——调度器会选择“剩余资源≥Pod请求资源”的节点,才能将Pod调度到该节点。requests是“最小保障”,K8s会确保Pod能获得至少requests指定的资源,不会被其他Pod抢占(除非开启资源抢占机制)。 示例:requests: {cpu: 100m, memory: 256Mi},表示Pod启动时至少需要100毫核CPU和256Mi内存,调度器只会将其调度到剩余CPU≥100m、剩余内存≥256Mi的节点。
- 资源限制(limits) :Pod运行时,允许占用的最大资源量,是“上限约束”——如果Pod的资源使用量超过limits,K8s会对Pod进行“限流”或“终止”:① CPU超过limits:K8s会对Pod进行CPU节流(throttling),限制Pod的CPU使用,不会终止Pod;② 内存超过limits:Pod会被标记为OOM(Out Of Memory),kubelet会终止该Pod,并重启(根据Pod的重启策略)。 示例:limits: {cpu: 500m, memory: 512Mi},表示Pod运行时,CPU最大只能使用500毫核,内存最大只能使用512Mi,超过则会被限流或终止。
原理拓展:
K8s的资源管理底层依赖Linux的cgroups(控制组):① CPU资源:通过cgroups的cpu子系统限制CPU的使用时间(如CPU limits通过cpu.cfs_quota_us和cpu.cfs_period_us配置,控制单位时间内Pod能使用的CPU时间);② 内存资源:通过cgroups的memory子系统限制Pod的内存使用量(如memory.limit_in_bytes配置内存上限),当内存使用超过上限时,内核会触发OOM killer,终止Pod的进程。
此外,K8s支持“资源超配”(Overcommit)——即节点的总资源请求可以超过节点的实际资源(如节点有1核CPU,多个Pod的CPU requests总和可以超过1核),适用于Pod资源使用率较低的场景,提高资源利用率;但如果Pod的实际资源使用量超过节点实际资源,会导致资源竞争,可能出现Pod被终止的情况,生产环境需谨慎配置。
延伸考点: 资源QoS(服务质量等级)——K8s根据Pod的requests和limits配置,将Pod分为三个QoS等级,用于在资源不足时,决定优先终止哪个Pod:① Guaranteed(保证级):Pod的requests和limits相等(如cpu: 500m,limits: 500m),资源优先级最高,只有当节点资源耗尽时,才会被终止;② Burstable(突发级):Pod的requests小于limits,资源优先级中等,当资源不足时,优先终止这类Pod;③ BestEffort(尽力而为级):Pod未配置requests和limits,资源优先级最低,资源不足时,最先被终止,适用于非核心、可容忍中断的应用。
2. K8s的调度策略有哪些?什么是污点(Taint)和容忍度(Toleration)?
答案:
K8s的调度策略是kube-scheduler将Pod分配到Node节点的依据,核心分为“默认调度策略”和“自定义调度策略”,目的是确保Pod被调度到合适的节点,提高集群资源利用率和服务可用性。
(1)常见调度策略(重点):
- 节点亲和性(Node Affinity) :Pod通过配置亲和性规则,指定“希望被调度到哪些节点”,分为两种:① 硬亲和性(requiredDuringSchedulingIgnoredDuringExecution):必须满足规则,否则Pod无法被调度(如Pod必须调度到有“disk=ssd”标签的节点);② 软亲和性(preferredDuringSchedulingIgnoredDuringExecution):优先满足规则,若没有满足的节点,也可以调度到其他节点(如优先调度到“region=beijing”的节点)。
- Pod亲和性/反亲和性(Pod Affinity/Anti-Affinity) :根据集群中已有的Pod的标签,决定新Pod的调度位置:① Pod亲和性:新Pod希望被调度到与指定Pod在同一节点/同一拓扑域(如同一机房、同一机架)的节点(如前端Pod希望与后端Pod在同一节点,减少网络延迟);② Pod反亲和性:新Pod不希望被调度到与指定Pod在同一节点/同一拓扑域的节点(如数据库Pod不希望与其他高负载Pod在同一节点,避免资源竞争)。
- 污点(Taint)和容忍度(Toleration) :与亲和性相反,污点是Node节点的“排斥规则”,容忍度是Pod的“接受规则”——Node节点添加污点后,会排斥所有没有对应容忍度的Pod,只有Pod配置了对应容忍度,才能被调度到该节点。
- 节点选择器(Node Selector) :简单的调度策略,Pod通过nodeSelector配置,指定要调度到具有特定标签的Node节点(如nodeSelector: {disk: ssd},Pod只能调度到有“disk=ssd”标签的节点),功能比节点亲和性简单,仅支持精确匹配。
(2)污点(Taint)和容忍度(Toleration)详解(面试高频):
① 污点的组成:每个污点由“key=value:effect”三部分组成,其中effect是污点的作用效果,分为三种:
- NoSchedule:仅排斥新Pod调度到该节点,已调度到该节点的Pod可以继续运行(不会被驱逐)。
- NoExecute:既排斥新Pod调度到该节点,也会将已调度到该节点、没有对应容忍度的Pod驱逐。
- PreferNoSchedule:优先排斥新Pod调度到该节点,若没有其他合适的节点,新Pod也可以被调度到该节点。
② 容忍度的配置:Pod通过tolerations配置,指定能容忍的污点,格式与污点对应,只需匹配key、value(可选)和effect,即可容忍该污点。
示例:Node节点添加污点“node-role.kubernetes.io/master:NoSchedule”(默认Master节点会添加该污点,避免普通Pod被调度到Master节点),若想让某个Pod被调度到Master节点,需在Pod中配置容忍度:
tolerations:
- key: "node-role.kubernetes.io/master"
operator: "Exists"
effect: "NoSchedule"
原理拓展:
污点和容忍度的核心作用是“节点隔离”,适用于特殊节点的管理:① Master节点:添加NoSchedule污点,避免普通Pod占用Master节点资源,影响控制平面运行;② 专用节点:如GPU节点,添加污点,只有需要GPU资源的Pod(配置了对应容忍度)才能被调度到该节点,避免资源浪费;③ 故障节点:给故障节点添加NoExecute污点,驱逐该节点上的所有Pod,避免故障影响服务。
延伸考点: 调度器的自定义配置——生产环境中,默认调度策略可能无法满足需求,可通过修改kube-scheduler的配置文件,自定义调度策略(如调整打分权重、添加自定义调度插件),实现更精细的调度控制。
四、持久化存储类(高频,考察生产实战)
1. K8s中的持久化存储是什么?为什么需要持久化存储?
答案:
K8s中的持久化存储(Persistent Storage)是指“不受Pod生命周期影响的存储”,用于存储应用的数据(如数据库数据、日志文件),即使Pod被删除、重启、重建,数据也不会丢失。
为什么需要持久化存储?——默认情况下,Pod使用的是“临时存储”(EmptyDir、HostPath等),存在两个问题:① EmptyDir:存储在Node节点的本地磁盘,Pod删除后,EmptyDir中的数据会被删除;② HostPath:存储在Node节点的本地目录,Pod被调度到其他Node节点后,无法访问原Node节点的HostPath数据,且Node节点故障会导致数据丢失。
对于有状态应用(如数据库、Redis、Elasticsearch),数据的持久性至关重要,临时存储无法满足需求,因此需要持久化存储,将数据存储在集群外部的独立存储设备(如磁盘阵列、云存储、分布式存储)中,实现数据的持久化和跨节点访问。
原理拓展:
K8s的持久化存储体系分为三层,从上到下依次是:PVC → PV → 存储后端,层层关联,实现存储的抽象和管理:
- 存储后端:实际的存储设备(如本地磁盘、NFS、阿里云OSS、Ceph、GlusterFS等),是数据存储的物理载体。
- PV(Persistent Volume,持久卷):由集群管理员创建,是对存储后端的“抽象”,定义了存储的容量、访问模式(如ReadWriteOnce、ReadOnlyMany、ReadWriteMany)、存储类型等,PV是集群级别的资源,不依赖于Pod,可被多个Pod复用。
- PVC(Persistent Volume Claim,持久卷声明):由用户创建,是Pod对存储的“请求”,用户通过PVC指定需要的存储容量、访问模式、存储类型等,K8s会自动匹配符合条件的PV,将PVC与PV绑定,Pod通过挂载PVC,即可访问对应的存储后端数据。
延伸考点: PV的访问模式(Access Modes)——三种核心访问模式,决定了PV可以被多少节点、多少Pod访问:① ReadWriteOnce(RWO):只能被一个节点上的一个或多个Pod以读写方式挂载(最常用,如数据库);② ReadOnlyMany(ROX):可以被多个节点上的多个Pod以只读方式挂载(如共享配置文件);③ ReadWriteMany(RWX):可以被多个节点上的多个Pod以读写方式挂载(如分布式存储,如Ceph、GlusterFS)。
2. PV和PVC的关系是什么?什么是StorageClass?
答案:
(1)PV和PVC的关系:一对一绑定、动态匹配,PV是“供给”,PVC是“需求”,二者通过“存储容量、访问模式、存储类型”进行匹配,绑定后,PVC就可以被Pod挂载使用,直到PVC被删除,PV才会被释放(根据PV的回收策略)。
核心特点:
- 绑定规则:一个PVC只能绑定一个PV,一个PV只能被一个PVC绑定(除非PV的访问模式是RWX,且PVC被删除后PV被重新绑定)。
- 匹配逻辑:K8s会优先匹配“存储类型、访问模式”完全一致,且“容量≥PVC请求容量”的PV,若有多个符合条件的PV,会选择容量最小的PV进行绑定。
- PV的回收策略:PV被PVC解绑后,数据的处理方式,分为三种:① Retain(保留):保留PV和数据,需要管理员手动删除PV和数据;② Delete(删除):自动删除PV和对应的存储后端数据(适用于云存储,如阿里云云盘);③ Recycle(回收,已废弃):清除PV中的数据,将PV重新变为可用状态,供其他PVC绑定。
(2)StorageClass(存储类):核心作用是“动态创建PV”,解决手动创建PV的繁琐问题(生产环境中,PV数量多,手动创建效率低,且难以适配PVC的动态需求)。
StorageClass的工作原理:
- 集群管理员创建StorageClass,定义存储的“ provisioner(供应者)”(如阿里云云盘的provisioner、NFS的provisioner)、存储类型、访问模式、回收策略等。
- 用户创建PVC时,指定对应的StorageClass名称,K8s会通过StorageClass的provisioner,自动创建对应的PV,并将PVC与PV绑定,无需管理员手动创建PV。
- 当PVC被删除后,PV会根据StorageClass定义的回收策略,自动删除或保留,实现存储的动态管理。
原理拓展:
StorageClass的核心是“provisioner(供应者)”,不同的存储后端对应不同的provisioner,provisioner负责与存储后端交互,实现PV的动态创建和删除:① 云存储(如阿里云、AWS):有对应的官方provisioner,可直接使用;② 本地存储(如NFS、本地磁盘):需要安装第三方provisioner(如nfs-subdir-external-provisioner),才能实现PV的动态创建。
延伸考点: 静态PV与动态PV的区别——① 静态PV:由管理员手动创建,适用于存储需求固定、数量较少的场景;② 动态PV:由StorageClass自动创建,适用于存储需求动态变化、数量较多的场景,生产环境首选动态PV,提高运维效率。
五、进阶实战类(面试难点,区分能力层次)
1. K8s的网络模型是什么?常见的网络插件有哪些?
答案:
K8s的网络模型核心目标是“实现集群内所有Pod的互联互通,且Pod的IP地址在集群内唯一”,K8s本身不实现网络功能,而是通过“网络插件”(CNI插件)实现,遵循CNI(Container Network Interface,容器网络接口)规范,确保不同网络插件的兼容性。
K8s网络模型的核心原则(必记):
- 每个Pod都有一个独立的IP地址,Pod内的所有容器共享该IP地址。
- 集群内所有Pod之间可以直接通信,无需NAT转换(Pod到Pod的通信是直连)。
- Pod与Node节点之间可以直接通信,无需NAT转换。
- Pod与外部网络之间的通信,需要通过Service(如NodePort、LoadBalancer)或Ingress实现,需要NAT转换。
常见的网络插件(面试高频,重点掌握前2个):
- Calico:目前最主流的K8s网络插件,基于BGP(边界网关协议)实现Pod之间的通信,支持网络策略(NetworkPolicy),可以实现Pod之间的网络隔离(如限制某个Pod只能访问特定Pod),性能优异,适用于大规模集群(千级、万级节点),支持多种网络模式(BGP、IPIP、VXLAN)。 原理:Calico为每个Node节点分配一个IP地址段,每个Pod从Node的IP段中获取IP地址;Node节点之间通过BGP协议交换路由信息,实现Pod之间的直连通信;网络策略通过iptables规则实现,控制Pod的入站和出站流量。
- Flannel:最基础、最常用的网络插件,易于部署和维护,适用于中小型集群,不支持网络策略(需配合其他插件,如Calico)。 原理:Flannel有多种后端模式(如vxlan、host-gw、udp),最常用的是vxlan模式——Flannel为每个Node节点分配一个IP地址段,Pod的IP地址从Node的IP段中获取;Node节点之间通过vxlan隧道封装IP数据包,实现Pod之间的跨节点通信(本质是将Pod的IP数据包封装在Node的IP数据包中,通过Node之间的网络传输)。
- Weave Net:轻量级网络插件,支持自动发现节点,无需额外配置,支持网络策略,适用于中小型集群,性能略逊于Calico。
- Cilium:基于eBPF(扩展Berkeley包过滤器)实现的高性能网络插件,支持网络策略、流量监控、可观测性,适用于对性能和可观测性要求较高的集群,是云原生场景的新兴选择。
拓展考点: 网络策略(NetworkPolicy)——K8s的网络安全机制,由网络插件(如Calico、Cilium)实现,用于控制Pod之间的网络通信,支持入站(Ingress)和出站(Egress)规则,可根据Pod标签、命名空间、IP地址、端口等条件,限制Pod的通信范围,提高集群的网络安全性。
2. K8s的集群故障排查思路是什么?常见的故障场景有哪些?
答案:
K8s集群故障排查的核心思路是“从顶层到底层,从现象到本质”,逐步定位故障原因,核心排查流程:查看Pod状态 → 查看Pod日志 → 查看控制器状态 → 查看节点状态 → 查看控制平面组件状态 → 排查网络/存储问题。
(1)核心排查命令(必记,面试高频):
- 查看Pod状态:kubectl get pods -n 命名空间(查看Pod的状态,如Pending、Running、Failed);kubectl describe pod Pod名称 -n 命名空间(查看Pod的详细信息,包括调度信息、事件、容器状态等)。
- 查看Pod日志:kubectl logs Pod名称 -n 命名空间(查看Pod的日志,排查容器故障);kubectl logs Pod名称 -n 命名空间 -c 容器名称(多容器Pod,指定容器查看日志)。
- 查看控制器状态:kubectl get deployment/rs/statefulset -n 命名空间(查看控制器的状态,如副本数、就绪数);kubectl describe deployment 名称 -n 命名空间(查看控制器的详细信息,包括滚动更新记录、事件等)。
- 查看节点状态:kubectl get nodes(查看所有节点的状态,如Ready、NotReady);kubectl describe node 节点名称(查看节点的资源使用情况、污点、事件等)。
- 查看控制平面组件状态:kubectl get pods -n kube-system(查看控制平面组件的Pod状态,如kube-apiserver、etcd、kube-controller-manager、kube-scheduler)。
- 查看网络状态:kubectl get svc/ingress -n 命名空间(查看Service、Ingress的状态);kubectl exec -it Pod名称 -n 命名空间 -- ping 目标IP(测试Pod之间的网络连通性)。
(2)常见故障场景及排查思路(面试高频):
- Pod处于Pending状态:排查方向:① 资源不足(查看节点资源使用情况,kubectl top node);② 镜像拉取失败(查看Pod事件,kubectl describe pod,确认镜像地址是否正确、私有镜像是否配置密钥);③ 节点污点(查看节点污点,kubectl describe node,确认Pod是否有对应容忍度);④ 调度器故障(查看kube-scheduler Pod状态,kubectl get pods -n kube-system)。
- Pod处于Running状态,但服务无法访问:排查方向:① 容器未正常启动(查看Pod日志,kubectl logs,确认应用是否报错);② 就绪探针失败(查看Pod描述,确认就绪探针配置是否正确,应用是否真正就绪);③ Service未关联Pod(查看Service的标签选择器,确认与Pod的标签匹配);④ 网络插件故障(查看网络插件Pod状态,如Calico、Flannel,测试Pod之间的网络连通性)。
- Pod频繁重启:排查方向:① 存活探针失败(查看存活探针配置,确认应用是否稳定运行);② 容器内存溢出(查看Pod资源限制,kubectl describe pod,确认内存limits是否足够,查看应用日志是否有OOM报错);③ 应用本身故障(查看Pod日志,排查应用代码或配置问题)。
- Node节点处于NotReady状态:排查方向:① 节点网络故障(检查节点与控制平面的网络连通性,如ping API Server的IP);② kubelet故障(查看kubelet服务状态,systemctl status kubelet);③ 节点资源耗尽(查看节点资源使用情况,kubectl top node,确认CPU、内存是否耗尽);④ 容器运行时故障(查看containerd/cri-o服务状态)。
- Service无法访问:排查方向:① Service的ClusterIP无法访问(测试Pod与Service的连通性,确认Service的标签选择器是否正确);② NodePort无法访问(检查NodePort端口是否开放,防火墙是否放行,kube-proxy是否正常运行);③ LoadBalancer无法访问(检查云厂商负载均衡器是否正常,后端节点是否健康)。
综上,K8s集群故障排查的核心是“精准定位、逐层排查”,熟练掌握核心排查命令,结合故障现象快速锁定问题层级(Pod、控制器、节点、控制平面、网络/存储),是面试中考察实战能力的核心要点,也是生产环境中保障集群稳定运行的必备技能。后续面试中,若遇到具体故障场景,可按照上述思路逐步拆解,结合原理分析问题根源,同时结合实际操作经验给出解决方案,更能体现自身的专业能力。