作者介绍:简历上没有一个精通的运维工程师。请点击上方的蓝色《运维小路》关注我,下面的思维导图也是预计更新的内容和当前进度(不定时更新)。
我们上一章介绍了Docker基本情况,目前在规模较大的容器集群基本都是Kubernetes,但是Kubernetes涉及的东西和概念确实是太多了,而且随着版本迭代功能在还增加,笔者有些功能也确实没用过,所以只能按照我自己的理解来讲解。
Pod是整个Kubernetes的最核心的资源,当我们完成部署集群部署以后,我们对集群的维护实际上主要的就是针对Pod维护,其他资源很少会修改调整,但是Pod却会因为版本发布而经常调整,所以我们用了单独一小节来介绍Pod的创建过程。该问题也是面试Kubernetes相关岗位最常问的问题之一。
下图来源于网络
-
通过
kubectl
或其他 API 方式向 Kubernetes API 服务器发出请求:-
用户使用
kubectl apply -f <pod-definition.yaml>
或其他 Kubernetes API 客户端工具提交创建 Pod 的请求。扫描二维码关注公众号,回复: 17578508 查看本文章
-
-
Kubernetes API 服务器 (
kube-apiserver
):-
接收并验证请求:API 服务器检查请求的语法、用户权限、资源配额等。
-
写入 etcd:验证通过后,API 服务器将 Pod 的定义写入 etcd,确保状态一致性和持久化。
-
返回响应:API 服务器向用户返回一个确认信息,表明 Pod 已成功创建。
-
-
Kubernetes 调度器 (
kube-scheduler
):-
监听 API 服务器:调度器通过 watch 机制持续监听 API 服务器上 Pod 的新建事件。
-
调度决策:一旦检测到新的 Pod,调度器开始执行调度逻辑,包括预选(过滤不符合 Pod 要求的节点)和优选(选择最适合运行 Pod 的节点)。
-
绑定节点:确定最佳节点后,调度器将 Pod 绑定到该节点,并通过 API 服务器更新 Pod 的状态。
-
-
调度结果反馈:
-
调度器将调度结果反馈给 API 服务器,API 服务器更新 Pod 的节点绑定信息,并将结果写入 etcd。
-
-
Kubelet 操作:
-
容器运行时接口 (CRI):用于创建和管理容器。
-
容器网络接口 (CNI):用于配置 Pod 的网络。
-
容器存储接口 (CSI):如果 Pod 需要持久化存储,Kubelet 将调用 CSI 接口。
-
监听 API 服务器:每个节点上的 Kubelet 组件也通过 watch 机制监听 API 服务器,等待分配到本节点的 Pod。
-
容器创建:当 Kubelet 发现有一个 Pod 被调度到它所在的节点,它将调用以下标准接口来创建 Pod:
-
-
健康检查和状态更新:
-
容器启动后,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实际上就是我监听你,然后你有变化我就能感知到,然后我会根据你的变化做对应的操作。
运维小路
一个不会开发的运维!一个要学开发的运维!一个学不会开发的运维!欢迎大家骚扰的运维!
关注微信公众号《运维小路》获取更多内容。