Kubelet 工作节点控制平面组件简介

kubelet  关于pod方面


kubelet 是运行在每个节点上的负责启动容器的重要的守护进程

1.  在启动时,Kubelet进程加载配置参数,向API Server 处创建一个Node 对象来注册自身的节点信息,例如操作系统、Kernel 版本、IP 地址、总容量(Capacity)和可供分配的容量(Allocatable Capacity)等。

2.  然后kubelet 须定时(默认值是每10s 通过NodeStatusUpdateFrequency 设置参数)向API Server 汇报自身情况,例如磁盘空间是否用满、CPU 和Memory 是否有压力自身服务是否Ready 等这些信息都将被调度器使用,在调度Pod 时给节点打分   

 kube-scheduler :

Kubernetes 的默认调度器还要负责对调度器缓存(即:scheduler cache)进行更新。事实上,Kubernetes 调度部分进行性能优化的一个最根本原则,就是尽最大可能将集群信息 Cache 化,以便从根本上提高 Predicate 和 Priority 调度算法的执行效率。)                          

Predicates 算法需要的 Node 信息,都是从 Scheduler Cache 里直接拿到的,这是调度器保证算法执行效率的主要手段之一。 

3.  如果kubelet停止汇报这些信息,那么NodeLifecycle 控制器将认为kubelet 已经不能正常工作,会将Node 状态设置为Unknown,并在一段时间后开始驱逐其上的Pod 对象。

节点上的Pod 来源有两个:普通Pod 和静态Pod(Static Pod)
  • 普通Pod,也就是通过API Server 创建的Pod,是被Scheduler 调度到该节点上的。
  • 静态Pod 是不经过API Serverkubelet 通过观测本地目录或者HTTP URL 下的定义文件所创建的Pod。静态Pod 始终绑定到kubelet 所在的节点上。
kubelet 会自动尝试在 API Server 上为每个静态 Pod 创建一个镜像 Pod Mirror Pod )。这意味着在节点上运行的静态Pod API Server 上可见,但不能从那里进行控制。本地目录可以通过配置参数staticPodPath 来指定。 HTTP URL 通过配置参数staticPodURL 来指定。在这个目录和URL 下的文件的所有更新都可以被kubelet 监测到,周期默认是20s,可以通过配置参数FileCheckFrequency 和HTTPCheckFrequency 来指定。

Pod 被调度到 kubelet 所在的节点上时, kubelet 首先将Pod 中申请的Volume 挂载到 当前节点上。当Volume 挂载完毕后 kubelet 才会调用容器运行时为Pod 创建容器沙箱( PodSandbox)和容器 kubelet 也会周期性地查询容器的状态,并定期汇报容器状态,通 过cAdvisor 监控容器资源的使用情况。

容器沙箱是 “pause” 容器的抽象概念,有时也称为 infra 容器, 与用户容器 “捆绑” 运行在同一个 Pod 中 ,共享 CGroup Namespace 等资源,与其他 Pod 资源隔离。 在PodSand box 中运行一个非常简单的pause 进程,它不执行任何功能,一启动就永远把自己阻塞住了(pause 系统调用)。容器沙箱最大的作用是维护 Pod 网络协议栈。

在创建容器之前,kubelet 首先会调用容器运行时为该Pod 创建容器沙箱,容器运行时为容器沙箱设置网络环境当容器沙箱成功启动后,kubelet 才会调用容器运行时在该容器沙箱的网络命名空间(Net Namespace)中创建和启动容器。用户的容器可能因为各种原因退出,但是因为有容器沙箱存在,容器的网络命名空间不会被摧毁,当重新创建用户容器时,无须再为它设置网络了。

[root@node1 ~]# cat /var/lib/kubelet/kubeadm-flags.env 
KUBELET_KUBEADM_ARGS="--network-plugin=cni --pod-infra-container-image=kubesphere/pause:3.2 --node-status-update-frequency=5s"


[root@node1 ~]# docker ps | grep pause
beadb8451a56   kubesphere/pause:3.2     "/pause"                 21 minutes ago   Up 21 minutes             k8s_POD_grafana-5d794f46d5-5nk4t_monitor_3709e4a0-9b61-4afa-a103-2d20073dfed2_0
d4d323887a49   kubesphere/pause:3.2     "/pause"                 22 minutes ago   Up 22 minutes             k8s_POD_rollingupdate-strategy-76bc87cfbf-zjmtp_devops_ae80edc5-0ed4-40a1-805e-c44c6c46ff53_15
9211be42e3d1   kubesphere/pause:3.2     "/pause"                 22 minutes ago   Up 22 minutes             k8s_POD_hostnames-766c597cd8-gxrdj_default_3bcc5430-96ee-4109-a9cd-dd3a59b68fbd_14
76c9ae5edcfb   kubesphere/pause:3.2     "/pause"                 22 minutes ago   Up 22 minutes             k8s_POD_example-pv-pod_default_9b748a48-8ce2-4739-85bb-34be8be4631f_4
8fa855d39993   kubesphere/pause:3.2     "/pause"                 22 minutes ago   Up 22 minutes             k8s_POD_nginx-green-7c47d45784-qkmjc_devops_4ca2b07b-6155-4079-8949-c251aecb6d28_7
a3a579120858   kubesphere/pause:3.2     "/pause"                 22 minutes ago   Up 22 minutes             k8s_POD_hostnames-766c597cd8-2gfnr_default_4665618b-4ed9-4748-8be1-29f64feda83e_15
bd1d7173ef44   kubesphere/pause:3.2     "/pause"                 22 minutes ago   Up 22 minutes             k8s_POD_example-app-7d95cbf666-l8msj_default_2ab21d1a-e08f-4595-baa4-d83c146ca4f0_12
922e161e53c7   kubesphere/pause:3.2     "/pause"                 22 minutes ago   Up 22 minutes             k8s_POD_dns-test_default_dd07f32b-b42b-4347-acbf-9367c3aea488_39
01638ddab8de   kubesphere/pause:3.2     "/pause"                 22 minutes ago   Up 22 minutes             k8s_POD_rollingupdate-strategy-76bc87cfbf-t5hn7_devops_7fa7751d-45fb-4047-a5e7-4724697a8e8d_17
abae2badf8fb   kubesphere/pause:3.2     "/pause"                 22 minutes ago   Up 22 minutes             k8s_POD_eureka-2_ms_c7654d45-14ba-4b7b-8bae-3e4714c082af_38
0a8f3be703e8   kubesphere/pause:3.2     "/pause"                 22 minutes ago   Up 22 minutes             k8s_POD_localprovi-provisioner-nfztt_kube-system_b24c3f0e-9b71-417d-88f4-c1be40ed7f99_4
4044da91a280   kubesphere/pause:3.2     "/pause"                 22 minutes ago   Up 22 minutes             k8s_POD_hostnames-766c597cd8-mbfdk_default_4646cd67-04f1-4e5d-ab5a-08b80f978ade_13
4debbbff4026   kubesphere/pause:3.2     "/pause"                 22 minutes ago   Up 22 minutes             k8s_POD_alertmanager-inst-0_monitoring_53fa2e2d-f3be-4fd8-8523-6977494709ec_10
02a794ba6f68   kubesphere/pause:3.2     "/pause"                 22 minutes ago   Up 22 minutes             k8s_POD_example-app-7d95cbf666-mgl82_default_1f811e50-9bed-45b0-adb9-6756df88a824_11
63cd691528f1   kubesphere/pause:3.2     "/pause"                 22 minutes ago   Up 22 minutes             k8s_POD_eureka-0_ms_054fe755-b85d-466b-b0cb-5e348bea5f4a_39
019bf89bbab1   kubesphere/pause:3.2     "/pause"                 22 minutes ago   Up 22 minutes             k8s_POD_prometheus-server-79b6f5f545-p2wsz_monitor_a0ab3856-ef9b-4324-8745-0eb088f317b3_2
c0b518fe4c4e   kubesphere/pause:3.2     "/pause"                 22 minutes ago   Up 22 minutes             k8s_POD_calico-node-6b6nz_kube-system_b39849d4-7c48-4ac8-9123-7fda91b77a61_45
2e84819246d6   kubesphere/pause:3.2     "/pause"                 22 minutes ago   Up 22 minutes             k8s_POD_kube-proxy-bvgqt_kube-system_c469a7eb-3b50-4f24-8d0b-1fa2028fd0ab_35
fab993500283   kubesphere/pause:3.2     "/pause"                 22 minutes ago   Up 22 minutes             k8s_POD_nodelocaldns-26x9q_kube-system_4ced12c3-f58b-447b-90c3-ce5ebe1c0be7_45
554e2489561e   kubesphere/pause:3.2     "/pause"                 22 minutes ago   Up 22 minutes             k8s_POD_node-exporter-jbbcq_monitor_090eccee-f405-4ac4-aca1-d98749a13bde_41

可以看出,kubelet 并不是直接进行容器操作的,如图1-14 所示。它都是通过容器运行时的接口(Container Runtime Interface,CRI)调用容器运行时对容器和镜像进行操作的,例如创建、启动、停止和删除容器,下载镜像等。

容器运行时的选用,这里有多条路可选:使用内置的dockershim 和远端的容器运行时等。目前默认情况下,kubelet 是通过内置的dockershim 调用 Docker 来完成容器操作的。我们也可以指定 remote 模式(通过参数--container-runtime 来指定),使用外部的遵循CRI 的容器运行时。虽然kubelet 不直接参与容器的创建与运行,但是它是管理和监控该节点上Pod 及Pod 中容器 “生老病死” 的核心。

 

                                                 图1-14 kubelet 的组织架构 

如图1-15 所示,kubelet 的核心函数是syncLoop。此函数是由事件驱动的。kubelet 会从API Server 的静态Pod 的本地目录和HTTP URL 处监听到Pod 资源对象的变化,产生新增、更改、删除事件。kubelet 还会启动一个PLEGPod Lifecycle Event Generator)线程,每秒钟重新查询一次容器运行时容器的状态,更新Pod 的缓存,并根据容器的状态产生同步的事件。

                                          图 1-15 kubelet 管理Pod 的核心流程  
kubelet syncLoop 函数将 Pod 对象及容器状态的变化产生的 4 UpdatePodOptions
SyncPodUpdate SyncPodCreate SyncPodKill SyncPodSync ) 分发给 Pod 对应的 Pod
Worker 进行处理。每个 Pod 都有一个 PodWorker PodWorker 会根据 UpdatePodOptions
类型调用相关容器运行时接口进行相关操作。对于 SyncPodUpdate SyncPodSync 类型的
UpdatePodOptions PodWorker 会事先根据当前 Pod Spec Status 调用 computePodAct
ions 函数计算下一步操作,例如需要停止的容器有哪些,是否需要删除容器沙箱等。 kube
let 就是通过这样的 闭环反馈 控制 Pod Status 及其 Spec 最终达到一致的。
从图 1-15 也可以看出,除管理 Pod 外, kubelet 还有很多其他功能:
  • 对容器的Liveness Readiness 进行检测。Liveness 用来探测容器是否处于 存活状态”,如果kubelet 检测容器当前处于 死亡状态,则kubelet 会停止此容器,并重新创建新的容器。
Readiness 用来探测容器中的用户进程是否处于 可服务状态 ,如果 kubelet 检测容器当前处于 “不可服务状态 ,则 kubelet 不会重启容器,但会把 Pod 中的容器状态更新为ContainersReady=false 。这对 Service 的高可用而言非常重要。如果 Pod 的容器处于 不可服务状态” Endpoint 控制器就会将该 Pod IP 地址从 Endpoint 中移除,该 Pod 将不能再接收任何用户请求。
  • 保护节点不被容器抢占所有资源。如果镜像占用磁盘空间的比例超过高水位(默认值为90%,可以通过参数ImageGCHighThresholdPercent 进行配置),kubelet 就会清理不用的镜像。
当节点CPU Memory 或磁盘少于某特定值或者比例(由参数 EvictionHard 配置)时,kubelet 就会驱逐低优先级的 Pod (例如 BestEffort Pod )。
通过这些操作,保障节点上已有的Pod 能够在保证的 QoS Quality of Service )下继续正常运行。
处理 Master 节点下发到本节点的任务, 比如exec、logs 和attach 等请求。API Server是无法完成这些工作的,此时API Server 需要向kubelet 发起请求,让kubelet 完成此类请求处理。

kubelet关于pv pvc方面


而 Kubernetes 需要做的工作,就是使用这些存储服务,来为容器准备一个持久化的宿主机目录,以供将来进行绑定挂载时使用。而所谓“持久化”,指的是容器在这个目录里写入的文件,都会保存在远程存储中,从而使得这个目录具备了“持久性”。

这个准备“持久化”宿主机目录的过程,我们可以形象地称为“两阶段处理”。

接下来,我通过一个具体的例子为你说明。

当一个 Pod 调度到一个节点上之后kubelet 就要负责为这个 Pod 创建它的 Volume 目录。默认情况下,kubelet 为 Volume 创建的目录是如下所示的一个宿主机上的路径: 

/var/lib/kubelet/pods/<Pod的ID>/volumes/kubernetes.io~<Volume类型>/<Volume名字>

 接下来,kubelet 要做的操作就取决于你的 Volume 类型了。

[root@node1 volumes]# ls
kubernetes.io~nfs  kubernetes.io~secret
[root@node1 volumes]# pwd
/var/lib/kubelet/pods/3709e4a0-9b61-4afa-a103-2d20073dfed2/volumes

如果你的 Volume 类型是远程块存储,比如 Google Cloud 的 Persistent Disk(GCE 提供的远程磁盘服务),那么 kubelet 就需要先调用 Goolge Cloud 的 API,将它所提供的 Persistent Disk 挂载到 Pod 所在的宿主机上。

备注:你如果不太了解块存储的话,可以直接把它理解为:一块磁盘。 

这相当于执行:

$ gcloud compute instances attach-disk <虚拟机名字> --disk <远程磁盘名字>

这一步为虚拟机挂载远程磁盘的操作,对应的正是“两阶段处理”的第一阶段。在 Kubernetes 中,我们把这个阶段称为 Attach。

Attach 阶段完成后,为了能够使用这个远程磁盘,kubelet 还要进行第二个操作,即:格式化这个磁盘设备,然后将它挂载到宿主机指定的挂载点上。不难理解,这个挂载点,正是我在前面反复提到的 Volume 的宿主机目录。所以,这一步相当于执行: 

# 通过lsblk命令获取磁盘设备ID
$ sudo lsblk
# 格式化成ext4格式
$ sudo mkfs.ext4 -m 0 -F -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/<磁盘设备ID>
# 挂载到挂载点
$ sudo mkdir -p /var/lib/kubelet/pods/<Pod的ID>/volumes/kubernetes.io~<Volume类型>/<Volume名字>

这个将磁盘设备格式化并挂载到 Volume 宿主机目录的操作,对应的正是“两阶段处理”的第二个阶段,我们一般称为:Mount。

Mount 阶段完成后,这个 Volume 的宿主机目录就是一个“持久化”的目录了,容器在它里面写入的内容,会保存在 Google Cloud 的远程磁盘中。

而如果你的 Volume 类型是远程文件存储(比如 NFS)的话,kubelet 的处理过程就会更简单一些。

因为在这种情况下,kubelet 可以跳过“第一阶段”(Attach)的操作,这是因为一般来说,远程文件存储并没有一个“存储设备”需要挂载在宿主机上。

所以,kubelet 会直接从“第二阶段”(Mount)开始准备宿主机上的 Volume 目录。

在这一步,kubelet 需要作为 client,将远端 NFS 服务器的目录(比如:“/”目录),挂载到 Volume 的宿主机目录上,即相当于执行如下所示的命令:

$ mount -t nfs <NFS服务器地址>:/ /var/lib/kubelet/pods/<Pod的ID>/volumes/kubernetes.io~<Volume类型>/<Volume名字> 

通过这个挂载操作,Volume 的宿主机目录就成为了一个远程 NFS 目录的挂载点,后面你在这个目录里写入的所有文件,都会被保存在远程 NFS 服务器上。所以,我们也就完成了对这个 Volume 宿主机目录的“持久化”。

而经过了“两阶段处理”,我们就得到了一个“持久化”的 Volume 宿主机目录。所以,接下来,kubelet 只要把这个 Volume 目录通过 CRI 里的 Mounts 参数,传递给 Docker,然后就可以为 Pod 里的容器挂载这个“持久化”的 Volume 了。其实,这一步相当于执行了如下所示的命令:

$ docker run -v /var/lib/kubelet/pods/<Pod的ID>/volumes/kubernetes.io~<Volume类型>/<Volume名字>:/<容器内的目标目录> 我的镜像 ...

 以上,就是 Kubernetes 处理 PV 的具体原理了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值