Когда последний раз вы подходили к вашему выгоревшему девопсу, по отцовски хлопали его по плечу и говорили — «Мне нравится твой пайплайн»?
Как гласит известная народная мудрость — «Кто как хочет, тот так и деплоит». И это не метафора, за свою недолгую карьеру, я ни разу не видел одинаковых пайплайнов.
Существует по меньшей мере десятки способов деплоя приложений в Kubernetes, но любой деплой всегда начинается с подготовки манифеста. В данной статье я нарочно обойду автоматизацию деплоя и CI\CD пайплайны, вернее обойду средства, с помощью которых эти пайплайны пишут. В данном материале поговорим про способы подготовки манифестов для Kubernetes.
Сегодня основным инструментом для передачи манифестов в Kubernetes является утилита kubectl
. Это первый и самый очевидный способ подготовки манифеста — манифест надо просто написать «руками». По сути данная утилита просто работает с kube‑apiserver и передает ему манифест. Подавляющее большинство учебных материалов для демонстрации деплоя используют kubectl
и статические манифесты. Но на практике таким подходом мало кто пользуется. Не поймите меня неправильно, но если, используя kubectl
и статические манифесты вы подойдете ко взрослым дядям и спросите как деплоить, то однозначно вам дадут две вещи:
леща
совет пользоваться шаблонизатором
Конечно, в использовании kubectl
в паре со статическими манифестами есть много плюсов. Как минимум вы всегда видите то что деплоите, и вы всегда на выходе получаете то что хотели, если конечно на входе не стоит какой‑нибудь Admission Controller, или внутри вашего кластера не работает сумасшедший оператор, который базовый манифест, поданный на вход, превращает в нечто другое. Но не будем о грустном. Статика это всегда ещё удобно и с точки зрения безопасности, понимания того, что происходит у вас в инфраструктурном коде с одного взгляда.
И все же, если вы разрабатываете современный продукт, то скорее всего вам нужна шаблонизация. На наше счастье далеко ходить не надо и в утилите kubectl
уже встроен инструмент kustomize
. Раньше данный инструмент был в инкубаторе и его приходилось использовать отдельно от kubectl
, да и функционалом он не блистал. По сути он просто мерджил заранее подготовленные куски манифестов. На мой личный взгляд единственная его сильная сторона это генерация секретов. В последних версиях инструмент конечно стал стабильнее, функционала стало существенно больше — например, забегая вперёд, с помощью kustomize
вы можете конвертировать и деплоить helm чарты.
Что бы начать пользоваться kustomize
вам всего лишь необходимо определять манифесты, следуя довольно не сложным правилам организации директорий. Есть директория с базовыми кусочками кода, которые используются всеми манифестами и есть директории с кусочками «кастомизированных» настроек. По сути это основа данного инструмента. Мы готовим кусочки манифестов, раскладываем их по каталогам, далее эти кусочки соединяются между собой в финальный манифест. Важно, что используя kustomize
вы сразу становитесь gitops ready, так как все перспективные CI\CD инструменты такие как Spinnake, FluxCD или ArgoCD уж очень любят kustomize
и с ним дружат из коробки. Ну и немаловажную роль играет то, что данный инструмент подготовки манифестов теперь является частью утилиты kubectl
.
Давайте чуть‑чуть выдохнем и сделаем лирическое отступление. Если конечно кто‑то вдыхал. Звучит так, как‑будто я рассчитываю что мою статью прочитают на одном дыхании:) Представим что у вас возникает вопрос, а можно ли как‑нибудь задеплоить приложение в Kubernetes без kubectl
? Ответ да. kubectl
это по сути REST API клиент и этот клиент оперирует обычными HTTP запросами в kube‑apiserver. Всё что делает kubectl
можно провернуть используя, скажем, curl
. И иногда это оправдано, но это тема для другой статьи. Скажем так: — Я это видел, я это делал, тебе это не нужно. Можно пойти еще дальше, в принципе вам ничего не мешает писать данные в обход API сразу в etcd кластера. И это будет работать и возможно существуют люди которые именно так и делают. За таких инженеров, пьют стоя и не чёкаясь.
Теперь вернемся к способам подготовки манифестов. «Я деплою в пятницу вечером и не боюсь смотреть людям в глаза». Это про тех кто использует Helm. Пожалуй это самая мощная на сегодняшний день утилита для подготовки манифестов.
На самом деле сам Helm не позиционирует себя как просто шаблонизатор, параметризатор или кастомайзер. Сам себя Helm громко называет пакетным менеджером для kubernetes. Первым и единственным. Он не только позволяет создавать манифесты, но он может сам их деплоить в kubernetes. Всё по честному, без использования kubectl
и прочих утилит. Кроме того у Helm есть свой набор правил и подходов к организации манифестов приложения. Всё это реализуется через сущность Helm Chart. Используя Helm Chart можно запаковать в дистрибутив (а по сути tar.gz архив) любое приложение состоящее из манифестов Kubernetes и даже, приготовьтесь, состояние такого приложения.
Уровень параметризации Helm чартов по истине запредельный - можно написать такой Helm Chart где каждая строчка манифеста, буквально, будет параметризированна. Ну или например можно написать один Helm Chart таким образом, что передавая параметры с помощью утилиты helm
мы сможем сгенерировать абсолютно любой манифест. Ниже, незамысловатый пример в котором, в зависимости от того, какой kind вы укажите в переменных, такой манифест на выходе получите. Пожалуйста, не делайте так.
---
{{ if eq .Values.kind "Secret" }}
apiVersion: v1
kind: {{ .Values.kind }}
metadata:
name: myregistrykey
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: 11
{{ end }}
{{ if eq .Values.kind "Deployment" }}
apiVersion: apps/v1
kind: {{ .Values.kind }}
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
{{ end }}
Среди прочих способов подготовки манифестов, Helm имеет поддержку версий чартов и репозитории для чартов, плагины, большое комьюнити, низкий порог входа и хорошую документацию. И да, манифесты написанные с помощью Helm легко переиспользуются, что бы это для вас не означало.
Идем дальше. Кто работает с Openshift знает про то, что существует утилита oc
и эта утилита имеет встроенный шаблонизатор под названием Template. Да, это не самый очевидный способ деплоя в kubernetes, но он вполне рабочий. Я знаю продуктовые команды которые успешно используют утилиту oc
в качестве основного шаблонизатора в проекте и подготавливают им манифесты. Главное, он позволяет определять в манифесте переменные, a что вам еще нужно?
Еще один распространенный способ подготовки манифестов это использование Ansible. Неожиданно, но этот мощный инструмент по конфигурации операционных систем может подготавливать манифесты с помощью шаблонизатора Jinja и даже деплоить манифесты в kubernetes.
Где‑то рядом с этим подходом стоят инженеры которые используют для генерации манифестов скриптовые языки. Достаточно взять статический манифест, добавить в него переменные, а потом прогнать эти манифесты через рендер с помощью интерпретатора Python, Bash или ещё какого‑нибудь скриптовый языка, подставив нужные параметры вместо переменных. Далее остается только с помощью kubectl
или curl
скормить манифест kube‑apiserver. В прочем минусы данного подхода довольно очевидны — с ростом проекта будет увеличиваться ресурс который необходимо закладывать на поддержку данного вида подготовки манифестов.
Еще один способ подходит для разработчиков со стажем. Существует огромное количество библиотек под языки программирования которые реализуют сущности kubernetes в парадигме данного языка. Это позволяет не просто деплоить приложения прямо из кода, но и писать специальные приложения для kubernetes которые называются операторами. Такие приложения часто реализуют логику деплоя или мутации. Если описать процесс общими словами, то вы отправляете запрос в kubernetes с минимальным количеством информации (CRD) — например образ контейнера и номер порта на котором хотите что бы работало ваше приложение. Оператор подхватывает ваш запрос и исходя из внутренней логики, начинает производит в кластере всяческие действия по добавлению манифестов — в итоге вы получаете приложение. Такой подход может показаться не гибким и требует постоянно поддерживать оператор, но у него есть и неоспоримые плюсы — например полный контроль параметров манифеста, что повышает стабильность и безопасность.
Напоследок, хотелось бы сказать что мир контейнерных приложений настолько разнообразен, что в нём можно увидеть много необычных и подчас странных способов реализации казалось бы простых задач. По этому я не удивлюсь если данный набор способов можно разбавить еще парой, а может и больше.