[Перевод] GitOps: сравнение методов Pull и Push
Прим. перев.: В сообществе Kubernetes явную популярность набирает тренд под названием GitOps, в чём мы лично убедились, посетив KubeCon Europe 2019. Этот термин был относительно недавно придуман главой компании Weaveworks — Alexis Richardson — и означает применение привычных для разработчиков инструментов (в первую очередь — Git, откуда и само название) для решения задач эксплуатации. В частности, речь об эксплуатации Kubernetes через хранение его конфигураций в Git и автоматического выката изменений в кластер. О двух подходах к этому выкату и рассказывает Matthias Jg в данной статье.
В прошлом году (на самом деле, формально это произошло в августе 2017 г. — прим. перев.) появился новый подход к развёртыванию приложений в Kubernetes. Он называется GitOps, а в его основе лежит базовое представление о том, что отслеживание версий deployment’ов ведется в безопасной среде Git-репозитория.
Основные преимущества у этого подхода следующие:
- Версионирование deployment’ов и история изменений. Состояние всего кластера хранится в Git-репозитории, а deployment’ы обновляются только путем коммитов. Кроме того, все изменения можно отслеживать с помощью истории коммитов.
- Откаты с использованием привычных команд Git. Простой
git reset
позволяет сбрасывать изменения в deployment’ах; всегда доступны прошлые состояния. - Готовый контроль доступа. Обычно Git-система содержит множество конфиденциальных данных, поэтому большинство компаний уделяют особое внимание ее защите. Соответственно, эта защита распространяется и на операции с deployment’ами.
- Политики для развертываний. Большинство Git-систем изначально поддерживают политики для разных веток — например, только pull request’ы могут обновлять master, а изменения должен проверить и принять другой член команды. Как и с контролем доступа, те же политики применяются к обновлениям deployment’ов.
Как видите, у метода GitOps есть множество преимуществ. За последний год особую популярность набрали два подхода. Один основан на push, другой — на pull. Прежде чем их рассмотреть, давайте сначала посмотрим, как выглядят типичные deployment’ы Kubernetes.
Способы развертывания
За последние годы в Kubernetes устоялись различные способы и инструменты для развертываний:
- На основе родных шаблонов Kubernetes/Kustomize. Это самый простой способ развертывания приложений в Kubernetes. Разработчик создает базовые YAML-файлы и применяет их. Чтобы избавиться от постоянного переписывания одних и тех же шаблонов, был разработан Kustomize (он превращает шаблоны Kubernetes в модули). Прим. перев.: Kustomize был интегрирован в kubectl с релизом Kubernetes 1.14.
- Чарты Helm. Чарты Helm позволяют создавать наборы шаблонов, init-контейнеров, sidecar’ов и т.п., которые применяются для деплоя приложений с более гибкими возможностями настройки, чем в подходе на основе шаблонов. В основе этого метода лежат шаблонизированные YAML-файлы. Helm заполняет их различными параметрами и затем отправляет Tiller’у — кластерному компоненту, который разворачивает их в кластере и позволяет выполнять обновления и откаты. Важно то, что по сути Helm просто вставляет нужные значения в шаблоны и затем применяет их так же, как это делается в традиционном подходе (подробнее о том, как это всё работает и как можно использовать, читайте в нашей статье по Helm — прим. перев.). Существует большое разнообразие готовых Helm-чартов, охватывающих широкий спектр задач.
- Альтернативные инструменты. Есть множество альтернативных инструментов. Всех их объединяет то, что они превращают некие файлы-шаблоны в понятные Kubernetes YAML-файлы и затем применяют их.
В своей работе мы постоянно используем Helm-чарты для важных инструментов (поскольку в них многое уже готово, что значительно упрощает жизнь) и «чистые» YAML-файлы Kubernetes для развертывания собственных приложений.
Pull & Push
В одной из своих недавних публикаций в блоге я представил инструмент Weave Flux, позволяющий коммитить шаблоны в Git-репозиторий и обновлять deployment после каждого коммита или push’а контейнера. Мой опыт показывает, что этот инструмент — один из основных в деле продвижения pull-подхода, поэтому буду часто ссылаться на него. Если хотите узнать больше о том, как его использовать, вот ссылка на статью.
NB! Все преимущества использования GitOps сохраняются для обоих подходов.
Подход на основе Pull
В основе подхода pull лежит тот факт, что все изменения применяются изнутри кластера. Внутри кластера есть оператор, который регулярно проверяет связанные репозитории Git и Docker Registry. Если в них происходят какие-либо изменения, состояние кластера обновляется изнутри. Обычно считается, что подобный процесс весьма безопасен, поскольку ни у одного внешнего клиента нет доступа к правам администратора кластера.
Плюсы:
- Ни один внешний клиент не имеет прав на внесение изменений в кластер, все обновления накатываются изнутри.
- Некоторые инструменты также позволяют синхронизировать обновления Helm-чартов и привязывать их к кластеру.
- Docker Registry можно сканировать на наличие новых версий. Если появляется новый образ, Git-репозиторий и deployment обновляются на новую версию.
- Pull-инструменты могут быть распределены по разным пространствам имен с разными репозиториями Git и правами доступа. Благодаря этому можно применять мультиарендную (multitenant) модель. Например, команда А может использовать пространство имен А, команда В — пространство имен В, а команда, занимающаяся инфраструктурой, может использовать глобальное пространство.
- Как правило, инструменты весьма легковесны.
- В сочетании с такими инструментами, как оператор Bitnami Sealed Secrets, секреты могут храниться в зашифрованном виде в репозитории Git и извлекаться внутри кластера.
- Отсутствует связь с CD-пайплайнами, поскольку развертывания происходят внутри кластера.
Минусы:
- Управлять секретами deployment’ов из Helm-чартов сложнее, чем обычными, поскольку сначала их приходится генерировать в виде, скажем, sealed secrets, затем расшифровывать внутренним оператором и только после этого они становятся доступны для pull-инструмента. Затем можно запускать релиз в Helm’е со значениями в уже развернутых секретах. Самый простой способ — создать секрет со всеми значения Helm, используемыми для deployment’а, расшифровать его и закоммитить в Git.
- Применяя pull-подход, вы оказываетесь привязаны к инструментам, оперирующим pull’ами. Это ограничивает возможность настройки процесса развертывания deployment’ов в кластере. Например, работа с Kustomize осложняется тем, что он должен выполняться до того, как окончательные шаблоны поступают в Git. Я не говорю, что нельзя использовать отдельные инструменты, но их сложнее интегрировать в процесс развертывания.
Подход на основе Push
В push-подходе внешняя система (преимущественно CD-пайплайны) запускает развертывания в кластер после коммита в Git-репозиторий или в случае успешного выполнения предыдущего CI-пайплайна. В этом подходе система обладает доступом в кластер.
Плюсы:
- Безопасность определяется Git-репозиторием и пайплайном сборки.
- Развертывать чарты Helm проще, есть поддержка плагинов Helm.
- Управлять секретами легче, поскольку секреты можно применять в пайплайнах, а также хранить в Git в зашифрованном виде (в зависимости от предпочтений пользователя).
- Отсутствие привязки к конкретному инструменту, поскольку можно использовать любые их типы.
- Обновления версий контейнеров могут быть инициированы пайплайном сборки.
Минусы:
- Данные для доступа к кластеру находятся внутри системы сборки.
- Обновление контейнеров deployment’ов по-прежнему проще проводить с pull-процессом.
- Сильная зависимость от 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), и внедриться в системы кластера. Таким образом, наиболее важными компонентами, требующими защиты, являются Git-репозиторий и CI/CD-системы, а не учетные данные кластера. Если у вас хорошо настроены политики и меры безопасности для систем такого типа, а учетные данные кластера извлекаются в пайплайны только в виде секретов, дополнительная безопасность pull-подхода может оказаться не такой ценной, как первоначально предполагалось.
Итак, если pull-подход более трудоемкий и не дает выигрыша в безопасности, не логично ли использовать только push-подход? Но ведь кто-то может заявить, что в push-подходе вы слишком завязаны на CD-систему и, возможно, лучше так не делать, чтобы в будущем было проще осуществлять миграции.
На мой взгляд (как и всегда), следует использовать то, что больше подходит к конкретному случаю или комбинировать. Лично я пользуюсь обоими подходами: Weave Flux для deployment’ов на основе pull, которые в основном включают наши собственные сервисы, и push-подход с Helm’ом и плагинами, упрощающий применение Helm-чартов к кластеру и позволяющий без проблем создавать секреты. Думаю, никогда не будет единого решения, подходящего для всех случаев, потому что нюансов всегда очень много и они зависят от конкретного варианта применения. При этом я настоятельно рекомендую GitOps — он сильно облегчает жизнь и повышает безопасность.
Надеюсь, мой опыт по данной теме поможет определиться, какой метод больше подходит для вашего типа deployment’ов, а я буду рад узнать ваше мнение.
P.S. Примечание от переводчика
В минусах pull-модели есть пункт про то, что сложно положить в Git отрендеренные манифесты, однако нет минуса, что CD-пайплайн в pull-модели живёт отдельно от выката и по сути становится пайплайном категории Continuous Apply. Поэтому потребуется ещё больше усилий для того, чтобы собирать со всех deployment’ов их статус и как-то давать доступ к логам/статусу, причем желательно с привязкой к CD системе.
В этом смысле push-модель позволяет дать хоть какие-то гарантии выката, потому что время жизни pipeline’а можно сделать равным времени жизни выката.
Мы опробовали обе модели и пришли к тем же выводам, что и автор статьи:
- Pull-модель подходит нам для организации обновления системных компонентов на большом количестве кластеров (см. статью про addon-operator).
- Push-модель на основе GitLab CI хорошо подходит для выката приложений с помощью Helm-чартов. При этом выкат deployment’ов в рамках пайплайнов отслеживается с помощью инструмента werf. К слову, в контексте этого нашего проекта мы и слышали постоянное «GitOps», когда обсуждали насущные проблемы DevOps-инженеров у своего стенда на KubeCon Europe'19.
P.P. S. от переводчика
Читайте также в нашем блоге: