当API收到创建Pod的请求,然后会将Pod的定义存储到etcd中,然后scheduler会将pod加入到调度队列中(如果没有做调度优先级配置,默认是放在队列最后),然后scheduler会根据预选、优选策略给pod分配一个最有的node节点,然后这个pod会被标记为Scheduled,并将其状态存储到etcd中。

    到目前为止pod还并没有被创建,因为创建Pod需要通过kubelet组件来完成。kubelet组件会通过apiserver来获取pod的状态,同样也会上报pod的状态。
    当某个节点检测到该pod是调度到自己节点的时候,就会在本节点创建这个pod,不过创建pod并不是kubelet自己动手,而是交给下面三个组件来完成。
    • 容器运行时接口(CRI):为 Pod 创建容器的组件。
    • 容器网络接口(CNI):将容器连接到集群网络并分配 IP 地址的组件。
    • 容器存储接口(CSI):在容器中装载卷的组件。

    到现在pod创建完成了,然后会将该pod的状态上报给apiserver并存储在etcd中。
    现在pod创建完成了,但是在k8s中,pod并不适合直接提供服务,如果在集群内部是通过service来提供服务,如果集群外部需要访问,是通过ingress来提供访问入口。那如果我ingress以及service的某个pod发生了变化,它们又该如何更新呢?

    service和pod是通过label selector(标签选择器)来进行关联的,只要符合service中定义的label selector,就会将其地址和端口维护到Endpoints中。
    Endpoints 对象会从 Pod 中收集所有的 IP 地址和端口,而且不仅一次。在以下情况中,Endpoint 对象将更新一个 endpiont 新列表:
    • Pod 创建时。
    • Pod 删除时。
    • 在 Pod 上修改标签时。

    当pod通过Readiness探针后,才标识这个pod真正可用。当pod可用过后,service会通过label selector找到所有匹配的Pod,然后通过k8s更新endpoint,Endpoints也会做相应的更新。
    除了service,还有kube-proxy,ingress都会使用到endpoint,它们也会进行相应的更新,kube-proxy会通过endpoint来更新iptables或者ipvs规则,ingress更新endpoint是为了让pod接入外部流量。

    创建pod的过程以及pod创建完成后的一系列变化可以总结如下:
    1、apiserver收到创建pod的请求(可以是直接创建pod的定义,也可以是通过其他控制器来完成的)。
    2、Pod 的定义存储在 etcd 中。
    3、scheduler参与调度Pod,为其分配最优节点,并把相关信息存储到etcd中。
    4、kubelet监听到pod的信息,在节点上创建pod,分配资源以及IP等,将信息存储到etcd中。
    5、kubelet等待pod的Readiness探针成功,并对相关的Endpoints对象更改进行通知。
    6、Endpoints将新的endpoint添加到列表中。
    7、其他组件控制器根据Endpoints做相应的更改配置,比如kube-proxy会重新创建或者更改iptables/ipvs规则等。