Хабрахабр

[Перевод] GitOps: сравнение методов Pull и Push

Прим. перев.: В сообществе Kubernetes явную популярность набирает тренд под названием GitOps, в чём мы лично убедились, посетив KubeCon Europe 2019. Этот термин был относительно недавно придуман главой компании Weaveworks — Alexis Richardson — и означает применение привычных для разработчиков инструментов (в первую очередь — Git, откуда и само название) для решения задач эксплуатации. В частности, речь об эксплуатации Kubernetes через хранение его конфигураций в Git и автоматического выката изменений в кластер. О двух подходах к этому выкату и рассказывает Matthias Jg в данной статье.

— прим. В прошлом году (на самом деле, формально это произошло в августе 2017 г. Он называется GitOps, а в его основе лежит базовое представление о том, что отслеживание версий deployment'ов ведется в безопасной среде Git-репозитория. перев.) появился новый подход к развёртыванию приложений в Kubernetes.

Основные преимущества у этого подхода следующие:

  1. Версионирование deployment'ов и история изменений. Состояние всего кластера хранится в Git-репозитории, а deployment'ы обновляются только путем коммитов. Кроме того, все изменения можно отслеживать с помощью истории коммитов.
  2. Откаты с использованием привычных команд Git. Простой git reset позволяет сбрасывать изменения в deployment'ах; всегда доступны прошлые состояния.
  3. Готовый контроль доступа. Обычно Git-система содержит множество конфиденциальных данных, поэтому большинство компаний уделяют особое внимание ее защите. Соответственно, эта защита распространяется и на операции с deployment'ами.
  4. Политики для развертываний. Большинство Git-систем изначально поддерживают политики для разных веток — например, только pull request'ы могут обновлять master, а изменения должен проверить и принять другой член команды. Как и с контролем доступа, те же политики применяются к обновлениям deployment'ов.

Как видите, у метода GitOps есть множество преимуществ. За последний год особую популярность набрали два подхода. Один основан на push, другой — на pull. Прежде чем их рассмотреть, давайте сначала посмотрим, как выглядят типичные deployment'ы Kubernetes.

Способы развертывания

За последние годы в Kubernetes устоялись различные способы и инструменты для развертываний:

  1. На основе родных шаблонов Kubernetes/Kustomize. Это самый простой способ развертывания приложений в Kubernetes. Разработчик создает базовые YAML-файлы и применяет их. Чтобы избавиться от постоянного переписывания одних и тех же шаблонов, был разработан Kustomize (он превращает шаблоны Kubernetes в модули). Прим. перев.: Kustomize был интегрирован в kubectl с релизом Kubernetes 1.14.
  2. Чарты Helm. Чарты Helm позволяют создавать наборы шаблонов, init-контейнеров, sidecar'ов и т.п., которые применяются для деплоя приложений с более гибкими возможностями настройки, чем в подходе на основе шаблонов. В основе этого метода лежат шаблонизированные YAML-файлы. Helm заполняет их различными параметрами и затем отправляет Tiller'у — кластерному компоненту, который разворачивает их в кластере и позволяет выполнять обновления и откаты. Важно то, что по сути Helm просто вставляет нужные значения в шаблоны и затем применяет их так же, как это делается в традиционном подходе (подробнее о том, как это всё работает и как можно использовать, читайте в нашей статье по Helm — прим. перев.). Существует большое разнообразие готовых Helm-чартов, охватывающих широкий спектр задач.
  3. Альтернативные инструменты. Есть множество альтернативных инструментов. Всех их объединяет то, что они превращают некие файлы-шаблоны в понятные Kubernetes YAML-файлы и затем применяют их.

В своей работе мы постоянно используем Helm-чарты для важных инструментов (поскольку в них многое уже готово, что значительно упрощает жизнь) и «чистые» YAML-файлы Kubernetes для развертывания собственных приложений.

Pull & Push

В одной из своих недавних публикаций в блоге я представил инструмент Weave Flux, позволяющий коммитить шаблоны в Git-репозиторий и обновлять deployment после каждого коммита или push'а контейнера. Мой опыт показывает, что этот инструмент — один из основных в деле продвижения pull-подхода, поэтому буду часто ссылаться на него. Если хотите узнать больше о том, как его использовать, вот ссылка на статью.

NB! Все преимущества использования GitOps сохраняются для обоих подходов.

Подход на основе Pull

Внутри кластера есть оператор, который регулярно проверяет связанные репозитории Git и Docker Registry. В основе подхода pull лежит тот факт, что все изменения применяются изнутри кластера. Обычно считается, что подобный процесс весьма безопасен, поскольку ни у одного внешнего клиента нет доступа к правам администратора кластера. Если в них происходят какие-либо изменения, состояние кластера обновляется изнутри.

Плюсы:

  1. Ни один внешний клиент не имеет прав на внесение изменений в кластер, все обновления накатываются изнутри.
  2. Некоторые инструменты также позволяют синхронизировать обновления Helm-чартов и привязывать их к кластеру.
  3. Docker Registry можно сканировать на наличие новых версий. Если появляется новый образ, Git-репозиторий и deployment обновляются на новую версию.
  4. Pull-инструменты могут быть распределены по разным пространствам имен с разными репозиториями Git и правами доступа. Благодаря этому можно применять мультиарендную (multitenant) модель. Например, команда А может использовать пространство имен А, команда В — пространство имен В, а команда, занимающаяся инфраструктурой, может использовать глобальное пространство.
  5. Как правило, инструменты весьма легковесны.
  6. В сочетании с такими инструментами, как оператор Bitnami Sealed Secrets, секреты могут храниться в зашифрованном виде в репозитории Git и извлекаться внутри кластера.
  7. Отсутствует связь с CD-пайплайнами, поскольку развертывания происходят внутри кластера.

Минусы:

  1. Управлять секретами deployment'ов из Helm-чартов сложнее, чем обычными, поскольку сначала их приходится генерировать в виде, скажем, sealed secrets, затем расшифровывать внутренним оператором и только после этого они становятся доступны для pull-инструмента. Затем можно запускать релиз в Helm'е со значениями в уже развернутых секретах. Самый простой способ — создать секрет со всеми значения Helm, используемыми для deployment'а, расшифровать его и закоммитить в Git.
  2. Применяя pull-подход, вы оказываетесь привязаны к инструментам, оперирующим pull'ами. Это ограничивает возможность настройки процесса развертывания deployment'ов в кластере. Например, работа с Kustomize осложняется тем, что он должен выполняться до того, как окончательные шаблоны поступают в Git. Я не говорю, что нельзя использовать отдельные инструменты, но их сложнее интегрировать в процесс развертывания.

Подход на основе Push

В этом подходе система обладает доступом в кластер. В push-подходе внешняя система (преимущественно CD-пайплайны) запускает развертывания в кластер после коммита в Git-репозиторий или в случае успешного выполнения предыдущего CI-пайплайна.

Плюсы:

  1. Безопасность определяется Git-репозиторием и пайплайном сборки.
  2. Развертывать чарты Helm проще, есть поддержка плагинов Helm.
  3. Управлять секретами легче, поскольку секреты можно применять в пайплайнах, а также хранить в Git в зашифрованном виде (в зависимости от предпочтений пользователя).
  4. Отсутствие привязки к конкретному инструменту, поскольку можно использовать любые их типы.
  5. Обновления версий контейнеров могут быть инициированы пайплайном сборки.

Минусы:

  1. Данные для доступа к кластеру находятся внутри системы сборки.
  2. Обновление контейнеров deployment'ов по-прежнему проще проводить с pull-процессом.
  3. Сильная зависимость от CD-системы, поскольку нужные нам пайплайны, возможно, изначально написаны под Gitlab Runners, а затем команда решит перейти на Azure DevOps или Jenkins… и придется производить миграцию большого количества пайплайнов сборки.

Итоги: Push или Pull?

Как обычно это бывает, у каждого подхода есть свои плюсы и минусы. Некоторые задачи легче осуществить с одним и сложнее — с другим. Поначалу я проводил развертывания вручную, но после того, как наткнулся на несколько статей о Weave Flux, решил внедрить GitOps-процессы для всех проектов. Для базовых шаблонов это оказалось легко, но потом я начал сталкиваться с трудностями в работе с Helm-чартами. В то время Weave Flux предлагал только зачаточную версию Helm Chart Operator, но даже сейчас некоторые задачи сложнее из-за необходимости вручную создавать секреты и применять их. Вы можете сказать, что pull-подход гораздо защищеннее, поскольку учетные данные кластера недоступны за его пределами, а это настолько повышает безопасность, что стоит дополнительных усилий.

Если говорить о компонентах, требующих максимальной защиты, в такой список войдут хранилища секретов и CI/CD-системы, Git-репозитории. Поразмыслив немного, я пришел к неожиданному выводу, что это не так. Кроме того, если кто-то проникнет в ваш репозиторий Git и сможет push'ить туда код, то он сможет развернуть все, что пожелает (независимо от выбранного подхода, будет это pull или push), и внедриться в системы кластера. Информация внутри них весьма уязвима и нуждается в максимальной защите. Если у вас хорошо настроены политики и меры безопасности для систем такого типа, а учетные данные кластера извлекаются в пайплайны только в виде секретов, дополнительная безопасность pull-подхода может оказаться не такой ценной, как первоначально предполагалось. Таким образом, наиболее важными компонентами, требующими защиты, являются Git-репозиторий и CI/CD-системы, а не учетные данные кластера.

Но ведь кто-то может заявить, что в push-подходе вы слишком завязаны на CD-систему и, возможно, лучше так не делать, чтобы в будущем было проще осуществлять миграции. Итак, если pull-подход более трудоемкий и не дает выигрыша в безопасности, не логично ли использовать только push-подход?

Лично я пользуюсь обоими подходами: Weave Flux для deployment'ов на основе pull, которые в основном включают наши собственные сервисы, и push-подход с Helm'ом и плагинами, упрощающий применение Helm-чартов к кластеру и позволяющий без проблем создавать секреты. На мой взгляд (как и всегда), следует использовать то, что больше подходит к конкретному случаю или комбинировать. При этом я настоятельно рекомендую GitOps — он сильно облегчает жизнь и повышает безопасность. Думаю, никогда не будет единого решения, подходящего для всех случаев, потому что нюансов всегда очень много и они зависят от конкретного варианта применения.

Надеюсь, мой опыт по данной теме поможет определиться, какой метод больше подходит для вашего типа deployment'ов, а я буду рад узнать ваше мнение.

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

В минусах pull-модели есть пункт про то, что сложно положить в Git отрендеренные манифесты, однако нет минуса, что CD-пайплайн в pull-модели живёт отдельно от выката и по сути становится пайплайном категории Continuous Apply. Поэтому потребуется ещё больше усилий для того, чтобы собирать со всех deployment'ов их статус и как-то давать доступ к логам/статусу, причем желательно с привязкой к CD системе.

В этом смысле push-модель позволяет дать хоть какие-то гарантии выката, потому что время жизни pipeline'а можно сделать равным времени жизни выката.

Мы опробовали обе модели и пришли к тем же выводам, что и автор статьи:

  1. Pull-модель подходит нам для организации обновления системных компонентов на большом количестве кластеров (см. статью про addon-operator).
  2. Push-модель на основе GitLab CI хорошо подходит для выката приложений с помощью Helm-чартов. При этом выкат deployment'ов в рамках пайплайнов отслеживается с помощью инструмента werf. К слову, в контексте этого нашего проекта мы и слышали постоянное «GitOps», когда обсуждали насущные проблемы DevOps-инженеров у своего стенда на KubeCon Europe'19.

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

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

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть