k8s集群部分使用gpu资源的pod出现UnexpectedAdmissionError问题

记录一次排查UnexpectedAdmissionError问题的过程

1. 问题

环境

3master节点+N个GPU节点

kubelet版本:v1.19.4

kubernetes版本:v1.19.4

生产环境K8S集群,莫名其妙的出现大量UnexpectedAdmissionError状态的Pod,导致部分任务执行异常,出现这种情况时,节点的资源是足以支持运行一个GPU Pod的。

报的错误:

Allocate failed due to requested number of devices unavailable for nvidia.com/gpu. Requested: 1, Available: 0, which is unexpected

因为Pod的调度都是指定了spec.nodeName属性的,所以跳过了Pending状态强制进行调度,在资源不足的情况下,就出现了UnexpectedAdmissionError异常。

image-20231207095349410

2.排查过程

确定节点资源是否正常

 kubectl describe node <node-name>

image-20231207095740526

通过describe命令可以看到节点的GPU卡是正常的,然后可以去节点上通过nvidia-dcgm,确定GPU设备是否健康

nvidia-dcgm:nvidia官网

在确定节点和GPU设备都是没问题的情况下,那么开始排查出现问题的原因

通过查看日志和源码,可以定位到日志是在manager.go#devicesToAllocate方法的698行出现

	// resource=nvidia.com/gpu
	// Gets Devices in use.
	devicesInUse := m.allocatedDevices[resource]
	// Gets Available devices.
	available := m.healthyDevices[resource].Difference(devicesInUse)
	if available.Len() < needed {
		return nil, fmt.Errorf("requested number of devices unavailable for %s. Requested: %d, Available: %d", resource, needed, available.Len())
	}

也就是,从健康的GPU集合中去除了已使用的GPU后,可用GPU数量少于所需要的数量,但是通过上面的排查,在创建的Pod.cm.resource.limit:nvidia.com/gpu=1的情况下,理论上应该是成功的,这里出现了报错,那么肯定是GPU卡被占用了。

查看kubelet日志,定位具体问题,日志位于/var/log/messages文件,由于kubelet默认日志级别为--v=2,这里需要将其更改为--v=4

查看是否有/etc/kubernetes/kubelet.env文件,如果有,直接更改KUBE_LOG_LEVEL配置

KUBE_LOGTOSTDERR="--logtostderr=true"
KUBE_LOG_LEVEL="--v=4"

如果没有,则修改/usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf文件

添加Environment

Environment="KUBE_LOGTOSTDERR=--logtostderr=true"
Environment="KUBE_LOG_LEVEL=--v=4"

修改ExecStart命令,在参数位追加$KUBE_LOGTOSTDERR $KUBE_LOG_LEVEL

ExecStart=/usr/bin/kubelet $KUBE_LOGTOSTDERR $KUBE_LOG_LEVEL $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS

修改后需要重启kubelet

systemctl daemon-reload && systemctl restart kubelet

通过grep命令查看关键日志

grep "package-instance-42895-test-4461" messages

从日志中发现,kubelet监听到了两次创建同一个Pod的事件,也就是为一个Job创建了两个Pod

但是Job的配置都是为1

spec:
  completions: 1
  backoffLimit: 0
  parallelism: 1

image-20231207102252049

在这样的配置下,应该只有一次创建Pod的事件才对。

再分别查看两次Pod的资源分配日志

通过less messages命令查看详细的日志过程

image-20231207102820350

从日志中可以看出,第一个Pod分配GPU资源是成功的

而在第二个Pod分配GPU资源时,就提示分配失败

image-20231207102934592

至此问题就定位到了,是因为kubelet本应只创建一个Pod,但是确监听到了多次创建Pod的事件。

从这个情况来看,应当所有的任务都失败才对,但只有小部分任务失败了,继续查看日志

image-20231207103436250

在下面的日志可以看到,kubelet随后就监听到了DELETE事件,删除了一个Pod,虽然在这个日志中删除的是创建失败的Pod

但是多观察几个Pod就会发现,删除完全的随机的,并不是根据状态来的,所以就会出现部分任务失败,但是大部分任务都成功的情况。

从上面的排查过程来看,kubeletenodegpu device都是没有问题的,那么,继续往上排查scheduler

同样的,scheduler的日志级别默认也是--v=2,这里也需要改成--v=4,修改kube-scheduler.yaml文件

vim /etc/kubernetes/manifests/kube-scheduler.yaml

command中追加一行--v=4

spec:
  containers:
  - command:
    - kube-scheduler
    - --authentication-kubeconfig=/etc/kubernetes/scheduler.conf
    - --authorization-kubeconfig=/etc/kubernetes/scheduler.conf
    - --bind-address=0.0.0.0
    - --kubeconfig=/etc/kubernetes/scheduler.conf
    - --leader-elect=false
    - --leader-elect-lease-duration=15s
    - --leader-elect-renew-deadline=10s
    - --port=0
    - --v=4

更改文件后保存,等待scheduler自动重建。注意重建后日志会清空,所以需要等待下次调度再次重新进行问题排查

然后通过kubectl logs命令,查看三个scheduler的调度日志

kubectl logs -n kube-system kube-scheduler-master-1| grep package-instance-42895-test-4461

kubectl logs -n kube-system kube-scheduler-master-2| grep package-instance-42895-test-4461

kubectl logs -n kube-system kube-scheduler-master-3| grep package-instance-42895-test-4461

[root@master-1 ~]# kubectl logs -n kube-system kube-scheduler-master-1| grep package-instance-42895-test-4461
I1206 03:23:08.641125       1 eventhandlers.go:225] add event for scheduled pod default/package-instance-42895-test-4461-xxp5t
I1206 03:23:08.641463       1 eventhandlers.go:225] add event for scheduled pod default/package-instance-42895-test-4461-72hdl
I1206 03:23:08.866294       1 eventhandlers.go:283] delete event for scheduled pod default/package-instance-42895-test-4461-72hdl

[root@master-1 ~]# kubectl logs -n kube-system kube-scheduler-master-2| grep package-instance-42895-test-4461
I1206 03:23:08.641125       1 eventhandlers.go:225] add event for scheduled pod default/package-instance-42895-test-4461-xxp5t
I1206 03:23:08.641463       1 eventhandlers.go:225] add event for scheduled pod default/package-instance-42895-test-4461-72hdl
I1206 03:23:08.866294       1 eventhandlers.go:283] delete event for scheduled pod default/package-instance-42895-test-4461-72hdl

[root@master-1 ~]# kubectl logs -n kube-system kube-scheduler-master-3| grep package-instance-42895-test-4461

从上面的日志可以看到,Pod确实被调度了两次,但是,schduler只是负责调度Pod,并不会控制Pod创建的数量。

而且,理论上,应该只有一个leader级别的schduler处于工作状态,其他两个schduler,应当是处于睡眠状态,不进行工作才对,也就说,其他的schduler不应该监听到调度事件。

虽然问题不在此,但是从这里可以发现schduler的部署是有问题的,查看schduler配置

spec:
  containers:
  - command:
    - kube-scheduler
    - --authentication-kubeconfig=/etc/kubernetes/scheduler.conf
    - --authorization-kubeconfig=/etc/kubernetes/scheduler.conf
    - --bind-address=0.0.0.0
    - --kubeconfig=/etc/kubernetes/scheduler.conf
    - --leader-elect=false
    - --leader-elect-lease-duration=15s
    - --leader-elect-renew-deadline=10s
    - --port=0
    - --v=4

在检查了三个节点的schduler配置后,发现有一个节点的schduler配置中,--leader-elect被设置成了fasle

Kubernetes的调度器可以使用leader选举来确保只有一个实例处于活跃状态,负责决策和分配Pod。一旦调度器的活跃实例失效,其他备用实例可以进行leader选举,确保集群的Pod能够被适当地调度到可用的节点上。

同样,如果多个调度器实例都设置为--leader-elect=false,它们将尝试同时管理Pod的调度决策,可能会导致混乱、资源冲突以及不一致的状态。

在这可以确定是--leader-elect=false导致的出现了多个leader级schduler,将此配置更改为--leader-elect=true

等待schudler重建,修复了schudler多leader的问题,但是,Pod重复调度的问题依旧没有解决,查看Pod调度调度流程

image-20231207110614916

从流程图上可以看出,创建Pod的请求,是由Job Controller发出的,在kubernetes中有很多的控制器,例如

Job ControllerDeployment Controller,这些控制器由控制平面进行管理kube-controller-manger

结合上面schduler的可以得出结论。是在Job Controller中,发出了两次创建Pod的请求,而kube-controller-manger集群跟schduler集群一样,理论上应该只有一个leader级别的处于工作中的状态,其他两个都应该处于休眠状态。但是这里发起了两次创建请求,显然是有一个以上的leader级kube-controller-manger,通过查看配置文件,问题跟schduler是一样的

YAML文件路径/etc/kubernetes/manifests/kube-controller-manager.yaml

有一个节点的YAML文件中--leader-elect=false,这个配置也被设置为了false,导致的出现了多个ledaer级的控制平面,从而导致Pod被多次创建

验证方式也是同样的,通过kubectl logs命令,查看三个kube-controller-manager的监听日志,发现有两个控制平面监听到了Create Job事件,从而导致的这次问题。

kubectl logs -n kube-system  kube-controller-manager-master-1 |grep package-instance-42895-test-4461

3. 解决方案

通过修改/etc/kubernetes/manifests/kube-scheduler.yaml/etc/kubernetes/manifests/kube-controller-manager.yaml两个YAML文件中的--leader-elect配置,将其修改为true,即可解决问题。

--leader-elect=false

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/241308.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C# | CountdownEvent使用教程 (通过与ManualResetEvent对比,快速了解其特性)

C# CountdownEvent使用教程 对于熟悉ManualResetEvent的同学来说&#xff0c;了解CountdownEvent的差异对于更好地利用它们是非常重要的。通过对ManualResetEvent和CountdownEvent的对比&#xff0c;我们可以更好地理解CountdownEvent的特点和使用场景。 ManualResetEvent回顾…

SpringCloud微服务 【实用篇】| Docker启示录

目录 一&#xff1a;Docker启示录 1. Docker启示录 2. Docker和虚拟机的区别 3. Docker架构 4. Centos7安装Docker 4.1. 卸载 4.2. 安装docker 4.3. 启动docker 4.4. 配置镜像加速 前些天突然发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽…

阿里云国际版如何为SSL证书更换域名?

如果您需要为已签发的SSL证书更换绑定的域名&#xff0c;您可以使用数字证书管理服务提供的更换域名功能。本文介绍如何为SSL证书更换域名。 操作步骤 为SSL证书变更域名&#xff0c;您相当于重新购买了一张新证书&#xff0c;需要支付一定的费用。 您在更换域名前&#xff…

快速解决Edge浏览器常见问题:完整教程

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 目录 文章目录 前言 一、Edge浏览器是什么&#xff1f; 二、常见的问题 1. DNS服务器出错 解决方案一&#xff1a;清除浏览器缓存和Cookie 2.网络问题 3.缓存和Cook…

Java .shp文件解析转换成地图可用的经纬度格式

1.新建ShapeUtils工具类解析shp文件 package com.ruoyi.info.geotoolsUtils; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Lis…

C语言实现在顺序表中找到最大值

用C语言实现在顺序表中找到最大值&#xff1a; #include <stdio.h> #define MAX_SIZE 100 int findMax(int arr[], int size) { int max arr[0]; // 假设第一个元素为最大值 for (int i 1; i < size; i) { // 从第二个元素开始遍历列表 if (…

新手上路:盘点「性能测试」必须掌握的技术点

前段时间&#xff0c;有一些小伙伴提出希望我们推送点性能测试的技术干货。所以&#xff0c;小编今天通过上网查资料&#xff0c;结合项目实操过程中的一些问题&#xff0c;总结了一些关于性能测试的内容&#xff0c;希望是大家想要了解的内容哈。 1、性能测试的目的 首先&am…

数据可视化:解锁企业经营的智慧之道

在现代企业管理中&#xff0c;数据可视化已经成为了一项重要的工具。它不仅仅是简单地展示数据&#xff0c;更是提供了深入理解数据、做出更明智决策的方法。作为一名可视化设计从业人员&#xff0c;我经手过一些企业自用的数据可视化项目&#xff0c;今天就来和大家聊聊数据可…

vue3 echarts 各省地图展示

效果&#xff1a; 1.在src下新建utils文件夹添加各省地图的json文件&#xff08;下载各省地图的网址 DataV.GeoAtlas地理小工具系列&#xff09; 2.安装echarts npm install echarts 3.在项目文件中中引入json <template><div class"back"><div id…

在接触新的游戏引擎的时候,如何能快速地熟悉并开发出一款新游戏?

引言 大家好&#xff0c;今天分享点个人经验。 有一定编程经验或者游戏开发经验的小伙伴&#xff0c;在接触新的游戏引擎的时候&#xff0c;如何能快速地熟悉并开发出一款新游戏&#xff1f; 利用现成开发框架。 1.什么是开发框架&#xff1f; 开发框架&#xff0c;顾名思…

微信小程序、uniapp仿扎克新闻(附源码)

介绍 本着试试 mpvue 的态度开发此程序&#xff0c;界面主要是模仿 ZAKER 新闻&#xff0c;数据全部是由 Mock 随机生成的&#xff0c;使用的是 Easy-Mock 服务。本程序只开发了的几个页面&#xff0c;尝试了自定义组件&#xff0c;路由跳转及参数传递等功能。再开发下去只是组…

微信游戏开发:连接社交与娱乐的创新之路

在移动互联网时代&#xff0c;微信已经成为了人们日常生活中不可或缺的社交工具。而微信游戏&#xff0c;作为在这一平台上崛起的新兴产业&#xff0c;不仅给用户提供了更多娱乐选择&#xff0c;也为开发者们创造了独特的机遇。本文将探讨微信游戏开发的关键步骤、技术要点以及…

C# OpenCvSharp DNN 部署yolov5旋转目标检测

目录 效果 模型信息 项目 代码 下载 C# OpenCvSharp DNN 部署yolov5旋转目标检测 效果 模型信息 Inputs ------------------------- name&#xff1a;images tensor&#xff1a;Float[1, 3, 1024, 1024] -------------------------------------------------------------…

六、CM4树莓派USBRS转485串口通讯

一、串行通讯接口 串行通讯接口简称串口&#xff08;UART&#xff09; 采用串行通信方式的扩展接口&#xff0c;数据位一位一位的按照顺序传送 优点&#xff1a;通信线路简单&#xff0c;只要一对传输线就可以实现双向通信能够大大降低成本&#xff0c;适合远距离通信。 缺点…

【后端学前端】第三天 css动画 动态搜索框(定位、动态设置宽度)

1、学习信息 视频地址&#xff1a;css动画 动态搜索框&#xff08;定位、动态设置宽度&#xff09;_哔哩哔哩_bilibili 2、源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>test3</title>…

紫光展锐CEO任奇伟博士:展锐5G芯筑基当下,迈向未来

12月5日&#xff0c;紫光集团执行副总裁、紫光展锐CEO任奇伟博士受邀出席2023世界5G大会5G产业强基发展论坛&#xff0c;发表了题为《展锐5G芯&#xff1a;筑基当下&#xff0c;迈向未来》的演讲。 ​ 世界5G大会由国务院批准&#xff0c;国家发展改革委、科技部、工信部与地方…

Re58:读论文 REALM: Retrieval-Augmented Language Model Pre-Training

诸神缄默不语-个人CSDN博文目录 诸神缄默不语的论文阅读笔记和分类 论文名称&#xff1a;REALM: Retrieval-Augmented Language Model Pre-Training 模型名称&#xff1a;Retrieval-Augmented Language Model pre-training (REALM) 本文是2020年ICML论文&#xff0c;作者来自…

使用 MySQL连接 c#(简易)

目录 一&#xff0c;下载与本机MySQL相应版本的连接插件1&#xff0c;查找本机下载的MySQL版本2&#xff0c;进入MySQL网站下载连接插件 二&#xff0c;使用C#创建项目进行插件引用1&#xff0c;打开C#创建一个新项目2&#xff0c;引用下载的连接插件 三&#xff0c;进行连接&a…

指针浅谈(四)

在指针浅谈(三)中http://t.csdnimg.cn/wYgJG我们知道了数组名是什么&#xff0c;任何用指针访问数组&#xff0c;一维数组传参的本质是什么&#xff0c;这一次我们来学习二级指针&#xff0c;指针数组&#xff0c;以及如何用指针数组模拟二维数组。 1.二级指针 指针变量也是变…

jmeter接口测试之使用rsa算法加密解密的代码

本篇介绍jmeter 使用rsa算法进行加密参数 如果测试过程中&#xff0c;部分接口采用了rsa加密算法&#xff0c;我们的jmeter 也是可以直接拿来调用的&#xff0c;不需要开发配合去掉加密代码&#xff01; 直接上代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 2…