文章目录
Kubernetes 群集调度管理
Kubernetes Pod 创建过程及组件协作
-
组件初始化与监听
- Controller Manager、Scheduler 和 kubelet 在启动时开始监听(Watch)APIServer 发出的事件。
- 这些组件通过 HTTPS 的 6443 端口与 APIServer 通信。
-
用户提交请求
- 用户通过 kubectl 或其他 API 客户端向 APIServer 提交请求,创建一个 Pod 对象副本。
-
APIServer 存储与反馈
- APIServer 尝试将 Pod 对象的相关元信息存入 etcd。
- 写入操作完成后,APIServer 返回确认信息至客户端。
-
etcd 发送 Create 事件
- etcd 接受创建 Pod 信息后,发送一个 Create 事件给 APIServer。
-
Controller Manager 处理 Create 事件
- Controller Manager 监听到 Create 事件后,调用 Replication Controller(RC)确保 Node 上需要创建的副本数量。
- RC 根据定义的副本数量自动创建或删除副本。
-
APIServer 更新 Pod 信息
- APIServer 在 etcd 中记录 Pod 的详细信息,如副本数、容器内容等。
- etcd 将更新信息通过事件发送给 APIServer。
-
Scheduler 调度 Pod
- Scheduler 监听到 Pod 创建事件后,根据调度算法和策略将 Pod 绑定到集群中的某个 Node 上。
- Scheduler 更新 Pod 信息至 APIServer,由 APIServer 更新至 etcd。
-
APIServer 反映调度结果
- etcd 将调度成功的事件发送给 APIServer。
- APIServer 开始反映此 Pod 对象的调度结果。
-
kubelet 启动容器
- kubelet 监听到 Pod 更新事件后,在当前 Node 上调用 Docker 启动容器。
- kubelet 将 Pod 及容器的状态回送至 APIServer。
-
APIServer 存储状态信息
- APIServer 将 Pod 状态信息存入 etcd。
- etcd 确认写入操作成功后,APIServer 将确认信息发送至相关的 kubelet。
Kubernetes 调度过程
Kubernetes 的调度器(Scheduler)负责将定义的 Pod 分配到集群的节点上。调度过程主要关注公平性、资源高效利用、效率和灵活性。调度器运行为一个独立的程序,持续监听 APIServer,并处理 spec.nodeName 为空的 Pod。
调度过程分为以下几个步骤:
-
Predicate(过滤阶段):
- 调度器首先会过滤掉不满足条件的节点。
- 常见的 Predicate 算法包括:PodFitsResources(检查节点资源是否足够)、PodFitsHost(检查节点名称是否与 Pod 指定的 NodeName 匹配)、PodFitsHostPorts(检查节点端口是否与 Pod 请求的端口冲突)、PodSelectorMatches(过滤掉与 Pod 指定的 label 不匹配的节点)和 NoDiskConflict(检查已挂载的 volume 是否与 Pod 指定的 volume 冲突)。
-
Priorities(优选阶段):
- 如果有多个节点满足条件,调度器会根据优先级对节点进行排序。
- 优先级由一系列键值对组成,表示不同的优先级项目和其权重。
- 常见的优先级选项包括:LeastRequestedPriority(倾向于资源使用比例更低的节点)、BalancedResourceAllocation(倾向于 CPU 和 Memory 使用率更接近的节点)和 ImageLocalityPriority(倾向于已经有要使用镜像的节点)。
-
Binding(绑定阶段):
- 调度器选择优先级最高的节点,并创建一个 binding,表明该 Pod 应该被调度到哪个节点上。
Kubernetes Scheduler 工作原理
Scheduler 是 Kubernetes 的核心组件,负责将 Pod 分配到集群的合适节点上。其调度过程主要关注以下方面:
- 公平性:确保每个节点都能被分配资源。
- 资源高效利用:最大化集群资源的利用率。
- 效率:快速调度大批量的 Pod。
- 灵活性:允许用户根据需求自定义调度逻辑。
Scheduler 启动后会持续监听 APIServer,获取 spec.nodeName 为空的 Pod,并为每个 Pod 创建一个 binding,指明其应部署的节点。
调度流程
调度过程主要分为以下步骤:
-
Predicate(过滤):首先排除不满足条件的节点。常见的 Predicate 算法包括检查节点资源是否充足、端口是否冲突、标签是否匹配等。
-
Priorities(优选):对通过 Predicate 的节点按照优先级排序。优先级由一系列键值对组成,键是优先级项的名称,值是权重。常见的优先级选项有资源使用率、资源均衡度、镜像本地性等。
-
选择节点:从排序后的节点中选择优先级最高的节点作为 Pod 的部署节点。
指定调度节点的方式
-
pod.spec.nodeName:直接将 Pod 调度到指定的 Node 节点上,跳过 Scheduler 的调度策略。这种方式是强制匹配。
-
pod.spec.nodeSelector:通过 Kubernetes 的 label-selector 机制选择节点。Scheduler 会根据 Pod 的 nodeSelector 和节点的标签进行匹配,然后将 Pod 调度到目标节点。这种方式属于强制约束。
示例操作
使用 nodeName 指定调度节点
- 创建一个 Deployment,指定
nodeName
为node01
。 - 应用 YAML 文件后,所有 Pod 都会被调度到
node01
上。 - 通过
kubectl describe pod
查看 Pod 事件,发现未经过 Scheduler 调度分配。
使用 pod.spec.nodeName:
- 通过在 Pod 定义中指定 nodeName,可以直接将 Pod 调度到指定的节点上,这会跳过调度器的调度策略。
- 示例 YAML 配置如下:
apiVersion: apps/v1 kind: Deployment metadata: name: myapp spec: replicas: 3 selector: matchLabels: app: myapp template: metadata: labels: app: myapp spec: nodeName: node01 containers: - name: myapp image: soscscs/myapp:v1 ports: - containerPort: 80
- 应用此配置后,Pod 会被调度到 node01 上。
使用 nodeSelector 指定调度节点
- 给节点
node01
和node02
分别设置标签myname=a
和myname=b
。 - 创建一个 Deployment,指定
nodeSelector
为myname=a
。 - 应用 YAML 文件后,所有 Pod 都会被调度到标签为
myname=a
的节点上(即node01
)。 - 通过
kubectl describe pod
查看 Pod 事件,发现先经过 Scheduler 调度分配。
使用 pod.spec.nodeSelector:
- 通过为节点和 Pod 设置 label,并使用 nodeSelector 选择具有特定 label 的节点,调度器会将 Pod 调度到匹配的节点上。
- 为节点设置 label 的命令如下:
kubectl label nodes node01 myname=a kubectl label nodes node02 myname=b
- 在 Pod 定义中使用 nodeSelector 的 YAML 配置如下:
apiVersion: apps/v1 kind: Deployment metadata: name: myapp1 spec: replicas: 3 selector: matchLabels: app: myapp1 template: metadata: labels: app: myapp1 spec: nodeSelector: myname: a containers: - name: myapp1 image: soscscs/myapp:v1 ports: - containerPort: 80
- 应用此配置后,Pod 会被调度到具有 label myname=a 的节点上(即 node01)。
修改和删除Label
- 使用
kubectl label
命令修改和删除节点标签。 - 修改节点的 label 需要使用
--overwrite
参数:kubectl label nodes node02 myname=a --overwrite
- 删除节点的 label 只需在命令行最后指定 label 的 key 名,并在其后加上减号:
kubectl label nodes node02 myname-
- 可以使用
-l
参数根据 label 查询节点:kubectl get node -l myname=a
亲和性
亲和性概述
在 Kubernetes 中,亲和性(Affinity)和反亲和性(Anti-Affinity)用于定义 Pod 调度到节点的规则。主要分为两类:
- 节点亲和性(Node Affinity):定义 Pod 与节点的关系。