Новый день, солнце, душ, кофе и инженер садится заниматься своими задачами по созданию или обновлению продукта. В свою очередь пользователь находится по другую сторону баррикад — использует готовый продукт, который упрощает его жизнь. Время показывает, что любой развивающийся бизнес должен идти в ногу со временем. По большей части, суть этой концепции в том, что каждый человек в этой цепочке чего-то хочет. Получается, что быстро придуманная идея — требует быстрой реализации. В текущих реалиях все IT-продукты разрабатываются с использованием какого-либо ПО, способного управлять репозиториями программного кода для Git. В нашем случае, хотелось бы рассказать про один из самых популярных продуктов Gitlab. «Gitlab — наше всё» должно быть слоганом каждой компании, которая его использует, иначе могут произойти события, которые приведут к печальным последствиям. На Habr можно найти множество различной информации, связанной с кейсами, туториалами или просто интересными историями про GitLab. Но сколько бы ни было написано, найти место где было бы собрано всё и сразу — не получилось. Придется исправлять.  Начнём? Новый день, солнце, душ, кофе и разработчик садится разбирать эпик. Первое, что он там видит — это деплой в среду тестирования нового функционала. Смело вешая тэг на master ветку, его релиз уверенно падает на стадии build-а образа контейнера. Как такое могло произойти и почему так вышло? Неожиданный результат, опубликованный в рамках канала slack, создаёт отклик в душе других сотрудников компании. Коллеги, не работают все процессы CI/CD, все релизы и тесты падают с различными ошибками. Как бы это странно ни звучало, но все Devops-инженеры, изучая проблему, приходят в лёгкое удивление, ведь причина возникновения множества ошибок непонятна. То, что вчера ещё работало — сегодня уже остановило весь процесс разработки.  Лучше всегда всё начинать сначала, этот подход помог и здесь. Ранее при первоначальных настройках различных pipelines во все проектах для стадий build, test и deploy использовался всем известный подход DIND (Docker-in-Docker) и тут нас не может не радовать, что образ для всех job имеет тэг latest. Вечерним релизом (накануне проблемы) разработчики продукта docker произвели обновление версии docker в образе dind до 24.0 и все описанные старым способом процессы сборки, тестирования и деплоя начали падать с ошибками docker. Быстрое понимание проблемы помогло найти и решение, изменив текущий tag образа в каждой джобе на 23.0-dind, но и тут возникла весьма интересная проблема, которая говорит об отсутствии детального понимания принципов настройки Gitlab и его раннеров. Образ джобы не был описан глобально, а в индивидуальном варианте для каждого pipeline. «Зачем?» — остается загадкой. В процессе настройки runner-ов каждый имеет свой подход: Закрепление runners за определенными группами, подгруппами, репозиториями. Настройка runners для деплоя джоб имеющих соответствующий ему tag. Подключение runners глобально на уровне панели администратора, предоставляя доступ к нему всем проектам вашего Gitlab. Если же вы используете именно последний подход, то самым простым и правильным вариантом решения для вас будет настройка образа джобы именно на уровне этого раннера в config.toml: Что получается в итоге?  При отсутствии описания во всех ваших .gitlab-ci.yml образа джобы, по умолчанию будет вызываться необходимый нам образ docker:23.0-dind. В результате подобного инцидента, который произошёл фактически из-за очень маленькой ошибки разработки, трудозатраты DevOps-инженеров на причину понимания проблемы, глобальные правки во всех манифестах .gitlab-ci.yml, которые не имели бы никакого смысла при исходно правильной настройке. Тот же день, пекло, обед, сэндвич, латте, yaml манифесты и IaC (Infrastructure-as-Code). IaC — это очень популярный и полезный подход, так как если мы говорим про Kubernetes, то в первую очередь мы подразумеваем декларативный подход. Соответственно, когда мы планируем использовать Terraform с использованием облачного провайдера для описания нашей инфраструктуры, то наш путь исконно верный. Ещё один интересный кейс, с которым мы столкнулись в схожей проблеме, был завязан вновь на неправильном подходе или настройке Gitlab.  Описав развертывание большого количества виртуальных машин в облаке и параллельно настроив сеть для них, межсетевое взаимодействие, security groups, релиз был успешно запушен в репозиторий, где посредством заранее описанного процесса CI/CD выполнялись стадии validate, plan, apply и сохранение terraform.state в Infrastructure/Terraform. После успешного отрабатывания всех 3-х стадий, можно фактически убедиться в веб-панели облака о наличии развернутых ресурсов, но каким было удивление, когда было обнаружено, что terraform.state был записан не полностью? Получается, все повторные запуски нашего pipeline при изменении ресурса имели безукоризненное падение, а при анализе вывода успешно отработанных джоб результат посмотреть не удавалось из-за ограниченности вывода количества информации в output. Как быть и как этого избежать? Вариантов решения данного вопроса множество, в первую очередь надо не забывать о существующих ограничениях в Gitlab на размер вашего terraform.tfstate: Во-вторых, не забываем поднимать лимит по количеству строк для gitlab-runners, добавляя output_limit в основной блок: В-третьих, очень важным моментом является разделение создаваемых ресурсов Terraform на различные модули. Как пример, вынос создания Network и Security groups в отдельные модули и дальнейшее переиспользование готовых сущностей через data sources для упрощения понимания аспектов управления инфраструктурой и уменьшение исходного tfstate. Самая интересная и самая любимая часть каждого Devops-инженера это, само собой, реализация подхода деплоя и здесь, когда спрашиваешь у коллеги: «А как сделали вы?», возникает целая дискуссия с дебатами и беспрерывными выяснениями, а кто же прав.  Поехали? :)  Каждый любит строить проект и процессы деплоя с нуля, но если вы находитесь на любой из стадий, то обратите сразу внимание на ряд принципиально важных моментов, которые упростят вам жизнь. Распределяйте все микросервисы по раздельным репозиториям в рамках определенной группы или подгруппы — это упростит предоставления доступов для каждого проекта, а также поможет в реализации использования Gitlab CI/CD variables. Тут же хочется поделиться, что периодически встречается архитектура, когда в рамках одного репозитория лежит 20 каталогов с различными микросервисами, где используются разные подходы и исходные образы для деплоя. «Зачем и почему?» — вопросы хорошие.  Определяйте переменные для Gitlab CI/CD пайплайнов глобально в панели администратора или на уровне групп, подгрупп. Согласитесь, дублировать одну и ту же переменную в рамках каждого репозитория — себя не уважать. Особенно будет интересно править их все после изменения переменной или протухания токена.  Отойдите от концепции использования кастомных .gitlab-ci.yml в рамках каждого процесса деплоя. Пишите шаблонизированные .gitlab-ci.yml, подвязываясь под внутренние переменные самого Gitlab, для реализации этого подхода вполне прекрасно подходят include, extends, reference. В дальнейшим их можно с лёгкостью переиспользовать для деплоя других микросервисов:Глобальный конфиг build:        Глобальный конфиг deploy:       Частный конфиг в виде джоб в pipeline: Если вы используете Gitlab CI/CD variables и у вас есть переменные, идентичные по названию, но разные по содержанию — всегда используйте Environments.  Самое интересное в этой маленькой, но приятной фиче, что у вас есть возможность использовать регулярные выражения при указании переменных в Gitlab, что делает весь этот механизм ещё более простым и комфортным. Выберите свой подход в процессе Continuous Deployment/Delivery приложений и микросервисов, если вы работаете с kubernetes. На данный момент есть несколько вариантов деплоя.    6.1. Деплой в kubernetes, OLD средствами.  Старое — не значит неработающее. Создаём Namespace, ServiceAccount, Secret, rbac policy и генерируем для него kubeconfig, с помощью которого можно будет безопасно и уверенно совершать деплой в определённый Namespace.  Удобен ли данный вариант? — Вряд ли Но он помогает детально понимать все аспекты деплоя со стороны безопасности в рамках кластера k8s и опять же в данном способе нет никаких завязок на стороннее ПО. При этом можно с легкостью автоматизировать весь этот процесс, написав Terraform модуль на основе kubernetes provider и gitlab provider. Но если безопасность у вас на данный момент не на первом месте и в целом вы человек прогрессивный, то никто не мешает обратиться к современным подходам. Перейдём к динозаврам...    6.2. Деплой в kubernetes через Gitlab интеграцию (Kubernetes cluster) — да, да, да.   Для тех кто не знал, расскажу просто и легко. После предоставления ca.crt вашего кластера kubernetes Gitlab-у, вы получаете из группы или подгруппы настроенный деплой из коробки. Если конкретизировать, то используя ca.crt, Gitlab integration генерирует kubeconfig для деплоя в namespace, добавляя его в виде tmp файла в рамках запущенной джобы вашего pipeline. Получается все шаги описанные в пункте 1 можно не делать? — да Помимо упрощения процесса деплоя эта интеграции предоставляет большое количество дополнительных функций. Как пример, при добавлении к deployment annotations можно было получить доступ до shell контейнера прямо из web интерфейса Gitlab. Но не бывает хороших новостей без плохих, в версии Gitlab 17.0.0 данный функционал возможно уберут и заменят на другой подход реализации процесса интеграции, если ранее процесс деплоя настраивался из Gitlab до K8S через kubeconfig, то теперь процесс работает по принципу взаимодействия:    6.3. Деплой в kubernetes через Gitlab интеграцию (Kubernetes cluster). Новый, актуальный, свежий и как уже было написано ранее — безопасный вариант. В настройке он также весьма прост. Делаем инсталляцию helm chart-а готовыми командами, предоставляемыми Gitlab-ом, и создаём конфигурацию в рамках репозитория, в которой мы подключали наш gitlab-agent: В нашем репозитории необходимо создать схожую структуру с одним yaml конфигом, в рамках которого будут описаны те проекты, которым должны предоставлять возможности деплоя через наш gitlab-agent. Файл лежит по следующему пути и выглядит примерно следующим образом:  Здесь важно  понимать, что вам нужно точечно на уровне репозиториев или глобально на уровне группы предоставить доступ для деплоя через gitlab-agent. Важно заметить, что gitlab-agent не может как и ранее выйти за пределы группы Gitlab. Получается в случае, если у вас 2 группы с микросервисами backend и frontend, то вам придётся для одного кластера создавать и деплоить 2 разных агента. Выглядит как минус и лишняя работа, но это маленький шаг в сторону безопасности. Однако нельзя забывать и про существенный минус, с которым можно столкнуться. Все инженеры любят (и правильно делают), когда обновляют Gitlab — важным моментом здесь является то, что люди, использующие интеграцию для деплоя, неожиданно для себя и для своей команды узнали об уходе в deprecated старого механизма деплоя. Перед обновлением на 17.0.0 версию Gitlab надо будет кардинально подготовиться и переключить все существующие деплои, потеряв часть приятного интерактивного функционала и минусом является даже не это, а то, что вероятнее всего в будущем ситуация повторится и нужно предельно внимательно следить за релизами и это, по сути, является императивной нормой любого продукта. Обновления — от них не застрахован никто. Весьма частая и регулярная задача, с которой сталкиваются администраторы и DevOps-инженеры — это обновление Gitlab. Первая ошибка новичка, само собой, обновиться сразу с версии 13 до версии 16.2.1 в 1 шаг. На этот случай Gitlab уже давно разработали весьма удобную площадку, описывающую поэтапность обновления с релизами c вашей версии до последней актуальной. Но самая банальность проблемы заключается в не изучении изменения функционала релиза. Используйте VPN, чтобы открыть сайт. К примеру, все ваши процессы build и deploy контейнера завязаны на использовании вышеописанных глобальных CI/CD переменных: В последнем релизе происходит удаление этой переменной или изменения её названия. Результат: все текущие и ранее актуальные pipeline переходят в нерабочий статус, что сразу же грозит простоем разработки и разбором нового инцидента.  Вечер, горячий чай, тёплый ужин и осознание… Имея под рукой Gitlab, у вас появляется большое количество возможностей и большое количество потенциальных проблем. Регулярные релизы со стороны разработки продукта покрывают оба описанных аспекта ранее, но многое зависит от инженера, реализующего подход как в деплое, так и в поддержке. Прочитав всё описанное выше, можно сказать, что многие вещи уже рассказаны в разных статьях и мануалах, но каждый раз, подключаясь на проект, видишь одни и те же ошибки или проблемы, которые не могут не огорчать. Порой ошибаются все и никто не безгрешен, но вовремя понять потенциальную проблему, нависшую над текущими рабочими процессами, и исправить её сразу — лучше, чем игнорировать и получать с утра пораньше сообщения о глобальном инциденте всех конвейеров. Главное — это понять, что правильные решения, видение инфраструктуры и процессов через 6 месяцев, поможет ускорить решение задач как со стороны инженеров, так и со стороны бизнеса. Ведь чем быстрее мы деплоим, тем быстрее растём. Получается, крепких пайплайнов и быстрых релизов! Если есть вопросы — пишите в комментариях. И, конечно, подписывайтесь на наш блог Хабр, TG-канал DevOps FM, интернет-издание VC и YouTube — мы всегда рады новым друзьям!    DevOps Engineer