K8s 特殊容器、调度管理与优先级学习笔记
K8s 特殊容器、调度管理与优先级学习笔记
一、K8s 特殊容器
K8s 中除了常规业务容器(主容器),还有三类核心特殊容器,分别承担初始化、辅助、调试等特定功能,与主容器协同工作,适配不同场景需求,且各自遵循独特的生命周期规则。
1.1 核心特殊容器类型(3类)
(1)Init 容器(初始化容器)
Init 容器是在主容器启动前执行的特殊容器,用于完成主容器启动前的初始化任务,必须全部执行成功,主容器才会启动。若 Init 容器执行失败,kubelet 会根据 Pod 的 restartPolicy 不断重启,直至执行成功(restartPolicy 为 Never 时,失败会直接导致 Pod 状态为失败)。
核心特性:
-
执行顺序:多个 Init 容器按配置顺序依次执行,前一个执行成功后,下一个才会启动。
-
资源隔离:拥有独立的资源请求/限制,不共享主容器的资源配置。
-
生命周期:执行完成后立即终止,不长期运行,不参与主容器的业务流程。
典型应用场景:
-
等待依赖服务就绪(如数据库、API 服务),通过循环检测服务可达性实现。
-
初始化配置:生成主容器所需的配置文件、密钥,或下载依赖资源。
-
前置校验:检查端口、文件是否存在,确保主容器启动环境符合要求。
(2)Sidecar 容器(边车容器)
Sidecar 容器与主容器并行运行,不参与核心业务逻辑,仅为主体容器提供辅助功能,通过共享 Pod 的网络命名空间和存储卷,与主容器实现紧密协同,是微服务架构中解耦辅助逻辑的核心方案。
核心特性:
-
生命周期同步:与主容器同时启动、同时终止,主容器异常时,Sidecar 容器也会随之终止。
-
资源共享:与主容器共享网络(可通过 localhost 直接通信)和存储卷,无需额外配置网络连接。
-
功能独立:辅助功能与主业务解耦,可单独升级、维护,不影响主容器。
典型应用场景:
-
日志收集:如使用 Fluentd、Filebeat 收集主容器的日志,统一上报至日志系统。
-
服务网格:如 Istio、Linkerd 的 Sidecar 容器,负责流量转发、监控、熔断等。
-
代理转发:通过 Sidecar 容器实现主容器的网络代理,简化主容器的网络配置。
(3)Ephemeral 容器(临时容器)
Ephemeral 容器是动态注入到运行中 Pod 的临时容器,主要用于调试或诊断,不参与 Pod 的原生生命周期管理,无法通过常规方式创建,也不能长期运行。
核心特性:
-
动态注入:需通过 kubectl 命令或 API 直接注入,无法在 Pod 初始 YAML 中定义,也不能通过 kubectl edit 修改。
-
生命周期独立:注入后完成调试任务即可删除,不影响主容器和 Pod 的运行状态。
-
启用条件:K8s 1.16+ 版本需启用 EphemeralContainers 特性门控(在 kube-apiserver 配置中添加 --feature-gates=EphemeralContainers=true)。
典型应用场景:
-
调试运行中 Pod:主容器无法进入(如命令行工具缺失)时,注入临时容器(如 busybox)排查问题。
-
临时工具注入:添加 curl、tcpdump 等调试工具,无需修改主容器镜像。
1.2 实操示例(YAML+命令)
示例1:Init 容器(等待依赖服务+初始化配置)
apiVersion: v1
kind: Pod
metadata:
name: init-demo-pod
spec:
containers:
- name: main-app
image: busybox
command: ["sh", "-c", "echo 主容器运行中 && sleep 3600"]
volumeMounts:
- name: config-volume
mountPath: /etc/config
# Init 容器(按顺序执行)
initContainers:
- name: wait-mysql
image: busybox
# 等待 mysql 服务就绪(循环检测域名解析)
command: ["sh", "-c", "until nslookup mysql; do echo 等待 mysql 服务; sleep 2; done"]
- name: init-config
image: busybox
command: ["sh", "-c", "echo 'app.config=demo' > /tmp/config/app.conf"]
volumeMounts:
- name: config-volume
mountPath: /tmp/config
volumes:
- name: config-volume
emptyDir: {}
查看 Init 容器执行状态:kubectl get pod init-demo-pod -w,状态流转为:Init:0/2 → Init:1/2 → PodInitializing → Running。
示例2:Sidecar 容器(日志收集)
apiVersion: v1
kind: Pod
metadata:
name: sidecar-demo-pod
spec:
containers:
# 主容器:输出日志到文件
- name: main-app
image: busybox
command: ["sh", "-c", "while true; do echo $(date) 业务日志 >> /var/log/app.log; sleep 1; done"]
volumeMounts:
- name: log-volume
mountPath: /var/log
# Sidecar 容器:收集日志并打印
- name: log-collector
image: busybox
command: ["sh", "-c", "tail -f /var/log/app.log"]
volumeMounts:
- name: log-volume
mountPath: /var/log
volumes:
- name: log-volume
emptyDir: {}
示例3:Ephemeral 临时容器(调试 Pod)
# 给运行中的 pod 注入临时容器(名为 debugger,镜像为 busybox)
kubectl debug -it sidecar-demo-pod --image=busybox --target=main-app --name=debugger
# 手动注入临时容器(YAML 方式)
kubectl patch pod sidecar-demo-pod -p '{
"spec": {
"ephemeralContainers": [
{
"name": "debugger",
"image": "busybox",
"command": ["sh"],
"tty": true,
"stdin": true
}
]
}
}'
1.3 常见问题与注意事项
-
Init 容器失败:检查 Init 容器的命令是否正确(如依赖服务地址错误),或 restartPolicy 配置是否合理,避免无限重启。
-
Sidecar 容器资源耗尽:Sidecar 需单独配置资源请求/限制,避免因资源不足导致主容器被驱逐。
-
临时容器注入失败:确认 K8s 版本≥1.16,且已启用 EphemeralContainers 特性门控;临时容器无法修改 Pod 的原有配置。
-
多 Init 容器顺序:严格按 YAML 中定义的顺序执行,前一个失败会阻塞后续所有容器启动。
二、K8s 调度管理
K8s 调度管理的核心是 kube-scheduler(调度器),其职责是根据集群节点资源、Pod 需求,将待调度的 Pod 合理分配到合适的节点上,实现资源高效利用和业务高可用。调度过程遵循“过滤→打分→绑定”的核心流程,支持多种调度策略适配不同场景。
2.1 核心调度原理
kube-scheduler 是集群级组件,运行在控制平面,核心流程分为3步:
-
过滤(Predicate):从所有节点中筛选出“满足 Pod 资源需求”的候选节点(如 CPU、内存充足,符合 Pod 的调度约束),排除不满足条件的节点(如节点污点未被容忍)。
-
打分(Priority):对候选节点进行优先级打分(0-10分),分数越高,节点越适合运行该 Pod(如节点资源剩余越多、负载越低,分数越高)。
-
绑定(Bind):将 Pod 绑定到打分最高的节点,完成调度;若多个节点分数相同,随机选择一个。
补充:可通过自定义调度器配置(K8s 1.25+ 稳定版),修改调度的各个阶段行为,支持多调度配置文件,通过 kube-scheduler --config 启用,需使用 kubeschedulerconfiguration v1 版本(v1beta3 已废弃)。
2.2 核心调度策略(4种常用)
(1)节点选择器(NodeSelector)
最基础的调度策略,通过“节点标签+Pod 选择器”,将 Pod 强制调度到带有指定标签的节点上,适用于简单的节点分组调度(如区分 CPU 型、GPU 型节点)。
# 1. 给节点打标签
kubectl label nodes node-1 node-type=cpu
# 2. Pod 配置 NodeSelector,强制调度到带有 node-type=cpu 标签的节点
apiVersion: v1
kind: Pod
metadata:
name: nodeselector-demo
spec:
containers:
- name: nginx
image: nginx:alpine
nodeSelector:
node-type: cpu # 匹配节点标签
(2)节点亲和性(NodeAffinity)
NodeSelector 的增强版,支持更灵活的匹配规则(如模糊匹配、逻辑运算),分为两种类型,适配不同约束需求:
-
requiredDuringSchedulingIgnoredDuringExecution(强制亲和):必须满足匹配规则,否则 Pod 无法调度(等价于 NodeSelector,但支持更复杂表达式)。
-
preferredDuringSchedulingIgnoredDuringExecution(优先亲和):优先调度到符合规则的节点,若没有符合条件的节点,可调度到其他节点,支持 weight 权重配置(0-100)。
apiVersion: v1
kind: Pod
metadata:
name: nodeaffinity-demo
spec:
containers:
- name: nginx
image: nginx:alpine
affinity:
nodeAffinity:
# 强制亲和:必须调度到带有 node-type=cpu 或 node-type=mix 的节点
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-type
operator: In # 匹配规则:In(包含)、NotIn(不包含)、Exists(存在标签)等
values: ["cpu", "mix"]
# 优先亲和:优先调度到带有 zone=zone1 标签的节点,权重 80
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
preference:
matchExpressions:
- key: zone
operator: In
values: ["zone1"]
(3)Pod 亲和性/反亲和性(PodAffinity/PodAntiAffinity)
根据“已运行 Pod 的标签”调度当前 Pod,实现 Pod 间的协同或隔离,适用于分布式应用(如数据库主从、服务集群)。
-
PodAffinity(Pod 亲和性):将当前 Pod 调度到“运行了指定标签 Pod”的节点上(如将前端 Pod 调度到后端 Pod 所在节点,减少网络延迟)。
-
PodAntiAffinity(Pod 反亲和性):将当前 Pod 调度到“未运行指定标签 Pod”的节点上(如避免同类型 Pod 调度到同一节点,实现容灾)。
(4)污点(Taint)与容忍度(Toleration)
与亲和性相反,污点作用于节点,用于排斥 Pod;容忍度作用于 Pod,用于让 Pod 容忍节点的污点,实现“反调度”控制,核心用于节点隔离(如 Master 节点、故障节点)。
核心污点效果(3种):
-
NoSchedule:仅排斥未配置对应容忍度的新 Pod,已运行的 Pod 不受影响(最常用,如 Master 节点默认污点)。
-
NoExecute:排斥未配置对应容忍度的新 Pod,且会驱逐已运行的、无对应容忍度的 Pod(如节点故障时标记污点,驱逐 Pod)。
-
PreferNoSchedule:尽量排斥未配置对应容忍度的 Pod,若没有其他合适节点,仍可调度(优先级最低)。
# 1. 给节点添加污点(key=node-role.kubernetes.io/control-plane,效果 NoSchedule)
kubectl taint nodes master node-role.kubernetes.io/control-plane:NoSchedule
# 2. Pod 配置容忍度,允许调度到带有该污点的节点
apiVersion: v1
kind: Pod
metadata:
name: toleration-demo
spec:
containers:
- name: nginx
image: nginx:alpine
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists" # 匹配规则:Exists(存在该key即可)、Equal(key和value都匹配)
effect: "NoSchedule"
补充:Master 节点默认带有 node-role.kubernetes.io/control-plane:NoSchedule 污点,因此普通 Pod 不会被调度到 Master 节点,需配置容忍度才能调度。
2.3 实操示例(调度排查+自定义调度)
# 查看 Pod 调度情况(查看调度到哪个节点、调度原因)
kubectl describe pod nodeselector-demo | grep -i "Node Selected"
# 查看调度器日志(排查调度失败原因)
kubectl logs -n kube-system kube-scheduler-master
# 强制指定节点(绕过调度器,直接绑定节点,仅用于调试)
apiVersion: v1
kind: Pod
metadata:
name: force-node-pod
spec:
nodeName: node-1 # 直接指定节点名称,跳过调度流程
containers:
- name: nginx
image: nginx:alpine
# 自定义调度器配置(极简示例)
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
clientConnection:
kubeconfig: /etc/srv/kubernetes/kube-scheduler/kubeconfig
profiles:
- schedulerName: my-scheduler # 自定义调度器名称
2.4 常见调度问题与最佳实践
(1)常见问题
-
Pod 一直 Pending(调度失败):检查节点资源是否充足(CPU/内存不足)、节点污点是否未被容忍、亲和性规则是否过严(无符合条件的节点)。
-
Pod 调度到不合适的节点:检查亲和性/反亲和性配置是否错误,或节点标签是否正确。
-
调度器异常:查看 kube-scheduler 日志,确认调度器是否正常运行,配置文件是否正确(如 v1beta3 版本已废弃)。
(2)最佳实践
-
节点分组:给节点打标签(如 node-type、zone),结合 NodeSelector 或节点亲和性,实现 Pod 按类型调度。
-
容灾隔离:使用 Pod 反亲和性,将核心服务的 Pod 调度到不同节点,避免单点故障;使用污点隔离 Master 节点和故障节点。
-
资源预留:给节点预留部分资源(如给系统组件),避免 Pod 资源耗尽导致节点不可用。
-
避免强制指定 nodeName:仅用于调试,生产环境优先使用调度策略,确保调度灵活性。
三、K8s Pod 优先级与抢占机制
K8s 中 Pod 优先级用于定义 Pod 的重要程度,优先级高的 Pod 会优先被调度;当集群资源不足时,高优先级 Pod 可“抢占”低优先级 Pod 的资源(驱逐低优先级 Pod),确保核心业务的可用性,该特性自 K8s 1.14 起稳定。
3.1 核心概念
(1)PriorityClass(优先级类)
集群级资源(不属于任何命名空间),用于定义优先级等级,映射“优先级名称”与“优先级数值”,数值越高,优先级越高。
核心属性:
-
value:优先级数值(32位整数,范围 -2147483648 ~ 1000000000,超过1000000000的数值预留用于系统核心组件)。
-
globalDefault:是否作为全局默认优先级(整个集群只能有一个 PriorityClass 设为 true),未指定优先级的 Pod 会使用该优先级(默认优先级为0)。
-
preemptionPolicy:抢占策略,可选 PreemptLowerPriority(默认,允许抢占低优先级 Pod)、Never(禁止抢占)。
-
description:优先级描述,用于说明该优先级的适用场景。
内置 PriorityClass(系统默认,不可修改):
-
system-node-critical(value=2000001000):节点关键组件(如 kubelet、容器运行时)。
-
system-cluster-critical(value=2000000000):集群核心组件(如 CoreDNS、etcd)。
(2)Pod 优先级配置
通过 Pod 的 priorityClassName 字段,引用已创建的 PriorityClass,实现 Pod 优先级的配置;也可直接设置 priority 字段(不推荐,优先级数值难以管理)。
(3)抢占机制(Preemption)
当高优先级 Pod 无法调度(资源不足)时,调度器会触发抢占逻辑,驱逐节点上优先级更低的 Pod,腾出资源供高优先级 Pod 运行,核心流程:
-
高优先级 Pod 创建,触发调度流程,发现无足够资源。
-
调度器评估候选节点,计算需要驱逐的低优先级 Pod(优先驱逐优先级最低、资源消耗最小的 Pod)。
-
驱逐低优先级 Pod,等待 Pod 终止后,将高优先级 Pod 绑定到该节点。
注意:抢占机制仅在资源不足时触发,且不会驱逐优先级相同或更高的 Pod;若低优先级 Pod 配置了 PodDisruptionBudget(PDB),可能会阻止抢占(避免驱逐过多 Pod 导致服务不可用)。
3.2 实操示例(PriorityClass+Pod 优先级+抢占)
示例1:创建 PriorityClass
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority # 高优先级(核心业务)
value: 1000000
globalDefault: false
preemptionPolicy: PreemptLowerPriority
description: "用于核心生产服务(如支付、订单)"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: low-priority # 低优先级(测试、批处理任务)
value: 100000
preemptionPolicy: Never # 禁止抢占其他 Pod
description: "用于测试环境和批处理任务,不抢占资源"
示例2:创建带优先级的 Pod
# 高优先级 Pod(核心服务)
apiVersion: v1
kind: Pod
metadata:
name: high-priority-pod
spec:
priorityClassName: high-priority # 引用高优先级类
containers:
- name: core-app
image: nginx:alpine
resources:
requests:
cpu: 100m
memory: 128Mi
---
# 低优先级 Pod(测试任务)
apiVersion: v1
kind: Pod
metadata:
name: low-priority-pod
spec:
priorityClassName: low-priority # 引用低优先级类
containers:
- name: test-app
image: busybox
command: ["sh", "-c", "sleep 3600"]
resources:
requests:
cpu: 100m
memory: 128Mi
示例3:查看优先级与抢占情况
# 查看所有 PriorityClass
kubectl get priorityclasses.scheduling.k8s.io
# 查看 Pod 的优先级(priority 字段)
kubectl get pods -o custom-columns=NAME:.metadata.name,PRIORITY:.spec.priority,NODE:.spec.nodeName
# 查看抢占事件(高优先级 Pod 驱逐低优先级 Pod 的日志)
kubectl get events | grep -i preemption
3.3 常见问题与最佳实践
(1)常见问题
-
高优先级 Pod 无法抢占低优先级 Pod:检查低优先级 Pod 是否配置了 PDB(Pod 中断预算),或高优先级 Pod 的 preemptionPolicy 设为 Never。
-
恶意高优先级 Pod 挤占资源:未授权用户创建高优先级 Pod,导致核心服务被抢占,需通过资源配额限制用户创建高优先级 Pod 的权限。
-
优先级配置错误:PriorityClass 的 value 超出范围,或多个 PriorityClass 设为 globalDefault,导致 Pod 优先级异常。
(2)最佳实践
-
合理划分优先级:按业务重要性划分优先级(如核心服务→普通服务→测试任务→批处理任务),避免优先级混乱。
-
限制高优先级使用:通过资源配额(ResourceQuota),限制不同用户/命名空间创建高优先级 Pod 的数量,防止恶意抢占。
-
批处理任务配置:给批处理、日志分析等非核心任务设置低优先级,并设 preemptionPolicy: Never,避免抢占核心服务。
-
不修改系统内置优先级:禁止修改 system-node-critical、system-cluster-critical 的优先级,确保集群核心组件正常运行。
四、总结
-
特殊容器:Init 容器负责主容器前置初始化,Sidecar 容器提供并行辅助功能,Ephemeral 容器用于临时调试,三者与主容器协同,覆盖初始化、辅助、排障等场景,需注意各自的生命周期规则。
-
调度管理:核心是 kube-scheduler,通过“过滤→打分→绑定”流程调度 Pod,常用调度策略包括 NodeSelector、节点亲和性、Pod 亲和性/反亲和性、污点与容忍度,用于实现 Pod 的精准调度和节点隔离。
-
优先级与抢占:通过 PriorityClass 定义 Pod 优先级,高优先级 Pod 优先调度,资源不足时可抢占低优先级 Pod,核心是保障核心业务的资源供给,需合理划分优先级并限制高优先级使用,避免资源滥用。
-
三者关联:特殊容器的运行依赖调度管理(如 Sidecar 与主容器需调度到同一节点),优先级决定 Pod 的调度顺序和资源抢占权限,结合使用可实现集群的高效、安全、稳定运行。
更多推荐



所有评论(0)