Сегодня мы рассмотрим вопросы о неизменяемости (immutability) в Kubernetes. На фоне новой волны интереса особенно заметно, что сообщество Kubernetes рассматривает эту тему с иной точки зрения, чем раньше. Пользователи меньше сосредоточены на неизменяемости на уровне отдельного узла и больше интересуются тем, как принципы неизменяемости применяются при управлении целым парком кластеров. Именно это является фундаментальной причиной существования проекта Cluster API.
Почему неизменяемость важна
Значимость неизменяемости проистекает из тех преимуществ, которые этот подход даёт приложениям, работающим поверх Kubernetes. Наиболее важные преимущества, которые пользователи Kubernetes получают благодаря неизменяемости, приведены ниже.
Скорость
В современной ИТ-среде скорость имеет первостепенное значение. Например, скорость необходима, когда нужно масштабировать инфраструктуру для обработки всплесков пользовательских запросов, она нужна при выполнении blue/green-развертываний или при масштабировании инфраструктуры вниз, чтобы держать под контролем стоимость приложений или освобождать ресурсы для других задач.
Скорость также критически важна при выполнении операций обслуживания, которые должны укладываться в ограниченное временное окно, или при реагировании на любые виды сбоев — от проблем с одним экземпляром приложения до ситуаций, когда выходит из строя целый регион.
Неизменяемость является фундаментальной основой для достижения скорости во всех этих сценариях и не только. Именно благодаря неизменяемости можно использовать инструменты, позволяющие за миллисекунды запускать десять идентичных Pod’ов, за секунды создавать новые клоны машин, на которых размещаются узлы Kubernetes, или за минуты поднимать новый полностью работоспособный кластер Kubernetes.
Операции в масштабе
С определённой точки зрения современные ИТ-операции находятся на пересечении масштаба и скорости. Неизменяемость крайне важна для решения подобных задач, потому что она создаёт основу для создания согласованных и доверенных клонов ваших Pod’ов, виртуальных машин и даже всего кластера Kubernetes.
Когда вы начинаете использовать такие доверенные клоны, появляется уверенность, что среды разработки, QA и production ведут себя одинаково. Без доверенных клонов вашей операционной команде придётся сталкиваться с дрейфом конфигураций, а «снежинки» (уникальные, неповторимые конфигурации хостов) плохо масштабируются.
Безопасность
Неизменяемость также часто связывают с безопасностью. Хотя это в целом верно, есть несколько уникальных преимуществ, которые неизменяемость даёт именно с точки зрения безопасности. При этом для некоторых аспектов безопасности существуют и другие достойные альтернативы, которые организации могут и должны рассматривать.
Например, одно из уникальных преимуществ — неизменяемость создаёт основу для построения систем, в которых базовые виртуальные машины являются эфемерными, поскольку они периодически пересоздаются «с нуля». Это создаёт движущуюся цель, значительно усложняя работу злоумышленников.
С другой стороны, например, неизменяемая операционная система может успешно использоваться для уменьшения поверхности атаки внутри виртуальной машины, но многие организации достигают той же цели с помощью AppArmor, SELinux, защищённых образов и других механизмов.
Продолжая тот же пример, процесс обновления A/B, характерный для неизменяемых ОС, также может иметь достойную и, возможно, более надёжную альтернативу — когда изменения разворачиваются путём создания новых машин и удаления старых. Результат тот же, но используются простые примитивы создания и удаления — такие же, какие Kubernetes применяет для Pod’ов.
Стабильность
Инженеры-разработчики те, кто поддерживает open source-проекты, постоянно сталкиваются с тем, что у любого проекта или системы есть ограниченный «бюджет сложности», который она может выдержать за определённое время. Когда этот бюджет исчерпывается, начинаются проблемы. Снижается качество, и становится сложно своевременно исправлять ошибки и уязвимости (CVE).
Неизменяемость значительно помогает справляться с этим бюджетом сложности. Она позволяет инженерам резко сократить количество переменных, которые нужно учитывать, например, при управлении жизненным циклом объектов вроде виртуальной машины, на которой работает узел Kubernetes. В результате системы, основанные на принципах неизменяемости, обычно обеспечивают более простую, стабильную и надёжную платформу для приложений. А стабильность и надёжность важны как сегодня, так и для долгосрочной устойчивости вашего технологического стека.
Как добиться неизменяемости в Kubernetes
В своей основе неизменяемость — это концепция, философия. Чтобы сделать её реальностью, нужны технологии, которые поддерживают этот подход. Kubernetes - отличная отправная точка: он предоставляет такие примитивы, как неизменяемые Pod’ы, а также более высокоуровневые абстракции - например Deployments и StatefulSet - для управления ими.
Однако Kubernetes не управляет базовой инфраструктурой. Именно здесь появляется Cluster API, поскольку один из фундаментальных принципов проекта — «Kubernetes на всех уровнях». Cluster API позволяет рассматривать Machine (элемент инфраструктуры, например виртуальную машину, на которой работает узел Kubernetes) как неизменяемый компонент.
Когда требуется изменение, вместо модификации существующей машины Cluster API создаёт новую и удаляет старую — аналогично тому, как Kubernetes заменяет Pod’ы. Предоставляя абстракции для управления группами машин, такие как KubeadmControlPlane и MachineDeployment, Cluster API позволяет усиливать преимущества неизменяемости при управлении целым кластером или даже парком кластеров.
Если вы хорошо знакомы с Cluster API, вы можете заметить, что здесь есть серая зона — операционная система, установленная на машине, управляемой CAPI. Cluster API не занимает жёсткой позиции относительно операционной системы на машине, потому что, как показал опыт последних лет, именно здесь разные организации и продукты могут и должны применять разные подходы.
Во-первых, у каждой организации есть собственные предпочтения относительно используемой ОС и допустимых компромиссов на уровне операционной системы. Во-вторых, многие организации не хотят вводить особый подход к операционной системе машин в кластере Kubernetes. Они предпочитают иметь одну поддерживаемую ОС и использовать её на разных платформах и для разных типов приложений — и чаще всего это не неизменяемая ОС.
Ключом к работе с такими различными требованиями и технологиями являются многочисленные точки расширения Cluster API. Используя эти точки расширения, теперь можно выполнять тщательно проверенный набор операций обновления «на месте» безопасным и полностью автоматизированным способом.
Несколько примеров
Пошаговые обновления (rolling upgrades)
Вместо выполнения сложных процедур обновления существующих машин Cluster API проводит rollout, при котором создаются новые «чистые» машины для замены старых. Этот подход, основанный на принципах неизменяемости, позволяет не только выполнять обновления Kubernetes, но и вносить любые изменения в машины (инфраструктура, ОС и компоненты Kubernetes), используя два простых примитива: создание и удаление Machine.
Процесс по своей природе повторяем и предсказуем; замена каждой машины гарантирует, что каждый узел достигнет желаемого состояния без сюрпризов, часто вызванных конфигурационным дрейфом. Это просто, надёжно, быстро и безопасно.
Кроме того, Cluster API гарантирует соблюдение требований к доступности во время rollout. Он также поддерживает цепочные обновления Kubernetes через несколько минорных версий, а рабочие узлы могут пропускать промежуточные минорные версии, если это допускается политикой version skew Kubernetes.
Восстановление нездоровых машин
Как поступить с машинами, которые постоянно работают некорректно — например, когда узел Kubernetes, размещённый на машине, сообщает состояние Ready = false более пяти минут? Cluster API позволяет определить MachineHealthChecks для обработки таких случаев. Когда запускается автоматическое восстановление, система использует принцип неизменяемости для быстрого и эффективного решения проблемы: быстро создаётся новая «чистая» машина-замена, а старая удаляется — снова используя те же два простых примитива: создание и удаление Machine.
Избегание ненужных rollout’ов
Машины — сложные компоненты, и иногда требуется внести изменения, которые не требуют drain узла или перезапуска Pod’ов; например, изменение сертификата реестра образов.
Если по какой-то причине вы хотите выполнить такие изменения без полного rollout машины, Cluster API предоставляет точки расширения, позволяющие выполнить тщательно проверенный набор обновлений «на месте» безопасным и полностью автоматизированным способом. Даже в этих случаях конфигурационный дрейф предотвращается за счёт одинакового применения изменений ко всем машинам.
Тот же пользовательский опыт, неизменяемость и лучшие стороны изменяемой инфраструктуры — всё под строгим контролем.
Итоги
Неизменяемость лежит в основе многих cloud-native систем, поскольку она обеспечивает скорость, масштабируемость операций и более сильные практики безопасности. В то же время сочетание неизменяемой инфраструктуры с тщательно контролируемыми изменяемыми операциями позволяет организациям использовать и другие проверенные операционные подходы там, где это уместно.
Именно этот баланс между неизменяемой и изменяемой инфраструктурой позволяет командам достигать скорости, безопасности и надёжности при управлении Kubernetes в большом масштабе.