Флант corporate blog
System administration
DevOps
Distributed systems
Kubernetes
24 October 2018

Как обеспечивается высокая доступность в Kubernetes

Original author: Andrew Chen, Dominik Tornow
Translation
Прим. перев.: Оригинальная статья была написана техническим писателем из Google, работающим над документацией для Kubernetes (Andrew Chen), и директором по software engineering из SAP (Dominik Tornow). Её цель — доступно и наглядно объяснить основы организации и реализации high availability в Kubernetes. Нам кажется, что у авторов получилось, поэтому мы рады поделиться переводом.



Kubernetes — движок оркестровки контейнеров, созданный для запуска контейнеризированных приложений на множестве узлов, которые обычно называют кластером. В этих публикациях мы используем подход системного моделирования с целью улучшить понимание Kubernetes и его нижележащих концепций. Читающим рекомендуется уже иметь базовое представление о Kubernetes.

Kubernetes — масштабируемый и надёжный движок оркестровки контейнеров. Масштабируемость здесь определяется отзывчивостью в присутствии нагрузки, а надёжность — отзывчивостью в присутствии отказов.

Заметьте, что масштабируемость и надёжность Kubernetes не означает масштабируемость и надёжность приложения, запущенного в нём. Kubernetes — масштабируемая и надёжная платформа, однако каждому приложению в K8s ещё только предстоит пройти определённые этапы для того, чтобы стать таковыми и избегать узких мест и единых точек отказа.

Например, если приложение развёрнуто как ReplicaSet или Deployment, Kubernetes (пере-)планирует и (пере-)запускает поды, затронутые падениями узла. Однако если приложение развёрнуто как поды, Kubernetes не предпримет никаких действий в случае отказа узла. Поэтому, хотя сам по себе Kubernetes остаётся функционирующим, отзывчивость вашего приложения зависит от выбранных решений по архитектуре и деплою.

В фокусе этой публикации — надёжность Kubernetes. Она рассказывает, как Kubernetes поддерживает отзывчивость в присутствии отказов.

Архитектура Kubernetes



Схема 1. Мастер и worker

На концептуальном уровне компоненты Kubernetes сгруппированы в два определённых класса: компоненты мастера (Master) и компоненты воркера (Worker).

Мастеры отвечают за управление всем кроме исполнения подов. Компоненты мастера включают в себя:


Воркеры отвечают за управление исполнением подов. У них один компонент:


Воркеры тривиально надёжны: временный или постоянный отказ любого воркера в кластере не затрагивает мастера или других воркеров кластера. Если приложение развёрнуто соответствующим образом, Kubernetes (пере-)планирует и (пере-)запускает любой под, затронутый отказом воркера.

Конфигурация с единственным мастером



Схема 2. Конфигурация с единственным мастером

В конфигурации с единственным мастером кластер Kubernetes состоит из одного мастера и множества воркеров. Последние напрямую подключаются к kube-apiserver мастера и взаимодействуют с ним.

В этой конфигурации отзывчивость Kubernetes зависит от:

  • единственного мастера,
  • подключения воркеров к единственному мастеру.

Поскольку единственный мастер — единая точка отказа, такая конфигурация не относится к категории высокой доступности.

Конфигурация с множеством мастеров



Схема 3. Конфигурация с множеством мастеров

В конфигурации с множеством мастеров кластер Kubernetes состоит из множества мастеров и множества воркеров. Воркеры подключаются к kube-apiserver любого мастера и взаимодействуют с ним через высокодоступный балансировщик нагрузки.

В этой конфигурации Kubernetes не зависит от:

  • единственного мастера,
  • подключения воркеров к единственному мастеру.

Поскольку единая точка отказа в такой конфигурации отсутствует, она считается высокодоступной.

Ведущий (leader) и ведомый (follower) в Kubernetes


В конфигурации с множеством мастеров задействованы многочисленные kube-controller-manager'ы и kube-scheduler'ы. Если два компонента будут модифицировать одни и те же объекты, могут возникнуть конфликты.

Дабы избежать потенциальных конфликтов, для kube-controller-manager и kube-scheduler в Kubernetes реализован паттерн «ведущий-ведомый» (leader/follower). Каждая группа выбирает одного ведущего (или лидера), и остальные члены группы берут роль ведомых. В любой момент времени активен лишь один ведущий, а ведомые пассивны.


Схема 4. Избыточный Deployment компонентов мастера в деталях

На этой иллюстрации показан подробный пример, в котором kube-controller-1 и kube-scheduler-2 являются ведущими среди kube-controller-manager'ов и kube-scheduler'ов. Поскольку каждая группа выбирает своего ведущего, они вовсе не обязательно должны находиться на одном и том же мастере.

Выбор ведущего


Новый ведущий выбирается членами группы в момент запуска или в случае падения ведущего. Ведущий — член, обладающий так называемым leader lease («арендованным» на данный момент статусом лидера).


Схема 5. Процесс выбора ведущего компонента мастера

Эта иллюстрация демонстрирует процесс выбора ведущего для kube-controller-manager и kube-scheduler. Логика этого процесса такова:

'Попытка получить статус лидера' успешна тогда и только тогда, когда:
- статусом лидера сейчас никто не обладает или
- время предыдущего лидера истекло

'Попытка обновить статус лидера' успешна тогда и только тогда, когда:
- leader lease существует и
- его время не истекло и
- его holderIdentity равен 'self'


Отслеживание ведущих


Текущие статусы лидеров для kube-controller-manager и kube-scheduler постоянно хранятся в объектном хранилище Kubernetes как endpoints objects в пространстве имён kube-system. Поскольку два объекта Kubernetes не могут одновременно иметь одинаковое название, тип (kind) и пространство имён, может существовать лишь один endpoint для kube-scheduler и для kube-controller-manager.

Демонстрация с использованием консольной утилиты kubectl:

$ kubectl get endpoints -n kube-system

NAME                      ENDPOINTS                   AGE
kube-scheduler            <none>                      30m
kube-controller-manager   <none>                      30m

Endpoint'ы kube-scheduler и kube-controller-manager хранят информацию о лидере в аннотации control-plane.alpha.kubernetes.io/leader:

$ kubectl describe endpoints kube-scheduler -n kube-system

Name:         kube-scheduler
Annotations:  control-plane.alpha.kubernetes.io/leader=
              {
                "holderIdentity": "scheduler-2",
                "leaseDurationSeconds": 15, 
                "acquireTime": "2018-01-01T08:00:00Z"
                "renewTime": "2018-01-01T08:00:30Z"
              }

Хотя Kubernetes гарантирует, что в один момент времени будет один ведущий, Kubernetes не гарантирует, что два и более компонентов мастера не будут ошибочно полагать, что являются ведущими в данный момент, — это состояние известно как split brain.

Поучительное обсуждение темы split brain и возможных способов её устранения можно найти в статье «How to do distributed locking» от Martin Kleppmann.

Kubernetes не применяет никакие контрмеры по защите от split brain. Вместо этого он полагается на свою возможность стремиться к желаемому состоянию в течение времени, что смягчает последствия конфликтных решений.

Заключение


В конфигурации с множеством мастеров Kubernetes — масштабируемый и надёжный движок оркестровки контейнеров. В этой конфигурации Kubernetes обеспечивает надёжность, используя множество мастеров и множество воркеров. Множество мастеров работает по паттерну ведущий/ведомый, а воркеры функционируют параллельно. В Kubernetes реализован свой процесс выбора ведущего, в котором информация о ведущем хранится как endpoints objects.

Информацию о том, как подготовить к работе кластер Kubernetes высокой доступности, можно получить в официальной документации.

О публикации


Этот пост — часть совместной инициативы CNCF, Google и SAP, направленной на улучшение понимания Kubernetes и его нижележащих концепций.

P.S. от переводчика


Читайте также в нашем блоге:


+26
9.4k 101
Support the author
Leave a comment
Top of the day