Це багатосторінковий друкований вигляд цього розділу. Натисність щоб друкувати.

Повернутися до звичайного перегляду сторінки.

Усунення несправностей кластерів

Налагодження поширених проблем кластера.

Цей документ присвячено усуненню несправностей кластера; ми припускаємо, що ви вже виключили свій застосунок як першопричину проблеми, з якою стикаєтеся. Поради щодо налагодження застосунків дивіться в посібнику з усунення несправностей застосунків. Докладніше також дивіться загальний документ з усунення несправностей.

Про усунення несправностей kubectl дивіться Усунення несправностей kubectl.

Виведення інформації про кластер

Перше, що слід перевірити під час налагодження кластера, — чи всі ваші вузли зареєстровано правильно.

Виконайте таку команду:

kubectl get nodes

І переконайтеся, що всі очікувані вузли присутні й перебувають у стані Ready.

Щоб отримати детальну інформацію про загальний стан вашого кластера, ви можете виконати:

kubectl cluster-info dump

Приклад: налагодження вимкненого/недоступного вузла

Іноді під час налагодження корисно переглянути стан вузла — наприклад, тому що ви помітили дивну поведінку Podʼа, який працює на вузлі, або щоб зʼясувати, чому Pod не призначається на вузол. Як і для Podʼів, для отримання детальної інформації про вузли можна використовувати kubectl describe node і kubectl get node -o yaml. Наприклад, ось що ви побачите, якщо вузол не працює (відʼєднаний від мережі, або kubelet завершився й не перезапускається тощо). Зверніть увагу на події, які показують, що вузол у стані NotReady, а також на те, що Podʼи більше не працюють (їх буде виселено після пʼяти хвилин у стані NotReady).

kubectl get nodes
NAME                     STATUS       ROLES     AGE     VERSION
kube-worker-1            NotReady     <none>    1h      v1.23.3
kubernetes-node-bols     Ready        <none>    1h      v1.23.3
kubernetes-node-st6x     Ready        <none>    1h      v1.23.3
kubernetes-node-unaj     Ready        <none>    1h      v1.23.3
kubectl describe node kube-worker-1
Name:               kube-worker-1
Roles:              <none>
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=kube-worker-1
                    kubernetes.io/os=linux
                    node.alpha.kubernetes.io/ttl: 0
                    volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp:  Thu, 17 Feb 2022 16:46:30 -0500
Taints:             node.kubernetes.io/unreachable:NoExecute
                    node.kubernetes.io/unreachable:NoSchedule
Unschedulable:      false
Lease:
  HolderIdentity:  kube-worker-1
  AcquireTime:     <unset>
  RenewTime:       Thu, 17 Feb 2022 17:13:09 -0500
Conditions:
  Type                 Status    LastHeartbeatTime                 LastTransitionTime                Reason              Message
  ----                 ------    -----------------                 ------------------                ------              -------
  NetworkUnavailable   False     Thu, 17 Feb 2022 17:09:13 -0500   Thu, 17 Feb 2022 17:09:13 -0500   WeaveIsUp           Weave pod has set this
  MemoryPressure       Unknown   Thu, 17 Feb 2022 17:12:40 -0500   Thu, 17 Feb 2022 17:13:52 -0500   NodeStatusUnknown   Kubelet stopped posting node status.
  DiskPressure         Unknown   Thu, 17 Feb 2022 17:12:40 -0500   Thu, 17 Feb 2022 17:13:52 -0500   NodeStatusUnknown   Kubelet stopped posting node status.
  PIDPressure          Unknown   Thu, 17 Feb 2022 17:12:40 -0500   Thu, 17 Feb 2022 17:13:52 -0500   NodeStatusUnknown   Kubelet stopped posting node status.
  Ready                Unknown   Thu, 17 Feb 2022 17:12:40 -0500   Thu, 17 Feb 2022 17:13:52 -0500   NodeStatusUnknown   Kubelet stopped posting node status.
Addresses:
  InternalIP:  192.168.0.113
  Hostname:    kube-worker-1
Capacity:
  cpu:                2
  ephemeral-storage:  15372232Ki
  hugepages-2Mi:      0
  memory:             2025188Ki
  pods:               110
Allocatable:
  cpu:                2
  ephemeral-storage:  14167048988
  hugepages-2Mi:      0
  memory:             1922788Ki
  pods:               110
System Info:
  Machine ID:                 9384e2927f544209b5d7b67474bbf92b
  System UUID:                aa829ca9-73d7-064d-9019-df07404ad448
  Boot ID:                    5a295a03-aaca-4340-af20-1327fa5dab5c
  Kernel Version:             5.13.0-28-generic
  OS Image:                   Ubuntu 21.10
  Operating System:           linux
  Architecture:               amd64
  Container Runtime Version:  containerd://1.5.9
  Kubelet Version:            v1.23.3
  Kube-Proxy Version:         v1.23.3
Non-terminated Pods:          (4 in total)
  Namespace                   Name                                 CPU Requests  CPU Limits  Memory Requests  Memory Limits  Age
  ---------                   ----                                 ------------  ----------  ---------------  -------------  ---
  default                     nginx-deployment-67d4bdd6f5-cx2nz    500m (25%)    500m (25%)  128Mi (6%)       128Mi (6%)     23m
  default                     nginx-deployment-67d4bdd6f5-w6kd7    500m (25%)    500m (25%)  128Mi (6%)       128Mi (6%)     23m
  kube-system                 kube-proxy-dnxbz                     0 (0%)        0 (0%)      0 (0%)           0 (0%)         28m
  kube-system                 weave-net-gjxxp                      100m (5%)     0 (0%)      200Mi (10%)      0 (0%)         28m
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource           Requests     Limits
  --------           --------     ------
  cpu                1100m (55%)  1 (50%)
  memory             456Mi (24%)  256Mi (13%)
  ephemeral-storage  0 (0%)       0 (0%)
  hugepages-2Mi      0 (0%)       0 (0%)
Events:
...
kubectl get node kube-worker-1 -o yaml
apiVersion: v1
kind: Node
metadata:
  annotations:
    node.alpha.kubernetes.io/ttl: "0"
    volumes.kubernetes.io/controller-managed-attach-detach: "true"
  creationTimestamp: "2022-02-17T21:46:30Z"
  labels:
    beta.kubernetes.io/arch: amd64
    beta.kubernetes.io/os: linux
    kubernetes.io/arch: amd64
    kubernetes.io/hostname: kube-worker-1
    kubernetes.io/os: linux
  name: kube-worker-1
  resourceVersion: "4026"
  uid: 98efe7cb-2978-4a0b-842a-1a7bf12c05f8
spec: {}
status:
  addresses:
  - address: 192.168.0.113
    type: InternalIP
  - address: kube-worker-1
    type: Hostname
  allocatable:
    cpu: "2"
    ephemeral-storage: "14167048988"
    hugepages-2Mi: "0"
    memory: 1922788Ki
    pods: "110"
  capacity:
    cpu: "2"
    ephemeral-storage: 15372232Ki
    hugepages-2Mi: "0"
    memory: 2025188Ki
    pods: "110"
  conditions:
  - lastHeartbeatTime: "2022-02-17T22:20:32Z"
    lastTransitionTime: "2022-02-17T22:20:32Z"
    message: Weave pod has set this
    reason: WeaveIsUp
    status: "False"
    type: NetworkUnavailable
  - lastHeartbeatTime: "2022-02-17T22:20:15Z"
    lastTransitionTime: "2022-02-17T22:13:25Z"
    message: kubelet has sufficient memory available
    reason: KubeletHasSufficientMemory
    status: "False"
    type: MemoryPressure
  - lastHeartbeatTime: "2022-02-17T22:20:15Z"
    lastTransitionTime: "2022-02-17T22:13:25Z"
    message: kubelet has no disk pressure
    reason: KubeletHasNoDiskPressure
    status: "False"
    type: DiskPressure
  - lastHeartbeatTime: "2022-02-17T22:20:15Z"
    lastTransitionTime: "2022-02-17T22:13:25Z"
    message: kubelet has sufficient PID available
    reason: KubeletHasSufficientPID
    status: "False"
    type: PIDPressure
  - lastHeartbeatTime: "2022-02-17T22:20:15Z"
    lastTransitionTime: "2022-02-17T22:15:15Z"
    message: kubelet is posting ready status
    reason: KubeletReady
    status: "True"
    type: Ready
  daemonEndpoints:
    kubeletEndpoint:
      Port: 10250
  nodeInfo:
    architecture: amd64
    bootID: 22333234-7a6b-44d4-9ce1-67e31dc7e369
    containerRuntimeVersion: containerd://1.5.9
    kernelVersion: 5.13.0-28-generic
    kubeProxyVersion: v1.23.3
    kubeletVersion: v1.23.3
    machineID: 9384e2927f544209b5d7b67474bbf92b
    operatingSystem: linux
    osImage: Ubuntu 21.10
    systemUUID: aa829ca9-73d7-064d-9019-df07404ad448

Аналіз логів

Наразі для глибшого дослідження кластера потрібно входити на відповідні машини. Ось розташування відповідних файлів логів. У системах на основі systemd замість перегляду файлів логів може знадобитися journalctl.

Вузли панелі управління

  • /var/log/kube-apiserver.log — API-сервер, відповідальний за обслуговування API
  • /var/log/kube-scheduler.log — планувальник, відповідальний за ухвалення рішень щодо планування
  • /var/log/kube-controller-manager.log — компонент, який запускає більшість вбудованих контролерів Kubernetes, за помітним винятком планування (плануванням займається kube-scheduler).

Робочі вузли

  • /var/log/kubelet.log — логи kubelet, відповідального за запуск контейнерів на вузлі
  • /var/log/kube-proxy.log — логи kube-proxy, відповідального за спрямування трафіку до точок доступу Service

Режими відмови кластера

Це неповний перелік того, що може піти не так, і того, як змінити налаштування кластера, щоб помʼякшити проблеми.

Причини відмов

  • Вимкнення віртуальних машин
  • Розділення мережі всередині кластера або між кластером і користувачами
  • Збої програмного забезпечення Kubernetes
  • Втрата даних або недоступність постійного сховища (наприклад, томів GCE PD або AWS EBS)
  • Помилка оператора, наприклад, неправильно налаштоване програмне забезпечення Kubernetes або застосунків

Конкретні сценарії

  • Вимкнення віртуальної машини API-сервера або збій apiserver
    • Результати
      • не вдається зупинити, оновити чи запустити нові Podʼи, Service, ReplicationController
      • наявні Podʼи та Service мають і далі працювати нормально, якщо вони не залежать від API Kubernetes
  • Втрата сховища, що лежить в основі API-сервера
    • Результати
      • компонент kube-apiserver не може успішно запуститися й стати справним
      • kubelet не зможуть звʼязатися з ним, але й далі запускатимуть ті самі Podʼи та забезпечуватимуть те саме проксіювання Service
      • перед перезапуском apiserver необхідно вручну відновити або відтворити його стан
  • Вимкнення віртуальних машин або збої допоміжних сервісів (контролер вузлів, менеджер контролерів реплікації, планувальник тощо)
    • наразі вони розміщені разом з apiserver, і їхня недоступність має схожі наслідки, як і недоступність apiserver
    • у майбутньому вони також будуть репліковані й можуть розміщуватися окремо
    • вони не мають власного постійного стану
  • Вимкнення окремого вузла (віртуальної або фізичної машини)
    • Результати
      • Podʼи на цьому вузлі припиняють роботу
  • Розділення мережі
    • Результати
      • розділ A вважає, що вузли в розділі B не працюють; розділ B вважає, що не працює apiserver. (За умови, що master VM опиниться в розділі A.)
  • Збій програмного забезпечення kubelet
    • Результати
      • kubelet, що аварійно завершився, не може запускати нові Podʼи на вузлі
      • kubelet може видаляти Podʼи або ні
      • вузол позначається як несправний
      • ReplicationController запускають нові Podʼи в інших місцях
  • Помилка оператора кластера
    • Результати
      • втрата Podʼів, Service тощо
      • втрата сховища, що лежить в основі apiserver
      • користувачі не можуть читати API
      • тощо

Помʼякшення

  • Дія: використовуйте можливість автоматичного перезапуску віртуальних машин IaaS-провайдера для віртуальних машин IaaS

    • Помʼякшує: вимкнення віртуальної машини apiserver або збій apiserver
    • Помʼякшує: вимкнення віртуальних машин або збої допоміжних сервісів
  • Дія: використовуйте надійне сховище IaaS-провайдера (наприклад, томи GCE PD або AWS EBS) для віртуальних машин з apiserver+etcd

    • Помʼякшує: втрату сховища, що лежить в основі apiserver
  • Дія: використовуйте конфігурацію з високою доступністю

    • Помʼякшує: вимкнення вузла панелі управління або збої компонентів панелі управління (планувальник, API-сервер, controller-manager)
      • Витримує одну або кілька одночасних відмов вузлів чи компонентів
    • Помʼякшує: втрату сховища, що лежить в основі API-сервера (тобто теки даних etcd)
      • Передбачає конфігурацію etcd з високою доступністю (HA)
  • Дія: регулярно створюйте знімки томів PD/EBS apiserver

    • Помʼякшує: втрату сховища, що лежить в основі apiserver
    • Помʼякшує: деякі випадки помилок оператора
    • Помʼякшує: деякі випадки збоїв програмного забезпечення Kubernetes
  • Дія: використовуйте ReplicationController і Service перед Podʼами

    • Помʼякшує: вимкнення вузла
    • Помʼякшує: збій програмного забезпечення kubelet
  • Дія: застосунки (контейнери), спроєктовані так, щоб витримувати неочікувані перезапуски

    • Помʼякшує: вимкнення вузла
    • Помʼякшує: збій програмного забезпечення kubelet

Що далі

1 - Конвеєр метрик ресурсів

Для Kubernetes Metrics API пропонує базовий набір метрик для підтримки автоматичного масштабування та подібних випадків використання. Це API робить доступною інформацію про використання ресурсів вузлами й Podʼами, зокрема метрики CPU та памʼяті. Якщо ви розгорнете Metrics API у своєму кластері, клієнти API Kubernetes зможуть запитувати цю інформацію, а ви зможете використовувати механізми контролю доступу Kubernetes для керування дозволами на це.

HorizontalPodAutoscaler (HPA) і VerticalPodAutoscaler (VPA) використовують дані з Metrics API, щоб коригувати кількість реплік і ресурси робочих навантажень відповідно до попиту користувачів.

Ви також можете переглядати метрики ресурсів, використовуючи команду kubectl top.

Примітка:

Metrics API та конвеєр метрик, який воно уможливлює, надають лише мінімальний набір метрик CPU та памʼяті для автоматичного масштабування за допомогою HPA та / або VPA. Якщо ви хочете надати повніший набір метрик, ви можете доповнити простіший Metrics API, розгорнувши другий конвеєр метрик, який використовує Custom Metrics API.

Схема 1 ілюструє архітектуру конвеєра метрик ресурсів.

flowchart RL
subgraph cluster[Кластер]
    direction RL
    S[ 

] A[Сервер-
метрик] subgraph B[Вузли] direction TB D[cAdvisor] --> C[kubelet] E[Середовище
виконання
контейнерів] --> D E1[Середовище
виконання
контейнерів] --> D P[Дані Podʼа] -.- C end L[API-сервер] W[HPA] C ---->|метрики ресурсів
на рівні вузла| A -->|Metrics
API| L --> W end L ---> K[kubectl
top] classDef box fill:#fff,stroke:#000,stroke-width:1px,color:#000; class W,B,P,K,cluster,D,E,E1 box classDef spacewhite fill:#ffffff,stroke:#fff,stroke-width:0px,color:#000 class S spacewhite classDef k8s fill:#326ce5,stroke:#fff,stroke-width:1px,color:#fff; class A,L,C k8s

Схема 1. Конвеєр метрик ресурсів

Компоненти архітектури, справа наліво на схемі, такі:

  • cAdvisor: демон, вбудований у kubelet, для збирання, агрегування та надання метрик контейнерів.

  • kubelet: агент вузла для керування ресурсами контейнерів. Метрики ресурсів доступні через точки доступу API kubelet /metrics/resource і /stats.

  • метрики ресурсів на рівні вузла: API, який надає kubelet для виявлення й отримання підсумкової статистики по вузлу, доступної через точку доступу /metrics/resource.

  • metrics-server: компонент-надбудова кластера, який збирає й агрегує метрики ресурсів, отримані від кожного kubelet. API-сервер обслуговує Metrics API для HPA, VPA і команди kubectl top. Metrics Server — це еталонна реалізація Metrics API.

  • Metrics API: API Kubernetes, що надає доступ до даних про CPU та памʼять, які використовуються для автомасштабування робочих навантажень. Щоб це працювало у вашому кластері, потрібен API-сервер розширення, який надає Metrics API.

    Примітка:

    cAdvisor підтримує читання метрик з cgroups, що працює зі звичайними середовищами виконання контейнерів у Linux. Якщо ви використовуєте середовище виконання контейнерів з іншим механізмом ізоляції ресурсів, наприклад віртуалізацією, це середовище виконання контейнерів має підтримувати метрики контейнерів CRI, щоб метрики були доступні kubelet.

Metrics API

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.37

Metrics-server реалізує Metrics API. Це API дає змогу отримати дані про використання CPU та памʼяті вузлами й Podʼами вашого кластера. Його основна роль — передавати метрики використання ресурсів компонентам автомасштабування K8s.

Ось приклад запиту до Metrics API для вузла minikube, обробленого через jq для зручного перегляду:

kubectl get --raw "/apis/metrics.k8s.io/v1/nodes/minikube" | jq '.'

Той самий виклик API за допомогою curl:

curl http://localhost:8080/apis/metrics.k8s.io/v1/nodes/minikube

Приклад відповіді:

{
  "kind": "NodeMetrics",
  "apiVersion": "metrics.k8s.io/v1",
  "metadata": {
    "name": "minikube",
    "selfLink": "/apis/metrics.k8s.io/v1/nodes/minikube",
    "creationTimestamp": "2022-01-27T18:48:43Z"
  },
  "timestamp": "2022-01-27T18:48:33Z",
  "window": "30s",
  "usage": {
    "cpu": "487558164n",
    "memory": "732212Ki"
  }
}

Ось приклад запиту до Metrics API для Podʼа kube-scheduler-minikube у просторі імен kube-system, обробленого через jq для зручного перегляду:

kubectl get --raw "/apis/metrics.k8s.io/v1/namespaces/kube-system/pods/kube-scheduler-minikube" | jq '.'

Той самий виклик API за допомогою curl:

curl http://localhost:8080/apis/metrics.k8s.io/v1/namespaces/kube-system/pods/kube-scheduler-minikube

Приклад відповіді:

{
  "kind": "PodMetrics",
  "apiVersion": "metrics.k8s.io/v1",
  "metadata": {
    "name": "kube-scheduler-minikube",
    "namespace": "kube-system",
    "selfLink": "/apis/metrics.k8s.io/v1/namespaces/kube-system/pods/kube-scheduler-minikube",
    "creationTimestamp": "2022-01-27T19:25:00Z"
  },
  "timestamp": "2022-01-27T19:24:31Z",
  "window": "30s",
  "containers": [
    {
      "name": "kube-scheduler",
      "usage": {
        "cpu": "9559630n",
        "memory": "22244Ki"
      }
    }
  ]
}

Metrics API визначено в репозиторії k8s.io/metrics. Вам потрібно увімкнути шар агрегації API та зареєструвати APIService для API metrics.k8s.io.

Щоб дізнатися більше про Metrics API, дивіться дизайн API метрик ресурсів, репозиторій metrics-server і API метрик ресурсів.

Примітка:

Щоб отримати доступ до Metrics API, потрібно розгорнути metrics-server або інший адаптер, який його надає.

Вимірювання використання ресурсів

CPU

CPU відображається як середнє використання ядер, виміряне в одиницях CPU. Один CPU у Kubernetes еквівалентний 1 vCPU/ядру в хмарних провайдерів і 1 гіперпотоку на процесорах Intel на bare-metal.

Це значення отримують, обчислюючи швидкість зміни накопичувального лічильника CPU, який надає ядро (і в Linux, і в Windows). Часове вікно, використане для обчислення CPU, показано в полі window у Metrics API.

Щоб дізнатися більше про те, як Kubernetes розподіляє та вимірює ресурси CPU, дивіться значення CPU.

Памʼять

Памʼять відображається як робочий набір, виміряний у байтах, у момент збору метрики.

В ідеальному світі "робочий набір" — це обсяг памʼяті, що використовується й не може бути звільнений за умов тиску на памʼять. Однак обчислення робочого набору залежить від ОС хоста й, як правило, значною мірою покладається на евристики для отримання оцінки.

Модель Kubernetes для робочого набору контейнера очікує, що середовище виконання контейнерів враховує анонімну памʼять, повʼязану з відповідним контейнером. Метрика робочого набору зазвичай також включає деяку кешовану памʼять (file-backed), оскільки ОС хоста не завжди може звільнити сторінки.

Щоб дізнатися більше про те, як Kubernetes розподіляє та вимірює ресурси памʼяті, дивіться значення памʼяті.

Metrics Server

Metrics-server отримує метрики ресурсів від kubelet і надає їх через Metrics API на API-сервері Kubernetes для використання HPA та VPA. Ці метрики також можна переглядати командою kubectl top.

Metrics-server використовує API Kubernetes для відстеження вузлів і Podʼів у вашому кластері. Metrics-server запитує кожен вузол через HTTP, щоб отримати метрики. Metrics-server також будує внутрішнє подання метаданих Podʼів і зберігає кеш стану справності Podʼів. Ця кешована інформація про стан справності Podʼів доступна через API розширення, яке надає metrics-server.

Наприклад, для запиту HPA metrics-server має визначити, які Podʼи відповідають селекторам міток у Deployment.

Metrics-server викликає API kubelet для збору метрик з кожного вузла. Залежно від версії metrics-server використовується:

  • Точка доступу ресурсів метрик /metrics/resource у версії v0.6.0+ або
  • Точка доступу Summary API /stats/summary у старіших версіях

Що далі

Щоб дізнатися більше про metrics-server, перегляньте репозиторій metrics-server.

Також можна переглянути таке:

Щоб дізнатися про те, як kubelet надає метрики вузла, і як ви можете отримати до них доступ через API Kubernetes, прочитайте Дані метрик вузлів.

2 - Налагодження вузлів Kubernetes за допомогою crictl

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.11

crictl — це інтерфейс командного рядка для середовищ виконання контейнерів, сумісних з CRI. За його допомогою можна оглядати й налагоджувати середовища виконання контейнерів і застосунки на вузлі Kubernetes. crictl і його вихідний код розміщено в репозиторії cri-tools.

Перш ніж ви розпочнете

Для роботи crictl потрібна операційна система Linux із середовищем виконання CRI.

Встановлення crictl

Стиснений архів crictl для кількох різних архітектур можна завантажити зі сторінки релізів cri-tools. Завантажте версію, яка відповідає вашій версії Kubernetes. Розпакуйте архів і перемістіть crictl у теку з вашого системного шляху, наприклад /usr/local/bin/.

Загальне використання

Команда crictl має кілька підкоманд і прапорців середовища виконання. Докладніше дивіться crictl help або crictl <subcommand> help.

Точку доступу для crictl можна встановити одним із таких способів:

  • Встановіть прапорці --runtime-endpoint та --image-endpoint.
  • Встановіть змінні середовища CONTAINER_RUNTIME_ENDPOINT та IMAGE_SERVICE_ENDPOINT.
  • Встановіть точку доступу у файлі конфігурації /etc/crictl.yaml. Щоб вказати інший файл, використовуйте прапорець --config=PATH_TO_FILE під час запуску crictl.

Примітка:

Якщо ви не встановите точку доступу, crictl намагатиметься підʼєднатися до відомих точок доступу зі списку, що може вплинути на продуктивність.

Також можна вказати тайм-аут підʼєднання до сервера й увімкнути або вимкнути налагодження, задавши значення timeout або debug у файлі конфігурації або використавши прапорці командного рядка --timeout і --debug.

Щоб переглянути або змінити поточну конфігурацію, перегляньте або відредагуйте вміст /etc/crictl.yaml. Наприклад, з середовищем виконання контейнерів containerd конфігурація буде схожа на таку:

runtime-endpoint: unix:///var/run/containerd/containerd.sock
image-endpoint: unix:///var/run/containerd/containerd.sock
timeout: 10
debug: true

Щоб дізнатися більше про crictl, зверніться до документації crictl.

Приклади команд crictl

Наведені нижче приклади показують деякі команди crictl і приклади їхнього виводу.

Отримання переліку Podʼів

Вивести всі Podʼи:

crictl pods

Вивід подібний до такого:

POD ID              CREATED              STATE               NAME                         NAMESPACE           ATTEMPT
926f1b5a1d33a       About a minute ago   Ready               sh-84d7dcf559-4r2gq          default             0
4dccb216c4adb       About a minute ago   Ready               nginx-65899c769f-wv2gp       default             0
a86316e96fa89       17 hours ago         Ready               kube-proxy-gblk4             kube-system         0
919630b8f81f1       17 hours ago         Ready               nvidia-device-plugin-zgbbv   kube-system         0

Вивести Podʼи за назвою:

crictl pods --name nginx-65899c769f-wv2gp

Вивід подібний до такого:

POD ID              CREATED             STATE               NAME                     NAMESPACE           ATTEMPT
4dccb216c4adb       2 minutes ago       Ready               nginx-65899c769f-wv2gp   default             0

Вивести Podʼи за міткою:

crictl pods --label run=nginx

Вивід подібний до такого:

POD ID              CREATED             STATE               NAME                     NAMESPACE           ATTEMPT
4dccb216c4adb       2 minutes ago       Ready               nginx-65899c769f-wv2gp   default             0

Отримання переліку образів

Вивести всі образи:

crictl images

Вивід подібний до такого:

IMAGE                                     TAG                 IMAGE ID            SIZE
busybox                                   latest              8c811b4aec35f       1.15MB
k8s-gcrio.azureedge.net/hyperkube-amd64   v1.10.3             e179bbfe5d238       665MB
k8s-gcrio.azureedge.net/pause-amd64       3.1                 da86e6ba6ca19       742kB
nginx                                     latest              cd5239a0906a6       109MB

Вивести образи за репозиторієм:

crictl images nginx

Вивід подібний до такого:

IMAGE               TAG                 IMAGE ID            SIZE
nginx               latest              cd5239a0906a6       109MB

Вивести лише ідентифікатори образів:

crictl images -q

Вивід подібний до такого:

sha256:8c811b4aec35f259572d0f79207bc0678df4c736eeec50bc9fec37ed936a472a
sha256:e179bbfe5d238de6069f3b03fccbecc3fb4f2019af741bfff1233c4d7b2970c5
sha256:da86e6ba6ca197bf6bc5e9d900febd906b133eaa4750e6bed647b0fbe50ed43e
sha256:cd5239a0906a6ccf0562354852fae04bc5b52d72a2aff9a871ddb6bd57553569

Отримання переліку контейнерів

Вивести всі контейнери:

crictl ps -a

Вивід подібний до такого:

CONTAINER ID        IMAGE                                                                                                             CREATED             STATE               NAME                       ATTEMPT
1f73f2d81bf98       busybox@sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47                                   7 minutes ago       Running             sh                         1
9c5951df22c78       busybox@sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47                                   8 minutes ago       Exited              sh                         0
87d3992f84f74       nginx@sha256:d0a8828cccb73397acb0073bf34f4d7d8aa315263f1e7806bf8c55d8ac139d5f                                     8 minutes ago       Running             nginx                      0
1941fb4da154f       k8s-gcrio.azureedge.net/hyperkube-amd64@sha256:00d814b1f7763f4ab5be80c58e98140dfc69df107f253d7fdd714b30a714260a   18 hours ago        Running             kube-proxy                 0

Вивести запущені контейнери:

crictl ps

Вивід подібний до такого:

CONTAINER ID        IMAGE                                                                                                             CREATED             STATE               NAME                       ATTEMPT
1f73f2d81bf98       busybox@sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47                                   6 minutes ago       Running             sh                         1
87d3992f84f74       nginx@sha256:d0a8828cccb73397acb0073bf34f4d7d8aa315263f1e7806bf8c55d8ac139d5f                                     7 minutes ago       Running             nginx                      0
1941fb4da154f       k8s-gcrio.azureedge.net/hyperkube-amd64@sha256:00d814b1f7763f4ab5be80c58e98140dfc69df107f253d7fdd714b30a714260a   17 hours ago        Running             kube-proxy                 0

Виконання команди в запущеному контейнері

crictl exec -i -t 1f73f2d81bf98 ls

Вивід подібний до такого:

bin   dev   etc   home  proc  root  sys   tmp   usr   var

Отримання логів контейнера

Отримати всі логи контейнера:

crictl logs 87d3992f84f74

Вивід подібний до такого:

10.240.0.96 - - [06/Jun/2018:02:45:49 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"
10.240.0.96 - - [06/Jun/2018:02:45:50 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"
10.240.0.96 - - [06/Jun/2018:02:45:51 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"

Отримати лише останні N рядків логів:

crictl logs --tail=1 87d3992f84f74

Вивід подібний до такого:

10.240.0.96 - - [06/Jun/2018:02:45:51 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"

Що далі

3 - Аудит

Аудит Kubernetes надає важливий для безпеки хронологічний набір записів, що документують послідовність дій у кластері. Кластер проводить аудит дій, ініційованих користувачами, застосунками, які використовують API Kubernetes, і самою панеллю управління.

Аудит дає змогу адміністраторам кластера відповісти на такі запитання:

  • що сталося?
  • коли це сталося?
  • хто це ініціював?
  • з чим це сталося?
  • де це було помічено?
  • звідки це було ініційовано?
  • куди це прямувало?

Записи аудиту починають свій життєвий цикл у компоненті kube-apiserver. Кожен запит на кожному етапі виконання генерує подію аудиту, яку потім попередньо обробляють відповідно до певної політики й записують у бекенд. Політика визначає, що записується, а бекенди зберігають записи. Поточні реалізації бекендів — файли логів і вебхуки.

Кожен запит можна записати з відповідним етапом (stage). Визначено такі етапи:

  • RequestReceived — етап для подій, що генеруються, щойно обробник аудиту отримує запит, і до того, як запит передано далі ланцюжком обробників.
  • ResponseStarted — після надсилання заголовків відповіді, але до надсилання тіла відповіді. Цей етап генерується лише для тривалих запитів (наприклад, watch).
  • ResponseComplete — тіло відповіді завершено, і більше жодних байтів не буде надіслано.
  • Panic — події, що генеруються, коли сталася паніка.

Примітка:

Конфігурація події аудиту відрізняється від обʼєкта API Event.

Можливість логування аудиту збільшує споживання памʼяті API-сервером, оскільки для кожного запиту зберігається певний контекст, потрібний для аудиту. Споживання памʼяті залежить від конфігурації логування аудиту.

Політика аудиту

Політика аудиту визначає правила щодо того, які події слід записувати і які дані вони мають містити. Структуру обʼєкта політики аудиту визначено в групі API audit.k8s.io. Під час обробки подію по черзі порівнюють зі списком правил. Перше правило, що збіглося, встановлює рівень аудиту події. Визначено такі рівні аудиту:

  • None — не записувати події, які відповідають цьому правилу.
  • Metadata — записувати події з метаданими (користувач, що надіслав запит, часова мітка, ресурс, дієслово тощо), але без тіла запиту чи відповіді.
  • Request — записувати події з метаданими й тілом запиту, але без тіла відповіді. Це не стосується запитів, не повʼязаних з ресурсами.
  • RequestResponse — записувати події з метаданими запиту, тілом запиту й тілом відповіді. Це не стосується запитів, не повʼязаних з ресурсами.

Файл з політикою можна передати kube-apiserver за допомогою прапорця --audit-policy-file. Якщо прапорець пропущено, жодні події не записуються. Зверніть увагу, що поле rules обовʼязково має бути у файлі політики аудиту. Політика без правил (0) вважається неприпустимою.

Нижче наведено приклад файлу політики аудиту:

apiVersion: audit.k8s.io/v1 # Це обовʼязково.
kind: Policy
# Не генерувати події аудиту для всіх запитів на етапі RequestReceived.
omitStages:
  - "RequestReceived"
rules:
  # Логувати зміни Podʼів на рівні RequestResponse
  - level: RequestResponse
    resources:
    - group: ""
      # Ресурс "pods" не охоплює запити до будь-якого субресурсу Podʼів,
      # що узгоджується з політикою RBAC.
      resources: ["pods"]
  # Логувати "pods/log", "pods/status" на рівні Metadata
  - level: Metadata
    resources:
    - group: ""
      resources: ["pods/log", "pods/status"]

  # Не логувати запити до ConfigMap з назвою "controller-leader"
  - level: None
    resources:
    - group: ""
      resources: ["configmaps"]
      resourceNames: ["controller-leader"]

  # Не логувати watch-запити від "system:kube-proxy" до endpoints або services
  - level: None
    users: ["system:kube-proxy"]
    verbs: ["watch"]
    resources:
    - group: "" # основна група API
      resources: ["endpoints", "services"]

  # Не логувати автентифіковані запити до певних URL-шляхів, що не є ресурсами.
  - level: None
    userGroups: ["system:authenticated"]
    nonResourceURLs:
    - "/api*" # Зіставлення за шаблоном.
    - "/version"

  # Логувати тіло запитів на зміну ConfigMap у kube-system.
  - level: Request
    resources:
    - group: "" # основна група API
      resources: ["configmaps"]
    # Це правило застосовується тільки до ресурсів в просторі імен "kube-system".
    # Порожній рядок "" можна використовувати для вибору ресурсів без простору імен.
    namespaces: ["kube-system"]

  # Логувати зміни ConfigMap і Secret у всіх інших просторах імен на рівні Metadata.
  - level: Metadata
    resources:
    - group: "" # основна група API
      resources: ["secrets", "configmaps"]

  # Логувати всі інші ресурси в групах core та extensions на рівні Request.
  - level: Request
    resources:
    - group: "" # основна група API
    - group: "extensions" # Версію групи НЕ слід вказувати.

  # Загальне правило для логування всіх інших запитів на рівні Metadata.
  - level: Metadata
    # Тривалі запити, як-от watch, що підпадають під це правило,
    # не генерують подію аудиту на етапі RequestReceived.
    omitStages:
      - "RequestReceived"

Можна використати мінімальний файл політики аудиту, щоб записувати всі запити на рівні Metadata:

# Записувати всі запити на рівні Metadata.
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata

Якщо ви створюєте власний профіль аудиту, за відправну точку можна взяти профіль аудиту для Google Container-Optimized OS. Перегляньте скрипт configure-helper.sh, який генерує файл політики аудиту. Більшу частину файлу політики аудиту можна побачити безпосередньо в скрипті.

Докладніше про визначені поля дивіться в довіднику конфігурації Policy.

Бекенди аудиту

Бекенди аудиту зберігають події аудиту в зовнішньому сховищі. Без додаткових налаштувань kube-apiserver надає два бекенди:

  • бекенд логів, який записує події у файлову систему
  • бекенд webhook, який надсилає події до зовнішнього HTTP API

У всіх випадках події аудиту мають структуру, визначену API Kubernetes у групі API audit.k8s.io.

Примітка:

У разі патчів тіло запиту — це масив JSON з операціями патча, а не обʼєкт JSON з відповідним обʼєктом API Kubernetes. Наприклад, наведене нижче тіло запиту є коректним запитом на патч до /apis/batch/v1/namespaces/some-namespace/jobs/some-job-name:

[
  {
    "op": "replace",
    "path": "/spec/parallelism",
    "value": 0
  },
  {
    "op": "remove",
    "path": "/spec/template/spec/containers/0/terminationMessagePolicy"
  }
]

Бекенд логів

Бекенд логів записує події аудиту у файл у форматі JSONlines. Бекенд аудиту логів можна налаштувати за допомогою таких прапорців kube-apiserver:

  • --audit-log-path вказує шлях до файлу логу, який бекенд логів використовує для запису подій аудиту. Якщо цей прапорець не вказано, бекенд логів вимкнено. - означає стандартний вивід
  • --audit-log-maxage визначає максимальну кількість днів для зберігання старих файлів логів аудиту
  • --audit-log-maxbackup визначає максимальну кількість файлів логів аудиту для зберігання
  • --audit-log-maxsize визначає максимальний розмір файлу логу аудиту в мегабайтах, після якого виконується його ротація

Якщо панель управління вашого кластера запускає kube-apiserver як Pod, не забудьте змонтувати hostPath у розташування файлу політики й файлу логів, щоб записи аудиту зберігалися. Наприклад:

  - --audit-policy-file=/etc/kubernetes/audit-policy.yaml
  - --audit-log-path=/var/log/kubernetes/audit/audit.log

потім змонтуйте томи:

...
volumeMounts:
  - mountPath: /etc/kubernetes/audit-policy.yaml
    name: audit
    readOnly: true
  - mountPath: /var/log/kubernetes/audit/
    name: audit-log
    readOnly: false

і нарешті налаштуйте hostPath:

...
volumes:
- name: audit
  hostPath:
    path: /etc/kubernetes/audit-policy.yaml
    type: File

- name: audit-log
  hostPath:
    path: /var/log/kubernetes/audit/
    type: DirectoryOrCreate

Бекенд Webhook

Бекенд аудиту webhook надсилає події аудиту до віддаленого веб-API, яке вважається різновидом API Kubernetes, зокрема щодо засобів автентифікації. Бекенд аудиту webhook можна налаштувати за допомогою таких прапорців kube-apiserver:

  • --audit-webhook-config-file вказує шлях до файлу з конфігурацією webhook. Конфігурація webhook фактично є спеціалізованим kubeconfig.
  • --audit-webhook-initial-backoff вказує час очікування після першого невдалого запиту перед повторною спробою. Подальші запити повторюються з експоненційною затримкою.

Файл конфігурації webhook використовує формат kubeconfig, щоб вказати віддалену адресу сервісу й облікові дані для підʼєднання до нього.

Пакетна обробка подій

Обидва бекенди, log і webhook, підтримують пакетну обробку. Нижче наведено перелік доступних прапорців для кожного бекенду. Стандартно пакетну обробку й тротлінг увімкнено для бекенду webhook і вимкнено для бекенду log.

  • --audit-webhook-mode визначає стратегію буферизації. Можливі значення:
    • batch — буферизувати події й асинхронно обробляти їх пакетами. Це стандартний режим для бекенду webhook.
    • blocking — блокувати відповіді API-сервера під час обробки кожної окремої події.
    • blocking-strict — те саме, що й blocking, але якщо під час логування аудиту на етапі RequestReceived стається збій, увесь запит до kube-apiserver завершується невдачею.

Такі прапорці використовуються лише в режимі batch:

  • --audit-webhook-batch-buffer-size визначає кількість подій для буферизації перед пакетною обробкою. Якщо швидкість надходження подій переповнює буфер, події відкидаються. Стандартне значення — 10000.
  • --audit-webhook-batch-max-size визначає максимальну кількість подій в одному пакеті. Стандартне значення — 400.
  • --audit-webhook-batch-max-wait визначає максимальний час очікування перед безумовною пакетною обробкою подій у черзі. Стандартне значення — 30 секунд.
  • --audit-webhook-batch-throttle-enable визначає, чи увімкнено тротлінг пакетів. Стандартно тротлінг увімкнено.
  • --audit-webhook-batch-throttle-qps визначає максимальну середню кількість пакетів, що генеруються за секунду. Стандартне значення — 10.
  • --audit-webhook-batch-throttle-burst визначає максимальну кількість пакетів, згенерованих у той самий момент, якщо дозволений QPS раніше використовувався не повністю. Стандартне значення — 15.
  • --audit-log-mode визначає стратегію буферизації. Можливі значення:
    • batch — буферизувати події й асинхронно обробляти їх пакетами. Пакетна обробка не рекомендується для бекенду log.
    • blocking — блокувати відповіді API-сервера під час обробки кожної окремої події. Це стандартний режим для бекенду log.
    • blocking-strict — те саме, що й blocking, але якщо під час логування аудиту на етапі RequestReceived стається збій, увесь запит до kube-apiserver завершується невдачею.

Такі прапорці використовуються лише в режимі batch (стандартно для бекенду log пакетну обробку вимкнено, і коли її вимкнено, усі прапорці, повʼязані з пакетною обробкою, ігноруються):

  • --audit-log-batch-buffer-size визначає кількість подій для буферизації перед пакетною обробкою. Якщо швидкість надходження подій переповнює буфер, події відкидаються.
  • --audit-log-batch-max-size визначає максимальну кількість подій в одному пакеті.
  • --audit-log-batch-max-wait визначає максимальний час очікування перед безумовною пакетною обробкою подій у черзі.
  • --audit-log-batch-throttle-enable визначає, чи увімкнено тротлінг пакетної обробки.
  • --audit-log-batch-throttle-qps визначає максимальну середню кількість пакетів, що генеруються за секунду.
  • --audit-log-batch-throttle-burst визначає максимальну кількість пакетів, згенерованих у той самий момент, якщо дозволений QPS раніше використовувався не повністю.

Налаштування параметрів

Параметри слід задавати з урахуванням навантаження на API-сервер.

Наприклад, якщо kube-apiserver отримує 100 запитів щосекунди і кожен запит проходить аудит лише на етапах ResponseStarted і ResponseComplete, слід розраховувати на ≅200 подій аудиту щосекунди. Якщо в пакеті до 100 подій, рівень тротлінгу слід встановити щонайменше 2 запити на секунду. Якщо бекенду може знадобитися до 5 секунд для запису подій, розмір буфера слід встановити так, щоб він вміщував події за 5 секунд, тобто 10 пакетів або 1000 подій.

Однак у більшості випадків стандартних параметрів має бути достатньо, і вам не потрібно задавати їх вручну. Щоб відстежувати стан підсистеми аудиту, можна переглядати такі метрики Prometheus, які надає kube-apiserver, а також логи.

  • Метрика apiserver_audit_event_total містить загальну кількість експортованих подій аудиту.
  • Метрика apiserver_audit_error_total містить загальну кількість подій, відкинутих через помилку під час експорту.

Обрізання записів логу

Обидва бекенди, логів і webhook, підтримують обмеження розміру подій, що записуються. Наприклад, ось перелік прапорців, доступних для бекенду логів:

  • audit-log-truncate-enabled — чи ввімкнено обрізання подій і пакетів.
  • audit-log-truncate-max-batch-size — максимальний розмір у байтах пакета, що надсилається до базового бекенду.
  • audit-log-truncate-max-event-size — максимальний розмір у байтах події аудиту, що надсилається до базового бекенду.

Стандартно обрізання вимкнено і для webhook, і для log; щоб увімкнути цю можливість, адміністратор кластера має встановити audit-log-truncate-enabled або audit-webhook-truncate-enabled.

Що далі

4 - Розробка та налагодження сервісів локально за допомогою telepresence

Примітка: Цей розділ містить посилання на проєкти сторонніх розробників, які надають функціонал, необхідний для Kubernetes. Автори проєкту Kubernetes не несуть відповідальності за ці проєкти. Проєкти вказано в алфавітному порядку. Щоб додати проєкт до цього списку, ознайомтеся з посібником з контенту перед надсиланням змін. Докладніше.

Застосунки Kubernetes зазвичай складаються з кількох окремих сервісів, кожен з яких працює у власному контейнері. Розробляти й налагоджувати ці сервіси у віддаленому кластері Kubernetes може бути незручно, бо для запуску інструментів налагодження потрібно отримати доступ до оболонки запущеного контейнера.

telepresence — це інструмент, що спрощує локальну розробку й налагодження сервісів, проксіюючи сервіс до віддаленого кластера Kubernetes. telepresence дає змогу використовувати для локального сервісу власні інструменти, як-от налагоджувач та IDE, і надає сервісу повний доступ до ConfigMap, Secrets і сервісів, що працюють у віддаленому кластері.

У цьому документі описано, як використовувати telepresence для локальної розробки й налагодження сервісів, що працюють у віддаленому кластері.

Перш ніж ви розпочнете

  • Кластер Kubernetes встановлено
  • kubectl налаштовано для звʼязку з кластером
  • Telepresence встановлено

Підʼєднання вашого локального компʼютера до віддаленого кластера Kubernetes

Після встановлення telepresence виконайте telepresence connect, щоб запустити його демон і підʼєднати вашу локальну робочу станцію до кластера.

$ telepresence connect

Launching Telepresence Daemon
...
Connected to context default (https://<cluster public IP>)

Ви можете звертатися до сервісів командою curl, використовуючи синтаксис Kubernetes, наприклад curl -ik https://kubernetes.default

Розробка або налагодження наявного сервісу

Під час розробки застосунку в Kubernetes ви зазвичай програмуєте або налагоджуєте один сервіс. Цьому сервісу може знадобитися доступ до інших сервісів для тестування й налагодження. Один із варіантів — використовувати конвеєр безперервного розгортання, але навіть найшвидший конвеєр розгортання додає затримку в цикл програмування чи налагодження.

Використовуйте команду telepresence intercept $SERVICE_NAME --port $LOCAL_PORT:$REMOTE_PORT, щоб створити «перехоплення» (intercept) для перенаправлення трафіку віддаленого сервісу.

Де:

  • $SERVICE_NAME — це назва вашого локального сервісу
  • $LOCAL_PORT — це порт, на якому ваш сервіс працює на вашій локальній робочій станції
  • $REMOTE_PORT — це порт, який ваш сервіс слухає в кластері

Ця команда вказує Telepresence надсилати віддалений трафік на ваш локальний сервіс замість сервісу у віддаленому кластері Kubernetes. Вносьте зміни у вихідний код сервісу локально, зберігайте їх, і відповідні зміни одразу набиратимуть чинності під час доступу до віддаленого застосунку. Ви також можете запускати локальний сервіс за допомогою налагоджувача чи будь-якого іншого локального інструмента розробки.

Як працює Telepresence?

Telepresence встановлює sidecar traffic-agent поруч із контейнером вашого наявного застосунку, що працює у віддаленому кластері. Потім він перехоплює всі запити трафіку, що надходять до Podʼа, і замість того, щоб пересилати їх застосунку у віддаленому кластері, спрямовує весь трафік (коли ви створюєте глобальне перехоплення) або його частину (коли ви створюєте персональне перехоплення) до вашого локального середовища розробки.

Що далі

Якщо вас цікавить практичний навчальний матеріал, перегляньте цей навчальний матеріал, у якому покроково описано локальну розробку застосунку Guestbook на Google Kubernetes Engine.

Докладніше дивіться на вебсайті Telepresence.

5 - Усунення несправностей керування топологією

Kubernetes приховує від користувача багато аспектів того, як Podʼи виконуються на вузлах. Це зроблено навмисно. Однак деяким робочим навантаженням для прийнятної роботи потрібні сильніші гарантії щодо затримки та/або продуктивності. kubelet надає методи для складніших політик розміщення робочих навантажень і водночас зберігає абстракцію вільною від явних директив розміщення.

Ви можете керувати топологією всередині вузлів. Це означає, що ви допомагаєте kubelet налаштувати операційну систему хоста так, щоб Podʼи й контейнери розміщувалися з правильного боку внутрішніх меж, таких як домени NUMA. (NUMA — абревіатура від non-uniform memory access (нерівномірний доступ до памʼяті); вона відображає ідею, що CPU можуть бути топологічно ближчими до певних ділянок памʼяті через фізичне розташування апаратних компонентів і спосіб їх зʼєднання.)

Джерела інформації для усунення несправностей

Щоб зʼясувати, чому Pod не вдалося розгорнути або чому його відхилено на вузлі в контексті керування топологією, можна скористатися такими засобами:

  • Статус Podʼа — показує помилки спорідненості топології
  • Системні логи — містять цінну інформацію для налагодження, наприклад, про згенеровані підказки
  • Файл стану kubelet — дамп внутрішнього стану менеджера памʼяті (включно з мапою вузлів і мапами памʼяті)
  • Ви можете використовувати API ресурсів втулка пристрою для отримання інформації про памʼять, зарезервовану для контейнерів

Усунення несправностей TopologyAffinityError

Ця помилка зазвичай виникає в таких ситуаціях:

  • вузол не має достатньо доступних ресурсів, щоб задовольнити запит Podʼа
  • запит Podʼа відхилено через обмеження певної політики менеджера топології

Помилка зʼявляється в статусі 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.

Перевірка API ресурсів втулка пристрою

kubelet надає gRPC-сервіс PodResourceLister, щоб уможливити виявлення ресурсів і повʼязаних з ними метаданих. Через його точку доступу gRPC List можна отримати інформацію про зарезервовану памʼять для кожного контейнера, яка міститься в повідомленні protobuf ContainerMemory.

Цю інформацію можна отримати лише для Podʼів класу QoS Guaranteed.