Kubernetes(k8s)-Pod创建流程

作者介绍:简历上没有一个精通的运维工程师。请点击上方的蓝色《运维小路》关注我,下面的思维导图也是预计更新的内容和当前进度(不定时更新)。

图片

我们上一章介绍了Docker基本情况,目前在规模较大的容器集群基本都是Kubernetes,但是Kubernetes涉及的东西和概念确实是太多了,而且随着版本迭代功能在还增加,笔者有些功能也确实没用过,所以只能按照我自己的理解来讲解。

Pod是整个Kubernetes的最核心的资源,当我们完成部署集群部署以后,我们对集群的维护实际上主要的就是针对Pod维护,其他资源很少会修改调整,但是Pod却会因为版本发布而经常调整,所以我们用了单独一小节来介绍Pod的创建过程。该问题也是面试Kubernetes相关岗位最常问的问题之一。

下图来源于网络

图片

  1. 通过 kubectl 或其他 API 方式向 Kubernetes API 服务器发出请求

    • 用户使用 kubectl apply -f <pod-definition.yaml> 或其他 Kubernetes API 客户端工具提交创建 Pod 的请求。

      扫描二维码关注公众号,回复: 17578508 查看本文章
  2. Kubernetes API 服务器 (kube-apiserver)

    • 接收并验证请求:API 服务器检查请求的语法、用户权限、资源配额等。

    • 写入 etcd:验证通过后,API 服务器将 Pod 的定义写入 etcd,确保状态一致性和持久化。

    • 返回响应:API 服务器向用户返回一个确认信息,表明 Pod 已成功创建。

  3. Kubernetes 调度器 (kube-scheduler)

    • 监听 API 服务器:调度器通过 watch 机制持续监听 API 服务器上 Pod 的新建事件。

    • 调度决策:一旦检测到新的 Pod,调度器开始执行调度逻辑,包括预选(过滤不符合 Pod 要求的节点)和优选(选择最适合运行 Pod 的节点)。

    • 绑定节点:确定最佳节点后,调度器将 Pod 绑定到该节点,并通过 API 服务器更新 Pod 的状态。

  4. 调度结果反馈

    • 调度器将调度结果反馈给 API 服务器,API 服务器更新 Pod 的节点绑定信息,并将结果写入 etcd。

  5. Kubelet 操作

    • 容器运行时接口 (CRI):用于创建和管理容器。

    • 容器网络接口 (CNI):用于配置 Pod 的网络。

    • 容器存储接口 (CSI):如果 Pod 需要持久化存储,Kubelet 将调用 CSI 接口。

    • 监听 API 服务器:每个节点上的 Kubelet 组件也通过 watch 机制监听 API 服务器,等待分配到本节点的 Pod。

    • 容器创建:当 Kubelet 发现有一个 Pod 被调度到它所在的节点,它将调用以下标准接口来创建 Pod:

  6. 健康检查和状态更新

    • 容器启动后,Kubelet 执行 Pod 的健康检查(如 livenessProbe 和 readinessProbe)。

    • 一旦容器通过健康检查,Kubelet 将更新 Pod 的状态为“运行中”  (1/1这样的状态),并将状态反馈给 API 服务器。

    • API 服务器将最新的 Pod 状态写入 etcd,确保集群状态的一致性。

基本上目前能看到的讲解Pod创建流程的图基本上都是以此图或者以此图为原型的一些改进版,所以我也会用该图来讲解,并且结合日志。

1.调整Kube-apiserver和Kube-scheduler的日志

#在静态pod的yaml文件启动参数添加一行#这个是最大日志级别会显示很多的内容,需要过滤才比较容易查看- --v=10

2.准备一个Pod​​​​​​​

apiVersion: v1            # API 版本
kind: Pod                 # 资源类型
metadata:
  name: example-pod       # Pod 名称
  labels:
    app: example          # 标签,用于标识和选择相关的资源
spec:
  containers:             # 容器列表
  - name: example-container  # 容器名称
    image: 192.168.31.43:5000/busybox      # 容器镜像
    imagePullPolicy: IfNotPresent
    command: ["sh", "-c", "tail -f /dev/null"]
    ports:
    - containerPort: 80      # 容器内的端口号

3.创建pod

kubectl  apply -f pod.yaml

4.日志分析

这个时候应该是上图写入了数据库,并且返回给用户,但是这个还没有调度,因为提示的是没有Node节点。​​​​​​​

#kube-apiserver日志
I0119 02:34:02.844378 graph_populator.go:148] updatePod default/example-pod, no node

kube-scheduler通过watch 到kube-server有Pod被创建。并且没有被调度,然后它就开始根据算法调度到了node01节点​​​​​​​

#kube-scheduler调度日志
I0119 02:34:02.844026       1 eventhandlers.go:118] "Add event for unscheduled pod" pod="default/example-pod"
I0119 02:34:02.844065       1 scheduling_queue.go:933] "About to try and schedule pod" pod="default/example-pod"
I0119 02:34:02.844073       1 scheduler.go:443] "Attempting to schedule pod" pod="default/example-pod"
I0119 02:34:02.844232       1 default_binder.go:52] "Attempting to bind pod to node" pod="default/example-pod" node="node01"
I0119 02:34:02.856122       1 eventhandlers.go:161] "Delete event for unscheduled pod" pod="default/example-pod"
I0119 02:34:02.856221       1 cache.go:385] "Finished binding for pod, can be expired" pod="default/example-pod"
I0119 02:34:02.856251       1 scheduler.go:623] "Successfully bound pod to node" pod="default/example-pod" node="node01" evaluatedNodes=2 feasibleNodes=1

kube-apiserver也显示调度到node01

#kube-apiserver日志
I0121 02:34:02.855314       1 graph_populator.go:158] updatePod default/example-pod for node node01

​​​​​​​

kubelet感知到他分配了Pod,他开始执行创建Pod操作。

#kubelet日志
Feb 15 16:37:57 node01 kubelet[3408]: I0215 16:37:57.087517    3408 config.go:383] "Receiving a new pod" pod="default/example-pod"
Feb 15 16:37:57 node01 kubelet[3408]: I0215 16:37:57.087602    3408 kubelet.go:2114] "SyncLoop ADD" source="api" pods=[default/example-pod]
Feb 15 16:37:57 node01 kubelet[3408]: I0215 16:37:57.087724    3408 pod_workers.go:571] "Pod is being synced for the first time" pod="default/example-pod" podUID=18736566-533b-4afa-99c5-b2471fe6b6e3
Feb 15 16:37:57 node01 kubelet[3408]: I0215 16:37:57.087760    3408 pod_workers.go:888] "Processing pod event" pod="default/example-pod" podUID=18736566-533b-4afa-99c5-b2471fe6b6e3 updateType=0
Feb 15 16:37:57 node01 kubelet[3408]: I0215 16:37:57.087774    3408 kubelet.go:1554] "syncPod enter" pod="default/example-pod" podUID=18736566-533b-4afa-99c5-b2471fe6b6e3
Feb 15 16:37:57 node01 kubelet[3408]: I0215 16:37:57.087785    3408 kubelet_pods.go:1441] "Generating pod status" pod="default/example-pod"
Feb 15 16:37:57 node01 kubelet[3408]: I0215 16:37:57.087811    3408 kubelet_pods.go:1453] "Got phase for pod" pod="default/example-pod" oldPhase=Pending phase=Pending
Feb 15 16:37:57 node01 kubelet[3408]: I0215 16:37:57.087850    3408 status_manager.go:529] "updateStatusInternal" version=1 pod="default/example-pod" podUID=18736566-533b-4afa-99c5-b2471fe6b6e3 containers="(example-container state=waiting previous=<none>)"

​​​​​​​

我们前面讲解RBAC权限的时候也提到了watch,这里的watch实际上就是我监听你,然后你有变化我就能感知到,然后我会根据你的变化做对应的操作。

运维小路

一个不会开发的运维!一个要学开发的运维!一个学不会开发的运维!欢迎大家骚扰的运维!

关注微信公众号《运维小路》获取更多内容。

猜你喜欢

转载自blog.csdn.net/dessler/article/details/146965057