kubernetes 由于init-container CPU NUMA拓扑错误,Pod失败并出现TopologyAffinityError,

km0tfn4u  于 6个月前  发布在  Kubernetes
关注(0)|答案(4)|浏览(73)

发生了什么?
我的节点有250Gi内存和64核CPU,有两个NUMA节点,每个节点都是125Gi和32核CPU,拓扑策略是单NUMA节点。
创建了两个pod,其中一个pod的init-container有1核CPU和1Gi内存,app container有26核和32Gi内存。
第一个pod创建成功。
第二个pod会因为TopologyAffinityError失败。
lscpu的结果:

NUMA node0 CPU(s):     0-15,32-47
NUMA node1 CPU(s):     16-31,48-63

/var/lib/kubelet/cpu_manager_state文件中:

{
  "policyName": "static",
  "defaultCpuSet": "1,3,15-31,47-63",
  "entries": {
    "69aa6124-4e0e-4c66-94ea-feae7df25b68": {  # the second Pod, init-container use NUMA 0
      "init-container": "35"
    },
    "e49ac32c-22a3-4c8c-8be3-721bd1fd9eaa": {   # the first Pod, use NUMA 0
      "centos": "0,2,4-14,32,34,36-46",
      "init-container": "33"
    }
  },
  "checksum": 3748757820
}

预期会发生什么?

两个pod都能成功创建。
第一个pod使用NUMA 0;
第二个pod的init-container可以使用NUMA 0或NUMA 1,但app container使用NUMA 1;

我们如何尽可能精确地重现它?

  1. 创建一个pod,使用该节点上32(Numa Node)CPU中的10个CPU
  2. 创建另一个pod,需要init-container 1核CPU,app container需要大部分NUMA Node CPU,例如25核(大于左侧的第一个NUMA)
  3. 第二个pod会因为TopologyAffinityError失败。

我们需要了解其他任何信息吗?

我认为bug存在于generateCPUTopologyHints函数中:
kubernetes/pkg/kubelet/cm/cpumanager/policy_static.go
第623行 in 7ea3d02
| | for_, c:=rangereusableCPUs.List() { |

  1. 当分配init-container CPU时,CPUManager会将cpuToReuse记录为pod的cpuToReuse。
    kubernetes/pkg/kubelet/cm/cpumanager/policy_static.go
    第345行 in 7ea3d02
    | | p.updateCPUsToReuse(pod, container, cpuset) |
  2. 在调用generateCPUTopologyHints之前,获取pod的cpuToReuse作为可重用的cpuToReuse。
    kubernetes/pkg/kubelet/cm/cpumanager/policy_static.go
    第587行 in 7ea3d02
    | | reusable:=p.cpusToReuse[string(pod.UID)] |
  3. 当计算app container CPU时,CPUManager会过滤掉与reusableCPU的NUMA Node不相等的NUMA Node。
    即使NUMA 1是唯一适合CPU资源获取的地方,它仍然会在计算TopologyHint时通过;NUMA 0与reusableCPU相匹配,但CPU剩余不足。

Kubernetes版本

Client Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.17", GitCommit:"a7736eaf34d823d7652415337ac0ad06db9167fc", GitTreeState:"clean", BuildDate:"2022-12-08T11:47:36Z", GoVersion:"go1.16.15", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.17", GitCommit:"a7736eaf34d823d7652415337ac0ad06db9167fc", GitTreeState:"clean", BuildDate:"2022-12-08T11:42:04Z", GoVersion:"go1.16.15", Compiler:"gc", Platform:"linux/amd64"}

云提供商

OS版本

# On Linux:
$ cat /etc/os-release
# paste output here
$ uname -a
# paste output here

# On Windows:
C:\> wmic os get Caption, Version, BuildNumber, OSArchitecture
# paste output here

安装工具

容器运行时(CRI)和版本(如果适用)

相关插件(CNI,CSI,...)和版本(如果适用)

3bygqnnd

3bygqnnd2#

/triage已接受
是的,这是一个导致TopologyAffinityError的bug,可以避免。

w51jfk4q

w51jfk4q4#

/priority important-longterm

相关问题