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

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

Моніторинг, логування та налагодження

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

Іноді речі йдуть не так. Цей посібник призначений для допомоги у виправленні помилок. Він має два розділи:

Вам також слід перевірити відомі проблеми для випуску, який ви використовуєте.

Отримання допомоги

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

Питання

Документація на цьому сайті структурована таким чином, щоб надавати відповіді на широкий спектр питань. Концепції пояснюють архітектуру Kubernetes та роботу кожного компонента, в той час, як Налаштування надає практичні інструкції для початку роботи. Завдання показують, як виконати широке коло завдань, а Посібники — це більш комплексні огляди сценаріїв реального життя, специфічних для галузей або розробки з початку до кінця. Розділ Довідник надає детальну документацію з API Kubernetes та інтерфейсів командного рядка (CLI), таких як kubectl.

Допоможіть! Моє питання не розглянуто! Мені потрібна допомога зараз!

Stack Exchange, Stack Overflow або Server Fault

Якщо у вас є питання, повʼязане з розробкою програмного забезпечення для вашого контейнеризованого застосунку, ви можете задати його на Stack Overflow.

Якщо у вас є питання про Kubernetes, повʼязані з управлінням кластером або конфігурацією, ви можете задати їх на Server Fault.

Також існують кілька більш конкретних сайтів мережі Stack Exchange, які можуть бути відповідним місцем для питань про Kubernetes в таких областях, як DevOps, Software Engineering або InfoSec.

Хтось зі спільноти може вже ставив схоже питання або може допомогти з вашою проблемою.

Команда Kubernetes також слідкуватиме за постами з теґом Kubernetes. Якщо немає наявних питань, які можуть допомогти, будь ласка, переконайтеся, що ваше питання відповідає правилам Stack Overflow, Server Fault або сайту мережі Stack Exchange, на якому ви його ставите, і ознайомтеся з інструкцією як поставити нове питання, перед тим як задавати нове!

Slack

Багато людей зі спільноти Kubernetes збираються у Kubernetes Slack в каналі #kubernetes-users. Slack вимагає реєстрації; ви можете запросити запрошення, і реєстрація відкрита для всіх). Запрошуємо приходити та ставити будь-які питання. Після реєстрації ви отримайте доступ до організації Kubernetes у Slack у вебоглядачі або в застосунку Slack.

Після реєстрації переглядайте список каналів для різних тем. Наприклад, люди, які тільки вчаться Kubernetes, також можуть приєднатися до каналу #kubernetes-novice. Як ще один приклад, розробникам корисно приєднатися до каналу #kubernetes-contributors.

Також існують багато каналів, специфічних для країн / мов. Запрошуємо приєднатися до цих каналів для локалізованої підтримки та інформації:

Країна / канал Slack
КраїнаКанали
Китай#cn-users, #cn-events
Фінляндія#fi-users
Франція#fr-users, #fr-events
Німеччина#de-users, #de-events
Індія#in-users, #in-events
Італія#it-users, #it-events
Японія#jp-users, #jp-events
Корея#kr-users
Нідерланди#nl-users
Норвегія#norw-users
Польща#pl-users
Росія#ru-users
Іспанія#es-users
Швеція#se-users
Туреччина#tr-users, #tr-events

Форум

Вас раді бачити на офіційному форумі Kubernetes: discuss.kubernetes.io.

Помилки та запитання щодо функціонала

Якщо у вас є ознаки помилки або ви хочете подати запит на новий функціонал, будь ласка, скористайтесь тікетами GitHub.

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

Якщо ви подаєте звіт про помилку, будь ласка, включіть детальні відомості про те, як відтворити проблему, таку як:

  • Версія Kubernetes: kubectl version
  • Хмарний провайдер, дистрибутив ОС, конфігурація мережі та версія оточення виконання контейнерів
  • Кроки для відтворення проблеми

1 - Налагодження застосунків

Виправлення загальних проблем з контейнеризованими застосунками.

Цей розділ містить набір ресурсів для виправлення проблем з контейнеризованими застосунками. Він охоплює такі речі, як загальні проблеми з ресурсами Kubernetes (наприклад, Pods, Services або StatefulSets), поради щодо розуміння повідомлень про припинення роботи контейнера та способи налагодження запущених контейнерів.

1.1 - Налагодження Podʼів

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

Діагностика проблеми

Перший крок у розвʼязанні проблем — сортування. Що сталося? Проблема у ваших Podʼах, Контролері Реплікацій чи Service?

Налагодження Podʼів

Перший крок у налагоджені Podʼа — це його перевірка. Перевірте поточний стан Podʼа та останні події за допомогою наступної команди:

kubectl describe pods ${POD_NAME}

Огляньте стан контейнерів у Podʼі. Чи всі вони Running (працюють)? Чи були нещодавні перезапуски?

Продовжуйте налагодження, виходячи зі стану Podʼів.

Мій Pod залишається в стані Pending

Якщо Pod застряг у стані Pending, це означає, що його не можна запланувати на вузол. Зазвичай це відбувається через недостатні ресурси одного типу чи іншого, які заважають плануванню. Подивіться на вивід команди kubectl describe ... вище. Там мають бути повідомлення від планувальника про причини, чому він не може запланувати ваш Pod. Причини включають:

  • У вас недостатньо ресурсів: Можливо, ви вичерпали запас CPU або памʼяті у вашому кластері, у цьому випадку вам потрібно видалити Podʼи, налаштувати запити на ресурси, або додати нові вузли до вашого кластера. Дивіться документ про обчислювальні ресурси для отримання додаткової інформації.

  • Ви використовуєте hostPort: Коли ви привʼязуєте Pod до hostPort, існує обмежена кількість місць, де можна запланувати цей Pod. У більшості випадків, hostPort не є необхідним, спробуйте використати обʼєкт Service для відкриття доступу вашому Podʼу. Якщо вам все ж потрібен hostPort, то ви можете запланувати лише стільки Podʼів, скільки у вас вузлів у кластері Kubernetes.

Мій Pod залишається у стані Waiting

Якщо Pod застряг у стані Waiting, то він був запланований на робочий вузол, але не може працювати на цій машині. Знову ж таки, вивід команди kubectl describe ... має бути інформативним. Найпоширенішою причиною Podʼів у стані Waiting є неможливість завантаження образу. Тут є три речі, які потрібно перевірити:

  • Переконайтеся, що ви правильно вказали імʼя образу.
  • Чи ви завантажили образ у реєстр?
  • Спробуйте вручну завантажити образ, щоб перевірити, чи можна його завантажити. Наприклад, якщо ви використовуєте Docker на вашому ПК, виконайте docker pull <image>.

Мій Pod залишається у стані Terminating

Якщо Pod застряг у стані Terminating (завершення), це означає, що було видано наказ про видалення Podʼа, але планпанель управління не може видалити обʼєкт Pod.

Це зазвичай відбувається, якщо у Podʼа є завершувач та встановлений вубхук допуску у кластері, який перешкоджає панелі управління видалити завершувач.

Щоб виявити цей сценарій, перевірте, чи у вашому кластері є вебхуки ValidatingWebhookConfiguration або MutatingWebhookConfiguration, які спрямовані на операції UPDATE для ресурсів pods.

Якщо вебхук надається стороннім вендором:

  • Переконайтеся, що ви використовуєте останню версію.
  • Вимкніть вебхук для операцій UPDATE.
  • Повідомте про проблему відповідного постачальника.

Якщо ви є автором вебхуку:

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

Мій Pod виходить з ладу або несправний іншим чином

Як тільки ваш Pod був запланований, методи, описані в Налагодження Запущених Подів, доступні для налагодження.

Мій Pod працює, але не робить те, що я йому сказав робити

Якщо ваш Pod не поводиться так, як ви очікували, це може бути повʼязано з помилкою у вашому описі Podʼа (наприклад, файл mypod.yaml на вашому локальному компʼютері), і цю помилку було мовчки проігноровано під час створення Podʼа. Часто розділ опису Podʼа вкладено неправильно, або імʼя ключа набрано неправильно, і тому ключ ігнорується. Наприклад, якщо ви помилилися в написанні command як commnd, тоді Pod буде створено, але не використовуватиме командний рядок, який ви планували.

Перша річ, яку варто зробити, — видалити свій Pod і спробувати створити його знову з опцією --validate. Наприклад, виконайте kubectl apply --validate -f mypod.yaml. Якщо ви помилилися в написанні command як commnd, то отримаєте помилку на кшталт цієї:

I0805 10:43:25.129850   46757 schema.go:126] unknown field: commnd
I0805 10:43:25.129973   46757 schema.go:129] this may be a false alarm, see https://github.com/kubernetes/kubernetes/issues/6842
pods/mypod

Наступне, що варто перевірити, — чи відповідає Pod на апісервері Podʼу, який ви збиралися створити (наприклад, у файлі YAML на вашому локальному компʼютері). Наприклад, виконайте kubectl get pods/mypod -o yaml > mypod-on-apiserver.yaml а потім вручну порівняйте оригінальний опис Podʼа, mypod.yaml, з тим, який ви отримали з апісервера, mypod-on-apiserver.yaml. Зазвичай деякі рядки в версії "апісервера" відсутні в оригінальній версії. Це очікувано. Однак, якщо є рядки в оригінальному описі, яких немає в версії апісервера, то це може свідчити про проблему з вашими специфікаціями Podʼа.

Налагодження Контролерів Реплікацій

Контролери реплікацій досить прості. Вони можуть або створювати Podʼи, або не можуть. Якщо вони не можуть створювати Podʼи, будь ласка, зверніться до інструкцій вище, щоб налагодити ваші Podʼи.

Ви також можете використовувати kubectl describe rc ${CONTROLLER_NAME} для вивчення подій, що стосуються контролера реплікацій.

Налагодження Serviceʼів

Serviceʼи забезпечують балансування навантаження між набором Podʼів. Є кілька загальних проблем, які можуть призвести до неправильної роботи Serviceʼів. Наступні інструкції допоможуть дослідити проблеми з Serviceʼами.

Спочатку перевірте, що для Service є точки доступу. Для кожного обʼєкта Service апісервер робить ресурс endpoints доступним.

Ви можете переглянути цей ресурс за допомогою:

kubectl get endpoints ${SERVICE_NAME}

Переконайтеся, що точки доступу відповідають кількості Podʼів, які ви очікуєте бачити в складі вашого Service. Наприклад, якщо ваш Service для контейнера nginx має 3 репліки, ви очікуєте побачити три різних IP-адреси у точках доступу Serviceʼу.

Мій Service відсутні точки доступу

Якщо вам не вистачає точок доступу, спробуйте передивитись перелік Podʼів за допомогою міток, які використовує Service. Уявіть, що у вас є Service, де є такі мітки:

...
spec:
  - selector:
     name: nginx
     type: frontend

Ви можете використовувати:

kubectl get pods --selector=name=nginx,type=frontend

щоб отримати перелік Podʼів, які відповідають цьому селектору. Перевірте, чи список відповідає Podʼам, які ви очікуєте бачити у вашому Service. Перевірте, чи containerPort Podʼа відповідає targetPort Serviceʼа.

Мережевий трафік не переспрямовується

Будь ласка, див. налагодження Service для отримання додаткової інформації.

Що далі

Якщо жоден із вищезазначених методів не розвʼязує вашу проблему, слідкуйте інструкціям у документі про налагодження Serviceʼу щоб переконатися, що ваш Service працює, має Endpoints, і ваші Podʼи фактично обслуговуються; DNS працює, встановлені правила iptables, і kube-proxy поводиться відповідно.

Ви також можете відвідати документ про налагодження для отримання додаткової інформації.

1.2 - Налагодження Service

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

Виконання команд у Podʼі

Для багатьох кроків ви захочете побачити, що бачить Pod, який працює в кластері. Найпростіший спосіб зробити це — запустити інтерактивний Pod busybox:

kubectl run -it --rm --restart=Never busybox --image=gcr.io/google-containers/busybox sh

Якщо у вас вже є Pod, який ви хочете використовувати для цього, ви можете виконати команду у ньому за допомогою:

kubectl exec <ІМ'Я-ПОДА> -c <ІМ'Я-КОНТЕЙНЕРА> -- <КОМАНДА>

Підготовка

Для цілей цього огляду запустімо кілька Podʼів. Оскільки ви, швидше за все, налагоджуєте власний Service, ви можете використати свої власні дані, або ви можете слідувати разом із нами та отримати інші дані.

kubectl create deployment hostnames --image=registry.k8s.io/serve_hostname
deployment.apps/hostnames created

Команди kubectl будуть виводити тип та імʼя створеного або зміненого ресурсу, які потім можна використовувати в наступних командах.

Масштабуймо Deployment до 3 реплік.

kubectl scale deployment hostnames --replicas=3
deployment.apps/hostnames scaled

Зверніть увагу, що це так само, якби ви запустили Deployment за допомогою наступного YAML:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: hostnames
  name: hostnames
spec:
  selector:
    matchLabels:
      app: hostnames
  replicas: 3
  template:
    metadata:
      labels:
        app: hostnames
    spec:
      containers:
      - name: hostnames
        image: registry.k8s.io/serve_hostname

За допомогою kubectl create deployment в значення мітки "app" автоматично встановлюється імʼя Deployment.

Ви можете підтвердити, що ваші Podʼи працюють:

kubectl get pods -l app=hostnames
NAME                        READY     STATUS    RESTARTS   AGE
hostnames-632524106-bbpiw   1/1       Running   0          2m
hostnames-632524106-ly40y   1/1       Running   0          2m
hostnames-632524106-tlaok   1/1       Running   0          2m

Ви також можете підтвердити, що ваші Podʼи обслуговуються. Ви можете отримати список IP-адрес Podʼів та протестувати їх безпосередньо.

kubectl get pods -l app=hostnames \
    -o go-template='{{range .items}}{{.status.podIP}}{{"\n"}}{{end}}'
10.244.0.5
10.244.0.6
10.244.0.7

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

З середини Podʼа:

for ep in 10.244.0.5:9376 10.244.0.6:9376 10.244.0.7:9376; do
    wget -qO- $ep
done

Ви маєте отримати щось на зразок:

hostnames-632524106-bbpiw
hostnames-632524106-ly40y
hostnames-632524106-tlaok

Якщо ви не отримуєте очікувані відповіді на цьому етапі, ваші Pod\и можуть бути несправними або можуть не прослуховувати порт, який ви вважаєте. Можливо, kubectl logs буде корисним для перегляду того, що відбувається, або, можливо, вам потрібно буде виконати kubectl exec безпосередньо у вашому Podʼі та робити налагодження звідти.

Якщо все пройшло згідно з планом до цього моменту, ви можете почати розслідування того, чому ваш Service не працює.

Чи Service існує?

Уважний читач може зауважити, що ви фактично ще не створили Service — це навмисно. Це крок, який іноді забувають, і це перше, що треба перевірити.

Що станеться, якщо ви спробуєте отримати доступ до Service, що не існує? Якщо у вас є інший Pod, який використовує цей Service за іменем, ви отримаєте щось на зразок:

wget -O- hostnames
Resolving hostnames (hostnames)... failed: Name or service not known.
wget: unable to resolve host address 'hostnames'

Перше, що треба перевірити — це чи насправді існує цей Service:

kubectl get svc hostnames
No resources found.
Error from server (NotFound): services "hostnames" not found

Створімо Service. Як і раніше, це для цього огляду — ви можете використовувати свої власні дані Service тут.

kubectl expose deployment hostnames --port=80 --target-port=9376
service/hostnames exposed

І перевіримо:

kubectl get svc hostnames
NAME        TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
hostnames   ClusterIP   10.0.1.175   <none>        80/TCP    5s

Тепер ви знаєте, що Service існує.

Як і раніше, це те саме, якби ви запустили Service за допомогою YAML:

apiVersion: v1
kind: Service
metadata:
  labels:
    app: hostnames
  name: hostnames
spec:
  selector:
    app: hostnames
  ports:
  - name: default
    protocol: TCP
    port: 80
    targetPort: 9376

Щоб підкреслити повний спектр налаштувань, Service, який ви створили тут, використовує інший номер порту, ніж Podʼи. Для багатьох реальних Serviceʼів ці значення можуть бути однаковими.

Чи впливають будь-які правила Network Policy Ingress на цільові Podʼи?

Якщо ви розгорнули будь-які правила Network Policy Ingress, які можуть вплинути на вхідний трафік до hostnames-* Pod, їх потрібно переглянути.

Будь ласка, зверніться до Мережевих політик для отримання додаткових відомостей.

Чи працює Service за DNS-іменем?

Один із найпоширеніших способів, яким клієнти використовують Service, — це через DNS-імʼя.

З Podʼа в тому ж Namespace:

nslookup hostnames
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local

Name:      hostnames
Address 1: 10.0.1.175 hostnames.default.svc.cluster.local

Якщо це не вдається, можливо, ваш Pod і Service знаходяться в різних Namespace, спробуйте використати імʼя з Namespace (знову ж таки, зсередини Podʼа):

nslookup hostnames.default
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local

Name:      hostnames.default
Address 1: 10.0.1.175 hostnames.default.svc.cluster.local

Якщо це працює, вам потрібно налаштувати свій застосунок на використання імені, яке входить у Namespace, або запустіть ваш застосунок та Service в тому ж Namespace. Якщо це все ще не працює, спробуйте повне імʼя:

nslookup hostnames.default.svc.cluster.local
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local

Name:      hostnames.default.svc.cluster.local
Address 1: 10.0.1.175 hostnames.default.svc.cluster.local

Зверніть увагу на суфікс тут: "default.svc.cluster.local". "default" — це Namespace, в якому ви працюєте. "svc" позначає, що це Service. "cluster.local" — це ваш домен кластера, який МОЖЕ відрізнятися у вашому власному кластері.

Ви також можете спробувати це з вузла в кластері:

nslookup hostnames.default.svc.cluster.local 10.0.0.10
Server:         10.0.0.10
Address:        10.0.0.10#53

Name:   hostnames.default.svc.cluster.local
Address: 10.0.1.175

Якщо ви можете зробити пошук повного імені, але не відноснлшл, вам потрібно перевірити, чи правильний ваш файл /etc/resolv.conf в Podʼі. Зсередини Podʼа:

cat /etc/resolv.conf

Ви повинні побачити щось на зразок:

nameserver 10.0.0.10
search default.svc.cluster.local svc.cluster.local cluster.local example.com
options ndots:5

Рядок nameserver повинен вказувати на Service DNS вашого кластера. Це передається в kubelet з прапорцем --cluster-dns.

Рядок search повинен включати відповідний суфікс, щоб ви змогли знайти імʼя Serviceʼу. У цьому випадку він шукає Serviceʼи в локальному Namespace ("default.svc.cluster.local"), Serviceʼи у всіх Namespace ("svc.cluster.local"), і наостанок для імен в кластері ("cluster.local"). Залежно від вашого власного налаштування, у вас можуть бути додаткові записи після цього (до 6 загалом). Суфікс кластера передається в kubelet з прапорцем --cluster-domain. У цьому документі передбачається, що суфікс кластера — "cluster.local". У ваших власних кластерах це може бути налаштовано по-іншому, у такому випадку вам слід змінити це в усіх попередніх командах.

Чи працює будь-який Service за допомогою DNS-імені?

Якщо вищезазначене все ще не працює, DNS-запити не працюють для вашого Service. Ви можете зробити крок назад і побачити, що ще не працює. Service майстра Kubernetes повинен завжди працювати. Зсередини Podʼа:

nslookup kubernetes.default
Server:    10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local

Name:      kubernetes.default
Address 1: 10.0.0.1 kubernetes.default.svc.cluster.local

Якщо це не вдається, будь ласка, перегляньте розділ kube-proxy цього документа, або навіть поверніться до початку цього документа і почніть знову, але замість налагодження вашого власного Service, спробуйте Service DNS.

Чи працює Service за IP?

Припускаючи, що ви підтвердили, що DNS працює, наступне, що варто перевірити, — це чи ваш Service працює за його IP-адресою. З Podʼа в вашому кластері, зверніться до IP-адреси Service (з вищезазначеного виводу kubectl get).

for i in $(seq 1 3); do 
    wget -qO- 10.0.1.175:80
done

Це має видати щось подібне:

hostnames-632524106-bbpiw
hostnames-632524106-ly40y
hostnames-632524106-tlaok

Якщо ваш Service працює, ви повинні отримати правильні відповіді. Якщо ні, існує кілька можливих причин, через які це може не працювати. Дивіться далі.

Чи правильно визначений Service?

Це може звучати дивно, але ви справді повинні подеколи перевірити, що ваш Service вірний і відповідає порту вашого Podʼа. Перегляньте свій Service і перевірте його:

kubectl get service hostnames -o json
{
    "kind": "Service",
    "apiVersion": "v1",
    "metadata": {
        "name": "hostnames",
        "namespace": "default",
        "uid": "428c8b6c-24bc-11e5-936d-42010af0a9bc",
        "resourceVersion": "347189",
        "creationTimestamp": "2015-07-07T15:24:29Z",
        "labels": {
            "app": "hostnames"
        }
    },
    "spec": {
        "ports": [
            {
                "name": "default",
                "protocol": "TCP",
                "port": 80,
                "targetPort": 9376,
                "nodePort": 0
            }
        ],
        "selector": {
            "app": "hostnames"
        },
        "clusterIP": "10.0.1.175",
        "type": "ClusterIP",
        "sessionAffinity": "None"
    },
    "status": {
        "loadBalancer": {}
    }
}
  • Чи вказано порт Serviceʼу, який ви намагаєтеся отримати доступ в spec.ports[]?
  • Чи правильний targetPort для ваших Podʼів (деякі Podʼи використовують інший порт, ніж Service)?
  • Якщо ви мали на увазі використання числового порту, це число (9376) чи рядок "9376"?
  • Якщо ви мали на увазі використання порту за іменем, чи ваші Podʼи використовують порт з тим самим імʼям?
  • Чи правильний протокол порту для ваших Podʼів?

Чи має Service будь-які Endpoints?

Якщо ви дійшли до цього пункту, ви підтвердили, що ваш Service правильно визначений і його можна знайти через DNS. Тепер перевірмо, що Podʼи, які ви запустили, фактично вибираються Serviceʼом.

Раніше ви бачили, що Podʼи працюють. Ви можете перевірити це ще раз:

kubectl get pods -l app=hostnames
NAME                        READY     STATUS    RESTARTS   AGE
hostnames-632524106-bbpiw   1/1       Running   0          1h
hostnames-632524106-ly40y   1/1       Running   0          1h
hostnames-632524106-tlaok   1/1       Running   0          1h

Аргумент -l app=hostnames — це селектор міток, налаштований у Service.

Стовпець "AGE" вказує, що ці Podʼи працюють добре і не мали збоїв.

Стовпець "RESTARTS" вказує, що ці Podʼи не часто мають збої або не перезавантажуються. Часті перезапуски можуть призвести до періодичних проблем зі зʼєднанням. Якщо кількість перезапусків висока, прочитайте більше про те, як налагоджувати Podʼи.

У межах системи Kubernetes є цикл керування, який оцінює селектор кожного Service і зберігає результати відповідно до обʼєкта Endpoints.

kubectl get endpoints hostnames

NAME        ENDPOINTS
hostnames   10.244.0.5:9376,10.244.0.6:9376,10.244.0.7:9376

Це підтверджує, що контролер Endpoints знайшов правильні Podʼи для вашого Service. Якщо стовпець ENDPOINTS має значення <none>, вам слід перевірити, що поле spec.selector вашого Service дійсно вибирає значення metadata.labels у ваших Podʼах. Частою помилкою є наявність хибодруку або іншої помилки, наприклад, Service вибирає app=hostnames, але Deployment вказує run=hostnames, як у версіях до 1.18, де команда kubectl run також могла бути використана для створення Deployment.

Чи працюють Podʼи?

На цьому етапі ви знаєте, що ваш Service існує і вибрав ваші Podʼи. На початку цього кроку ви перевірили самі Podʼи. Давайте ще раз перевіримо, що Podʼи дійсно працюють — ви можете оминути механізм Service і звернутися безпосередньо до Podʼів, які вказані в Endpoints вище.

З середини Podʼа:

for ep in 10.244.0.5:9376 10.244.0.6:9376 10.244.0.7:9376; do
    wget -qO- $ep
done

Це повинно показати щось на зразок:

hostnames-632524106-bbpiw
hostnames-632524106-ly40y
hostnames-632524106-tlaok

Ви очікуєте, що кожний Pod в списку Endpoints поверне свій власний hostname. Якщо це не те, що відбувається (або будь-яка інша правильна поведінка для ваших власних Podʼів), вам слід дослідити, що відбувається там.

Чи працює kube-proxy?

Якщо ви дісталися до цього моменту, ваш Service працює, має Endpoints, і ваші Podʼи фактично обслуговують запити. На цьому етапі увесь механізм проксі Service під підозрою. Підтвердьмо це крок за кроком.

Стандартна реалізація Service, і та, яка використовується в більшості кластерів, — це kube-proxy. Це програма, яка працює на кожному вузлі і конфігурує один з невеликого набору механізмів для надання абстракції Service. Якщо ваш кластер не використовує kube-proxy, наступні розділи не застосовуються, і вам доведеться дослідити будь-яку реалізацію Service, яку ви використовуєте.

Чи запущено kube-proxy?

Підтвердіть, що kube-proxy працює на ваших Вузлах. Запустіть команду безпосередньо на Вузлі, і ви повинні побачити щось на зразок такого:

ps auxw | grep kube-proxy
root  4194  0.4  0.1 101864 17696 ?    Sl Jul04  25:43 /usr/local/bin/kube-proxy --master=https://kubernetes-master --kubeconfig=/var/lib/kube-proxy/kubeconfig --v=2

Далі переконайтесь, що він не має явних проблем, таких як неможливість звʼязатися з майстром. Для цього вам доведеться переглянути логи. Доступ до логів залежить від вашої ОС Вузла. На деяких ОС це файл, наприклад /var/log/kube-proxy.log, тоді як на інших ОС використовується journalctl для доступу до логів. Ви повинні побачити щось на зразок:

I1027 22:14:53.995134    5063 server.go:200] Running in resource-only container "/kube-proxy"
I1027 22:14:53.998163    5063 server.go:247] Using iptables Proxier.
I1027 22:14:54.038140    5063 proxier.go:352] Setting endpoints for "kube-system/kube-dns:dns-tcp" to [10.244.1.3:53]
I1027 22:14:54.038164    5063 proxier.go:352] Setting endpoints for "kube-system/kube-dns:dns" to [10.244.1.3:53]
I1027 22:14:54.038209    5063 proxier.go:352] Setting endpoints for "default/kubernetes:https" to [10.240.0.2:443]
I1027 22:14:54.038238    5063 proxier.go:429] Not syncing iptables until Services and Endpoints have been received from master
I1027 22:14:54.040048    5063 proxier.go:294] Adding new service "default/kubernetes:https" at 10.0.0.1:443/TCP
I1027 22:14:54.040154    5063 proxier.go:294] Adding new service "kube-system/kube-dns:dns" at 10.0.0.10:53/UDP
I1027 22:14:54.040223    5063 proxier.go:294] Adding new service "kube-system/kube-dns:dns-tcp" at 10.0.0.10:53/TCP

Якщо ви бачите повідомлення про помилки щодо неможливості звʼязатися з майстром, вам слід перевірити конфігурацію і кроки інсталяції вашого Вузла.

Одна з можливих причин невдачі коректної роботи kube-proxy — неможливість знайти необхідний бінарний файл conntrack. Це може статися на деяких Linux-системах, залежно від того, як ви встановлюєте кластер, наприклад, якщо ви встановлюєте Kubernetes з нуля. У цьому випадку вам потрібно вручну встановити пакунок conntrack (наприклад, sudo apt install conntrack на Ubuntu), а потім спробувати ще раз.

Kube-proxy може працювати в одному з декількох режимів. У вищенаведеному журналі рядок Using iptables Proxier вказує на те, що kube-proxy працює в режимі "iptables". Ще один поширений режим — "ipvs".

Режим iptables

У режимі "iptables" ви повинні побачити щось на зразок наступного на Вузлі:

iptables-save | grep hostnames
-A KUBE-SEP-57KPRZ3JQVENLNBR -s 10.244.3.6/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-57KPRZ3JQVENLNBR -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.3.6:9376
-A KUBE-SEP-WNBA2IHDGP2BOBGZ -s 10.244.1.7/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-WNBA2IHDGP2BOBGZ -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.1.7:9376
-A KUBE-SEP-X3P2623AGDH6CDF3 -s 10.244.2.3/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-X3P2623AGDH6CDF3 -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.2.3:9376
-A KUBE-SERVICES -d 10.0.1.175/32 -p tcp -m comment --comment "default/hostnames: cluster IP" -m tcp --dport 80 -j KUBE-SVC-NWV5X2332I4OT4T3
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.33332999982 -j KUBE-SEP-WNBA2IHDGP2BOBGZ
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-X3P2623AGDH6CDF3
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -j KUBE-SEP-57KPRZ3JQVENLNBR

Для кожного порту кожного Service повинно бути 1 правило у KUBE-SERVICES і один ланцюжок KUBE-SVC-<хеш>. Для кожного endpoint Podʼа повинна бути невелика кількість правил у цьому KUBE-SVC-<хеш> і один ланцюжок KUBE-SEP-<хеш> з невеликою кількістю правил. Точні правила будуть варіюватися залежно від вашої конфігурації (включаючи порти вузлів та балансувальники навантаження).

Режим IPVS

У режимі "ipvs" ви повинні побачити щось на зразок наступного на Вузлі:

ipvsadm -ln
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
...
TCP  10.0.1.175:80 rr
  -> 10.244.0.5:9376               Masq    1      0          0
  -> 10.244.0.6:9376               Masq    1      0          0
  -> 10.244.0.7:9376               Masq    1      0          0
...

Для кожного порту кожного Service, плюс будь-які NodePorts, зовнішні IP-адреси та IP-адреси балансувальника навантаження, kube-proxy створить віртуальний сервер. Для кожного endpoint Podʼа він створить відповідні реальні сервери. У цьому прикладі служба hostnames(10.0.1.175:80) має 3 endpoint (10.244.0.5:9376, 10.244.0.6:9376, 10.244.0.7:9376).

Чи kube-proxy керує трафіком?

Якщо ви бачите один із вищезазначених випадків, спробуйте ще раз отримати доступ до вашого Service за допомогою IP з одного з ваших Вузлів:

curl 10.0.1.175:80
hostnames-632524106-bbpiw

Якщо це все ще не вдається, перегляньте логи kube-proxy на наявність конкретних рядків, подібних до:

Setting endpoints for default/hostnames:default to [10.244.0.5:9376 10.244.0.6:9376 10.244.0.7:9376]

Якщо ви не бачите цього, спробуйте перезапустити kube-proxy з прапорцем -v, встановленим на 4, і потім знову перегляньте логи.

Крайній випадок: Pod не може звернутися до себе за допомогою IP-адреси Service

Це може здатися малоймовірним, але це може трапитися і має працювати.

Це може статися, коли мережа не належним чином налаштована для "зачісування" трафіку, зазвичай коли kube-proxy працює в режимі iptables, а Podʼи підключені за допомогою мережі bridge. Kubelet надає прапорець hairpin-mode, який дозволяє точкам доступу Service балансувати навантаження поверненням до себе, якщо вони намагаються отримати доступ до своєї власної VIP-адреси Service. Прапорець hairpin-mode має бути встановлено на значення hairpin-veth або promiscuous-bridge.

Загальні кроки для розвʼязання цього випадку мають бути такими:

  • Підтвердіть, що hairpin-mode встановлено у значення hairpin-veth або promiscuous-bridge. Можливий вигляд нижченаведеного. У наступному прикладі hairpin-mode встановлено на promiscuous-bridge.
ps auxw | grep kubelet
root      3392  1.1  0.8 186804 65208 ?        Sl   00:51  11:11 /usr/local/bin/kubelet --enable-debugging-handlers=true --config=/etc/kubernetes/manifests --allow-privileged=True --v=4 --cluster-dns=10.0.0.10 --cluster-domain=cluster.local --configure-cbr0=true --cgroup-root=/ --system-cgroups=/system --hairpin-mode=promiscuous-bridge --runtime-cgroups=/docker-daemon --kubelet-cgroups=/kubelet --babysit-daemons=true --max-pods=110 --serialize-image-pulls=false --outofdisk-transition-frequency=0
  • Підтвердіть поточний hairpin-mode. Для цього вам потрібно переглянути логи kubelet. Доступ до логів залежить від вашої операційної системи. На деяких ОС це файл, наприклад /var/log/kubelet.log, тоді як на інших ОС використовується journalctl для доступу до логів. Зверніть увагу, що поточний режим hairpin може не відповідати прапорцю --hairpin-mode через сумісність. Перевірте, чи є будь-які рядки в лозі з ключовим словом hairpin в kubelet.log. Повинні бути рядки в лозі, які показують поточний режим hairpin, схожі на наступне:
I0629 00:51:43.648698    3252 kubelet.go:380] Hairpin mode set to "promiscuous-bridge"
  • Якщо поточний режим hairpin — hairpin-veth, переконайтеся, що Kubelet має дозвіл на роботу в /sys на вузлі. Якщо все працює належним чином, ви побачите щось на зразок:
for intf in /sys/devices/virtual/net/cbr0/brif/*; do cat $intf/hairpin_mode; done
1
1
1
1
  • Якщо поточний режим hairpin — promiscuous-bridge, переконайтеся, що Kubelet має дозвіл на маніпулювання bridge в Linux на вузлі. Якщо bridge cbr0 використовується і налаштований належним чином, ви побачите:
ifconfig cbr0 |grep PROMISC
UP BROADCAST RUNNING PROMISC MULTICAST  MTU:1460  Metric:1
  • Зверніться за допомогою, якщо жоден з вищезазначених методів не працює.

Пошук допомоги

Якщо ви дійшли до цього моменту, відбувається щось дуже дивне. Ваш Service працює, має точки доступу, і ваші Podʼи насправді обслуговують запити. DNS працює, і kube-proxy схоже не діє неправильно. Проте ваш Service не працює. Будь ласка, дайте нам знати, що відбувається, щоб ми могли допомогти вам розслідувати цю проблему!

Звертайтеся до нас у Slack або на Форум чи у GitHub.

Що далі

Відвідайте документ про загальні відомості про усунення несправностей для отримання додаткової інформації.

1.3 - Налагодження StatefulSet

Ця задача показує, як усувати несправності у StatefulSet.

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

  • Вам потрібен кластер Kubernetes, та інструмент командного рядка kubectl повинен бути налаштований на звʼязок з вашим кластером.
  • Ви повинні мати запущений StatefulSet, який ви хочете дослідити.

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

Для того, щоб переглянути всі Podʼи, які належать до StatefulSet і мають мітку app.kubernetes.io/name=MyApp на них, ви можете використовувати наступне:

kubectl get pods -l app.kubernetes.io/name=MyApp

Якщо ви помітили, що будь-які Podʼи вказані у стані Unknown або Terminating протягом тривалого періоду часу, зверніться до завдання Видалення Podʼів StatefulSet за інструкціями щодо дії з ними. Ви можете усувати несправності окремих Podʼів у StatefulSet, використовуючи Посібник з усунення несправностей Podʼів.

Що далі

Дізнайтеся більше про усунення несправностей контейнера ініціалізації.

1.4 - Визначення причини збою Podʼа

Ця сторінка показує, як записувати та читати повідомлення про припинення роботи контейнера.

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

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

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

Запис та читання повідомлення про припинення роботи

У цьому завданні ви створюєте Pod, який запускає один контейнер. У маніфесті для цього Podʼа вказано команду, яка виконується при запуску контейнера:

apiVersion: v1
kind: Pod
metadata:
  name: termination-demo
spec:
  containers:
  - name: termination-demo-container
    image: debian
    command: ["/bin/sh"]
    args: ["-c", "sleep 10 && echo Sleep expired > /dev/termination-log"]
  1. Створіть Pod на основі конфігураційного файлу YAML:

    kubectl apply -f https://k8s.io/examples/debug/termination.yaml
    

    У файлі YAML у полях command та args ви можете побачити, що контейнер перебуває в стані очікування (спить) протягом 10 секунд, а потім записує "Sleep expired" у файл /dev/termination-log. Після того, як контейнер записує повідомлення "Sleep expired", він завершує роботу.

  2. Покажіть інформацію про Pod:

    kubectl get pod termination-demo
    

    Повторіть попередню команду, доки Pod більше не буде запущений.

  3. Покажіть детальну інформацію про Pod:

    kubectl get pod termination-demo --output=yaml
    

    Вивід містить повідомлення "Sleep expired":

    apiVersion: v1
    kind: Pod
    ...
        lastState:
          terminated:
            containerID: ...
            exitCode: 0
            finishedAt: ...
            message: |
              Sleep expired          
            ...
    
  4. Використовуйте шаблон Go для фільтрування виводу так, щоб він містив лише повідомлення про припинення роботи контейнера:

    kubectl get pod termination-demo -o go-template="{{range .status.containerStatuses}}{{.lastState.terminated.message}}{{end}}"
    

Якщо у вас працює багатоконтейнерний Pod, ви можете використовувати шаблон Go, щоб включити імʼя контейнера. Таким чином, ви можете визначити, який з контейнерів несправний:

kubectl get pod multi-container-pod -o go-template='{{range .status.containerStatuses}}{{printf "%s:\n%s\n\n" .name .lastState.terminated.message}}{{end}}'

Налаштування повідомлення про припинення роботи

Kubernetes отримує повідомлення про припинення роботи з файлу повідомлення, вказаного в полі terminationMessagePath контейнера, яке має стандартне значення /dev/termination-log. Налаштувавши це поле, ви можете сказати Kubernetes використовувати інший файл. Kubernetes використовує вміст зазначеного файлу для заповнення повідомлення про стан контейнера як у випадку успіху, так і невдачі.

Повідомлення про припинення має бути коротким остаточним статусом, таким як повідомлення про помилку твердження. Kubelet обрізає повідомлення, які довше 4096 байтів.

Загальна довжина повідомлення по всіх контейнерах обмежена 12KiB і рівномірно розподілена між всіма контейнерами. Наприклад, якщо є 12 контейнерів (initContainers або containers), кожен має 1024 байти доступного простору для повідомлень про припинення роботи.

Стандартний шлях для повідомлення про припинення роботи — /dev/termination-log. Ви не можете встановити шлях повідомлення про припинення роботи після запуску Podʼа.

У наступному прикладі контейнер записує повідомлення про завершення в /tmp/my-log для отримання Kubernetes:

apiVersion: v1
kind: Pod
metadata:
  name: msg-path-demo
spec:
  containers:
  - name: msg-path-demo-container
    image: debian
    terminationMessagePath: "/tmp/my-log"

Крім того, користувачі можуть налаштувати поле terminationMessagePolicy контейнера для подальшої настройки. Типово це поле встановлене на "File", що означає, що повідомлення про припинення роботи отримуються лише з файлу повідомлення про припинення роботи. Встановивши terminationMessagePolicy на "FallbackToLogsOnError", ви можете вказати Kubernetes використовувати останній фрагмент виводу контейнера, якщо файл повідомлення про припинення роботи порожній, і контейнер завершився з помилкою. Вивід логу обмежується 2048 байтами або 80 рядками, якщо вибірка менша.

Що далі

1.5 - Налагодження контейнерів ініціалізації

Ця сторінка показує, як розвʼязувати проблеми, повʼязані з запуском контейнерів ініціалізації. Приклади команд нижче вказують на Pod як <pod-name> та на контейнери ініціалізації як <init-container-1> та <init-container-2>.

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

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

Для перевірки версії введіть kubectl version.

Перевірка стану контейнерів ініціалізації

Показ статусу вашого Podʼа:

kubectl get pod <pod-name>

Наприклад, статус Init:1/2 вказує на те, що один з двох контейнерів ініціалізації успішно завершено:

NAME         READY     STATUS     RESTARTS   AGE
<pod-name>   0/1       Init:1/2   0          7s

Дивіться Розуміння статусів Podʼа для отримання прикладів значень статусу та їх значень.

Отримання деталей про контейнери ініціалізації

Показ більш детальної інформації про виконання контейнерів ініціалізації:

kubectl describe pod <pod-name>

Наприклад, Pod з двома контейнерами ініціалізації може показати наступне:

Init Containers:
  <init-container-1>:
    Container ID:    ...
    ...
    State:           Terminated
      Reason:        Completed
      Exit Code:     0
      Started:       ...
      Finished:      ...
    Ready:           True
    Restart Count:   0
    ...
  <init-container-2>:
    Container ID:    ...
    ...
    State:           Waiting
      Reason:        CrashLoopBackOff
    Last State:      Terminated
      Reason:        Error
      Exit Code:     1
      Started:       ...
      Finished:      ...
    Ready:           False
    Restart Count:   3
    ...

Ви також можете отримувати доступ до статусів контейнерів ініціалізації програмно, читаючи поле status.initContainerStatuses у Pod Spec:

kubectl get pod nginx --template '{{.status.initContainerStatuses}}'

Ця команда поверне ту саму інформацію, що і вище у форматі JSON.

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

Вкажіть імʼя контейнера ініціалізації разом з імʼям Podʼа, щоб отримати його логи.

kubectl logs <pod-name> -c <init-container-2>

Контейнери ініціалізації, що виконують скрипт оболонки, друкують команди в міру їх виконання. Наприклад, це можна зробити в Bash, запустивши set -x на початку скрипта.

Розуміння статусів Podʼа

Статус Podʼа, що починається з Init:, узагальнює стан виконання контейнерів ініціалізації. У таблиці нижче наведено деякі приклади значень статусу, які ви можете бачити під час налагодження контейнерів ініціалізації.

СтатусЗначення
Init:N/MPod має M контейнерів ініціалізації, і N вже завершено.
Init:ErrorКонтейнер ініціалізації не вдалося виконати.
Init:CrashLoopBackOffКонтейнер ініціалізації неперервно виходить з ладу.
PendingPod ще не розпочав виконувати контейнер ініціалізації.
PodInitializing або RunningPod вже завершив виконання контейнерів ініціалізації.

1.6 - Налагодження запущених Podʼів

Ця сторінка пояснює, як налагоджувати Podʼи, що запущені (або зазнають збою) на вузлі.

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

  • Ваш Pod вже повинен бути запланований та запущений. Якщо ваш Pod ще не запущений, почніть з Налагодження Podʼів.
  • Для деяких з розширених кроків налагодження вам потрібно знати, на якому вузлі запущений Pod, і мати доступ до оболонки для виконання команд на цьому вузлі. Вам не потрібен такий доступ для виконання стандартних кроків налагодження, що використовують kubectl.

Використання kubectl describe pod для отримання деталей про Podʼи

Для цього прикладу ми використовуватимемо Deployment для створення двох Podʼів, схожих на попередній приклад.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        resources:
          limits:
            memory: "128Mi"
            cpu: "500m"
        ports:
        - containerPort: 80

Створіть Deployment, запустивши наступну команду:

kubectl apply -f https://k8s.io/examples/application/nginx-with-request.yaml
deployment.apps/nginx-deployment created

Перевірте статус Podʼа за допомогою наступної команди:

kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-67d4bdd6f5-cx2nz   1/1     Running   0          13s
nginx-deployment-67d4bdd6f5-w6kd7   1/1     Running   0          13s

Ми можемо отримати більше інформації про кожен з цих Podʼів, використовуючи kubectl describe pod. Наприклад:

kubectl describe pod nginx-deployment-67d4bdd6f5-w6kd7
Name:         nginx-deployment-67d4bdd6f5-w6kd7
Namespace:    default
Priority:     0
Node:         kube-worker-1/192.168.0.113
Start Time:   Thu, 17 Feb 2022 16:51:01 -0500
Labels:       app=nginx
              pod-template-hash=67d4bdd6f5
Annotations:  <none>
Status:       Running
IP:           10.88.0.3
IPs:
  IP:           10.88.0.3
  IP:           2001:db8::1
Controlled By:  ReplicaSet/nginx-deployment-67d4bdd6f5
Containers:
  nginx:
    Container ID:   containerd://5403af59a2b46ee5a23fb0ae4b1e077f7ca5c5fb7af16e1ab21c00e0e616462a
    Image:          nginx
    Image ID:       docker.io/library/nginx@sha256:2834dc507516af02784808c5f48b7cbe38b8ed5d0f4837f16e78d00deb7e7767
    Port:           80/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 17 Feb 2022 16:51:05 -0500
    Ready:          True
    Restart Count:  0
    Limits:
      cpu:     500m
      memory:  128Mi
    Requests:
      cpu:        500m
      memory:     128Mi
    Environment:  <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-bgsgp (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  kube-api-access-bgsgp:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   Guaranteed
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  34s   default-scheduler  Successfully assigned default/nginx-deployment-67d4bdd6f5-w6kd7 to kube-worker-1
  Normal  Pulling    31s   kubelet            Pulling image "nginx"
  Normal  Pulled     30s   kubelet            Successfully pulled image "nginx" in 1.146417389s
  Normal  Created    30s   kubelet            Created container nginx
  Normal  Started    30s   kubelet            Started container nginx

Тут ви можете побачити інформацію про конфігурацію контейнерів та Podʼа (мітки, вимоги до ресурсів і т. д.), а також інформацію про статус контейнерів та Podʼа (стан, готовність, кількість перезапусків, події й т.д.).

Стан контейнера може бути Waiting (очікування), Running (виконання) або Terminated (завершено). Залежно від стану, буде надано додаткову інформацію — наприклад, ви можете побачити, коли контейнер був запущений, якщо він перебуває в стані Running.

Ready показує, чи пройшов контейнер останню пробу готовності. (У цьому випадку контейнер не має налаштованої проби готовності; вважається, що контейнер готовий, якщо проба готовності не налаштована.)

Restart Count показує, скільки разів контейнер був перезапущений; ця інформація може бути корисною для виявлення циклів аварійного перезапуску в контейнерах, які налаштовані на перезапуск завжди ('always').

Наразі єдина умова, повʼязана з Podʼом, — це бінарна умова Ready, яка вказує, що Pod може обслуговувати запити та повинен бути доданий до пулів балансування навантаження всіх відповідних Serviceʼів.

Нарешті, ви бачите логи недавніх подій, що стосуються вашого Podʼа. "From" вказує на компонент, який реєструє подію. "Reason" та "Message" розповідають вам, що сталося.

Приклад: налагодження Podʼів у стані Pending

Одна з поширених ситуацій, яку ви можете виявити за допомогою подій, — це коли ви створили Pod, який не може бути розміщений на жодному вузлі. Наприклад, Pod може вимагати більше ресурсів, ніж вільно на будь-якому вузлі, або він може вказати селектор міток, який не відповідає жодному вузлу. Скажімо, ми створили Deployment з 5 репліками (замість 2) і вимагаємо 600 міліядер замість 500, на чотирьох вузловому кластері, де кожна (віртуальна) машина має 1 ЦП. У цьому випадку один з Podʼів не зможе бути запланованим. (Зауважте, що через надбудови кластера, такі як fluentd, skydns тощо, які працюють на кожному вузлі, якби ми запросили 1000 міліядер, то жоден з Podʼів не міг би бути запланованим.)

kubectl get pods
NAME                                READY     STATUS    RESTARTS   AGE
nginx-deployment-1006230814-6winp   1/1       Running   0          7m
nginx-deployment-1006230814-fmgu3   1/1       Running   0          7m
nginx-deployment-1370807587-6ekbw   1/1       Running   0          1m
nginx-deployment-1370807587-fg172   0/1       Pending   0          1m
nginx-deployment-1370807587-fz9sd   0/1       Pending   0          1m

Щоб дізнатися, чому Pod nginx-deployment-1370807587-fz9sd не працює, ми можемо використовувати kubectl describe pod у Podʼі у стані Pending та переглянути його події:

kubectl describe pod nginx-deployment-1370807587-fz9sd
  Name:		nginx-deployment-1370807587-fz9sd
  Namespace:	default
  Node:		/
  Labels:		app=nginx,pod-template-hash=1370807587
  Status:		Pending
  IP:
  Controllers:	ReplicaSet/nginx-deployment-1370807587
  Containers:
    nginx:
      Image:	nginx
      Port:	80/TCP
      QoS Tier:
        memory:	Guaranteed
        cpu:	Guaranteed
      Limits:
        cpu:	1
        memory:	128Mi
      Requests:
        cpu:	1
        memory:	128Mi
      Environment Variables:
  Volumes:
    default-token-4bcbi:
      Type:	Secret (a volume populated by a Secret)
      SecretName:	default-token-4bcbi
  Events:
    FirstSeen	LastSeen	Count	From			        SubobjectPath	Type		Reason			    Message
    ---------	--------	-----	----			        -------------	--------	------			    -------
    1m		    48s		    7	    {default-scheduler }			        Warning		FailedScheduling	pod (nginx-deployment-1370807587-fz9sd) failed to fit in any node
  fit failure on node (kubernetes-node-6ta5): Node didn't have enough resource: CPU, requested: 1000, used: 1420, capacity: 2000
  fit failure on node (kubernetes-node-wul5): Node didn't have enough resource: CPU, requested: 1000, used: 1100, capacity: 2000

Тут ви можете побачити подію, створену планувальником, яка говорить, що Pod не вдалося запланувати з причиною FailedScheduling (і, можливо, інші). Повідомлення говорить нам, що на будь-якому з вузлів не було достатньо ресурсів для Podʼа.

Для виправлення цієї ситуації ви можете використовувати kubectl scale, щоб оновити ваш Deployment та вказати чотири або менше реплік. (Або ви можете залишити один Pod у стані Pending, що нешкідливо.)

Події, такі як ті, які ви бачили в кінці kubectl describe pod, зберігаються в etcd та надають високорівневу інформацію про те, що відбувається в кластері. Щоб переглянути всі події, ви можете використовувати

kubectl get events

але вам потрібно памʼятати, що події належать до простору імен. Це означає, що якщо вас цікавлять події для обʼєкта з простором імен (наприклад, що сталося з Podʼами в просторі імен my-namespace), вам потрібно явно вказати простір імен для команди:

kubectl get events --namespace=my-namespace

Щоб побачити події з усіх просторів імен, ви можете використовувати аргумент --all-namespaces.

Крім команди kubectl describe pod, інший спосіб отримати додаткову інформацію про Pod (поза тим, що надає kubectl get pod) — це передати прапорець формату виводу -o yaml команді kubectl get pod. Це надасть вам, у форматі YAML, ще більше інформації, ніж kubectl describe pod — фактично всю інформацію, яку система має про Pod. Тут ви побачите такі речі, як анотації (це метадані ключ-значення без обмежень міток, які використовуються внутрішньо компонентами системи Kubernetes), політику перезапуску, порти та томи.

kubectl get pod nginx-deployment-1006230814-6winp -o yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: "2022-02-17T21:51:01Z"
  generateName: nginx-deployment-67d4bdd6f5-
  labels:
    app: nginx
    pod-template-hash: 67d4bdd6f5
  name: nginx-deployment-67d4bdd6f5-w6kd7
  namespace: default
  ownerReferences:
  - apiVersion: apps/v1
    blockOwnerDeletion: true
    controller: true
    kind: ReplicaSet
    name: nginx-deployment-67d4bdd6f5
    uid: 7d41dfd4-84c0-4be4-88ab-cedbe626ad82
  resourceVersion: "1364"
  uid: a6501da1-0447-4262-98eb-c03d4002222e
spec:
  containers:
  - image: nginx
    imagePullPolicy: Always
    name: nginx
    ports:
    - containerPort: 80
      protocol: TCP
    resources:
      limits:
        cpu: 500m
        memory: 128Mi
      requests:
        cpu: 500m
        memory: 128Mi
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: kube-api-access-bgsgp
      readOnly: true
  dnsPolicy: ClusterFirst
  enableServiceLinks: true
  nodeName: kube-worker-1
  preemptionPolicy: PreemptLowerPriority
  priority: 0
  restartPolicy: Always
  schedulerName: default-scheduler
  securityContext: {}
  serviceAccount: default
  serviceAccountName: default
  terminationGracePeriodSeconds: 30
  tolerations:
  - effect: NoExecute
    key: node.kubernetes.io/not-ready
    operator: Exists
    tolerationSeconds: 300
  - effect: NoExecute
    key: node.kubernetes.io/unreachable
    operator: Exists
    tolerationSeconds: 300
  volumes:
  - name: kube-api-access-bgsgp
    projected:
      defaultMode: 420
      sources:
      - serviceAccountToken:
          expirationSeconds: 3607
          path: token
      - configMap:
          items:
          - key: ca.crt
            path: ca.crt
          name: kube-root-ca.crt
      - downwardAPI:
          items:
          - fieldRef:
              apiVersion: v1
              fieldPath: metadata.namespace
            path: namespace
status:
  conditions:
  - lastProbeTime: null
    lastTransitionTime: "2022-02-17T21:51:01Z"
    status: "True"
    type: Initialized
  - lastProbeTime: null
    lastTransitionTime: "2022-02-17T21:51:06Z"
    status: "True"
    type: Ready
  - lastProbeTime: null
    lastTransitionTime: "2022-02-17T21:51:06Z"
    status: "True"
    type: ContainersReady
  - lastProbeTime: null
    lastTransitionTime: "2022-02-17T21:51:01Z"
    status: "True"
    type: PodScheduled
  containerStatuses:
  - containerID: containerd://5403af59a2b46ee5a23fb0ae4b1e077f7ca5c5fb7af16e1ab21c00e0e616462a
    image: docker.io/library/nginx:latest
    imageID: docker.io/library/nginx@sha256:2834dc507516af02784808c5f48b7cbe38b8ed5d0f4837f16e78d00deb7e7767
    lastState: {}
    name: nginx
    ready: true
    restartCount: 0
    started: true
    state:
      running:
        startedAt: "2022-02-17T21:51:05Z"
  hostIP: 192.168.0.113
  phase: Running
  podIP: 10.88.0.3
  podIPs:
  - ip: 10.88.0.3
  - ip: 2001:db8::1
  qosClass: Guaranteed
  startTime: "2022-02-17T21:51:01Z"

Перегляд логі Podʼа

Спочатку перегляньте журнали ураженого контейнера:

kubectl logs ${POD_NAME} ${CONTAINER_NAME}

Якщо ваш контейнер раніше впав, ви можете отримати доступ до попереднього логу аварії контейнера за допомогою:

kubectl logs --previous ${POD_NAME} ${CONTAINER_NAME}

Налагодження за допомогою виконання команд у контейнері

Якщо образ контейнера містить утиліти для налагодження, як це трапляється в образах, побудованих на основі базових образів операційних систем Linux і Windows, ви можете виконати команди всередині конкретного контейнера за допомогою kubectl exec:

kubectl exec ${POD_NAME} -c ${CONTAINER_NAME} -- ${CMD} ${ARG1} ${ARG2} ... ${ARGN}

Наприклад, щоб переглянути логи з робочого Podʼа Cassandra, ви можете виконати

kubectl exec cassandra -- cat /var/log/cassandra/system.log

Ви можете запустити оболонку, яка підключена до вашого термінала, використовуючи аргументи -i і -t для kubectl exec, наприклад:

kubectl exec -it cassandra -- sh

Для отримання додаткових відомостей дивіться Отримання оболонки до запущеного контейнера.

Налагодження за допомогою ефемерного контейнера

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.25 [stable]

Ефемерні контейнери корисні для інтерактивного усунення несправностей, коли kubectl exec недостатній через аварію контейнера або те, що образ контейнера не містить утиліт для налагодження, наприклад, в образах distroless.

Приклад налагодження за допомогою ефемерних контейнерів

Ви можете використовувати команду kubectl debug, щоб додати ефемерні контейнери до запущеного Podʼа. Спочатку створіть Pod для прикладу:

kubectl run ephemeral-demo --image=registry.k8s.io/pause:3.1 --restart=Never

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

Якщо ви спробуєте використати kubectl exec для створення оболонки, ви побачите помилку, оскільки в цьому образі контейнера немає оболонки.

kubectl exec -it ephemeral-demo -- sh
OCI runtime exec failed: exec failed: container_linux.go:346: starting container process caused "exec: \"sh\": executable file not found in $PATH": unknown

Замість цього ви можете додати контейнер для налагодження за допомогою kubectl debug. Якщо ви вказуєте аргумент -i/--interactive, kubectl автоматично приєднується до консолі ефемерного контейнера.

kubectl debug -it ephemeral-demo --image=busybox:1.28 --target=ephemeral-demo
Defaulting debug container name to debugger-8xzrl.
If you don't see a command prompt, try pressing enter.
/ #

Ця команда додає новий контейнер busybox і приєднується до нього. Параметр --target спрямовує простір імен процесу до іншого контейнера. Це необхідно тут, оскільки kubectl run не ввімкнув процес спільного використання простору імен у Pod, який він створює.

Ви можете переглянути стан нового ефемерного контейнера, використовуючи kubectl describe:

kubectl describe pod ephemeral-demo
...
Ephemeral Containers:
  debugger-8xzrl:
    Container ID:   docker://b888f9adfd15bd5739fefaa39e1df4dd3c617b9902082b1cfdc29c4028ffb2eb
    Image:          busybox
    Image ID:       docker-pullable://busybox@sha256:1828edd60c5efd34b2bf5dd3282ec0cc04d47b2ff9caa0b6d4f07a21d1c08084
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Wed, 12 Feb 2020 14:25:42 +0100
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:         <none>
...

Використовуйте kubectl delete, щоб видалити Pod, коли ви закінчите:

kubectl delete pod ephemeral-demo

Налагодження за допомогою копії Podʼа

Іноді параметри конфігурації Podʼа ускладнюють усунення несправностей у певних ситуаціях. Наприклад, ви не можете виконувати kubectl exec, щоб усунути несправності у вашому контейнері, якщо ваш образ контейнера не містить оболонки або якщо ваш застосунок аварійно завершується при запуску. У цих ситуаціях ви можете використовувати kubectl debug, щоб створити копію Podʼа зі зміненими значеннями конфігурації для полегшення налагодження.

Копіювання Podʼа з додаванням нового контейнера

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

Наприклад, можливо, образ контейнера вашого застосунку збудований на основі busybox, але вам потрібні засоби для налагодження, які не включені в busybox. Ви можете симулювати цей сценарій за допомогою kubectl run:

kubectl run myapp --image=busybox:1.28 --restart=Never -- sleep 1d

Виконайте цю команду, щоб створити копію myapp з назвою myapp-debug, яка додає новий контейнер Ubuntu для налагодження:

kubectl debug myapp -it --image=ubuntu --share-processes --copy-to=myapp-debug
Defaulting debug container name to debugger-w7xmf.
If you don't see a command prompt, try pressing enter.
root@myapp-debug:/#

Не забудьте прибрати Pod для налагодження, коли ви закінчите:

kubectl delete pod myapp myapp-debug

Копіювання Podʼа зі зміною його команди

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

Щоб симулювати аварійне завершення застосунку, використайте kubectl run, щоб створити контейнер, який негайно завершується:

kubectl run --image=busybox:1.28 myapp -- false

Ви можете побачити за допомогою kubectl describe pod myapp, що цей контейнер аварійно завершується:

Containers:
  myapp:
    Image:         busybox
    ...
    Args:
      false
    State:          Waiting
      Reason:       CrashLoopBackOff
    Last State:     Terminated
      Reason:       Error
      Exit Code:    1

Ви можете використовувати kubectl debug, щоб створити копію цього Podʼа з командою зміненою на інтерактивну оболонку:

kubectl debug myapp -it --copy-to=myapp-debug --container=myapp -- sh
If you don't see a command prompt, try pressing enter.
/ #

Тепер у вас є інтерактивна оболонка, яку ви можете використовувати для виконання завдань, таких як перевірка шляхів файлової системи або виконання команди контейнера вручну.

Не забудьте прибрати Pod для налагодження, коли ви закінчите:

kubectl delete pod myapp myapp-debug

Копіювання Podʼа з заміною образів контейнерів

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

Наприклад, створіть Pod за допомогою kubectl run:

kubectl run myapp --image=busybox:1.28 --restart=Never -- sleep 1d

Тепер використовуйте kubectl debug, щоб створити копію та змінити його образ контейнера на ubuntu:

kubectl debug myapp --copy-to=myapp-debug --set-image=*=ubuntu

Синтаксис --set-image використовує ту ж синтаксис container_name=image, що й kubectl set image. *=ubuntu означає зміну образу всіх контейнерів на ubuntu.

Не забудьте прибрати Pod для налагодження, коли ви закінчите:

kubectl delete pod myapp myapp-debug

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

Якщо жоден з цих підходів не працює, ви можете знайти вузол, на якому працює Pod, і створити Pod, який буде виконуватися на цьому вузлі. Щоб створити інтерактивну оболонку на вузлі за допомогою kubectl debug, виконайте:

kubectl debug node/mynode -it --image=ubuntu
Creating debugging pod node-debugger-mynode-pdx84 with container debugger on node mynode.
If you don't see a command prompt, try pressing enter.
root@ek8s:/#

При створенні сесії налагодження на вузлі майте на увазі, що:

  • kubectl debug автоматично генерує назву нового Podʼа на основі назви вузла.
  • Коренева файлова система вузла буде змонтована в /host.
  • Контейнер працює у просторах імен IPC, мережі та PID вузла, хоча Pod не є привілейованим, тому читання деякої інформації про процеси може не вдатися, і chroot /host може не спрацювати.
  • Якщо вам потрібен привілейований Pod, створіть його вручну або використовуйте прапорець --profile=sysadmin

Не забудьте прибрати Pod для налагодження, коли ви закінчите з ним:

kubectl delete pod node-debugger-mynode-pdx84

Профілі налагодження

Коли ви використовуєте kubectl debug для налагодження вузла за допомогою Podʼа налагодження, Pod за ефемерним контейнером або скопійованого Pod, ви можете застосувати до них профіль налагодження за допомогою прапорця --profile. Застосовуючи профіль, встановлюються конкретні властивості, такі як securityContext, що дозволяє адаптуватися до різних сценаріїв.

Доступні наступні профілі:

ПрофільОпис
legacyНабір властивостей для зворотної сумісності з поведінкою 1.22
generalРозумний набір загальних властивостей для кожного завдання налагодження
baselineНабір властивостей, сумісних з Політикою базової безпеки PodSecurityStandard
restrictedНабір властивостей, сумісних з Політикою обмеженої безпеки PodSecurityStandard
netadminНабір властивостей, включаючи привілеї адміністратора мережі
sysadminНабір властивостей, включаючи привілеї системного адміністратора (root)

Припустимо, що ви створюєте Pod і налагоджуєте його. Спочатку створіть Pod з назвою myapp, наприклад:

kubectl run myapp --image=busybox:1.28 --restart=Never -- sleep 1d

Потім, перевірте Pod за допомогою ефемерного контейнера. Якщо ефемерному контейнеру потрібно мати привілеї, ви можете використовувати профіль sysadmin:

kubectl debug -it myapp --image=busybox:1.28 --target=myapp --profile=sysadmin
Targeting container "myapp". If you don't see processes from this container it may be because the container runtime doesn't support this feature.
Defaulting debug container name to debugger-6kg4x.
If you don't see a command prompt, try pressing enter.
/ #

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

/ # grep Cap /proc/$$/status
...
CapPrm:	000001ffffffffff
CapEff:	000001ffffffffff
...

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

Ви також можете перевірити, що ефемерний контейнер був створений як привілейований контейнер:

kubectl get pod myapp -o jsonpath='{.spec.ephemeralContainers[0].securityContext}'
{"privileged":true}

Очистіть Pod, коли ви закінчите з ним:

kubectl delete pod myapp

1.7 - Отримання доступу до оболонки запущеного контейнера

Ця сторінка показує, як використовувати kubectl exec для отримання доступу до оболонки запущеного контейнера.

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

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

Отримання доступу до оболонки контейнера

У цьому завданні ви створите Pod, який має один контейнер. Контейнер виконує образ nginx. Ось файл конфігурації для Podʼа:

apiVersion: v1
kind: Pod
metadata:
  name: shell-demo
spec:
  volumes:
  - name: shared-data
    emptyDir: {}
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - name: shared-data
      mountPath: /usr/share/nginx/html
  hostNetwork: true
  dnsPolicy: Default

Створіть Pod:

kubectl apply -f https://k8s.io/examples/application/shell-demo.yaml

Перевірте, що контейнер працює:

kubectl get pod shell-demo

Отримайте доступ до оболонки запущеного контейнера:

kubectl exec --stdin --tty shell-demo -- /bin/bash

У своїй оболонці виведіть список кореневої теки:

# Виконайте це всередині контейнера
ls /

У своїй оболонці експериментуйте з іншими командами. Ось деякі приклади:

# Ви можете виконати ці приклади команд всередині контейнера
ls /
cat /proc/mounts
cat /proc/1/maps
apt-get update
apt-get install -y tcpdump
tcpdump
apt-get install -y lsof
lsof
apt-get install -y procps
ps aux
ps aux | grep nginx

Редагування головної сторінки nginx

Знову перегляньте файл конфігурації вашого Podʼа. Pod має том emptyDir, і контейнер монтує цей том в /usr/share/nginx/html.

У своїй оболонці створіть файл index.html у теці /usr/share/nginx/html:

# Виконайте це всередині контейнера
echo 'Hello shell demo' > /usr/share/nginx/html/index.html

У своїй оболонці надішліть GET-запит до сервера nginx:

# Виконайте це в оболонці всередині вашого контейнера
apt-get update
apt-get install curl
curl http://localhost/

Результат покаже текст, який ви написали в файл index.html:

Hello shell demo

Коли ви закінчите з вашою оболонкою, введіть exit.

exit # Щоб вийти з оболонки в контейнері

Виконання окремих команд в контейнері

У звичайному вікні команд виведіть змінні оточення в запущеному контейнері:

kubectl exec shell-demo -- env

Експериментуйте з виконанням інших команд. Ось деякі приклади:

kubectl exec shell-demo -- ps aux
kubectl exec shell-demo -- ls /
kubectl exec shell-demo -- cat /proc/1/mounts

Відкриття оболонки, коли в Podʼі є більше одного контейнера

Якщо в Podʼі є більше одного контейнера, використовуйте --container або -c для зазначення контейнера в команді kubectl exec. Наприклад, припустимо, у вас є Pod на ім’я my-pod, і в Podʼі є два контейнери з іменами main-app та helper-app. Наступна команда відкриє оболонку до контейнера main-app.

kubectl exec -i -t my-pod --container main-app -- /bin/bash

Що далі

2 - Налагодження кластера

Виправлення загальних проблем з кластером Kubernetes.

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

Щодо усунення несправностей інструменту kubectl, звертайтеся до Посібника з усунення несправностей kubectl.

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

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

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

kubectl get nodes

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

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

kubectl cluster-info dump

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

Іноді при налагодженні може бути корисно переглянути стан вузла, наприклад, через те, що ви помітили дивну поведінку Podʼа, який працює на вузлі, або щоб дізнатися, чому Pod не може розміститися на вузлі. Так само як і з Podʼами, ви можете використовувати kubectl describe node та kubectl get node -o yaml, щоб отримати детальну інформацію про вузли. Наприклад, ось що ви побачите, якщо вузол вимкнено (відключено від мережі, або kubelet припинив роботу і не може перезапуститися і т. д.). Зверніть увагу на події, які показують, що вузол не готовий, і також зверніть увагу, що 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
Annotations:        kubeadm.alpha.kubernetes.io/cri-socket: /run/containerd/containerd.sock
                    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:
    kubeadm.alpha.kubernetes.io/cri-socket: /run/containerd/containerd.sock
    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. AppArmor enabled
    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 endpoints.

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

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

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

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

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

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

Помʼякшення

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

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

    • Помʼякшує: Втрата даних, на яких ґрунтується API сервер
  • Дія: Використовуйте конфігурацію високої доступності

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

    • Помʼякшує: Втрата сховища даних для API сервера
    • Помʼякшує: Деякі випадки помилок оператора
    • Помʼякшує: Деякі випадки несправності програмного забезпечення Kubernetes
  • Дія: Використовуйте контролер реплікацій та служби перед Podʼами

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

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

Що далі

2.1 - Усунення несправностей kubectl

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

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

Перевірка налаштувань kubectl

Переконайтеся, що ви правильно встановили та налаштували kubectl на вашому локальному компʼютері. Перевірте версію kubectl, щоб впевнитися, що вона актуальна та сумісна з вашим кластером.

Перевірка версії kubectl:

kubectl version

Ви побачите подібний вивід:

Client Version: version.Info{Major:"1", Minor:"27", GitVersion:"v1.27.4",GitCommit:"fa3d7990104d7c1f16943a67f11b154b71f6a132", GitTreeState:"clean",BuildDate:"2023-07-19T12:20:54Z", GoVersion:"go1.20.6", Compiler:"gc", Platform:"linux/amd64"}
Kustomize Version: v5.0.1
Server Version: version.Info{Major:"1", Minor:"27", GitVersion:"v1.27.3",GitCommit:"25b4e43193bcda6c7328a6d147b1fb73a33f1598", GitTreeState:"clean",BuildDate:"2023-06-14T09:47:40Z", GoVersion:"go1.20.5", Compiler:"gc", Platform:"linux/amd64"}

Якщо замість Server Version ви бачите Unable to connect to the server: dial tcp <server-ip>:8443: i/o timeout, вам потрібно дослідити проблеми зʼєднання kubectl з вашим кластером.

Переконайтеся, що ви встановили kubectl, слідуючи офіційній документації з встановлення kubectl, і правильно налаштували змінну середовища $PATH.

Перевірка kubeconfig

kubectl вимагає файл kubeconfig для зʼєднання з Kubernetes кластером. Файл kubeconfig зазвичай знаходиться в теці ~/.kube/config. Переконайтеся, що у вас є валідний файл kubeconfig. Якщо у вас немає файлу kubeconfig, ви можете отримати його у вашого адміністратора Kubernetes, або ви можете скопіювати його з теки /etc/kubernetes/admin.conf вашої панелі управління Kubernetes. Якщо ви розгортали ваш Kubernetes кластер на хмарній платформі та втратили ваш файл kubeconfig, ви можете згенерувати його знову за допомогою інструментів вашого хмарного провайдера. Дивіться документацію хмарного провайдера щодо генерації файлу kubeconfig.

Перевірте, чи правильно налаштовано змінну середовища $KUBECONFIG. Ви можете встановити змінну середовища $KUBECONFIG або використовувати параметр --kubeconfig з kubectl, щоб вказати теку файлу kubeconfig.

Перевірка VPN зʼєднання

Якщо ви використовуєте Віртуальну Приватну Мережу (VPN) для доступу до вашого Kubernetes кластеру, переконайтеся, що ваше VPN зʼєднання активне і стабільне. Іноді, перебої у зʼєднанні VPN можуть призвести до проблем зі зʼєднанням з кластером. Підʼєднайтеся до VPN знову і спробуйте отримати доступ до кластера знову.

Автентифікація та авторизація

Якщо ви використовуєте автентифікацію на базі токенів і kubectl повертає помилку щодо автентифікаційного токена або адреси сервера автентифікації, перевірте, що токен автентифікації Kubernetes та адреса сервера автентифікації налаштовані правильно.

Якщо kubectl повертає помилку щодо авторизації, переконайтеся, що ви використовуєте дійсні дані користувача. Та маєте дозвіл на доступ до ресурсу, який ви запросили.

Перевірка контекстів

Kubernetes підтримує роботу з кількома кластерами та контекстами. Переконайтеся, що ви використовуєте правильний контекст для взаємодії з вашим кластером.

Перелік доступних контекстів:

kubectl config get-contexts

Перемикання на відповідний контекст:

kubectl config use-context <context-name>

API сервер та балансувальник навантаження

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

Перевірте, чи доступний хост сервера API, використовуючи команду ping. Перевірте мережеве зʼєднання кластера та файервол. Якщо ви використовуєте хмарного провайдера для розгортання кластера, перевірте стан проб справності вашого хмарного провайдера для сервера API кластера.

Перевірте стан балансувальника навантаження (якщо використовується), щоб переконатися, що він справний і передає трафік на сервер API.

Проблеми з TLS

  • Потрібні додаткові інструменти — base64 та openssl версії 3.0 або вище.

Сервер API Kubernetes типово обслуговує лише HTTPS запити. У цьому випадку можуть виникнути проблеми з TLS з різних причин, таких як закінчення строку дії сертифіката або дійсність ланцюга довіри.

Ви можете знайти TLS сертифікат у файлі kubeconfig, який знаходиться у теці ~/.kube/config. Атрибут certificate-authority містить сертифікат ЦА, а атрибут client-certificate містить клієнтський сертифікат.

Перевірте строк дії цих сертифікатів:

kubectl config view --flatten --output 'jsonpath={.clusters[0].cluster.certificate-authority-data}' | base64 -d | openssl x509 -noout -dates

вивід:

notBefore=Feb 13 05:57:47 2024 GMT
notAfter=Feb 10 06:02:47 2034 GMT
kubectl config view --flatten --output 'jsonpath={.users[0].user.client-certificate-data}'| base64 -d | openssl x509 -noout -dates

вивід:

notBefore=Feb 13 05:57:47 2024 GMT
notAfter=Feb 12 06:02:50 2025 GMT

Перевірка допоміжних інструментів kubectl

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

Перевірте конфігурацію kubectl для отримання інформації про автентифікацію:

kubectl config view

Якщо раніше ви використовували допоміжний інструмент (наприклад, kubectl-oidc-login), переконайтеся, що він все ще встановлений і правильно налаштований.

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

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

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

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

Схема 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.

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

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

Metrics API

СТАН ФУНКЦІОНАЛУ: Kubernetes 1.8 [beta]

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

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

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

Той же самий виклик API, використовуючи curl:

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

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

{
  "kind": "NodeMetrics",
  "apiVersion": "metrics.k8s.io/v1beta1",
  "metadata": {
    "name": "minikube",
    "selfLink": "/apis/metrics.k8s.io/v1beta1/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/v1beta1/namespaces/kube-system/pods/kube-scheduler-minikube" | jq '.'

Той же самий виклик API, використовуючи curl:

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

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

{
  "kind": "PodMetrics",
  "apiVersion": "metrics.k8s.io/v1beta1",
  "metadata": {
    "name": "kube-scheduler-minikube",
    "namespace": "kube-system",
    "selfLink": "/apis/metrics.k8s.io/v1beta1/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 метрик ресурсів.

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

ЦП

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

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

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

Памʼять

Відомості про памʼять показуються як обсяг робочого набору, виміряний в байтах, в момент збору метрики.

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

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

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

Metrics Server

Metrics-server витягує метрики ресурсів з kubeletʼів і надає їх в API-серверу Kubernetes через Metrics API для використання 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.3 - Інструменти для моніторингу ресурсів

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

У Kubernetes моніторинг застосунків не залежить від єдиного рішення для моніторингу. На нових кластерах ви можете використовувати конвеєри метрик ресурсів або повні метрики, щоб збирати статистику для моніторингу.

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

Конвеєр метрик ресурсів надає обмежений набір метрик, повʼязаних з компонентами кластера, такими як контролер Горизонтального автомасштабування Podʼів та утилітою kubectl top. Ці метрики збираються легким, тимчасовим, розташованим в памʼяті metrics-server та експонується через API metrics.k8s.io.

Metrics-server виявляє всі вузли в кластері та запитує kubelet кожного вузла для визначення використання центрального процесора та памʼяті. Kubelet виступає як міст між майстром Kubernetes та вузлами, керуючи Podʼами та контейнерами, що працюють на машині. Kubelet перетворює кожний Pod у його складові контейнери та отримує статистику використання кожного контейнера через інтерфейс середовища виконання контейнерів. Якщо ви використовуєте середовище виконання контейнерів, яке використовує Linux cgroups та простори імен для роботи контейнерів, і середовище виконання контейнерів не публікує статистику використання, тоді kubelet може отримувати ці статистичні дані безпосередньо (використовуючи код з cAdvisor). Незалежно від того, як надходять ці статистичні дані, kubelet після цього використовує агреговану статистику використання ресурсів Podʼів через metrics-server Resource Metrics API. Цей API надається за адресою /metrics/resource/v1beta1 на автентифікованих та портах kublet, доступних тільки для читання.

Конвеєр повних метрик

Конвеєр повних метрик дає вам доступ до більш розширених метрик. Kubernetes може відповідати на ці метрики, автоматично масштабуючи або адаптуючи кластер на основі його поточного стану за допомогою механізмів, таких як Горизонтальне автомасштабування Podʼів. Конвеєр моніторингу витягує метрики з kubelet та експонує їх в Kubernetes через адаптер, реалізуючи API custom.metrics.k8s.io або external.metrics.k8s.io.

Kubernetes розроблено для роботи з OpenMetrics, який є одним із проєктів моніторингу CNCF, побудованим на основі формату експонування метрик Prometheus та розширюючи його майже у 100% сумісний спосіб.

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

При проєктуванні та реалізації конвеєра повних метрик ви можете зробити ці моніторингові дані доступні зворотньо у Kubernetes. Наприклад, HorizontalPodAutoscaler може використовувати оброблені метрики для розрахунку кількості Podʼів, які потрібно запустити як складову вашого навантаження.

Інтеграція конвеєра повних у вашу реалізацію Kubernetes знаходиться поза межами документації Kubernetes через дуже широкий спектр можливих рішень.

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

Що далі

Дізнайтеся про додаткові інструменти для налагодження, включаючи:

2.4 - Відстеження стану вузлів

Node Problem Detector — це служба для моніторингу та звітування про стан вузла. Ви можете запустити Node Problem Detector як DaemonSet або окремий демон. Node Problem Detector збирає інформацію про проблеми вузла з різних демонів і повідомляє їх на сервер API як стан вузла або як події.

Для отримання інформації щодо встановлення та використання Node Problem Detector, див. Документацію проєкту Node Problem Detector.

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

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

Обмеження

Увімкнення Node Problem Detector

Деякі хмарні постачальники увімкнуть Node Problem Detector як надбудову. Ви також можете увімкнути Node Problem Detector за допомогою kubectl або створити Addon DaemonSet.

Використання kubectl для увімкнення Node Problem Detector

kubectl надає найбільш гнучке керування Node Problem Detector. Ви можете перезаписати типову конфігурацію, щоб вона відповідала вашому середовищу або виявляла спеціалізовані проблеми вузла. Наприклад:

  1. Створіть конфігурацію Node Problem Detector, аналогічну node-problem-detector.yaml:

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: node-problem-detector-v0.1
      namespace: kube-system
      labels:
        k8s-app: node-problem-detector
        version: v0.1
        kubernetes.io/cluster-service: "true"
    spec:
      selector:
        matchLabels:
          k8s-app: node-problem-detector  
          version: v0.1
          kubernetes.io/cluster-service: "true"
      template:
        metadata:
          labels:
            k8s-app: node-problem-detector
            version: v0.1
            kubernetes.io/cluster-service: "true"
        spec:
          hostNetwork: true
          containers:
          - name: node-problem-detector
            image: registry.k8s.io/node-problem-detector:v0.1
            securityContext:
              privileged: true
            resources:
              limits:
                cpu: "200m"
                memory: "100Mi"
              requests:
                cpu: "20m"
                memory: "20Mi"
            volumeMounts:
            - name: log
              mountPath: /log
              readOnly: true
          volumes:
          - name: log
            hostPath:
              path: /var/log/
  2. Запустіть Node Problem Detector за допомогою kubectl:

    kubectl apply -f https://k8s.io/examples/debug/node-problem-detector.yaml
    

Використання Podʼа надбудови для увімкнення Node Problem Detector

Якщо ви використовуєте власне рішення для ініціалізації кластера та не потребуєте перезапису типової конфігурації, ви можете скористатися Podʼом надбудови, щоб автоматизувати розгортання.

Створіть node-problem-detector.yaml та збережіть конфігурацію в теці Podʼа надбудови /etc/kubernetes/addons/node-problem-detector на вузлі панелі управління.

Перезапис конфігурації

Типова конфігурація вбудована під час збирання Docker-образу Node Problem Detector.

Однак ви можете використовувати ConfigMap для перезапису конфігурації:

  1. Змініть файли конфігурації в config/.

  2. Створіть ConfigMap node-problem-detector-config:

    kubectl create configmap node-problem-detector-config --from-file=config/
    
  3. Змініть node-problem-detector.yaml, щоб використовувати ConfigMap:

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: node-problem-detector-v0.1
      namespace: kube-system
      labels:
        k8s-app: node-problem-detector
        version: v0.1
        kubernetes.io/cluster-service: "true"
    spec:
      selector:
        matchLabels:
          k8s-app: node-problem-detector  
          version: v0.1
          kubernetes.io/cluster-service: "true"
      template:
        metadata:
          labels:
            k8s-app: node-problem-detector
            version: v0.1
            kubernetes.io/cluster-service: "true"
        spec:
          hostNetwork: true
          containers:
          - name: node-problem-detector
            image: registry.k8s.io/node-problem-detector:v0.1
            securityContext:
              privileged: true
            resources:
              limits:
                cpu: "200m"
                memory: "100Mi"
              requests:
                cpu: "20m"
                memory: "20Mi"
            volumeMounts:
            - name: log
              mountPath: /log
              readOnly: true
            - name: config # Overwrite the config/ directory with ConfigMap volume
              mountPath: /config
              readOnly: true
          volumes:
          - name: log
            hostPath:
              path: /var/log/
          - name: config # Define ConfigMap volume
            configMap:
              name: node-problem-detector-config
  4. Перестворіть Node Problem Detector з новим файлом конфігурації:

    # Якщо у вас вже працює Node Problem Detector, видаліть перед перстворенням
    kubectl delete -f https://k8s.io/examples/debug/node-problem-detector.yaml
    kubectl apply -f https://k8s.io/examples/debug/node-problem-detector-configmap.yaml
    

Перезапис конфігурації не підтримується, якщо Node Problem Detector працює як надбудова кластера. Менеджер надбудов не підтримує ConfigMap.

Демони проблем

Демон проблем — це піддемон Node Problem Detector. Він моніторить певні види проблем вузла та повідомляє про них Node Problem Detector. Існує кілька типів підтримуваних демонів проблем.

  • Тип демона SystemLogMonitor моніторить системні логи та повідомляє про проблеми та метрики згідно з попередньо визначеними правилами. Ви можете настроїти конфігурації для різних джерел логів таких як filelog, kmsg, kernel, abrt, та systemd.

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

  • Тип демона CustomPluginMonitor викликає та перевіряє різні проблеми вузла, запускаючи сценарії, визначені користувачем. Ви можете використовувати різні власні втулки для моніторингу різних проблем і настроювати поведінку демона, оновивши файл конфігурації.

  • Тип демона HealthChecker перевіряє стан kubelet та контейнерного середовища на вузлі.

Додавання підтримки для іншого формату логів

Монітор системного логу наразі підтримує файлові логи, journald та kmsg. Додаткові джерела можна додати, реалізувавши новий спостерігач за логами.

Додавання власних втулків моніторингу

Ви можете розширити Node Problem Detector для виконання будь-яких сценаріїв моніторингу, написаних будь-якою мовою програмування, розробивши власний втулок. Сценарії моніторингу повинні відповідати протоколу втулка щодо коду виходу та стандартного виводу. Для отримання додаткової інформації див. пропозицію інтерфейсу втулка.

Експортер

Експортер повідомляє про проблеми та/або метрики вузлів до певних бекендів. Підтримуються наступні експортери:

  • Експортер Kubernetes: цей експортер повідомляє про проблеми вузлів на сервер API Kubernetes. Тимчасові проблеми повідомляються як Події, а постійні проблеми — як Стан вузла.

  • Експортер Prometheus: цей експортер локально повідомляє про проблеми вузлів та метрики у форматі Prometheus (або OpenMetrics). Ви можете вказати IP-адресу та порт для експортера, використовуючи аргументи командного рядка.

  • Експортер Stackdriver: цей експортер повідомляє про проблеми вузлів та метрики в службу моніторингу Stackdriver. Поведінку експорту можна налаштувати, використовуючи файл конфігурації.

Рекомендації та обмеження

Рекомендується запускати Node Problem Detector в вашому кластері для моніторингу стану вузлів. При запуску Node Problem Detector можна очікувати додаткове навантаження ресурсів на кожному вузлі. Зазвичай це прийнятно, оскільки:

  • Лог ядра росте відносно повільно.
  • Для Node Problem Detector встановлено обмеження ресурсів.
  • Навіть при великому навантаженні використання ресурсів прийнятне. Докладніше див. результати бенчмарків Node Problem Detector.

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

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.11 [stable]

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

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

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

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

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

Використання

Команда crictl має кілька підкоманд та прапорців для використання. Використовуйте crictl help або crictl <підкоманда> help для отримання більш детальної інформації.

Ви можете встановити точку доступу для crictl, виконавши одну з наступних дій:

  • Встановіть прапорці --runtime-endpoint та --image-endpoint.
  • Встановіть змінні середовища CONTAINER_RUNTIME_ENDPOINT та IMAGE_SERVICE_ENDPOINT.
  • Встановіть точку доступу в файлі конфігурації /etc/crictl.yaml. Щоб вказати інший файл, використовуйте прапорець --config=ШЛЯХ_ДО_ФАЙЛУ під час запуску 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.gcr.io/hyperkube-amd64                v1.10.3             e179bbfe5d238       665MB
k8s.gcr.io/pause                          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 хвилин тому       Running             sh                         1
9c5951df22c78       busybox@sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47                                   8 хвилин тому       Exited              sh                         0
87d3992f84f74       nginx@sha256:d0a8828cccb73397acb0073bf34f4d7d8aa315263f1e7806bf8c55d8ac139d5f                                     8 хвилин тому       Running             nginx                      0
1941fb4da154f       k8s-gcrio.azureedge.net/hyperkube-amd64@sha256:00d814b1f7763f4ab5be80c58e98140dfc69df107f253d7fdd714b30a714260a   18 годин тому        Running             kube-proxy                 0

Вивести працюючі контейнери:

crictl ps

Вихідний результат схожий на такий:

CONTAINER ID        IMAGE                                                                                                             CREATED             STATE               NAME                       ATTEMPT
1f73f2d81bf98       busybox@sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47                                   6 хвилин тому       Running             sh                         1
87d3992f84f74       nginx@sha256:d0a8828cccb73397acb0073bf34f4d7d8aa315263f1e7806bf8c55d8ac139d5f                                     7 хвилин тому       Running             nginx                      0
1941fb4da154f       k8s-gcrio.azureedge.net/hyperkube-amd64@sha256:00d814b1f7763f4ab5be80c58e98140dfc69df107f253d7fdd714b30a714260a   17 годин тому        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" "-"

Що далі

2.6 - Аудит

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

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

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

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

Кожний запит може бути записаний з асоційованим stage. Визначені етапи:

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

Функція логування аудиту збільшує витрати памʼяті сервера 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:
  # Логувати зміни у вузлах на рівні RequestResponse
  - level: RequestResponse
    resources:
    - group: ""
      # Ресурс "pods" не відповідає запитам на будь-який підресурс вузлів,
      # що відповідає політиці 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"]

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

  # Загальне правило для логування всіх інших запитів на рівні Metadata.
  - level: Metadata
    # Довгострокові запити, такі як watches, які підпадають під це правило,
    # не генерують подію аудиту на етапі 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.

Бекенд логів

Бекенд логів записує події аудиту у файл у форматі 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, яке вважається формою Kubernetes API, включаючи засоби автентифікації. Ви можете налаштувати бекенд webhook за допомогою наступних прапорців kube-apiserver:

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

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

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

Обидва типи бекенд систем, як логів, так і webhook, підтримують пакетну обробку. Використаємо webhook як приклад, ось перелік доступних прапорців. Щоб отримати такий же прапорець для логів, замініть webhook на log у назві прапорця. Стандартно пакетна обробка увімкнена для webhook і вимкнена для log. Так само, типово, обмеження пропускної здатності увімкнено в webhook і вимкнене в log.

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

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

  • --audit-webhook-batch-buffer-size визначає кількість подій для буферизації перед пакетною обробкою. Якщо швидкість надходження подій переповнює буфер, події відкидаються.
  • --audit-webhook-batch-max-size визначає максимальну кількість подій в одному пакеті.
  • --audit-webhook-batch-max-wait визначає максимальний час очікування перед безумовною буферизацією подій у черзі.
  • --audit-webhook-batch-throttle-qps визначає максимальну середню кількість пакетів, що генеруються за секунду.
  • --audit-webhook-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, щоб увімкнути цю функцію.

Що далі

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

Ця сторінка показує, як налагоджувати вузол на кластері Kubernetes за допомогою команди kubectl debug.

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

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

Версія вашого Kubernetes сервера має бути не старішою ніж 1.2. Для перевірки версії введіть kubectl version.

Вам потрібно мати дозвіл на створення Podʼів та призначення їх новим Вузлам. Також вам потрібно мати дозвіл на створення Podʼів, які мають доступ до файлових систем з хосту.

Налагодження вузла за допомогою kubectl debug node

Використовуйте команду kubectl debug node, щоб розмістити Pod на Вузлі, який ви хочете налагодити. Ця команда корисна в сценаріях, коли ви не можете отримати доступ до свого Вузла за допомогою зʼєднання SSH. Після створення Podʼа, відкривається інтерактивний інтерфейс оболонки на Вузлі. Щоб створити інтерактивну оболонку на Вузлі з назвою “mynode”, виконайте:

kubectl debug node/mynode -it --image=ubuntu
Creating debugging pod node-debugger-mynode-pdx84 with container debugger on node mynode.
If you don't see a command prompt, try pressing enter.
root@mynode:/#

Команда налагоджування допомагає збирати інформацію та розвʼязувати проблеми. Команди, які ви можете використовувати, включають ip, ifconfig, nc, ping, ps тощо. Ви також можете встановити інші інструменти, такі як mtr, tcpdump та curl, з відповідного менеджера пакунків.

Pod налагодження може отримувати доступ до кореневої файлової системи Вузла, підключеної за адресою /host в Podʼі. Якщо ви використовуєте kubelet у просторі імен файлової системи, Pod налагодження бачить корінь для цього простору імен, а не всього Вузла. Для типового вузла Linux ви можете переглянути наступні шляхи для пошуку відповідних логів:

/host/var/log/kubelet.log
Логи kubelet, який відповідає за запуск контейнерів на вузлі.
/host/var/log/kube-proxy.log
Логи kube-proxy, який відповідає за направлення трафіку на точки доступу Service.
/host/var/log/containerd.log
Логи процесу containerd, який працює на вузлі.
/host/var/log/syslog
Показує загальні повідомлення та інформацію щодо системи.
/host/var/log/kern.log
Показує логи ядра.

При створенні сеансу налагодження на Вузлі майте на увазі, що:

  • kubectl debug автоматично генерує імʼя нового контейнера на основі імені вузла.
  • Коренева файлова система Вузла буде змонтована за адресою /host.
  • Хоча контейнер працює у просторі імен IPC, мережі та PID хосту, Pod не є привілейованим. Це означає, що читання деякої інформації про процес може бути неможливим, оскільки доступ до цієї інформації мають тільки суперкористувачі. Наприклад, chroot /host буде невдалим. Якщо вам потрібен привілейований контейнер, створіть його вручну або використовуйте прапорець --profile=sysadmin.
  • Застосовуючи профілі налагодження, ви можете встановити конкретні властивості, такі як securityContext до Podʼу налагодження.

Очищення

Коли ви закінчите використання Podʼа налагодження, видаліть його:

kubectl get pods
NAME                          READY   STATUS       RESTARTS   AGE
node-debugger-mynode-pdx84    0/1     Completed    0          8m1s
# Змініть імʼя контейнера відповідно
kubectl delete pod node-debugger-mynode-pdx84 --now
pod "node-debugger-mynode-pdx84" deleted

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

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

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

У цьому документі описано використання 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 ви зазвичай програмуєте або налагоджувати один сервіс. Цей сервіс може потребувати доступу до інших сервісів для тестування та налагодження. Один із варіантів — використання конвеєра постійного розгортання (continuous deployment pipeline), але навіть найшвидший конвеєр розгортання додає затримку в цикл програмування або налагодження.

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

Де:

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

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

Як працює Telepresence?

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

Що далі

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

Також читання відвідайте вебсайт Telepresence.

2.9 - Поради щодо налагодження Windows

Розвʼязання проблем на рівні вузла

  1. Мої Podʼи застрягли на "Container Creating" або постійно перезавантажуються.

    Переконайтеся, що ваш образ pause відповідає версії вашої операційної системи Windows. Див. Контейнер pause для перегляду останнього/рекомендованого образу pause та/або отримання додаткової інформації.

  2. Мої Podʼи показують статус як ErrImgPull або ImagePullBackOff.

    Переконайтеся, що ваш Pod планується на сумісний вузол Windows.

    Додаткову інформацію про те, як вказати сумісний вузол для вашого Podʼа, можна знайти в цьому посібнику.

Розвʼязання проблем мережі

  1. Мої Podʼи Windows не мають підключення до мережі.

    Якщо ви використовуєте віртуальні машини, переконайтеся, що MAC spoofing увімкнено на всіх адаптерах мережі віртуальних машин.

  2. Мої Podʼи Windows не можуть пінгувати зовнішні ресурси.

    Podʼи Windows не мають правил для вихідного трафіку, програмованих для протоколу ICMP. Однак, підтримується TCP/UDP. При спробі продемонструвати підключення до ресурсів за межами кластера, замініть ping <IP> відповідними командами curl <IP>.

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

    Одним із вимог мережі Kubernetes (див. Модель Kubernetes) є внутрішнє звʼязування кластера без NAT всередині. Щоб відповідати цій вимозі, існує ExceptionList для всього трафіку, де ви не хочете, щоб відбувалось використання NAT назовні. Однак, це також означає, що вам потрібно виключити зовнішню IP-адресу, яку ви намагаєтесь запитати з ExceptionList. Тільки тоді трафік, який походить з вашого Podʼа Windows, буде коректно SNAT'ed для отримання відповіді зі світу. З цього погляду ваш ExceptionList у cni.conf повинен виглядати так:

    "ExceptionList": [
                    "10.244.0.0/16",  # Підмережа кластера
                    "10.96.0.0/12",   # Підмережа служби
                    "10.127.130.0/24" # Управління (хост) підмережа
                ]
    
  3. Мій вузол Windows не може отримати доступ до служб типу NodePort.

    Доступ до локального NodePort з самого вузла не вдається. Це відоме обмеження. Доступ до NodePort працює з інших вузлів або зовнішніх клієнтів.

  4. vNICs та HNS точки доступу контейнерів видаляються.

    Цю проблему може викликати відмова в передачі параметра hostname-override до kube-proxy. Щоб вирішити це, користувачі повинні передавати імʼя хосту kube-proxy наступним чином:

    C:\k\kube-proxy.exe --hostname-override=$(hostname)
    
  5. Мій вузол Windows не може отримати доступ до моїх Service за допомогою IP-адреси Service

    Це відоме обмеження стека мережі на Windows. Однак, Podʼи Windows можуть отримувати доступ до IP-адреси Service.

  6. Під час запуску kubelet не знайдено мережевого адаптера.

    Для правильної роботи мережі Windows потрібен віртуальний адаптер. Якщо наступні команди не повертають результатів (в оболонці адміністратора), створення віртуальної мережі, необхідна передумова для роботи kubelet, не вдалося:

    Get-HnsNetwork | ? Name -ieq "cbr0"
    Get-NetAdapter | ? Name -Like "vEthernet (Ethernet*"
    

    Часто варто змінити параметр InterfaceName у скрипті start.ps1, в разі, якщо мережевий адаптер хосту не є "Ethernet". В іншому випадку зверніться до виводу скрипту start-kubelet.ps1, щоб побачити, чи є помилки під час створення віртуальної мережі.

  7. DNS-перетворення не працює належним чином.

    Перевірте обмеження DNS для Windows у цьому розділі.

  8. kubectl port-forward видає помилку "unable to do port forwarding: wincat not found"

    Це було реалізовано в Kubernetes 1.15, включивши wincat.exe в інфраструктурний контейнер pause mcr.microsoft.com/oss/kubernetes/pause:3.6. Будьте впевнені, що використовуєте підтримувану версію Kubernetes. Якщо ви хочете побудувати власний контейнер інфраструктури pause, обовʼязково додайте wincat.

  9. Моє встановлення Kubernetes падає, тому що мій вузол сервера Windows знаходиться за проксі

    Якщо ви перебуваєте за проксі, наступні змінні середовища PowerShell повинні бути визначені:

    [Environment]::SetEnvironmentVariable("HTTP_PROXY", "http://proxy.example.com:80/", [EnvironmentVariableTarget]::Machine)
    [Environment]::SetEnvironmentVariable("HTTPS_PROXY", "http://proxy.example.com:443/", [EnvironmentVariableTarget]::Machine)
    

Розвʼязання проблем Flannel

  1. З Flannel мої вузли мають проблеми після повторного приєднання до кластера.

    Кожного разу, коли раніше видалений вузол повторно приєднується до кластера, flannelD намагається призначити нову підмережу Podʼа вузлу. Користувачі повинні видалити старі файли конфігурації підмережі Podʼа за наступними шляхами:

    Remove-Item C:\k\SourceVip.json
    Remove-Item C:\k\SourceVipRequest.json
    
  2. Flanneld застрягає в "Waiting for the Network to be created"

    Є численні звіти про цю проблему; ймовірно, це проблема з часом встановлення управлінської IP-адреси мережі flannel. Обхідним рішенням є перезапуск start.ps1 або перезапуск його вручну так:

    [Environment]::SetEnvironmentVariable("NODE_NAME", "<Windows_Worker_Hostname>")
    C:\flannel\flanneld.exe --kubeconfig-file=c:\k\config --iface=<Windows_Worker_Node_IP> --ip-masq=1 --kube-subnet-mgr=1
    
  3. Мої Podʼи Windows не можуть запуститися через відсутність /run/flannel/subnet.env.

    Це вказує на те, що Flannel не запустився правильно. Ви можете спробувати перезапустити flanneld.exe або вручну скопіювати файли з /run/flannel/subnet.env на майстрі Kubernetes в C:\run\flannel\subnet.env на робочий вузол Windows та змінити рядок FLANNEL_SUBNET на інший номер. Наприклад, якщо підмережа вузла 10.244.4.1/24 бажана:

    FLANNEL_NETWORK=10.244.0.0/16
    FLANNEL_SUBNET=10.244.4.1/24
    FLANNEL_MTU=1500
    FLANNEL_IPMASQ=true
    

Подальші дослідження

Якщо ці кроки не розвʼязують вашої проблеми, ви можете отримати допомогу у запуску контейнерів Windows на вузлах Windows у Kubernetes у наступних ресурсах: