Улучшая надёжность Kubernetes: как быстрее замечать, что нода упала

в 10:43, , рубрики: devops, docker, kubernetes, Блог компании Флант, отказоустойчивость, системное администрирование

В кластере Kubernetes нода может умереть или перезапуститься.

Инструменты вроде Kubernetes обеспечивают высокую доступность, спроектированы для надёжного функционирования и автоматического восстановления в подобных сценариях, и Kubernetes действительно прекрасно со всем этим справляется.
Улучшая надёжность Kubernetes: как быстрее замечать, что нода упала - 1
Однако вы можете заметить: когда нода падает, поды сломанной ноды на протяжении какого-то времени всё ещё запущены и получают запросы, которые уже не выполняются.

И по умолчанию это время, как мне кажется, слишком велико — его можно уменьшить. На него влияют несколько параметров, настраиваемых в Kubelet и Controller Manager.

Вот описание процессов, которые возникают, когда нода падает:

1. Kubelet отправляет свой статус мастерам с -node-status-update-frequency=10s;

2. Нода в Kubernetes умирает.

3. Демон kube-controller-manager, который мониторит ноды, с интервалом -node-monitor-period=5s проверяет в мастерах статус ноды, полученный от Kubelet.

4. Kube-controller-manager видит, что нода не отвечает, и на протяжении мягкого интервала -node-monitor-grace-period=40s ожидает, стоит ли считать ноду проблемной. Этот параметр должен равняться node-status-update-frequency, умноженному на N, где N — количество попыток, разрешённых Kubelet для отправки статуса ноды. N — константа, для которой в коде определёно значение 5 (см. переменную nodeStatusUpdateRetry в kubelet/kubelet.go).

Обратите внимание, что значение по умолчанию не соответствует тому, что говорится в документации, потому что:

node-status-update-frequency × N != node-monitor-grace-period (10 × 5 != 40)

Насколько я понимаю, 5 попыток отправки статуса (каждая по 10 секунд) выполняются за 40 секунд, потому что первая выполняется сразу, а вторая и последующие — по 10 секунд. В результате, пять попыток завершаются за 40 секунд.

То есть реальная формула выглядит следующим образом:

node-status-update-frequency × (N-1) != node-monitor-grace-period

Подробности можно увидеть в коде controller/node/nodecontroller.go.

5. Когда нода отмечена проблемной, kube-controller-manager удаляет поды с применением параметра -pod-eviction-timeout=5m0s.

Это очень важный таймаут и по умолчанию он равен 5 минутам, что, на мой взгляд, очень большое значение. Хотя нода уже отмечена как проблемная, kube-controller-manager в течение указанного времени не удалит её поды, поэтому они будут доступны через свои службы, но запросы к ним не выполнятся.

6. Kube-proxy постоянно наблюдает за статусами через API, поэтому сразу же заметит момент, когда поды выведены из строя, и обновит правила iptables для ноды, после чего упавшие поды перестанут быть доступными.

Итак, упомянутые значения можно изменить, чтобы уменьшить количество невыполненных запросов, когда нода падает.

Для своего кластера Kubernetes я их настроил следующим образом:

  • kubelet: node-status-update-frequency=4s (вместо 10s)
  • controller-manager: node-monitor-period=2s (вместо 5s)
  • controller-manager: node-monitor-grace-period=16s (вместо 40s)
  • controller-manager: pod-eviction-timeout=30s (вместо 5m)

Результаты достаточно хороши: падение ноды определяется не за 5 минут 40 секунд, а за 46 секунд.

P.S. От переводчика: для себя мы пока подбираем оптимальные значения в зависимости от конфигурации сети (один или разные ЦОД, одна стойка и т.п.) и планируем поделиться результатами изысканий (т.е. оптимальных значений), когда они будут получены опытным путём.

Автор: Флант

Источник

Поделиться

* - обязательные к заполнению поля