Как Kubernetes управляет вашим кластером с помощью концепций системного программирования

Раскрытие информации: Manifold , торговая площадка для разработчиков, ранее спонсировала Hacker Noon. Используйте код HACKERNOON2018, чтобы получить скидку 10 долларов на любую услугу.

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

Kubernetes в конечном итоге достигает желаемого количества запущенных контейнеров вовремя. Он неумолимо поддерживает это число. В документации Kubernetes это называется самовосстановлением Kubernetes. Такое поведение проистекает из основной философии разработки Kubernetes.

«Целеустремленное поведение контура управления очень стабильно. Это было доказано в Kubernetes, где у нас были ошибки, которые остались незамеченными, потому что цикл управления в основном стабилен и со временем исправится.

Если вы срабатываете по краю, вы рискуете скомпрометировать свое состояние и никогда не сможете его воссоздать. Если вы запускаете уровень, шаблон очень щадящий и оставляет место для компонентов, которые ведут себя не так, как они должны быть исправлены. Это то, что заставляет Kubernetes так хорошо работать ».

- Джо Беда, технический директор Heptio (цитируется в Cloud Native Infrastructure Джастином Гаррисоном и Крисом Нова)

Прерывания: запуск по фронту и уровню

Запуск по фронту и по уровню - это концепции, пришедшие из электроники и системного программирования. Они относятся к тому, как система должна реагировать на форму электрического сигнала (или цифровой логики) с течением времени. Должна ли система заботиться о том, когда сигнал меняется с низкого на высокий и с высокого на низкий, или она должна заботиться о том, если сигнал высокий?

Чтобы объяснить это по-другому, с учетом следующего простого добавления:

> let a = 3;
> a += 4;
< 7

В представлении операции с запуском по фронту мы увидим:

add 4 to a

Это произойдет один раз во время добавления.

В представлении операции с триггером уровня мы увидим:

a is 7

Мы будем наблюдать это постоянно с момента добавления до следующего события.

Запуск по границе и по уровню в распределенных системах

Говоря абстрактно, нет очевидной разницы между срабатыванием по фронту и по уровню. В реальном мире, даже на уровне системного программирования, нам приходится иметь дело с практическими ограничениями. Распространенным ограничением является частота дискретизации. Если система не производит выборку сигнала достаточно часто, она может пропустить триггер либо для перехода фронта, либо для кратковременного изменения уровня.

В большем масштабе целых компьютеров и больших сетей приходится иметь дело с большим количеством проблем. Сеть ненадежна. Люди неповоротливы. Белки неумолимы. В некотором смысле эти проблемы похожи на плохую или непостоянную частоту дискретизации. Они заслоняют наш взгляд на сигнал.

Нарушения меняют восприятие

Давайте посмотрим, как нарушение сигнала влияет на его наблюдение в системах с синхронизацией по фронту и уровню:

Идеальные условия

В идеальных условиях системы с синхронизацией по фронту и по уровню обеспечивают правильное отображение сигнала. Сразу после того, как сигнал переходит из включенного в выключенное состояние, они оба видят, что сигнал находится в выключенном состоянии.

Два сбоя

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

Одно нарушение

Меньшее количество сбоев не всегда приводит к лучшему результату. С единичным срывом, скрывающим падение от высокого к низкому, система, запускаемая уровнем, в основном снова верна. Система с синхронизацией по фронту видит только два подъема, что приводит к состоянию, в котором исходный сигнал никогда не находился.

Чтобы выразить это еще раз с добавлением, сигнал выражался:

> let a = 1;
> a += 1;
> a -= 1;
> a += 1;
< 2

Но по системе с торцевым срабатыванием наблюдаются:

> let a = 1;
> a += 1;
> a += 1;
< 3

Согласование желаемого и фактического состояний

Kubernetes отслеживает не просто один сигнал, а два: желаемое состояние кластера и фактическое состояние. Желаемое состояние - это состояние, в котором люди, использующие кластер, хотят, чтобы он находился («Запустить два экземпляра контейнера моего приложения»). Фактическое состояние идеально соответствует желаемому, но оно подвержено любому количеству аппаратных сбоев и злонамеренных грызунов. Они могут увести его из желаемого состояния. Важным фактором является даже время, поскольку невозможно мгновенно привести фактическое состояние в соответствие с желаемым. Образы контейнеров должны загружаться из реестра, приложениям требуется время для корректного завершения работы и т. Д.

Kubernetes должен принять фактическое состояние и согласовать его с желаемым состоянием. Он делает это непрерывно, принимая оба состояния, определяя различия между ними и применяя любые изменения, которые необходимо внести, чтобы привести фактическое состояние к желаемому состоянию.

Масштабирование развертывания в Kubernetes

Даже без сбоев в сети система с запуском по фронту, пытающаяся согласовать два состояния, может закончиться неверным результатом.

Если мы начнем с одной реплики контейнера и хотим масштабироваться до 5 реплик, а затем до двух реплик, система с запуском по границе увидит следующее для желаемого состояния:

> let replicas = 1;
> replicas += 4;
> replicas -= 3;

Фактическое состояние системы не может мгновенно реагировать на эти команды. Как показано на диаграмме, он может завершить работу трех реплик, если их всего три. Это оставляет нам 0 реплик вместо 2 желаемых.

В системе с триггером уровней мы всегда полностью сравниваем желаемое и фактическое состояния. Это снижает вероятность десинхронизации состояния (ошибка).

Выравнивание

Запуск по фронту не является плохим по своей сути; у него есть преимущества перед запуском по уровню. Запуск по фронту передает только то, что изменилось, когда оно изменилось.

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

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

Особая благодарность Мэг Смит за диаграммы, включенные в эту статью.