Эффективный рабочий процесс GitLab CI / CD с несколькими конфигурациями Terraform? - PullRequest
0 голосов
/ 12 апреля 2019

Моя команда использует AWS для нашей инфраструктуры через 3 различных учетных записей AWS . Мы назовем их просто sandbox, staging и production.

Недавно я настроил Terraform для нашей инфраструктуры AWS, и ее иерархия сопоставляется с нашими учетными записями, а затем с помощью приложения или самой службы AWS. Структура репо выглядит примерно так:

staging
  iam
    groups
      main.tf
    users
      main.tf
  s3
    main.tf
sandbox
  iam
    ...
production
  applications
    gitlab
      main.tf
  route53
    main.tf
  ...

Мы используем отдельные конфигурации для каждой службы AWS (например, IAM или S3) или приложения (например, GitLab), поэтому мы не получаем огромных файлов .tf на учетную запись, для применения которых потребуется много времени за любое изменение. В идеале мы хотели бы отойти от подхода конфигурации на основе служб и перейти к более конфигурациям на основе приложений, но проблема в любом случае остается той же.

Этот подход хорошо работал при применении обновлений вручную из командной строки, но я бы хотел переместить его на GitLab CI / CD, чтобы лучше автоматизировать наш рабочий процесс, и именно здесь все сломалось.

В моей существующей установке, если я внесу одно изменение, скажем, staging/s3/main.tf, GitLab, похоже, не найдет хорошего выхода из коробки, чтобы запустить только terraform plan или terraform apply для этой конкретной конфигурации. .

Если бы я вместо этого переместил все в один файл main.tf для всей учетной записи AWS (или нескольких файлов, но привязанных к одному файлу состояния), я мог бы просто заставить GitLab запускать задание plan или apply только в этой конфигурации. Запуск может занять 15 минут в зависимости от количества ресурсов AWS, имеющихся у нас в каждой учетной записи, но я полагаю, что это потенциальный вариант.

Кажется, что моя проблема в конечном счете может быть связана с тем, как GitLab обрабатывает "monorepos", чем с тем, как Terraform обрабатывает свой рабочий процесс (в конце концов, Terraform с радостью спланирует / применит мои изменения, если я просто скажу , что имеет изменилось), хотя мне также было бы интересно услышать о том, как люди структурируют свою среду Terraform, заданную - или чтобы полностью избежать - этих ограничений.

Кто-нибудь решил такую ​​проблему в своей среде?

1 Ответ

3 голосов
/ 12 апреля 2019

Приятной особенностью Terraform является то, что он идемпотентен, поэтому вы можете просто подать заявку, даже если ничего не изменилось, и в любом случае это будет неактивное действие.

Если по какой-то причине вы действительно хотите запускать план / применять к определенному каталогу, когда что-то меняется, вы можете добиться этого, используя only.changes, так что Gitlab будет запускать задание только в том случае, если указанные файлы были изменены.

Итак, если у вас есть существующая структура, это так просто, как сделать что-то вроде этого:

stages:
  - terraform plan
  - terraform apply

.terraform_template:
  image: hashicorp/terraform:latest
  before_script:
    - LOCATION=$(echo ${CI_JOB_NAME} | cut -d":" -f2)
    - cd ${LOCATION}
    - terraform init

.terraform_plan_template:
  stage: terraform plan
  extends: .terraform_template
  script:
    - terraform plan -input=false -refresh=true -module-depth=-1 .

.terraform_apply_template:
  stage: terraform apply
  extends: .terraform_template
  script:
    - terraform apply -input=false -refresh=true -auto-approve=true .

terraform-plan:production/applications/gitlab:
  extends: .terraform_plan_template
  only:
    refs:
      - master
    changes:
      - production/applications/gitlab/*
      - modules/gitlab/*

terraform-apply:production/applications/gitlab:
  extends: .terraform_apply_template
  only:
    refs:
      - master
    changes:
      - production/applications/gitlab/*
      - modules/gitlab/*

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

Если это не так, и у вас более плоская структура, и вы рады, что у вас есть одна заявка, вы можете упростить это до:

stages:
  - terraform

.terraform_template:
  image: hashicorp/terraform:latest
  stage: terraform
  before_script:
    - LOCATION=$(echo ${CI_JOB_NAME} | cut -d":" -f2)
    - cd ${LOCATION}
    - terraform init
  script:
    - terraform apply -input=false -refresh=true -auto-approve=true .
  only:
    refs:
      - master
    changes:
      - ${CI_JOB_NAME}/*

production/applications/gitlab:
  extends: .terraform_template

В общем, этого можно избежать, позволяя Terraform запускать все соответствующие каталоги при каждом нажатии (возможно, только при применении push to master или другой соответствующей ветви), потому что, как уже упоминалось, Terraform является идемпотентом, поэтому он победил ' ничего не делать, если ничего не изменилось. Это также имеет то преимущество, что если ваш код автоматизации не изменился, но что-то изменилось в вашем провайдере (например, кто-то открыл группу безопасности), то Terraform вернется к тому, каким он должен быть при следующем запуске.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...