Мы продолжаем серию статей о применении подхода GitOps к инфраструктуре нашей организации. Первую часть можно почитать тут.  

Я – ведущий DevOps инженер в IT-хабe группы компаний Dyninno. Мы (команда больше 300 человек) занимаемся разработкой ПО и отвечаем за IT инфраструктуру всех компаний группы. Dyninno – международный холдинг, который работает в трех сегментах бизнеса: авиаперелеты, финансовый сектор и индустрия развлечений (кастинг актеров). В прошлой статье я рассказывал о нашем переходе на GitOps, а сегодня хочу остановиться подробнее на управлении инфраструктурой в рамках этого перехода. Эта статья может быть интересна тем, кто задумывается о внедрении GitOps в свою инфраструктуру.   

Для большей связанности повествования повторим два ключевых тезиса из предыдущего материала:  

  1. Все наши сервисы в процессе миграции на Kubernetes.  

  1. Мы используем подход GitOps с ArgoCD для управления Kubernetes. 

Уже написано много материалов о том, что такое “Инфраструктура-как-Код” (IaC), поэтому я не буду останавливаться на общих вещах, и расскажу подробнее про наш опыт. 

Итак, когда зашла речь о том, какое же IaC решение использовать, мы остановили свой выбор на Terraform, а не на CloudFormation или других аналогах, даже несмотря на то, что большая часть нашей инфраструктуры расположена в AWS. Главный плюс Терраформа в том, что мы можем использовать унифицированное решение для всех сред.  

Терраформ дает возможность сосредоточиться на освоении одного инструмента, и при необходимости легко переключаться между провайдерами, которые отвечают за взаимодействие с конкретным сервисом или облаком. Более того, существует возможность создавать свои собственные интеграции тогда, когда каких-то конкретных интеграций не хватает. Например, мы почти полностью переписали провайдер для работы с Dkron чтобы он отвечал нашим требованиям.  

C чем мы столкнулись 

В какой-то момент у нас назрела необходимость в решении, которое позволяло бы управлять доступом к инфраструктуре для большого количества операционных команд с различными ролями и правами. Мы рассматривали несколько вариантов решения этой задачи. Например, изучали возможность разделения Терраформа на несколько проектов, давая каждому члену команды доступ только к той части инфраструктуры, за которую он отвечает. Также мы рассматривали вариант раздавать IAM-роли по пользователям или группам пользователей. Оба эти варианта приводили к усложнению всей схемы и существенному увеличению времени необходимого для сопровождение этого сетапа.  

В итоге мы пришли к выводу, что нам необходим вариант построения IaC, не требующий раздачи поголовного доступа к облаку. К тому же, нельзя было забывать о том, что все изменения, сделанные во время написания Терраформ кода, должны быть отражены в гит репозитории.  

В результате мозгового штурма на тему улучшения workflow мы решили запускать Терраформ через GitLab-ci пайплайн. Такой подход сразу же показал качественное улучшение процесса по сравнению с локальным запуском Терраформа. Так, больше не нужно было предоставлять всем учетные данные для доступа к облаку. Но мы не были полностью удовлетворены таким решением. Во-первых, было неудобно каждый раз заходить в детали пайплайна, и искать в логах джоба результаты исполнения Терраформ команд. Это занимало много времени, особенно когда изменения вносились десятки раз в день. Во-вторых, конфигурацию пайплайна нельзя было назвать user-friendly. Например, один из темплейтов пайплайн джобов выглядел вот так: 

.plan: 
  stage: plan 
  rules: 
    # run on merge requests, when TF folder changes 
    - if: $CI_PIPELINE_SOURCE == "merge_request_event" 
      changes: 
        - $TF_ROOT/* 
    # run on default branch, when TF folder changes 
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH 
      changes: 
        - $TF_ROOT/* 
  script: 
    # run terraform 
    - cd ${TF_ROOT} 
    - terraform init -input=false -reconfigure 
    # create plan for apply 
    - terraform plan -input=false -out="${PLAN_CACHE}" 
    # print plan for gitlab reports 
    - terraform show -json "${PLAN_CACHE}" | jq -r "${JQ_PLAN}" > "${PLAN_JSON}" 
  artifacts: 
    paths: 
      - ${TF_ROOT}/${PLAN_CACHE} 
    reports: 
      terraform: ${TF_ROOT}/${PLAN_JSON}

Такая конфигурация — это не бином Ньютона, но все же хотелось использовать что-то более простое. И в-третьих, нам нужно было передавать кеш Терраформа между джобами init/plan/apply, что требовало дополнительной конфигурации, а этого хотелось бы избежать. К тому же, поскольку мы используем временные поды, которые поднимаются только для исполнения конкретного пайплайна, нам пришлось выделить внешнее хранилище кеша, что усложнило сетап еще больше. И чем больше команд начинало работать в этом сетапе, тем больше не самых положительных отзывов мы получали. Поэтому мы начали искать другой подход.

К чему мы пришли

В итоге очередного мозгового штурма мы решили поднять тестовый сетап на базе Atlantis, который является альтернативным решением для управления взаимодействиями Терраформа. Как и в предыдущих вариантах, Atlantis устраняет необходимость в создании учетных данных для каждого пользователя. Кроме того, Atlantis выгодно отличается тем, что добавляет комментарии с результатами исполнения команд Терраформа к соответствующему Merge Request. Эта функция позволяет всем членам команды просматривать историю взаимодействия с Терраформом и управлять этим взаимодействием без чтения километровых логов.

Проще говоря, в Atlantis реализован эффективный подход к взаимодействию с Терраформом, который позволяет команде легко управлять инфраструктурой через комментарии в Merge Request. И для этого нам нужно было сделать лишь одну небольшую конфигурацию, которая выглядит так:

version: 3 
projects: 
  - dir: terraform/provision 
    terraform_version: v1.2.0 
    workflow: terraform 
    autoplan: 
      enabled: true 
      when_modified: ["**/*.tf", "**/*.tfvars"]

В итоге мы пришли к следующей схеме, которая полностью перекрывает наши потребности: 

Как сейчас построен рабочий процесс
Как сейчас построен рабочий процесс

Что мы получили в результате  

Приведу несколько преимуществ, которые мы ощутили, перейдя на подход Инфраструктура-как-Код (IaC) с помощью Терраформа и Atlantis:  

  • Больше нет необходимости давать прямой доступ к облаку каждому члену команды, что повысило безопасность и снизило сложность управления доступами. 

  • Все изменения легко отслеживаются и ими можно управлять через IaC с Терраформом. Вся история доступна через контроль версий, что улучшило управляемость.  

  • Мы пришли к стандартизированному подходу, который можно использовать на всех наших проектах, что сокращает время адаптации при переходе специалистов с одного проекта на другой.  

Используя Терраформ и IaC в целом, мы смогли оптимизировать управление нашей инфраструктурой и снизили влияние человеческого фактора.

Автор:  
Вадим Гедзь, ведущий DevOps инженер, Dyninno Group 
https://github.com/shini4i 

 

Комментарии (8)


  1. trublast
    14.06.2023 06:27

    >Главный плюс Терраформа в том, что мы можем использовать унифицированное решение для всех сред

    Поделитесь, как вы переносите свою IaC, описанную терраформом, например из AWS в GCP, или в какой-нибудь OpenStack?


    1. Numen_Divinum
      14.06.2023 06:27

      Думаю, унифицированность здесь в использовании Терраформа как решения для всех сред, т.е. специалистам нужно знать всего один инструмент. Один и тот же код для разных провайдеров, очевидно, использовать не получится


      1. Ezhische
        14.06.2023 06:27

        Можно и код унифицировать через собственные модули с интерфейсом независимым от облачного провайдера


    1. smarthomeblog
      14.06.2023 06:27

      Terraform-ом можно описывать не только инфраструктуру в AWS, но и сопутсвтующие сервисы тоже - дашборды в Sumo Logic, алерты в PagerDuty или Grafana. Ну и так далее. Плюс подозреваю, найти инженера, знающего Terraform и имеющего опыт работы с ним проще, чем на вендорозависимый CloudFormation.


      1. ALexhha
        14.06.2023 06:27
        +1

        Плюс подозреваю, найти инженера, знающего Terraform и имеющего опыт работы с ним проще, чем на вендорозависимый CloudFormation

        Легче, только опыт работы с тераформом в aws не особо поможет в gcp или azure. Слишком все разное. Ну а сам по себе terraform, без привязки к провайдеру, осваивается за пару недель.


    1. Hledacek
      14.06.2023 06:27

      Не знаю как это делает топикстартер, но мы используем уже существующие YAML файлы как структуру и базу для написания новой конфигурации для нового провайдера, уж слишком много нюансов у каждого вендора. Однако при переходе из одного облака в другое, инфраструктура не самая большая проблама, перенос и обеспечение консистентности данных особенно при zero downtime - реальная боль.


  1. smarthomeblog
    14.06.2023 06:27

    Мы сделали проще. В PR при создании или любом последующем коммите добавляем план, сгенерированный Терраформом. При мерже, идет автоматический apply. Крутится все на self-hosted runners, прибитых к AWS аккаунтам. Так что никаких кредов не нужно.

          - name: Terraform Plan
            id: plan
            run: |
              terraform plan -refresh=false -no-color -out out.plan
    
          - name: Comment PR
            if: github.event_name == 'pull_request'
            uses: peter-evans/create-or-update-comment@v2
            with:
              issue-number: ${{ github.event.pull_request.number }}
              body: ${{steps.plan.outputs.stdout}}
    
          - name: Terraform Apply
            if: github.ref == 'refs/heads/develop' && github.event_name == 'push'
            run: terraform apply -auto-approve


  1. teamfighter
    14.06.2023 06:27

    Тоже используем atlantis, но терраформ сверху ещё обмазали terragrunt. План для атлантиса можно составлять автоматически, с помощью terraform-atlantis-config.