Kubernetes 入门教程之二
大纲
- Kubernetes 入门教程之一、Kubernetes 入门教程之二、Kubernetes 入门教程之三
- Kubernetes 入门教程之四、Kubernetes 入门教程之五、Kubernetes 入门教程之六
- Kubernetes 入门教程之七、Kubernetes 入门教程之八、Kubernetes 入门教程之九
- Kubernetes 入门教程之十
Kubernetes 核心技术
Pod
Pod 的基础概念
Pod 的概述
Pod 是 Kubernetes 中可以创建和管理的最小资源单元,是用户在资源对象模型中创建或部署的基本单位,也是 Kubernetes 上运行容器化应用的直接载体。Kubernetes 并不会直接管理容器,而是通过管理 Pod 来间接管理容器。一个 Pod 通常由一个或多个容器组成,这些容器共享网络、存储等资源,并作为一个整体被调度和管理。在 Kubernetes 中,其他资源对象主要用于支撑或扩展 Pod 的功能,例如:Controller 资源用于管理和控制 Pod 的生命周期;Service 或 Ingress 资源用于暴露和访问 Pod;而 PersistentVolume (PV) 等存储资源用于为 Pod 提供持久化存储支持。此外,每个 Pod 都包含一个特殊的系统容器,称为 Pause 容器,它作为 Pod 的 “根容器” 存在,用于占据 Pod 的网络命名空间等资源。除了 Pause 容器,Pod 中还包含一个或多个紧密相关的用户业务容器,所有业务容器都在同一个 Namespace 里面,可以实现网络共享;这些容器协同工作,共同完成某项具体的业务功能。
Pod 的特性
资源共享
- 一个 Pod 里的多个容器可以共享存储和网络,可以看作一个逻辑的主机(服务器),共享 Namespace(命名空间)、Cgroups(控制组)或者其他的隔离资源。
- 同一个 Pod 中的多个容器共享同一个 Network Namespace,因此它们共享同一个 IP 地址和端口空间。也就是说,Pod 内的容器可以通过
localhost进行通信。需要注意的是,多个容器在同一个 Pod 中运行时,应避免端口冲突。不同的 Pod 之间具有各自独立的 IP 地址,默认情况下,不同 Pod 中的容器之间不能通过 IPC 机制通信(除非做了特殊配置),通常使用 Pod 的 IP 地址进行网络通信。 - 一个 Pod 中的多个容器可以共享同一个存储卷,该存储卷作为 Pod 的一部分被定义,并可以挂载到该 Pod 内所有容器的文件系统中,从而实现数据共享和持久化存储。
生命周期短暂
- Pod 是生命周期相对短暂的组件,例如当 Pod 所在的节点发生故障时,该节点上的 Pod 会被重新调度到其他节点上运行。但需要注意的是,重新调度后创建的是一个全新的 Pod,与原来的 Pod 没有任何关联,原有的状态、数据和标识都会丢失,二者之间没有任何直接关系。
平坦的网络
- Kubernetes 集群中的所有 Pod 都处于同一个共享的网络地址空间中,这意味着每个 Pod 都可以通过其他 Pod 的 IP 地址直接进行访问和通信,无需进行额外的网络配置。
Docker 容器与宿主机进程的关系
- Docker 容器里的进程没有独立 Linux 内核,使用的是宿主机内核,它本质就是宿主机进程。
- Docker 容器只是由 Linux 内核提供的隔离(Namespace) + 资源限制(Cgroups)环境。
- 当宿主机关掉 Docker 容器主进程,容器就会退出运行(容器生命周期依赖主进程)。换言之,Docker 容器主进程如果挂掉,容器就会停止运行。
- Docker 容器的 Linux 内核版本永远等于宿主机的内核版本,更换镜像也换不掉内核。比如,当宿主机内核版本低(例如
3.3),容器里即使是最新版本的 Ubuntu,也无法使用高版本内核才有的特性(比如一些新 Cgroup 特性、eBPF)。
Pod 的分类
Pod 有两种类型:
普通 Pod
- 普通 Pod 被创建后会被存储到 Etcd 中,随后由 Kubernetes Master 调度到某个特定的 Node(工作节点)上并与之绑定。该 Node(工作节点)上的 kubelet 进程会负责将 Pod 实例化为一组相关的容器(如 Docker 容器)并启动它们。默认情况下,如果 Pod 中的某个容器停止运行,Kubernetes 会自动检测并重启该 Pod 内的所有容器。如果 Pod 所在的 Node(工作节点)发生宕机,Kubernetes 会将该 Node(工作节点)上的所有 Pod 重新调度到其他可用节点上。
静态 Pod
- 静态 Pod 是由 kubelet 直接管理的特殊 Pod,仅存在于特定的 Node(工作节点)上。它们不受 API Server 管理,也无法与 Replication Controller、Deployment 或 DaemonSet 等控制器关联。此外,kubelet 对静态 Pod 的健康检查能力有限,通常仅能监控其运行状态,而不会像普通 Pod 那样提供完整的健康检查机制。
Pod 的定义
定义 Pod 的 YAML 配置示例如下(<string> 是占位符,需要根据实际情况填写):
1 | apiVersion: v1 |
Pod 的运行方式
在 Kubernetes 中,运行的容器要求其主程序必须始终在前台运行,而不能以后台方式执行。如果应用默认是以后台运行的方式启动,就需要进行修改,使其在前台运行。否则,当 kubelet 创建包含该容器的 Pod 并执行启动命令后,会因为容器立即退出而认为该 Pod 已经结束,从而立刻销毁该 Pod。如果该 Pod 是由控制器(如 Replication Controller)管理的,那么就会不断尝试重新创建和销毁 Pod,陷入无限循环。需要注意的是,一个 Pod 可以由一个或多个容器组成。
- 下面的 YAML 配置内容定义了一个包含单个容器的 Pod,容器使用的是官方 Tomcat 镜像,并包含基本的端口和挂载配置
1 | apiVersion: v1 |
- YAML 配置内容的详细说明
| 配置项 | 说明 |
|---|---|
metadata.name | Pod 的名称,必须唯一 |
metadata.labels | 标签,用于标识和选择 Pod |
spec.containers | 容器列表,一个 Pod 可包含一个或多个容器 |
spec.containers[].name | 容器的名称,在 Pod 内部唯一 |
spec.containers[].image | 容器使用的镜像,这里是 tomcat:9.0 |
spec.containers[].ports | 容器开放的端口列表 |
spec.containers[].ports[].containerPort | 容器内部监听的端口号(如 Tomcat 默认 8080) |
spec.containers[].volumeMounts | 容器内挂载的卷配置 |
spec.containers[].volumeMounts[].name | 要挂载的卷名称,对应 spec.volumes 中定义的名称 |
spec.containers[].volumeMounts[].mountPath | 挂载点路径,如 /usr/local/tomcat/webapps |
spec.volumes | 定义 Pod 中使用的卷 |
spec.volumes[].name | 卷的名称,与 volumeMounts 中的名称对应 |
spec.volumes[].emptyDir | 使用一个空目录卷,Pod 删除时数据也会被清除 |
Pod 的生命周期
Pod 的生命周期状态有以下几种:
| 生命周期状态 | 说明 |
|---|---|
| Pending | API Server 已创建该 Pod,但 Pod 中的一个或多个容器的镜像尚未创建(包括镜像下载过程)。 |
| Running | Pod 内所有容器已创建,且至少有一个容器处于运行状态(包括正在启动或重启的状态)。 |
| Completed | Pod 内所有容器均已成功执行并退出,且不会再重启。 |
| Failed | Pod 内所有容器均已退出,但至少有一个容器退出失败。 |
| Unknown | 由于某些原因(如网络通信不畅)无法获取 Pod 的状态。 |
Pod 的状态条件
Pod 的状态条件(Conditions)有以下几种:
| 状态条件 | 触发时机 | 正常状态 | 说明 |
|---|---|---|---|
PodScheduled | 当 Scheduler 为 Pod 分配了目标 Node(工作节点)后 | True | 表示 Pod 已被调度到某个 Node(工作节点)上。如果为 False,可能是集群资源不足或调度约束冲突。 |
Initialized | 当所有 Init 容器(如果有)成功执行完成后 | True | 仅对包含 Init 容器的 Pod 有意义。若 Init 容器失败,此条件会显示 False 并记录原因。 |
ContainersReady | 当 Pod 内所有主容器(非 Init 容器)的状态均为 Running 时 | True | 仅表示容器已启动,但不保证容器内应用已就绪(需结合 Readiness Probe(就绪探针)判断)。 |
Ready | 当 Pod 满足以下条件时: 1. 所有主容器 Running;2. 通过 Readiness Probe(就绪探针)检测(如果配置了)。 | True | 表示 Pod 可正常接收流量。若为 False,该 Pod 会被从 Service 的 Endpoints 中移除。 |
Pod 状态条件的附加说明
- (1) 状态值:
- 每个 Condition 的状态可能是
True、False或Unknown。
- 每个 Condition 的状态可能是
- (2) 依赖关系:
PodScheduled→Initialized→ContainersReady→Ready(存在先后顺序)。
- (3) 常见问题:
- 若
PodScheduled=False,需检查节点资源或亲和性规则。 - 若
Initialized=False,需排查 Init 容器的日志。 - 若
Ready=False但ContainersReady=True,通常是 Readiness Probe(就绪探针)配置问题。
- 若
- (4) 查看命令:
1
2
3
4
5# 以结构化格式提取 Pod 状态条件(Conditions)的详细信息
kubectl get pod <pod-name> -o jsonpath='{.status.conditions}'
# 或使用 describe 查看 Pod 的详细状态
kubectl describe pod <pod-name>
Pod 的重启策略
Pod 的重启策略包括 Always、OnFailure 和 Never,默认值是 Always。
| 重启策略 | 说明 |
|---|---|
| Always | 默认值,当容器退出时,总是由 kubelet 自动重启该容器(适用于长期运行的 Pod,如 Web 服务)。 |
| OnFailure | 仅在容器异常退出(非 0 状态码)时,由 kubelet 自动重启该容器(适合批处理任务)。 |
| Never | 无论容器如何退出,kubelet 都不会重启该容器(适合一次性任务)。 |
Pode 重启策略的配置示例如下:
1 | apiVersion: v1 |
Pod 的状态转换
Pod 生命周期状态的转换表(基于容器事件和重启策略)如下:
| Pod 包含的容器数 | Pod 当前的运行状态 | 发生的事件 | Pod 的结果状态(RestartPolicy = Always) | Pod 的结果状态(RestartPolicy = OnFailure) | Pod 的结果状态(RestartPolicy = Never) |
|---|---|---|---|---|---|
| 1 个容器 | Running | 容器成功退出 | Running | Succeeded | Succeeded |
| 1 个容器 | Running | 容器失败退出 | Running | Running | Failed |
| 2 个容器 | Running | 其中 1 个容器失败退出 | Running | Running | Running |
| 2 个容器 | Running | 2 个容器被 OOM 终止 | Running | Running | Failed |
- 关键说明:
- OOM:表示容器因内存不足(Out Of Memory)被系统终止
- 状态转换规则:
Always:任何容器终止都会触发重启(保持 Running 状态)OnFailure:仅当容器异常退出(非 0 状态码 / OOM)时重启Never:容器终止后直接反映最终状态(Succeeded/Failed)
- 多容器 Pod 的状态由所有容器的综合状态决定
Pod 的健康检查
Kubernetes 提供以下三种探针(Probe)来监控容器的运行状态:
存活探针(
livenessProbe)- 作用:检测容器是否正常运行。如果检测不通过,Kubernetes 会杀死容器并根据
restartPolicy(重启策略)重启容器。 - 适用场景:用于修复死锁、无响应的应用(如数据库卡死)。
- 配置示例:
1
2
3
4
5
6livenessProbe:
exec:
command: ["cat", "/tmp/healthy"] # 执行命令检查文件是否存在
initialDelaySeconds: 5 # 容器启动后等待5秒开始检查
periodSeconds: 5 # 每5秒检查一次
failureThreshold: 3 # 连续失败3次后判定为不健康
- 作用:检测容器是否正常运行。如果检测不通过,Kubernetes 会杀死容器并根据
就绪探针(
readinessProbe)- 作用:检测容器是否准备好接收流量。如果检测不通过,Kubernetes 会将 Pod 从 Service 的 Endpoints 中剔除,并且 Pod 会被标记为
NotReady,但不会被重启。 - 适用场景:用于控制流量进入(如应用启动时需要加载大量数据,导致容器启动后无法立刻对外提供服务
- 配置示例:
1
2
3
4
5
6
7readinessProbe:
httpGet:
path: /healthz # 发送 HTTP 请求进行检测
port: 8080
initialDelaySeconds: 10 # 容器启动后等待10秒开始检查
periodSeconds: 3 # 每3秒检查一次
successThreshold: 1 # 成功1次即标记为就绪
- 作用:检测容器是否准备好接收流量。如果检测不通过,Kubernetes 会将 Pod 从 Service 的 Endpoints 中剔除,并且 Pod 会被标记为
启动探针(
startupProbe)- 作用:从 Kubernetes
1.16+版本开始引入,专门检测慢启动应用是否完成初始化。在启动探针成功之前,其他探针不会生效。可以避免因应用启动过慢,导致被存活 / 就绪探针误杀。 - 适用场景:启动时间较长的应用(如 Java/SpringBoot 应用、需要加载大数据量的服务)。
- 配置示例:
1
2
3
4
5
6startupProbe:
httpGet:
path: /actuator/health # Spring Boot 健康检查端点
port: 8080
failureThreshold: 30 # 允许的最大失败次数
periodSeconds: 10 # 每10秒检查一次
- 作用:从 Kubernetes
探针(Probe)支持以下三种检测方法(三种类型的探针都支持):
| 检测方法 | 说明 | 配置示例 |
|---|---|---|
exec | - 在容器内执行命令,返回状态码为 0 表示检测成功。- 适用于复杂检测逻辑或没有 HTTP 接口的服务。 | command: ["cat", "/tmp/healthy"] |
httpGet | - 通过发送 HTTP 请求检查服务是否正常。 - 返回状态码 200 ~ 399 表示检测成功。 | httpGet: { path: /health, port: 80 } |
tcpSocket | - 通过容器 IP + 端口建立 TCP 连接, - 连接成功,即表示容器健康。 | tcpSocket: { port: 3306 } |
探针(Probe)的三种探测结果状态:
| 探测结果状态 | 说明 |
|---|---|
Success | 容器通过检查,状态正常。 |
Failure | 容器未通过检查,状态异常。 |
Unknown | 无法执行检查,因此不采取任何措施。 |
探针(Probe)的关键参数:
| 参数 | 作用 | 默认值 | 最小值 | 适用探针类型 |
|---|---|---|---|---|
initialDelaySeconds | 容器启动后,等待多少秒才开始第一次执行探测,避免容器未完成启动就被误判为失败。 | 0 秒 | 0 秒 | liveness、readiness、startup |
periodSeconds | 探测的执行频率,即两次探测之间的间隔时间。 | 10 秒 | 1 秒 | liveness、readiness |
timeoutSeconds | 单次探测的超时时间,超过该时间未响应则判定为探测失败。 | 1 秒 | 1 秒 | liveness、readiness |
failureThreshold | 探测成功后,连续失败多少次才会被认定为容器不健康。 | 3 | 1 | liveness、readiness、startup |
successThreshold | 对于已标记为不健康的容器,需要连续成功多少次才会重新标记为健康。对于 Liveness Probe,该值必须为 1。 | 1 | 1 | liveness、readiness |
基于存活探针检测容器的健康状态
1 | apiVersion: v1 |
启动探针、存活探针和就绪探针三者可以配合使用:
1 | apiVersion: v1 |
Pod 的资源限制
每个 Pod 都可以对其可使用的 Node(工作节点)计算资源设置限额。Kubernetes 支持对以下两种计算资源进行配额限制:
资源类型
- CPU 资源:以绝对值的 CPU 数量为单位(比如
500m表示 0.5 个 CPU 核心)。 - Memory 资源:内存大小以字节数为单位(比如
512Mi表示 512 MiB 内存)。
- CPU 资源:以绝对值的 CPU 数量为单位(比如
配额参数
- 每种资源需要定义两个关键参数:
- Requests
- 表示该资源的最小申请量。
- Kubernetes 调度器会确保 Node(工作节点)剩余资源大于等于 Requests 值,否则 Pod 无法被调度。
- Limits
- 表示该资源的最大允许使用量。若容器尝试使用超过 Limits 的资源:
- 对于 CPU 资源,容器会被限制(Throttled)。
- 对于 Memory 资源,容器可能被 Kubernetes 终止(OOM Kill)并重启。
- 表示该资源的最大允许使用量。若容器尝试使用超过 Limits 的资源:
Pod 资源限制的配置示例如下,表示 MySQL 容器申请最少 0.25 个 CPU 以及 64MiB 内存,在运行过程中容器所能使用的最大资源配额为 0.5 个 CPU 以及 128MiB 内存。
1 | apiVersion: v1 |
CPU 资源限制的单位
- (1) 在 Kubernetes 的资源限制配置中,
cpu: "500m"表示 500 毫核(millicores)。 - (2)
1m = 0.001 个 CPU 核心,而500m等价于0.5个 CPU 核心(即 50% 的单核算力)。 - (3) Kubernetes 常见的 CPU 单位如下表所示:
| CPU 单位 | 含义 | 配置示例 |
|---|---|---|
1 | 1 个完整的 CPU 核心 | cpu: "1" |
1000m | 1 个完整的 CPU 核心 | cpu: "1000m" |
500m | 0.5 核(即 50% 的单核算力) | cpu: "500m" |
250m | 0.25 核(即 25% 的单核算力) | cpu: "250m" |
Pod 的镜像拉取策略
Pod 有以下几种镜像拉取策略:
| 策略名称 | 描述 |
|---|---|
IfNotPresent | 默认值,只有当镜像在宿主机上不存在时才会拉取 |
Always | 每次创建 Pod 时都会重新拉取一次镜像(即使宿主机上已存在) |
Never | Pod 永远不会主动拉取镜像,仅使用宿主机上已有的镜像(若宿主机上不存在,则报错) |
Pode 镜像拉取策略的配置示例如下:
1 | apiVersion: v1 |
Pod 的调度策略
提示
更多关于 Kubernetes 调度器的介绍请看 这里。
Pod 的创建流程

(1) 用户提交 Pod 创建请求
- 用户通过
kubectl命令行工具或其他客户端工具提交 Pod 创建请求 - 请求会发送到 Master 节点的 API Server
- 用户通过
(2) API Server 处理
- API Server 接收并验证请求
- 将 Pod 配置信息写入 Etcd 进行持久化存储
(3) Scheduler 调度
- Scheduler 组件监控 API Server,发现有未调度的新 Pod
- Scheduler 通过调度算法(考虑资源需求、节点亲和性等)选择最适合的 Node(工作节点)
- Scheduler 将调度决策(绑定信息)通过 API Server 更新到 Etcd
(4) Node(工作节点)执行
- 目标 Node(工作节点)上的 kubelet 组件会定期查询 API Server
- kubelet 发现分配给本节点的 Pod 信息(从 Etcd 读取)
- kubelet 根据 Pod 描述文件:
- 通过容器运行时(如 Docker、Containerd)创建容器
- 配置容器网络、存储等资源
- 启动容器
(5) Pod 状态更新
- kubelet 监控容器状态,并将容器最新状态报告给 API Server
- API Server 将 Pod 状态信息写入 Etcd
- 用户可以通过
kubectl命令行工具查看 Pod 的运行状态
影响 Pod 调度的因素
在 Kubernetes 中,影响 Pod 调度的主要因素有以下几种。
Pod 资源限制
- Pod 资源限制(Resource Requests)
- 核心机制:
- Pod 通过
resources.requests声明所需的最小资源量 - 调度器(Scheduler)根据这些请求寻找有足够资源的节点
- Pod 通过
- 配置示例:
1
2
3
4
5
6
7
8spec:
containers:
- name: db
image: mysql
resources:
requests:
memory: "64Mi"
cpu: "250m" - 调度行为:
- 调度器会排除所有可用资源(Allocatable)小于请求值的节点
- 资源包括 CPU、内存、GPU 等
- 实际调度基于节点的剩余资源(Allocatable - Requested)
- 核心机制:
节点选择器
- 节点选择器(Node Selector)
- 核心机制:
- 通过
nodeSelector字段指定 Pod 必须运行在具有特定标签的节点上 - 这是简单的节点选择约束方式
- 通过
- 配置示例:
1
2
3
4
5
6spec:
nodeSelector:
env_role: dev
containers:
- name: nginx
image: nginx:1.15 - 节点的标签操作:
- 给节点打上标签:
1
kubectl label nodes <node-name> env_role=prod
- 查看节点上的标签:
1
kubectl get nodes --show-labels
- 给节点打上标签:
- 核心机制:
节点亲和性
- 节点亲和性(Node Affinity)
- 概述:
- K8s 节点亲和性(Node Affinity)规则有两种:硬亲和性(
required)、软亲和性(preferred)
- K8s 节点亲和性(Node Affinity)规则有两种:硬亲和性(
- 作用:
- 节点亲和性调度使得 Pod 对象被吸引运行到一类特定的节点上。
- 特性:
- 比
nodeSelector字段更灵活的规则 - 支持硬亲和性(约束条件必须满足)和软亲和性(尝试满足约束条件,但不保证满足)
- 支持常用操作:
In、NotIn、Exists、Gt、Lt、DoesNotExist
- 比
- 配置示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21spec:
affinity:
nodeAffinity:
# 节点硬亲和性
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: env_role
operator: In
values:
- dev
- test
# 节点软亲和性
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: group
operator: In
values:
- otherprod
- 概述:
污点和容忍
污点(Taints)
- 污点的概述:
- 节点可以设置污点(Taints)来拒绝普通 Pod 的调度
- 污点的定义:
- 定义在节点(Node)上的键值型属性数据
- 字段
spec.taints,语法是key=value:effect
- 污点的类型:
NoSchedule- 作用:
- 默认值,新 Pod 无法调度到该节点(除非明确容忍此污点)
- 已运行的 Pod 若不容忍此污点,不会被驱逐(Evict)
- 场景:保留节点给特定用途(如 GPU 节点、生产环境专用节点)
- 作用:
PreferNoSchedule- 作用:
- 调度器尽量避免将 Pod 分配到该节点,但若无其他可用节点仍会调度,不驱逐已运行的 Pod
- 已运行的 Pod 若不容忍此污点,不会被驱逐(Evict)
- 场景:软性隔离(如临时维护节点,但不强制拒绝调度)
- 作用:
NoExecute- 作用:
- 新 Pod 无法调度到该节点(同
NoSchedule) - 已运行的 Pod 若不容忍此污点,会被驱逐(Evict)
- 新 Pod 无法调度到该节点(同
- 场景:节点故障维护或紧急隔离(如节点磁盘故障需立即迁移所有 Pod)
- 作用:
- 污点的适用场景:
- 专用节点隔离:保留节点给特定 Pod(如 GPU 节点只运行 AI 任务)
- 节点维护:标记节点为不可调度(如
NoSchedule),避免新 Pod 被分配到正在维护的节点 - 特殊硬件限制:防止普通 Pod 调度到带特殊硬件(如 FPGA)的节点
- 节点的污点操作示例:
1 | # 给节点添加污点 |
1 | # 查看节点的污点 |
1 | # 删除节点的单个污点(末尾的 "-" 符号表示删除) |
容忍(Tolerations)
- 容忍的概述:
- 节点设置污点后,Pod 必须声明可以容忍哪些污点,才允许其被调度到具有这些污点的节点上。
- 容忍的定义:
- 定义在 Pod 上的键值型属性数据。
- 字段
spec.tolerations,语法是key=value:effect。 - 字段
tolerationSeconds用于定义延迟驱逐 Pod 的时间tolerationSeconds仅在effect: NoExecute的容忍规则中生效;- 超过设定时间后,若节点上的污点仍存在,则 Pod 会被驱逐;
- 如果未设置
tolerationSeconds,则表示 Pod 将无限期地容忍该污点,即 Pod 不会因为该污点被驱逐。
- 容忍的类型
NoSchedule- 作用:允许 Pod 调度到带有
NoSchedule污点的节点 - 场景:让关键 Pod(如存储服务)无视节点的硬性隔离规则
- 作用:允许 Pod 调度到带有
PreferNoSchedule- 作用:允许 Pod 调度到带有
PreferNoSchedule污点的节点(但调度器仍可能优先选择其他节点) - 场景:非关键 Pod 在资源不足时仍可使用软隔离节点
- 作用:允许 Pod 调度到带有
NoExecute- 作用:
- 允许 Pod 调度到带有
NoExecute污点的节点 - 豁免驱逐:即使节点新增
NoExecute污点,Pod 也不会被驱逐
- 允许 Pod 调度到带有
- 场景:守护进程(如日志收集器)需长期运行,无视节点维护状态
- 作用:
空值(不指定effect字段)- 作用:容忍所有污点类型(包括未来可能新增的类型)
- 场景:超级特权 Pod(如集群管理组件)需在任何节点运行
- 容忍的适用场景:
- 特权 Pod 调度:允许关键 Pod(如日志收集组件)无视污点,调度到任意节点
- 故障恢复:容忍
NoExecute污点,使 Pod 在节点故障时不被驱逐(如数据库 Pod) - 共享特殊节点:让普通 Pod 通过容忍临时使用专用节点(如容忍 GPU 节点污点)
- Pod 的容忍配置示例:
1 | spec: |
Pod 亲和性和反亲和性
- Pod 亲和性
- 控制 Pod 倾向于与指定 Pod 调度到同一拓扑域(共存关系)。
- 适用于需要紧密协作或低延迟通信的场景,以降低网络延迟、提升性能。
- 配置示例:
1
2
3
4
5
6
7
8
9
10
11spec:
affinity:
# Pod 亲和性
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values: ["cache"]
topologyKey: "kubernetes.io/hostname" - 配置说明:
- Kubernetes 调度器会强制保证,Pod 调度到与匹配
labelSelector条件的 Pod 所在的同一zone中。 - 如果集群中所有
zone都没有匹配的 Pod,则新 Pod 会一直处于Pending状态。
- Kubernetes 调度器会强制保证,Pod 调度到与匹配
- Pod 反亲和性
- 控制 Pod 不与指定 Pod 调度到同一拓扑域(互斥关系)。
- 适用于高可用场景,比如:将 Pod 副本分布到不同机架(Rack)或可用区(Zone) 中,避免单点故障。
- 配置示例:
1
2
3
4
5
6
7
8
9
10
11
12spec:
affinity:
# Pod 反亲和性
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- cache
topologyKey: zone - 配置说明:
- Kubernetes 调度器会强制保证,同一
zone下,不会与匹配labelSelector条件的 Pod 同时调度运行。 - 如果所有
zone都有匹配的 Pod,则新 Pod 会一直处于Pending状态。
- Kubernetes 调度器会强制保证,同一
提示
Pod 亲和性和反亲和性的更详细介绍,可以看这里。
Pod 优先级与抢占式调度
在 Pod 上定义容忍(Tolerations)时,Pod 的优先级与抢占式调度机制如下:
优先级(Pod Priority)
- 表示 Pod 对象的重要程度。
- 作用:
- 影响调度顺序:高优先级 Pod 会优先被调度。
- 影响驱逐次序:节点资源不足时,低优先级 Pod 会先被驱逐。
抢占机制(Preemption)
- 当一个 Pod 无法被调度时,调度器会尝试驱逐节点上优先级更低的 Pod,为当前高优先级 Pod 腾出资源。
- 适合关键业务 Pod 需要资源保障的场景。
启用方法
- Pod 优先级与抢占式调度机制默认处于禁用状态,需要手动启用。
- 启用方式:在以下组件的启动参数中增加
--feature-gates=PodPriority=true:kube-apiserverkube-schedulerkubelet
使用步骤
(1) 创建优先级类别(
PriorityClass)- 定义不同的优先级,如关键业务、高优先级、低优先级等。
- 配置示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority # 优先级类别名称
value: 1000 # 优先级值,数值越大优先级越高
globalDefault: false # 是否为默认优先级类别
description: "用于关键业务 Pod,例如存储、网络组件" # 优先级的描述信息
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: low-priority # 优先级类别名称
value: 100 # 优先级值,数值越大优先级越高
globalDefault: false # 是否为默认优先级类别
description: "用于低优先级 Pod,例如测试或批处理任务" # 优先级的描述信息
(2) 在 Pod 中指定优先级
- 创建 Pod 时,通过
priorityClassName属性绑定到对应的优先级类别。 - 配置示例:
1
2
3
4
5
6
7
8
9apiVersion: v1
kind: Pod
metadata:
name: critical-app
spec:
priorityClassName: high-priority # Pod 绑定高优先级类别
containers:
- name: critical-container
image: nginx
- 创建 Pod 时,通过
Pod 的优先级与抢占式调度总结
高优先级 Pod 无法被调度 → 调度器检查目标节点 → 驱逐低优先级 Pod → 为高优先级 Pod 腾出资源 → 高优先级 Pod 调度成功。
Pod 的调度决策流程
- (1) 预选阶段:排除不满足条件的节点(资源不足、标签不匹配等)。
- (2) 优选阶段:对剩余节点打分 (考虑资源平衡、亲和性等因素)。
- (3) 绑定阶段:选择最高分节点,将绑定信息写入 API Server。
- (4) 执行阶段:目标 Node(工作节点)的 Kubelet 拉起 Pod。
提示
Kubernetes 调度器的详细工作流程,可以看这里。
Label
Label 的概念
Label 是 Kubernetes 中的核心概念之一,用于为集群中的各种资源对象打上自定义的标记。
Label 的核心概念:
- 一个 Label 是一个
key=value形式的键值对,其中key和value由用户自定义。 - Label 可以附加到各种 Kubernetes 资源对象上,例如 Node、Pod、Service、Replication Controller(RC)等。
- 一个资源对象可以拥有任意数量的 Label,同一个 Label 也可以被应用到任意数量的资源对象上。
- Label 通常在资源对象创建时通过
metadata.labels字段定义,也可以在对象创建后动态添加或删除。
- 一个 Label 是一个
Label 的核心作用
- Label 附加到 Kubernetes 资源对象上的主要目的是对这些对象进行分组管理。
- Kubernetes 分组管理的核心机制是 Label Selector(标签选择器):
- Label Selector 根据指定的匹配规则筛选出符合条件的资源对象,实现分组控制和管理。
- Label 和 Label Selector 都不能单独存在,必须附加在某些资源对象的定义文件中,才能发挥作用。
- 在实际使用中,Label 通常附加在 Pod 上,而 Label Selector 则常用于 Replication Controller(RC)、Replica Set(RS) 或 Service 等资源定义文件中,通过匹配特定 Label 来选择和管理 Pod。
Label 的常见用途
- 通过在对象的定义中添加
metadata.labels,为对象打上标签。 - 其他资源(如 Service、Deployment)可以通过
spec.selector来选择和关联具有特定 Label 的对象,实现分组管理和调度。
- 通过在对象的定义中添加
Label 的注意事项
- Label 和 Label Selector 都不能单独存在,必须附加在某些资源对象的定义文件中,常见组合是:
- Pod + Label
- Replication Controller(RC) / Replica Set(RS) / Service + Label Selector
- Label 和 Label Selector 都不能单独存在,必须附加在某些资源对象的定义文件中,常见组合是:
Label 的使用
- 配置示例
1 | apiVersion: v1 |
- 配置说明:
- Replication Controller(RC):
- 通过
selector选择并管理所有带有app=nginx标签的 Pod。 - 确保 Pod 的副本数量维持在 3 个,由 RC 创建的 Pod 会包含
app=nginx标签。
- 通过
- Service:
- 通过
selector匹配同样带有app=nginx标签的 Pod,并将流量分发给这些 Pod。 - 通过
nodePort: 3333在集群外部暴露服务。
- 通过
- Replication Controller(RC):
Node(工作节点)的标签操作
- 给 Node(工作节点)打上标签:
kubectl label nodes <node-name> env_role=prod - 查看 Node(工作节点)上的标签:
kubectl get nodes --show-labels
