pod创建流程简述如下:
1、用户提交创建POD请求。
2、API Server 处理用户请求,存储Pod数据到Etcd。
3、Schedule通过和 API Server的监听机制,查看到新的pod,尝试为Pod绑定Node。
4、过滤主机:调度器用一组规则过滤掉不符合要求的主机,比如Pod指定了所需要的资源,那么就要过滤掉资源不够的主机。
5、主机打分:对第一步筛选出的符合要求的主机进行打分,在此阶段,调度器会考虑一些整体优化策略,比如把一个Replication Controller的副本分布到不同的主机上,使用最低负载的主机等。
6、选择主机:选择得分最高的主机,进行binding操作,结果存储到Etcd中。
7、kubelet根据调度结果执行Pod创建操作:绑定成功后,会启动container, Docker run, scheduler会调用API Server的API在etcd中创建一个bound pod对象,描述在一个工作节点上绑定运行的所有pod信息。运行在每个工作节点上的kubelet也会定期与etcd同步bound pod信息,一旦发现应该在该工作节点上运行的bound pod对象没有更新,则调用Docker API创建并启动pod内的容器。
8、POD创建完成。
详解如下:
一般来说,Kubernetes创建Pod的工作流程有如下图所示的几个阶段,如下图:****
第一步: 用户通过kubectl等接口提交创建Pod的yaml文件,向Kubernetes系统发起资源请求
第二步: Api-server接收到用户请求之后,会做出相应的认证,然后检查信息并且将元数据信息存储到etcd中,创建Pod资源初始化,这是第一次写etcd动作
第三步: Scheduler通过list-watch的监听机制,查看要创建Pod资源,APIServer会立即把创建Pod的消息通知Scheduler,Scheduler发现Pod的属性中Dest Node为空时(Dest Node=””),便会立即触发调度流程进行调度。而调度流程分为以下几个步骤,如下图:****
3.1. 过滤:首先是kube-scheduler调度器用一组规则过滤掉不满足条件的主机,这个过程称为predicate,比如明确指定所需要的资源类型,这样就可以过滤掉不满足条件的主机。
Predicate有一系列的算法可以使用:
-
PodToleratesNodeTaints:检查Pod是否容忍Node Taints
-
CheckNodeMemoryPressure:检查Pod是否可以调度到MemoryPressure的节点上
-
CheckNodeDiskPressure:检查Pod是否可以调度到DiskPressure的节点上
-
NoVolumeNodeConflict:检查节点是否满足Pod所引用的Volume的条件
-
PodFitsPorts:同PodFitsHostPorts
-
PodFitsHostPorts:检查是否有Host Ports冲突
-
PodFitsResources:检查Node的资源是否充足,包括允许的Pod数量、CPU、内存、GPU个数以及其他的OpaqueIntResources
-
HostName: 检查Pod.Spec.NodeName是否与候选节点一致
-
MatchNodeSelector:检查候选节点的Pod.Spec.NodeSelector 是否匹配
-
NoVolumeZoneConflict:检查 volume zone是否冲突
-
MaxEBSVolumeCount:检查AWS EBS Volume数量是否过多(默认不超过 39)
-
MaxGCEPDVolumeCount:检查GCE PD Volume数量是否过多(默认不超过 16)
-
MaxAzureDiskVolumeCount:检查Azure Disk Volume数量是否过多(默认不超过 16)
-
MatchInterPodAffinity:检查是否匹配Pod的亲和性要求
-
NoDiskConflict:检查是否存在Volume冲突,仅限于GCE PD、AWS EBS、Ceph RBD以及ISCSI
-
GeneralPredicates:
分noncriticalPredicates和EssentialPredicates
3.2. 评分:对第一步筛选出的符合要求的主机进行打分,这个过程称为 priority,在此阶段,如果在 predicate过程中没有合适的节点,Pod 会一直处于pending状态,不断重试调度,直到有节点满足条件。
经过这个步骤,如果有多个节点满足条件,就继续 priorities 过程:按照优先级大小对节点排序。
Priorities优先级选项包括:
- LeastRequestedPriority:优先调度到请求资源少的节点上
- NodePreferAvoidPodsPriority: alpha.kubernetes.io/preferAvoidPods 字段判断, 权重为10000,避免其他优先级策略的影响
- NodeAffinityPriority:优先调度到匹配 NodeAffinity 的节点上
- TaintTolerationPriority:优先调度到匹配 TaintToleration 的节点上
- ServiceSpreadingPriority:尽量将同一个 service 的 Pod 分布到不同节点上
- MostRequestedPriority:尽量调度到已经使用过的 Node 上,特别适用于
- SelectorSpreadPriority: 优先减少节点上属于同一个Service或Replication Controller的Pod数量
- InterPodAffinityPriority:优先将 Pod 调度到相同的拓扑上(如同一个节点、Rack、Zone 等)
- BalancedResourceAllocation:优先平衡各节点的资源使用
3.3. 选择优先级最高的节点:选择得分最高的主机,进行binding操作,结果存储到Etcd中。
第四步: kubelet根据调度结果执行Pod创建操作,绑定成功后,会启动容器运行时,container, docker run, scheduler会调用API Server的API在etcd中创建一个bound Pod对象,它描述在一个工作节点上绑定运行的所有pod信息。
运行在每个工作节点上的kubelet也会定期与api-server同步bound Pod的信息,一旦发现在该工作节点上运行的bound Pod对象没有更新,则调用Docker API创建并启动pod内的容器.
第五步: kube-proxy为新创建的pod注册动态DNS到CoreOS,然后给pod的service添加对应的iptables规则,用于服务发现和负载均衡。
第六步: 至此,Pod创建完成。