Kubernetes приховує від користувача багато аспектів того, як Podʼи виконуються на вузлах. Це зроблено навмисно. Однак деяким робочим навантаженням для прийнятної роботи потрібні сильніші гарантії щодо затримки та/або продуктивності. kubelet надає методи для складніших політик розміщення робочих навантажень і водночас зберігає абстракцію вільною від явних директив розміщення.
Ви можете керувати топологією всередині вузлів. Це означає, що ви допомагаєте kubelet налаштувати операційну систему хоста так, щоб Podʼи й контейнери розміщувалися з правильного боку внутрішніх меж, таких як домени NUMA. (NUMA — абревіатура від non-uniform memory access (нерівномірний доступ до памʼяті); вона відображає ідею, що CPU можуть бути топологічно ближчими до певних ділянок памʼяті через фізичне розташування апаратних компонентів і спосіб їх зʼєднання.)
Щоб зʼясувати, чому Pod не вдалося розгорнути або чому його відхилено на вузлі в контексті керування топологією, можна скористатися такими засобами:
TopologyAffinityErrorЦя помилка зазвичай виникає в таких ситуаціях:
Помилка зʼявляється в статусі Podʼа:
kubectl get pods
NAME READY STATUS RESTARTS AGE
guaranteed 0/1 TopologyAffinityError 0 113s
Використовуйте kubectl describe pod <id> або kubectl events, щоб отримати детальне повідомлення про помилку:
Warning TopologyAffinityError 10m kubelet, dell8 Resources cannot be allocated with Topology locality
Шукайте в системних логах записи щодо конкретного Podʼа.
Набір підказок, згенерованих менеджером CPU, має бути в логах. Також у логах можна знайти набір підказок, які менеджер памʼяті згенерував для Podʼа.
Менеджер топології обʼєднує ці підказки, щоб обчислити одну найкращу підказку. Найкраща підказка також має бути в логах.
Найкраща підказка вказує, де виділити всі ресурси. Менеджер топології перевіряє цю підказку на відповідність своїй поточній політиці й, залежно від результату, або допускає Pod на вузол, або відхиляє його.
Також шукайте в логах записи, повʼязані з менеджером памʼяті, наприклад, щоб знайти інформацію про оновлення cgroups і cpuset.mems.
Спочатку розгорнімо зразковий Pod Guaranteed з такою специфікацією:
apiVersion: v1
kind: Pod
metadata:
name: guaranteed
spec:
containers:
- name: guaranteed
image: consumer
imagePullPolicy: Never
resources:
limits:
cpu: "2"
memory: 150Gi
requests:
cpu: "2"
memory: 150Gi
command: ["sleep","infinity"]
Далі увійдіть на вузол, де його розгорнуто, і перегляньте файл стану в /var/lib/kubelet/memory_manager_state:
{
"policyName":"Static",
"machineState":{
"0":{
"numberOfAssignments":1,
"memoryMap":{
"hugepages-1Gi":{
"total":0,
"systemReserved":0,
"allocatable":0,
"reserved":0,
"free":0
},
"memory":{
"total":134987354112,
"systemReserved":3221225472,
"allocatable":131766128640,
"reserved":131766128640,
"free":0
}
},
"nodes":[
0,
1
]
},
"1":{
"numberOfAssignments":1,
"memoryMap":{
"hugepages-1Gi":{
"total":0,
"systemReserved":0,
"allocatable":0,
"reserved":0,
"free":0
},
"memory":{
"total":135286722560,
"systemReserved":2252341248,
"allocatable":133034381312,
"reserved":29295144960,
"free":103739236352
}
},
"nodes":[
0,
1
]
}
},
"entries":{
"fa9bdd38-6df9-4cf9-aa67-8c4814da37a8":{
"guaranteed":[
{
"numaAffinity":[
0,
1
],
"type":"memory",
"size":161061273600
}
]
}
},
"checksum":4142013182
}
З файлу стану можна зробити висновок, що Pod закріплено за обома вузлами NUMA, тобто:
"numaAffinity":[
0,
1
],
Термін «закріплений» означає, що споживання памʼяті Podʼом обмежено (через конфігурацію cgroups) цими вузлами NUMA.
Це автоматично означає, що менеджер памʼяті створив нову групу з цих двох вузлів NUMA, тобто вузлів NUMA з індексами 0 і 1.
Щоб проаналізувати ресурси памʼяті, доступні в групі, потрібно підсумувати відповідні записи з вузлів NUMA, що належать до групи.
Наприклад, загальний обсяг вільної «звичайної» памʼяті в групі можна обчислити, додавши вільну памʼять, доступну на кожному вузлі NUMA групи, тобто в розділі "memory" вузла NUMA 0 ("free":0) і вузла NUMA 1 ("free":103739236352). Отже, загальний обсяг вільної «звичайної» памʼяті в цій групі дорівнює 0 + 103739236352 байтів.
Рядок "systemReserved":3221225472 показує, що адміністратор цього вузла зарезервував 3221225472 байти (тобто 3Gi) для kubelet і системних процесів на вузлі NUMA 0 за допомогою прапорця --reserved-memory.
kubelet надає gRPC-сервіс PodResourceLister, щоб уможливити виявлення ресурсів і повʼязаних з ними метаданих. Через його точку доступу gRPC List можна отримати інформацію про зарезервовану памʼять для кожного контейнера, яка міститься в повідомленні protobuf ContainerMemory.
Цю інформацію можна отримати лише для Podʼів класу QoS Guaranteed.