kubelet - container manager

containerManager 负责 node 节点上运行的容器的配置信息,如cgroupcpudevice

 

pod的创建流程参考:

http://www.tianfeiyu.com/?p=2825

 

一构成

1.QOSContainerManager维护pod对应的Qos,用于调度、驱逐、设置各资源的cgroup等模块

2.cgroupManager根据pod的Qos设置不同级别的cgroup参数,并不断根据pod的变化维护这些cgroup参数

3.devicemanager管理节点上的device,主要包含分配、回收、本地记录存储;

4.cpumanager管理节点上的cpu,主要包含分配、回收、本地记录存储

5.devicemanager通过topologymanagercontainer选择最优的device组合

6.cpumanager通过topologymanagercontainer选择最优cpuset

 

调用流程:

1.kubeRuntimeManager.SyncPod创建完container后,通过cpumanager设置container的启动参数;

2.kubeRuntimeManager.SyncPod.startContainer启动container时会调用containerManager获取container跑在device上的参数,最终回调用到devicemanager

3.Kubelet.SyncPod设置cgroup参数阶段-->podContainerManager-->cgroupManager(依赖QOSContainerManager设置QOS)-->runc.libcontainer.cgroupfs将设置的参数apply到container

 

 

二、Kubelet.syncPod vs kubeRuntimeManager.SyncPod:调用关系:

 

Kubelet.syncPod

1.如果pod需要被删除,调用containerRuntime.KillPod杀掉pod

2.为第一次创建的pod记录创建时间,当pod状态变化时也记录当前时间

3.通过一系列admit判断pod是否能在当前node上运行,如安全相关的appArmorValidatorcontainerRuntime是否允许root Privilege

4.设置podcgroup参数

5.static pod创建mirror pod

6.创建相应的工作目录,如pod的工作目录、存储目录、插件plugins目录

7,等待volume挂载到pod的存储目录下

8.拉取下载container imagesecret

9.调用kubeRuntimeManager.SyncPodpod创建container

10.statusManager更新pod的状态

 

kubeRuntimeManager.SyncPod

//  1. Compute sandbox and container changes.
//  2. Kill pod sandbox if necessary.
//  3. Kill any containers that should not be running.
//  4. Create sandbox if necessary.
//  5. Create ephemeral containers.
//  6. Create init containers.
//  7. Create normal containers.

这部分的修改不会导致pod重建

 

 

二cgroupmanager

cgroupmanager负责 node 节点上运行的容器的 cgroup 配置信息,kubelet 启动参数如果指定 --cgroups-per-qos 的时候,kubelet 会启动 goroutine 来周期性的更新 pod 的 cgroup 信息,维护其正确性,该参数默认为 true,实现了 pod 的Guaranteed/BestEffort/Burstable 三种级别的 Qos。

目前 kubernetes 仅支持 cpu、memory、pids 、hugetlb 四个 cgroup 子系统

runtime 有两种 cgroup 驱动:一种是 systemd,另外一种是 cgroupfs

  • cgroupfs 比较好理解,比如说要限制内存是多少、要用 CPU share 为多少,其实直接把 pid 写入到对应cgroup task 文件中,然后把对应需要限制的资源也写入相应的 memory cgroup 文件和 CPU 的 cgroup 文件就可以了;

  • 另外一个是 systemd 的 cgroup 驱动,这个驱动是因为 systemd 本身可以提供一个 cgroup 管理方式。所以如果用 systemd 做 cgroup 驱动的话,所有的写 cgroup 操作都必须通过 systemd 的接口来完成,不能手动更改 cgroup 的文件;


 

Kubelet cgroup level:

/sys/fs/cgroup/cpu/kubepods – kubepods cgroup
/sys/fs/cgroup/cpu/kubepods/burstable – Qos level cgroup
/sys/fs/cgroup/cpu/kubepods/burstable/pod<UID> – pod level cgroup
/sys/fs/cgroup/cpu/kubepods/burstable/pod<UID>/container<UID> – container level cgroup

1.cgroupmanager 会把本机的 allocatable 资源写入到 kubepods 下对应的 cgroup 文件中,比如 kubepods/cpu.share

2.Qos level cgroup有两个cgroupburstable besteffort,分别作为 burstable级别podbesteffort级别pod的父cgroup;而Guaranteed Qos 对应的 pod 会直接在 kubepods 同级的 cgroup 中创建 pod cgroup,原因:guaranteed 级别的 pod 有明确的资源申请量(request)和资源限制量(limit),不需要qos级别的cgroup来管理和限制资源

3.pod level cgroup包含pod对应的container level cgroup

4.创建流程kubepods>qos>pod>container,设置流程container->pod->qos->kubepods,即设置好container level cgroup中各文件的限制,再层层往外更新其它level的限制

5.从级别和目录可以看出:burstable 的 cgroup 需要为比他等级高的 guaranteed 级别的 pod 的内存资源做预留,而 besteffort 需要为 burstable 和 guaranteed 都要预留内存资源。


 

例:

/sys/fs/cgroup/cpu/kubepods/burstable/pod<UID>/container<UID>/cpu.shares=2

/sys/fs/cgroup/cpu/kubepods/burstable/pod<UID>/cpu.shares=204
/sys/fs/cgroup/cpu/kubepods/burstable/cpu.shares=1126
/sys/fs/cgroup/cpu/kubepods/cpu.shares=49512

 

对于每一个 pod 设定的 requests 和 limits,kubernetes 都会转换为 cgroup 中的计算方式,CPU 的转换方式如下所示:

  • cpu.shares = (cpu in millicores * 1024) / 1000

  • cpu.cfs_period_us = 100000 (i.e. 100ms)

  • cpu.cfs_quota_us = quota = (cpu in millicores * 100000) / 1000

  • memory.limit_in_bytes

CPU 最终都会转换为以微秒为单位,memory 会转换为以 bytes 为单位

如果 pod 指定了 requests 和 limits,kubelet 会按以上的计算方式为 pod 设置资源限制,如果没有指定 limit 的话,那么 cpu.cfs_quota_us 将会被设置为 -1,即没有限制。而如果 limit 和 request 都没有指定的话,cpu.shares 将会被指定为 2,这个是 cpu.shares 允许指定的最小数值了,可见针对这种 pod,kubernetes 只会给它分配最少的 cpu 资源。而对于内存来说,如果没有 limit 的指定的话,memory.limit_in_bytes 将会被指定为一个非常大的值,一般是 2^64 ,可见含义就是不对内存做出限制。

参考:https://www.jianshu.com/p/924e3c48cb9b

 

三QOSContainerManager

QoS(Quality of Service) 即服务质量,QoS 是一种控制机制,它提供了针对不同用户或者不同数据流采用相应不同的优先级,或者是根据应用程序的要求,保证数据流的性能达到一定的水准。kubernetes 中有三种 Qos,分别为:

  • 1、Guaranteed:pod 的 requests 与 limits 设定的值相等;

  • 2、Burstable:pod requests 小于 limits 的值且不为 0;

  • 3、BestEffort:pod 的 requests 与 limits 均为 0;

三者的优先级如下所示,依次递增,OOM_SCORE_ADJ递减

BestEffort -> Burstable -> Guaranteed

三种 Qos 在调度和底层表现上都不一样:

  • 1、在调度时调度器只会根据 request 值进行调度;

  • 2、二是当系统 OOM上时对于处理不同 OOMScore 的进程表现不同,OOMScore 是针对 memory 的,当宿主上 memory 不足时系统会优先 kill 掉 OOMScore 值低的进程,可以使用 $ cat /proc/$PID/oom_score 查看进程的 OOMScore。OOMScore 的取值范围为 [-1000, 1000],Guaranteed pod 的默认值为 -998,Burstable pod 的值为 2~999,BestEffort pod 的值为 1000,也就是说当系统 OOM 时,首先会 kill 掉 BestEffort pod 的进程,若系统依然处于 OOM 状态,然后才会 kill 掉 Burstable pod,最后是 Guaranteed pod;

  • 3、三是 cgroup 的配置不同,kubelet 为会三种 Qos 分别创建对应的 QoS level cgroups,Guaranteed Pod Qos 的 cgroup level 会直接创建在 RootCgroup/kubepods 下,Burstable Pod Qos 的创建在 RootCgroup/kubepods/burstable 下,BestEffort Pod Qos 的创建在 RootCgroup/kubepods/BestEffort 下,上文已经说了 root cgroup 可以通过 $ mount | grep cgroup看到,在 cgroup 的每个子系统下都会创建 Qos level cgroups, 此外在对应的 QoS level cgroups 还会为 pod 创建 Pod level cgroups;


 

qos的计算方式:

memoryRequest := container.Resources.Requests.Memory().Value()
        oomScoreAdjust := 1000 - (1000*memoryRequest)/memoryCapacity
        // A guaranteed pod using 100% of memory can have an OOM score of 10. Ensure
        // that burstable pods have a higher OOM score adjustment.
        if int(oomScoreAdjust) < (1000 + guaranteedOOMScoreAdj) {
                return (1000 + guaranteedOOMScoreAdj)
        }
        // Give burstable pods a higher chance of survival over besteffort pods.
        if int(oomScoreAdjust) == besteffortOOMScoreAdj {
                return int(oomScoreAdjust - 1)
        }
        return int(oomScoreAdjust)

可见:pod的container使用memory越多,它的 OOMScore越小,越不容易被驱逐。

 

 

 

三 device manager

 

四topology manager

白话:为container的resource选择最优组合,如同组的cpuset,container所需的device来自同一个NUMA Node.

topology manager不是单独起作用的,当前k8s 1.17.3中,它和CPU manager,device manager共同为pod分配资源,优化资源访问。

topology manager从Hint Providers中以bitmask的形式接受NUMA拓扑信息(Topology Hint),包括当前可用的NUMA节点和倾向的资源分配指示。Topology manager策略对提供的hint进行一系列操作以后将所有的hint决定汇聚起来,得出一个最佳的hint(bestHint)。通过配置的策略(policy),主机节点可以选择接受或者拒绝pod。

topology manager当前所支持的策略有四个:None,BestEffort,Restricted和SingleNumaNode。

 

None是默认的策略,这个策略不会做任何的NUMA感知的资源对齐。

 

BestEffort对于pod里面的每一个container都会调用它们的hint provider来发现它们的资源可用性。topology manager计算存储这些container的NUMA亲和度的信息,如果亲和度不能被满足的话,manager也会存储亲和度信息同时也会允许pod加入这个主机节点。

 

Restricted同样也会对pod里面的每一个container计算NUMA亲和度。不同的是,如果亲和度不能被满足的话,主机节点会拒绝这个pod的加入。这样会导致pod处于Terminated的状态。如果pod被接受了,那么亲和度信息将会被用于container的资源分配。

 

SingleNumaNode策略用来判断单个NUMA节点的亲和度是否满足,如果满足的话hint provider即可利用亲和度信息进行资源分配;如果不满足的话主机节点会拒绝pod的加入,这样也会导致pod处于Terminated的状态。

 

参考:https://blog.youkuaiyun.com/qjm1993/article/details/103237944

 

 

 

五cpu manager

白话:根据NUMA为container选择最优的cpuset,让container从cpu方向得到更高的性能

目前CPU Manager支持两种Policy,分别为none和static,通过kubelet --cpu-manager-policy设置,未来会增加dynamic policy做Container生命周期内的cpuset动态调整。

    • none: 为cpu manager的默认值,相当于没有启用cpuset的能力。cpu request对应到cpu share,cpu limit对应到cpu quota。

    • static: 目前,请设置--cpu-manager-policy=static来启用,kubelet将在Container启动前分配绑定的cpu set,分配时还会考虑cpu topology来提升cpu affinity,后面会提到。

  • 确保kubelet为--kube-reserved--system-reserved都配置了值,可以不是整数个cpu,最终会计算reserved cpus时会向上取整。这样做的目的是为了防止CPU Manager把Node上所有的cpu cores分配出去了,导致kubelet及系统进程都没有可用的cpu了。

注意CPU Manager还有一个配置项 --cpu-manager-reconcile-period,用来配置CPU Manager Reconcile Kubelet内存中CPU分配情况到cpuset cgroups的修复周期。如果没有配置该项,那么将使用 --node-status-update-frequency default 10s 配置的值。

使用CPU Manager的Pod、Container具备以下两个条件:

  • Pod QoS为Guaranteed;

  • Pod中该Container的Cpu request必须为整数CPUs;

工作流程:

  • Kuberuntime调用容器运行时去create该Container。

  • 创建完后,调用PreStartContainer将该Container交给CPU Manager处理。

  • 创建业务container时,先把init container占用的cpu释放

  • CPU Manager为Container按照static policy逻辑进行处理。

  • CPU Manager从当前Shared Pool中挑选“最佳”Set拓扑结构的CPU,对于不满足Static Policy的Contianer,则返回Shared Pool中所有CPUS组成的Set。

  • 挑选方式:根据Node上的NUMA CPU Topology划分cpu组,当container需要多个cpu时,让这几个cpu尽量来自同一个组(简单理解为一个插槽),这样同组访问能加快速度提高性能。

  • CPU Manager将对该Container的CPUs分配情况记录到Checkpoint State中,并且从Shared Pool中删除刚分配的CPUs。

  • CPU Manager再从state中读取该Container的CPU分配信息,然后通过UpdateContainerResources cRI接口将其更新到Cpuset Cgroups中,包括对于非Static Policy Container。

  • Kuberuntime调用容器运行时Start该容器。

Checkpoint文件内容就是CPUManagerCheckpoint结构体的json格式,其中Entries的key是ContainerID,value为该Container对应的Assigned CPU Set信息。

当这些通过CPU Manager分配CPUs的Container要Delete时,CPU Manager工作流大致如下:

  1. Kuberuntime会调用CPU Manager去按照static policy中定义逻辑处理。

  2. CPU Manager将该Container分配的Cpu Set重新归还到Shared Pool中。

  3. Kuberuntime调用容器运行时Remove该容器。

  4. CPU Manager会异步地进行Reconcile Loop,为使用Shared Pool中的Cpus的Containers更新CPU集合。

 

CPU Manager Reconcile按照--cpu-manager-reconcile-period配置的周期进行Loop,Reconcile注意进行如下处理:

  • 遍历所有activePods中的所有Containers,注意包括InitContainers,对每个Container继续进行下面处理。

  • 检查该ContainerID是否在CPU Manager维护的Memory State assignments中,

    • 如果不在Memory State assignments中:

      • 再检查对应的Pod.Status.Phase是否为Running且DeletionTimestamp为nil,如果是,则调用CPU Manager的AddContainer对该Container/Pod进行QoS和cpu request检查,如果满足static policy的条件,则调用takeByTopology为该Container分配“最佳”CPU Set,并写入到Memory State和Checkpoint文件(cpu_manager_sate)中,并继续后面流程。

      • 如果对应的Pod.Status.Phase是否为Running且DeletionTimestamp为nil为false,则跳过该Container,该Container处理结束。不满足static policy的Containers因为不在Memory State assignments中,所以对它们的处理流程也到此结束。

    • 如果ContainerID在CPU Manager assignments维护的Memory State中,继续后面流程。

  • 然后从Memory State中获取该ContainerID对应的CPU Set。

  • 最后调用CRI UpdateContainerCPUSet更新到cpuset cgroups中。

 

cpumanager调用State进行validate处理:

  • 当Memory State中Shared(Default) CPU Set为空时,CPU Assginments也必须为空,然后对Memory State中的Shared Pool进行初始化,并写入到Checkpoint文件中(初始化Checkpoint)。

  • 只要我们没有手动去删Checkpoint文件,那么在前面提到的state.NewCheckpointState中会根据Checkpoint文件restore到Memory State中,因此之前Assgned CPU Set、Default CPU Set都还在。

  • 当检测到Memory State已经成功初始化(根据Checkpoint restore),则检查这次启动时reserved cpu set是否都在Default CPU Set中,如果不是(比如kube/system reserved cpus增加了),则报错返回,因为这意味着reserved cpu set中有些cpus被Assigned到了某些Container中了,这可能会导致这些容器启动失败,此时需要用户自己手动的去修正Checkpoint文件。

  • 检测reserved cpu set通过后,再检测Default CPU Set和Assigned CPU Set是否有交集,如果有交集,说明Checkpoint文件restore到Memory State的数据有错,报错返回。

  • 最后检查这次启动时从cAdvisor中获取到的CPU Topology中的所有CPUs是否与Memory State(从Checkpoint中restore)中记录的所有CPUs(Default CPU Set + Assigned CPU Set)相同,如果不同,则报错返回。可能因为上次CPU Manager停止到这次启动这个时间内,Node上的可用CPUs发生变化。

参考:https://blog.youkuaiyun.com/weixin_34050389/article/details/92574505

 

 

 

 

 

 

<think>好的,我现在需要回答用户关于kubelet在Kubernetes中的具体作用和功能的详细问题。用户之前已经提供了一些相关的引用内容,包括kubelet的基本职责、参数配置等。我需要结合这些信息,以及我的知识库中的知识,来组织一个结构清晰、内容详实的回答。 首先,我应该从用户提供的引用中提取关键点。引用[3]提到kubelet是每个Node上的关键服务,负责执行Master的任务,管理Pod及其容器,具体职责包括执行任务、管理Pod生命周期、注册Node、汇报状态和监控资源。引用[2]补充了kubelet维护多个子控制循环,如Volume Manager、Image Manager等。引用[4]展示了kubelet的启动参数,这可能涉及到配置方面的细节。 接下来,我需要将这些信息结构化。可能的分点包括核心职责、工作流程、子控制循环、关键参数、排障方法等。同时,用户希望尽可能参考之前的回答,所以我需要回顾之前的对话,确保内容的一致性。例如,之前回答中提到了kubelet在集群中的作用,这里可以进一步扩展。 还要注意用户提到的引用中的细节,比如kubelet的参数配置,这可能涉及到启动时的配置文件路径、容器运行时设置等。这部分需要解释每个参数的作用,帮助用户理解kubelet的配置方式。 另外,用户可能对kubelet与其他组件(如kube-proxy、容器运行时)的交互感兴趣,或者想知道kubelet在故障排除中的常见问题。需要确保回答覆盖这些方面,或者通过相关问题引导用户进一步提问。 现在,我需要检查是否有遗漏的重要点。比如,kubelet如何与API Server通信,如何处理Pod的创建和更新,健康检查机制,资源监控的具体实现(如cAdvisor)等。这些内容在引用中提到过,应该详细说明。 最后,生成相关问题时要考虑用户可能感兴趣的扩展方向,比如参数调优、排障方法、与其他组件的协作等。确保问题具有引导性,帮助用户深入理解kubelet的作用。</think>### Kubelet 在 Kubernetes 中的核心作用与功能详解 --- #### 一、核心职责概述 kubelet 是 Kubernetes 集群中每个工作节点(Node)的“守护进程”,负责将集群控制平面(Control Plane)的指令转化为节点上的具体操作。其核心作用可概括为以下四方面: 1. **Pod 生命周期管理** - 通过监听 API Server 接收 Pod 创建/更新/删除指令 - 调用容器运行时(如 containerd、CRI-O)执行容器操作 - 确保 Pod 内容器按预期状态运行(如副本数、资源限制) 2. **节点状态管理** - 定期向 API Server 上报节点信息(CPU/内存/磁盘/网络) - 注册节点到集群(首次启动时通过 `--bootstrap-kubeconfig` 认证)[^4] 3. **资源监控与限制** - 集成 cAdvisor 收集容器资源使用数据 - 通过 Cgroups 实施 CPU/Memory 资源隔离 - 触发驱逐策略(Eviction)保障节点稳定性[^3] 4. **扩展功能支持** - 管理 Volume 挂载(如 CSI 插件交互) - 处理容器镜像拉取(与 Image Manager 协作) - 执行存活/就绪探针(Liveness/Readiness Probes) --- #### 二、详细工作流程解析(以 Pod 创建为例) ```mermaid sequenceDiagram participant APIServer participant Kubelet participant ContainerRuntime APIServer->>Kubelet: Watch到新Pod调度到本节点 Kubelet->>Kubelet: 校验Pod合法性(权限/资源) Kubelet->>ContainerRuntime: 创建Pod沙箱环境 Kubelet->>VolumeManager: 挂载持久化存储卷 Kubelet->>ImageManager: 拉取容器镜像 Kubelet->>ContainerRuntime: 启动容器进程 loop 持续监控 Kubelet->>APIServer: 上报Pod状态(ContainerStatuses) end ``` --- #### 三、关键子模块解析 | **子模块** | **功能描述** | **典型参数**[^4] | |---------------------|-----------------------------------------------------------------------------|-----------------------------------------| | Volume Manager | 管理存储卷的挂载/卸载(支持PVC/PV) | `--volume-plugin-dir=/usr/libexec/kubernetes` | | Image Manager | 控制镜像拉取速率和垃圾回收 | `--image-pull-progress-deadline=30s` | | Node Status Manager | 同步节点状态到API Server | `--node-status-update-frequency=10s` | | Eviction Manager | 监控资源压力并驱逐低优先级Pod | `--eviction-hard=memory.available<500Mi`| | CRI(容器运行时接口)| 与容器运行时交互的标准化接口 | `--container-runtime-endpoint=unix:///run/containerd/containerd.sock` | --- #### 四、关键配置参数解析(基于典型生产环境配置[^4]) ```bash /usr/bin/kubelet \ --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf \ # TLS引导认证 --kubeconfig=/etc/kubernetes/kubelet.conf \ # 长期身份认证 --config=/var/lib/kubelet/config.yaml \ # 动态配置入口 --container-runtime=remote \ # 使用CRI接口 --container-runtime-endpoint=unix:///run/containerd/containerd.sock \ # 容器运行时地址 --resolv-conf=/run/systemd/resolve/resolv.conf \ # DNS配置来源 --runtime-cgroups=/system.slice/containerd.service \ # 运行时Cgroup隔离 --runtime-request-timeout=15m # CRI调用超时设置 ``` --- #### 五、典型问题排查方法 1. **Pod 无法启动** ```bash # 检查kubelet日志 journalctl -u kubelet --since "5 minutes ago" | grep -i error # 查看Pod事件详情 kubectl describe pod <pod-name> -n <namespace> # 验证容器运行时状态 crictl ps -a ``` 2. **节点失联处理** ```bash # 检查kubelet进程状态 systemctl status kubelet # 验证证书有效期 openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates # 检测网络连通性 nc -zv <API-Server-IP> 6443 ``` --- #### 六、性能优化建议 1. **调整状态上报频率** ```yaml # /var/lib/kubelet/config.yaml nodeStatusUpdateFrequency: 20s # 默认10s,适当降低可减少API Server负载 ``` 2. **启用并行镜像拉取** ```bash --serialize-image-pulls=false # 默认true,关闭可加速多容器启动 ``` 3. **优化容器运行时配置** ```bash --runtime-request-timeout=10m # 根据容器启动耗时调整 ``` --- ### 相关问题 1. 如何通过 kubelet 日志诊断 Pod 创建失败的根本原因? 2. Kubernetes 节点 NotReady 状态时,kubelet 的排查流程有哪些关键步骤? 3. 如何配置 kubelet 的资源预留参数(System Reserved/Eviction Thresholds)?[^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值