百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

「技术干货」kubelet cgroup分析 kubelet主要功能

suiw9 2024-10-31 16:04 25 浏览 0 评论


作者/李逸锋


cgroup简介


控制组cgroup(control group)是Linux kernel的一项功能,它用来控制进程对资源的分配,包括CPU、内存、网络带宽等。


Linux kernel提供一系列资源管控器,由systemd自动挂载。Red Hat Enterprise Linux 7下默认挂载了如下子系统:



blkio:对输入/输出访问存取块设备设定权限。


cpu:使用CPU调度程序让cgroup的任务可以存取CPU。它与cpuacct管控器一起挂载在同一mount上。


cpuacct:自动生成cgroup中任务占用CPU资源的报告。它与CPU管控器一起挂载在同一mount上。


cpuset:给cgroup中的任务分配独立CPU(在多芯系统中)和内存节点。


devices:允许或禁止cgroup中的任务存取设备。


freezer:暂停或恢复cgroup中的任务。


memory:对cgroup中的任务可用内存做出限制,并且自动生成任务占用内存资源报告。


net_cls:使用等级识别符(classid)标记网络数据包,这让Linux流量控制器(tc指令)可以识别来自特定cgroup任务的数据包。


perf_event:允许使用perf工具来监控cgroup。


hugetlb:允许使用大篇幅的虚拟内存页,并且给这些内存页强制设定可用资源量。


kubelet中用到了下面这些子系统(除systemd)



下面列举一些常用的cgroup参数:


cpu.cfs_period_us:此参数可以设定重新分配cgroup可用CPU资源的时间间隔。


cpu.cfs_quota_us:此参数可以设定在某一阶段(由cpu.cfs_period_us规定)某个cgroup中所有任务可运行的时间总量。


cpu.shares:此参数用一个整数来设定cgroup中任务CPU可用时间的相对比例。


memory.limit_in_bytes:设定用户内存(包括文件缓存)的最大用量。


memory.oom_control:当触发oom时oom-killer的行为。


cgroup的详细配置参考红帽文档:


https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/7/html/resource_management_guide/sec-cpu


kubelet配置


kubelet的详细配置参考k8s文档:


https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/#kubelet-config-k8s-io-v1beta1-KubeletConfiguration


cgroup相关参数


enforce-node-allocatable:默认为pods,要为kube组件和System进程预留资源,则需要设置为pods,kube-reserved,system-reserve。


cgroups-per-qos:Enabling QoS and Pod level cgroups,默认开启。开启后,kubelet会将管理所有workload Pods的cgroups。


cgroup-driver:默认为cgroupfs,另一可选项为systemd。取决于容器运行时使用的cgroup driver,kubelet与其保持一致。比如你配置docker使用systemd cgroup driver,那么kubelet也需要配置–cgroup-driver=systemd,否则kubelet启动会报错。


kube-reserved:为Kubernetes组件保留的计算资源,例如docker daemon、kubelet、kube-proxy等,比如—kube-reserved=cpu=1000m,memory=8Gi,ephemeral-storage=16Gi。


kube-reserved-cgroup:如果你设置了–kube-reserved,那么请一定要设置对应的cgroup,并且该cgroup目录要事先创建好(/sys/fs/cgroup/{subsystem}/kubelet.slice),否则kubelet将不会自动创建导致kubelet启动失败。比如设置为kube-reserved-cgroup=/kubelet.slice,需要在每个subsystem的根目录下创建kubelet.slice目录。


system-reserved:用于配置为System进程预留的资源量,比如—system-reserved=cpu=500m,memory=4Gi,ephemeral-storage=4Gi。


system-reserved-cgroup:如果你设置了–system-reserved,那么请一定要设置对应的cgroup,并且该cgroup目录要事先创建好(/sys/fs/cgroup/{subsystem}/system.slice),否则kubelet将不会自动创建导致kubelet启动失败。比如设置为system-reserved-cgroup=/system.slice,需要在每个subsystem的根目录下创建system.slice目录。


cgroup-root:kubelet中所有的cgroup层级都会在该root路径下,默认是/,如果开启--cgroups-per-qos=true,则在kubelet containerManager中会调整为/kubepods。


驱逐相关参数


eviction-minimum-reclaim:表示每一次eviction必须至少回收多少资源。


eviction-pressure-transition-period:默认为5分钟,脱离pressure condition的时间,超过阈值时,节点会被设置为memory pressure或者disk pressure,然后开启pod eviction。


eviction-hard:一系列的阈值,比如memory.available<1Gi,即当节点可用内存低于1Gi时,会立即触发一次pod eviction。


eviction-soft:与hard相对应,也是一系列法制,比如memory.available<1.5Gi。但它不会立即执行pod eviction,而会等待eviction-soft-grace-period时间,假如该时间过后,依然还是达到了eviction-soft,则触发一次pod eviction。


eviction-soft-grace-period:默认为90秒

eviction-max-pod-grace-periopd:eviction-soft时,终止pod的grace时间。


k8s推荐的cgroup配置参考:


https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/node-allocatable.md#recommended-cgroups-setup


我的节点配置


# 我的节点cn-hangzhou.i-bp10p1cp6vlexdnt67vf上的/var/lib/kubelet/config.yaml


https://gitee.com/liyifeng1026908346/k8s-learning/blob/master/k8s%E8%8A%82%E7%82%B9%E9%85%8D%E7%BD%AE/config.yaml


配置如下参数:


# cgroup相关


--cgroup-driver = systemd // cgroup驱动为systemd


--cgroup-root = / // 根cgroup


--cgroups-per-qos = true // 启用qos pod cgroup


--enforce-node-allocatable = [“pods”,“kube-reserved”,“system-reserved”]//开启kube、system资源预留


--kube-reserved-cgroup: /kubelet.slice // kube cgroup路径


--system-reserved-cgroup: /system.slice // system cgroup路径


--kube-reserved: cpu=100m,memory=200Mi // 为kube组件预留的资源


--system-reserved: cpu=200m,memory=1000Mi // 为系统daemon预留的资源


# 驱逐相关


--eviction-minimum-reclaim:... // 每次驱逐必须回收多少资源


--eviction-pressure-transition-period:5m // 脱离pressure condition的时间


--eviction-hard:memory.available<15%,nodefs.available<15%,nodefs.inodesFree<10%,imagefs.available<10% // 硬驱逐阈值


--eviction-soft:imagefs.available<20%,nodefs.available<20% // 软驱逐阈值


--eviction-soft-grace-period:默认90秒 // 软驱逐的死缓时间


--eviction-max-pod-grace-period:600 // pod最大的grace时间


节点Allocatable资源计算公式为:


[Allocatable] = [Node Capacity] - [Kube-Reserved] - [System-Reserved] - [Hard-Eviction-Threshold]


该配置下,当前节点2u8G可分配资源Allocatable为:


Allocatable (cpu) = 2 - 0.1 - 0.2 - 2*15% = 1.4u


Allocatable (memory) = 8 - 0.2 - 1 - 8*15% = 5.6G


源码分析


分析kubelet对node、pod做了哪些cgroup配置:


node的cgroup配置


当前节点kubelet配置如图:



kubelet启动后,会根据kubelet配置参数,设置cgroup限制kube组件、系统进程的资源使用。



中间包含一些内部结构的转化,flag--- > &CgroupConfig{...} ---> &libcontainerconfigs.Cgroup{...},libcontainer这个库就是docker贡献的,封装了包括对cgroup的操作,结构描述如下:


&libcontainerconfigs.Cgroup{..}。



&Resources{...},包含了所有的cgroup配置参数。




最终写到文件系统上表现为:


/sys/fs/cgroup/kubelet.slice


.
├── cpu
│   ├── cpu.cfs_period_us 100000
│   ├── cpu.cfs_quota_us -1
│   ├── cpu.rt_period_us 1000000
│   ├── cpu.rt_runtime_us 0
│   └── cpu.shares 102
├── memory
│   ├── memory.kmem.limit_in_bytes 9223372036854771712
│   ├── memory.kmem.tcp.limit_in_bytes 9223372036854771712
│   ├── memory.limit_in_bytes 209715200
│   ├── memory.memsw.limit_in_bytes 9223372036854771712
│   ├── memory.oom_control 始终开启oom-killer
│   └── memory.soft_limit_in_bytes 9223372036854771712
└── ...


/sys/fs/cgroup/system.slice


.
├── cpu
│   ├── cpu.cfs_period_us 100000
│   ├── cpu.cfs_quota_us -1
│   ├── cpu.rt_period_us 1000000
│   ├── cpu.rt_runtime_us 0
│   └── cpu.shares 204
├── memory
│   ├── memory.kmem.limit_in_bytes 9223372036854771712
│   ├── memory.kmem.tcp.limit_in_bytes 9223372036854771712
│   ├── memory.limit_in_bytes 1048576000
│   ├── memory.memsw.limit_in_bytes 9223372036854771712
│   ├── memory.oom_control 始终开启oom-killer
│   └── memory.soft_limit_in_bytes 9223372036854771712
└── ...


该配置表示:


kube进程最多可用的CPU时间不受限制,cpu.cfs_quota_us = -1。


kube进程最低可用的CPU时间为1CPU02/sum(其它进程cpu.shares),当发CPU竞争时生效(kube-reserved: cpu=100m)。


kube进程最多可用内存为209715200,即200M(kube-reserved: memory=200Mi)。


kube进程最低可用内存不对应任何cgroup配置。


system进程最多可用的CPU时间不受限制,cpu.cfs_quota_us = -1。


system进程最低可用的CPU时间为204/sum(其它进程cpu.shares),当发CPU竞争时生效(system-reserved: cpu=200m)。


system进程最多可用内存为1048576000,即1000M(system-reserved: memory=1000Mi)。


system进程最低可用内存不对应任何cgroup配置。


qos pods的cgroup配置


创建一个pod,资源限制如下:



pod创建前,会对其做cgroup配置:



相关的子系统包括CPU、memory、hugelb:



限制每个qos等级的pods资源:




这里,会去设置pod的cgroup:





最终写到文件系统上的cgroup配置如下:


.
├── cpu
│   ├── cpu.cfs_period_us 100000
│   ├── cpu.cfs_quota_us 20000
│   ├── cpu.rt_period_us 1000000,指定在某个时间段内对cpu资源访问重新分配的频率
│   ├── cpu.rt_runtime_us 0 ,指定某个时间段中cgroup中的任务对cpu资源的最长连续访问时间
│   └── cpu.shares 102
├── memory
│   ├── memory.kmem.limit_in_bytes 9223372036854771712
│   ├── memory.kmem.tcp.limit_in_bytes 9223372036854771712
│   ├── memory.limit_in_bytes 314572800
│   ├── memory.memsw.limit_in_bytes 9223372036854771712
│   ├── memory.oom_control 始终开启oom-killer
│   └── memory.soft_limit_in_bytes 9223372036854771712
├── pids
│   ├── pids.max 需kubelet启用特性SupportPodPidsLimit
└── ...


该配置表示:


该pod最多可用的CPU时间为20000/100000 = 0.2,即200m(limits.cpu)。


该pod最低可用的CPU时间权重为102/sum(其它进程cpu.shares),当发CPU竞争时生效(requests.cpu)。


该pod最多可用内存为314572800,即300M(limit.memory)。


该pod最低可用内存不对应任何cgroup配置。


问题记录


kubele启动失败,/system.slice cgroup does not exis


对于Centos系统,cpuset和hugetlb subsystem是默认没有初始化system.slice,因此需要手动创建,否则会报Failed to start ContainerManager Failed to enforce System Reserved Cgroup Limits on “/system.slice”: “/system.slice” cgroup does not exist的错误日志。


kubelet启动失败,device or resource busy


配置的system-reserved过低,导致cgroup配置无法写入,报错提示”device or resource busy”。


其原因为:若写入的memory.limit_in_bytes值小于当前已使用的内存,将触发os内存回收。若系统无法将内存无法回收至阈值以下,则会报这个错。



kubelet cgroup参数配置步骤整理


# 修改kubelet配置文件/usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf,启动kubelet前先创建下面几个cgroup目录:


ExecStartPre=/usr/bin/mkdir -p /sys/fs/cgroup/cpu,cpuacct/kubelet.slice


ExecStartPre=/usr/bin/mkdir -p /sys/fs/cgroup/memory/kubelet.slice


ExecStartPre=/usr/bin/mkdir -p /sys/fs/cgroup/systemd/kubelet.slice


ExecStartPre=/usr/bin/mkdir -p /sys/fs/cgroup/pids/kubelet.slice


ExecStartPre=/usr/bin/mkdir -p /sys/fs/cgroup/cpu,cpuacct/kubelet.slice


ExecStartPre=/usr/bin/mkdir -p /sys/fs/cgroup/cpuset/kubelet.slice


ExecStartPre=/usr/bin/mkdir -p /sys/fs/cgroup/hugetlb/kubelet.slice


ExecStartPre=/usr/bin/mkdir -p /sys/fs/cgroup/cpuset/system.slice


ExecStartPre=/usr/bin/mkdir -p /sys/fs/cgroup/hugetlb/system.slice


# 修改/var/lib/kubelet/config.yaml,增加下面几项配置:


enforceNodeAllocatable:
- pods
- kube-reserved  #开启kube资源预留
- system-reserved #开启system资源预留 
kubeReserved:
  cpu: 200m
  memory: 500Mi
kubeReservedCgroup: /kubelet.slice # 指定kube资源预留的 cgroup
systemReserved:
  cpu: 300m
  memory: 1000Mi  # 此处配置的内存要大于系统已使用内存,否则kubelet无法启动
systemReservedCgroup: /system.slice # 指定system资源预留的 cgroup


# 部署一个应用测试做CPU、内存压力测试


# deploy-stress.yaml


apiVersion: apps/v1
kind: Deployment
metadata:
  name: liyifeng-stress
spec:
  selector:
    matchLabels:
      app.kubernetes.io/component: stress
  template:
    metadata:
      labels:
        app.kubernetes.io/component: stress
    spec:
      nodeSelector:
         kubernetes.io/hostname: 6448bb57-6bb3-4c89-b806-3a3656ef349e
      containers:
      - args:
        - stress
        - --cpu
        - "2"
        - --vm
        - "1"
        - --vm-bytes
        - "100M"
        image: polinux/stress
        imagePullPolicy: IfNotPresent
        name: stress


# 增加用户进程CPU、内存的申请量,观察kubelet不同配置情况下的节点健康情况。


参考文档


https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/7/html/resource_management_guide/sec-cpu(红帽cgroup配置)


https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/node-allocatable.md#recommended-cgroups-setup(k8s官方建议cgroup配置)


https://github.com/rootsongjc/qa/issues/3(device or resource busy)

相关推荐

俄罗斯的 HTTPS 也要被废了?(俄罗斯网站关闭)

发布该推文的ScottHelme是一名黑客,SecurityHeaders和ReportUri的创始人、Pluralsight作者、BBC常驻黑客。他表示,CAs现在似乎正在停止为俄罗斯域名颁发...

如何强制所有流量使用 HTTPS一网上用户

如何强制所有流量使用HTTPS一网上用户使用.htaccess强制流量到https的最常见方法可能是使用.htaccess重定向请求。.htaccess是一个简单的文本文件,简称为“.h...

https和http的区别(https和http有何区别)

“HTTPS和HTTP都是数据传输的应用层协议,区别在于HTTPS比HTTP安全”。区别在哪里,我们接着往下看:...

快码住!带你十分钟搞懂HTTP与HTTPS协议及请求的区别

什么是协议?网络协议是计算机之间为了实现网络通信从而达成的一种“约定”或“规则”,正是因为这个“规则”的存在,不同厂商的生产设备、及不同操作系统组成的计算机之间,才可以实现通信。简单来说,计算机与网络...

简述HTTPS工作原理(简述https原理,以及与http的区别)

https是在http协议的基础上加了一层SSL(由网景公司开发),加密由ssl实现,它的目的是为用户提供对网站服务器的身份认证(需要CA),以至于保护交换数据的隐私和完整性,原理如图示。1、客户端发...

21、HTTPS 有几次握手和挥手?HTTPS 的原理什么是(高薪 常问)

HTTPS是3次握手和4次挥手,和HTTP是一样的。HTTPS的原理...

一次安全可靠的通信——HTTPS原理

为什么HTTPS协议就比HTTP安全呢?一次安全可靠的通信应该包含什么东西呢,这篇文章我会尝试讲清楚这些细节。Alice与Bob的通信...

为什么有的网站没有使用https(为什么有的网站点不开)

有的网站没有使用HTTPS的原因可能涉及多个方面,以下是.com、.top域名的一些见解:服务器性能限制:HTTPS使用公钥加密和私钥解密技术,这要求服务器具备足够的计算能力来处理加解密操作。如果服务...

HTTPS是什么?加密原理和证书。SSL/TLS握手过程

秘钥的产生过程非对称加密...

图解HTTPS「转」(图解http 完整版 彩色版 pdf)

我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取。所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。...

HTTP 和 HTTPS 有何不同?一文带你全面了解

随着互联网时代的高速发展,Web服务器和客户端之间的安全通信需求也越来越高。HTTP和HTTPS是两种广泛使用的Web通信协议。本文将介绍HTTP和HTTPS的区别,并探讨为什么HTTPS已成为We...

HTTP与HTTPS的区别,详细介绍(http与https有什么区别)

HTTP与HTTPS介绍超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的...

一文让你轻松掌握 HTTPS(https详解)

一文让你轻松掌握HTTPS原文作者:UC国际研发泽原写在最前:欢迎你来到“UC国际技术”公众号,我们将为大家提供与客户端、服务端、算法、测试、数据、前端等相关的高质量技术文章,不限于原创与翻译。...

如何在Spring Boot应用程序上启用HTTPS?

HTTPS是HTTP的安全版本,旨在提供传输层安全性(TLS)[安全套接字层(SSL)的后继产品],这是地址栏中的挂锁图标,用于在Web服务器和浏览器之间建立加密连接。HTTPS加密每个数据包以安全方...

一文彻底搞明白Http以及Https(http0)

早期以信息发布为主的Web1.0时代,HTTP已可以满足绝大部分需要。证书费用、服务器的计算资源都比较昂贵,作为HTTP安全扩展的HTTPS,通常只应用在登录、交易等少数环境中。但随着越来越多的重要...

取消回复欢迎 发表评论: