Управління New Relic за допомогою Terraform: Частина III — Детальний посібник

У попередніх статтях (Частина I та Частина II) я пояснив, як можна використовувати Terraform для розгортання ресурсів New Relic. Однак ці дії виконувались локально, що не є ідеальним для корпоративних середовищ, де потрібна співпраця. Ця стаття буде складатися з двох основних частин:

  1. Налаштування зовнішнього зберігання стану Terraform.
  2. Створення пайплайна в GitHub Actions для обробки побудови, тестування, розгортання та генерування документації.

Налаштування зовнішнього зберігання стану Terraform

Якщо ви слідували попереднім статтям, ви вже бачили кілька внутрішніх файлів Terraform. Ці файли зберігають повні конфігурації ресурсів для певного каталогу Terraform. Тепер ми змінимо конфігурацію Terraform, щоб зберігати налаштування бекенду у зовнішньому сховищі. У моєму випадку це буде обліковий запис Azure Storage.

  1. Почніть із завантаження репозиторію.
  2. Створіть новий каталог з назвою PartIII та скопіюйте вміст з PartII. В PartIII/environments/example1/main.tf додайте конфігурацію бекенду всередині об'єкта terraform:
terraform {  
 required_version = ">= 0.12"  
 required_providers {  
 newrelic = {  
 source = "newrelic/newrelic"  
 }  
 }  
 backend "azurerm" {  
 resource_group_name = "demo-resource-group"  
 storage_account_name = "demostorageaccount"  
 container_name = "tfstate"  
 key = "example1.terraform.tfstate"  
 }  
}

Конфігурація бекенду вказує Terraform, де зберігати файл стану. Якщо ви хочете налаштувати це на іншому бекенді, більше деталей можна знайти в документації. У моєму випадку потрібно створити групу ресурсів Azure з назвою ‘demo-resource-group’, обліковий запис з назвою ‘demostorageaccount’ та контейнер з назвою ‘tfstate’. Ось як це має виглядати:

pic

Якщо ви хочете зберегти старий файл стану, ця стаття пояснює, як ефективно мігрувати стан.

Пайплайни

Перший пайплайн генерує документацію щоразу, коли створюється pull request. Для генерації документації ми будемо використовувати terraform-docs. Це дозволить нам генерувати Markdown файли для кожного модуля. Для пайплайнів я використаю GitHub Actions, але те ж саме можна зробити за допомогою інших інструментів CI/CD, таких як Azure DevOps або TeamCity.

Ідея GitHub Actions добре пояснена в цій статті. Загалом є кілька ресурсів, які потрібно створити для роботи пайплайна. По-перше, потрібно визначити workflow, який має бути розміщений у каталозі .github/workflows. Потім у workflow необхідно вказати подію, яка повинна його запускати. Workflow складається з jobs, кожен з яких містить кілька кроків. Кроки всередині job використовують один і той самий runner, що дозволяє безперешкодно обмінюватися даними між ними.

pic

Зображення з https://docs.github.com/en/actions/about-github-actions/understanding-github-actions

У попередньому пункті я описав, як перемістити файл стану до спільного бекенду. Після цього опублікуйте файли в будь-якому репозиторії на GitHub.

На цьому етапі у вас має бути локальний репозиторій, підключений до віддаленого на GitHub. Я рекомендую виконувати наступні дії в локальному репозиторії, а потім зафіксувати та надіслати їх на віддалений.

Пайплайн для документації

Щоб визначити новий workflow:

  1. Створіть каталог .github/workflows на кореневому рівні репозиторію. GitHub автоматично виявляє пайплайни в цьому каталозі.
    2.
  2. Створіть порожній файл з назвою terraform-docs.yml в цьому каталозі.
  3. Додайте визначення пайплайна до terraform-docs.yml, як показано нижче.
name: 'Terraform - Documentation'  

on:  
 push:  
 branches:  
 - '**'  
 - '!main'  
 paths:  
 - 'PartIII/**/*.tf'  
 - '.github/workflows/terraform-docs.yml'  

jobs:  
 generate_docs:  
 name: 'Generate Documentation'  
 runs-on: ubuntu-latest  
 steps:  
 - uses: actions/checkout@v4  
 with:  
 ref: ${{ github.ref }}  

 - name: Generate TF docs - Modules  
 uses: terraform-docs/[email protected]  
 with:  
 working-dir: PartIII/  
 recursive: true  
 recursive-path: modules  
 git-push: "true"  

 - name: Generate TF docs - Environments  
 uses: terraform-docs/[email protected]  
 with:  
 working-dir: PartIII/  
 recursive: true  
 recursive-path: environments  
 git-push: "true"

Цей workflow буде:

  • бачитися як "Terraform — Documentation" (значення з поля name),
  • виконуватиметься при push до всіх гілок, окрім main (визначено в секції on),
  • мати один job, generate_docs, який містить три кроки.

Job буде виконуватися на контейнері ubuntu-latest. Перший крок виконає checkout репозиторію з посилання на головну гілку pull request. Потім, використовуючи крок спільноти terraform-docs/[email protected], буде згенеровано документацію та надіслано її до гілки pull request. Документацію для terraform-docs/[email protected] можна знайти тут.

Ви можете зафіксувати зміни в локальному репозиторії, але не натискати їх на віддалений, оскільки нам потрібно буде змінити налаштування репозиторію для дозволу пайплайнів на внесення змін у репозиторій.

Для цього відкрийте налаштування репозиторію (Settings > Actions > General), знайдіть Workflow permissions та змініть значення на Read and write permissions.

pic

Тепер ви можете надіслати ваш локальний репозиторій до віддаленого. Після об'єднання змін у гілку main ви повинні побачити визначення workflow у вкладці Actions:

pic

Щоб перевірити це, оновіть опис змінної в одному з модулів, надішліть зміну в гілку віддаленого репозиторію, відмінну від main, а потім створіть pull request. Почекайте хвилину чи дві та перевірте, які файли були змінені в цьому pull request. У списку ви повинні побачити файли README.md з оновленою документацією.

Пайплайн для перевірки якості

Другий пайплайн призначений для базової перевірки якості. В каталозі .github/workflows додайте новий файл з назвою terraform-quality.yml. Нижче наведено вміст файлу:

name: 'Terraform - Code Quality'  

on:  
 push:  
 branches:  
 - '**'  
 paths:  
 - 'PartIII/environments/**/*.tf'  
 - 'PartIII/environments/**/*.tfvars'  
 - '.github/workflows/terraform-checks.yml'  
 pull_request:  
 paths:  
 - 'PartIII/environments/**/*.tf'  
 - 'PartIII/environments/**/*.tfvars'  
 - '.github/workflows/terraform-checks.yml'  

jobs:  
 terraform-checks:  
 name: 'Terraform Checks'  
 runs-on: ubuntu-latest  

 steps:  
 - name: Checkout  
 uses: actions/checkout@v4  

 - name: Setup Terraform  
 uses: hashicorp/setup-terraform@v3  
 with:  
 terraform_version: "1.7.0"  

 - name: Terraform Format Check  
 run: terraform fmt -check -recursive  

 - name: Terraform Init  
 run: terraform init -backend=false  

 - name: Terraform Validate  
 run: terraform validate

Цей пайплайн виконує checkout репозиторію, перевіряє формат за допомогою terraform fmt, намагається ініціалізувати Terraform за допомогою terraform init, а потім виконує команду terraform validate.

На цьому етапі ми маємо просту перевірку якості коду та генерацію документації.
Далі додайте пайплайн, який генеруватиме плани для розробки.

Пайплайн для перевірки

Ще раз створіть новий файл в каталозі .github/workflows і назвіть його terraform-ci.yml.
Нижче наведено вміст файлу:

name: 'Terraform - CI Validation'  

on:  
 push:  
 branches:  
 - '**'  
 - '!main'  
 pull_request:  
 paths:  
 - 'PartIII/environments/**/*.tf'  
 - 'PartIII/environments/**/*.tfvars'  
 - '.github/workflows/terraform-ci.yml'  

env:  
 ARM_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}  
 ARM_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}  
 ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}  
 ARM_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}  
 NEW_RELIC_API_KEY: ${{ secrets.NEW_RELIC_API_KEY }}  
 NEW_RELIC_ACCOUNT_ID: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}  

jobs:  
 detect-changes:  
 runs-on: ubuntu-latest  
 outputs:  
 changed_dirs: ${{ steps.set-dirs.outputs.changed_dirs }}  
 steps:  
 - name: Checkout  
 uses: actions/checkout@v4  
 with:  
 fetch-depth: 0  

 - name: Get Changed Directories  
 id: set-dirs  
 run: |  
 # For new branches or first commits, check all environments  
 if ! git rev-parse --verify HEAD~1 >/dev/null 2>&1; then  
 echo "New branch detected - checking all environments"  
 CHANGED_DIRS=$(find PartIII/environments/* -type d -maxdepth 0 | jq -R -s -c 'split("\n")[:-1]')  
 echo "changed_dirs=${CHANGED_DIRS}" >> $GITHUB_OUTPUT  
 echo "Checking all Terraform directories:"  
 echo "$CHANGED_DIRS" | jq -r '.[]'  
 exit 0  
 fi  

 # Determine the comparison base  
 if [["${{ github.event_name }}" == "pull_request"]]; then  
 echo "Checking changes in pull request"  
 git fetch origin ${{ github.base_ref }}  
 CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | grep '^PartIII/environments/.*\.\(tf\|tfvars\)$' || true)  
 else  
 echo "Checking changes in push"  
 CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD | grep '^PartIII/environments/.*\.\(tf\|tfvars\)$' || true)  
 fi  

 # If no changes detected in diff, check if we're in a new branch  
 if [-z "$CHANGED_FILES"]; then  
 echo "No changes detected in diff, checking current branch files"  
 CHANGED_FILES=$(git ls-files | grep '^PartIII/environments/.*\.\(tf\|tfvars\)$' || true)  
 fi  

 # Extract unique directory paths (up to environment level)  
 CHANGED_DIRS=$(echo "$CHANGED_FILES" | sed -E 's|^(PartIII/environments/[^/]+).*|\1|' | sort -u | jq -R -s -c 'split("\n")[:-1]')  

 # Set output  
 echo "changed_dirs=${CHANGED_DIRS}" >> $GITHUB_OUTPUT  

 # Display appropriate message based on changes  
 if ["$CHANGED_DIRS" == "[]" ] || [-z "$CHANGED_FILES"]; then  
 echo "No Terraform directories were changed in this commit."  
 else  
 echo "Changed Terraform directories:"  
 echo "$CHANGED_DIRS" | jq -r '.[]'  
 fi  

 terraform-plan:  
 needs: detect-changes  
 if: ${{ needs.detect-changes.outputs.changed_dirs != '[]' && needs.detect-changes.outputs.changed_dirs != '' }}  
 name: 'Terraform Plan - ${{ matrix.directory }}'  
 runs-on: ubuntu-latest  
 strategy:  
 matrix:  
 directory: ${{ fromJson(needs.detect-changes.outputs.changed_dirs) }}  
 fail-fast: false  

 defaults:  
 run:  
 working-directory: ${{ matrix.directory }}  

 steps:  
 - name: Checkout  
 uses: actions/checkout@v4  

 - name: Setup Terraform  
 uses: hashicorp/setup-terraform@v3  
 with:  
 terraform_version: "1.7.0"  

 - name: Terraform Init  
 run: terraform init -lock=false  

 - name: Terraform Plan  
 id: plan  
 run: |  
 echo "::group::Terraform Plan Output"  
 echo "Running terraform plan for ${{ matrix.directory }}"  
 echo "----------------------------------------"  
 terraform plan -no-color -input=false -lock=false  
 planExitCode=$?  
 echo "----------------------------------------"  
 echo "::endgroup::"  
 exit $planExitCode  
 continue-on-error: true  

 - name: Check Plan Status  
 if: steps.plan.outcome == 'failure'  
 run: |  
 echo "Terraform plan failed for ${{ matrix.directory }}"  
 exit 1

Цей пайплайн буде активуватися для всіх гілок, окрім main, і спробує створити план для всіх змінених директорій.
Для генерації плану потрібно пройти автентифікацію в Azure для доступу до бекенду. Використовуйте автентифікацію через Service Principal наступним чином:

  1. Створіть новий Service Principal.
  2. Призначте відповідні дозволи для Service Principal (SPN).
  3. Згенеруйте секрет для Service Principal.
  4. Для детальних кроків зверніться до цього посібника.

Потім передайте Client ID, Secret, Tenant ID та Subscription ID як змінні середовища, і пайплайн працюватиме як очікується.

Якщо зупинитися на цьому етапі, додати пайплайн і запустити його, він зазнає невдачі під час автентифікації до New Relic. У попередній статті ми припускали, що New Relic API Key та Account ID будуть надані в файлі, але для CI краще мати їх як змінні середовища, подібно до облікових даних для Azure бекенду. Тому ми оголошуємо дві змінні середовища в пайплайні, що стосуються New Relic.

Змінна ${{ secrets.NEW_RELIC_ACCOUNT_ID }} отримує секрет NEW_RELIC_ACCOUNT_ID із функції Secrets GitHub. Щоб оголосити секрет у GitHub, виконайте наступні кроки:

  1. Перейдіть у Settings > Secrets and Variables > Actions в репозиторії.
  2. Виберіть New repository secret.
  3. Вкажіть Name та Secret, потім натисніть Add secret.

Хоча плани видні в логах виконання пайплайна, зберігання цієї інформації лише в логах може бути незручним.
Наступний пайплайн вирішує цю проблему, публікуючи плани безпосередньо в коментарях до pull request.

Пайплайн для pull request

Щоб додати цей пайплайн, створіть новий файл з назвою terraform-pr-plan.yml з наступним вмістом:

name: 'Terraform - PR Plan'  

on:  
 pull_request:  
 branches:  
 - main  
 types: [opened, synchronize, reopened]  

env:  
 ARM_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}  
 ARM_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}  
 ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}  
 ARM_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}  
 NEW_RELIC_API_KEY: ${{ secrets.NEW_RELIC_API_KEY }}  
 NEW_RELIC_ACCOUNT_ID: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}  

jobs:  
 detect-changes:  
 runs-on: ubuntu-latest  
 outputs:  
 changed_dirs: ${{ steps.set-dirs.outputs.changed_dirs }}  
 steps:  
 - name: Checkout  
 uses: actions/checkout@v4  
 with:  
 fetch-depth: 0  

 - name: Get Changed Directories  
 id: set-dirs  
 run: |  
 # Fetch base branch  
 git fetch origin ${{ github.base_ref }}  

 # Get changed files between PR and base branch  
 CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | grep '^PartIII/environments/.*\.tf$' || true)  

 # Extract unique directory paths  
 CHANGED_DIRS=$(echo "$CHANGED_FILES" | sed -E 's|^(PartIII/environments/[^/]+).*|\1|' | sort -u | jq -R -s -c 'split("\n")[:-1]')  

 # Set output  
 echo "changed_dirs=${CHANGED_DIRS}" >> $GITHUB_OUTPUT  

 # Create summary of changes  
 if ["$CHANGED_DIRS" == "[]" ] || [-z "$CHANGED_FILES"]; then  
 echo "### No Terraform Changes Detected" >> $GITHUB_STEP_SUMMARY  
 echo "No Terraform directories were modified in this pull request." >> $GITHUB_STEP_SUMMARY  
 else  
 echo "### Changed Terraform Directories" >> $GITHUB_STEP_SUMMARY  
 echo "$CHANGED_DIRS" | jq -r '.[]' | sed 's/^/- /' >> $GITHUB_STEP_SUMMARY  
 fi  

 terraform-plan:  
 needs: detect-changes  
 if: ${{ needs.detect-changes.outputs.changed_dirs != '[]' && needs.detect-changes.outputs.changed_dirs != '' }}  
 name: 'Plan - ${{ matrix.directory }}'  
 runs-on: ubuntu-latest  
 strategy:  
 matrix:  
 directory: ${{ fromJson(needs.detect-changes.outputs.changed_dirs) }}  
 fail-fast: false  

 defaults:  
 run:  
 working-directory: ${{ matrix.directory }}  

 steps:  
 - name: Checkout  
 uses: actions/checkout@v4  

 - name: Setup Terraform  
 uses: hashicorp/setup-terraform@v3  
 with:  
 terraform_version: "1.7.0"  

 - name: Terraform Init  
 run: terraform init  

 - name: Terraform Plan  
 id: plan  
 run: |  
 terraform plan -no-color -input=false -detailed-exitcode > plan.txt 2>&1  
 EXIT_CODE=$?  
 echo "${EXIT_CODE}"  
 echo "exit_code=${EXIT_CODE}" >> $GITHUB_OUTPUT  

 # Check if plan has changes  
 if [$EXIT_CODE -eq 0]; then  
 echo "has_changes=false" >> $GITHUB_OUTPUT  
 else  
 echo "has_changes=true" >> $GITHUB_OUTPUT  
 fi  
 continue-on-error: true  

 - name: Post Plan to PR  
 uses: actions/github-script@v7  
 with:  
 github-token: ${{ secrets.GITHUB_TOKEN }}  
 script: |  
 const fs = require('fs');  
 const planOutput = fs.readFileSync('${{ matrix.directory }}/plan.txt', 'utf8');  
 const exitCode = '${{ steps.plan.outputs.exit_code }}';  

 let status = '✅';  
 if (exitCode === '1') {  
 status = '❌';  
 } else if (exitCode === '2') {  
 status = '⚠️';  
 }  

 if (planOutput.includes('No changes.')) {  
 const body = `### Terraform Plan for \`${{ matrix.directory }}\` ${status}  
 No changes.

Цей пайплайн буде активуватися для всіх pull request, що намагаються об'єднати зміни в гілку main, та спробує створити план для всіх змінених директорій.
Інфраструктура актуальна.`;

await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: body
});
} else {
const planSummary = planOutput.split('\n')
.filter(line => line.match(/Plan:|Changes to Outputs:|No changes./))
.join('\n');

const body = ### Terraform Plan для \${{ matrix.directory }}` ${status}\` ;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: body
});
}
`` Цей workflow ефективний, оскільки обробляє тільки ті директорії, в яких є зміни. Він запускає Terraform плани паралельно для кількох середовищ і публікує результати безпосередньо до pull request. Кожен коментар плану містить чітке форматування та індикатори статусу (✅, ⚠️, або ❌), а також як підсумковий, так і детальний перегляд запропонованих змін інфраструктури.

Пайплайн для розгортання

Workflow для розгортання Terraform активується або при push до гілки main, або вручну через workflow dispatch. Створіть новий файл terraform-deploy.ym. Пайплайн починається з фази виявлення, під час якої пайплайн визначає всі доступні середовища, скануючи каталог PartIII/environments, що закладає основу для паралельної обробки кількох середовищ.

Далі пайплайн переходить до фази планування, під час якої генеруються Terraform плани для кожного виявленого середовища. Ці плани зберігаються як артефакти і відображаються в деталях, щоб забезпечити прозорість запропонованих змін.

Далі йде важливий етап схвалення, на якому призначені затверджувачі (налаштовані через змінну TERRAFORM_APPROVERS) повинні явним чином затвердити зміни. Запит на схвалення містить всебічне резюме запланованих змін, з особливим виділенням середовищ, в яких є модифікації. Цей механізм схвалення виступає як захисний механізм, що гарантує перевірку змін інфраструктури перед їх впровадженням.

Нарешті, після отримання необхідних схвалень, пайплайн переходить до фази розгортання. Він поетапно застосовує раніше згенеровані та затверджені Terraform плани до кожного середовища. Процес розгортання надійно керує автентифікацією як для Azure, так і для New Relic, використовуючи збережені облікові дані, що забезпечує безперебійну та безпечну реалізацію.
Нижче наведено код пайплайна:

name: 'Terraform - Deploy'  

on:  
 push:  
 branches:  
 - main  
 paths:  
 - 'PartIII/environments/**/*.tf'  
 - 'PartIII/environments/**/*.tfvars'  
 - '.github/workflows/terraform-deploy.yml'  
 workflow_dispatch:  

env:  
 ARM_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}  
 ARM_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}  
 ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}  
 ARM_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}  
 NEW_RELIC_API_KEY: ${{ secrets.NEW_RELIC_API_KEY }}  
 NEW_RELIC_ACCOUNT_ID: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}  

jobs:  
 discover-environments:  
 runs-on: ubuntu-latest  
 outputs:  
 environments: ${{ steps.set-environments.outputs.environments }}  
 steps:  
 - name: Checkout  
 uses: actions/checkout@v4  

 - name: Get Environments  
 id: set-environments  
 run: |  
 ENVIRONMENTS=$(ls -d PartIII/environments/*/ | xargs -n 1 basename | jq -R -s -c 'split("\n")[:-1]')  
 echo "environments=${ENVIRONMENTS}" >> $GITHUB_OUTPUT  

 terraform-plan:  
 needs: discover-environments  
 name: 'Terraform Plan - ${{ matrix.environment }}'  
 runs-on: ubuntu-latest  
 strategy:  
 matrix:  
 environment: ${{ fromJson(needs.discover-environments.outputs.environments) }}  
 environment: ${{ matrix.environment }}  
 defaults:  
 run:  
 working-directory: PartIII/environments/${{ matrix.environment }}  

 steps:  
 - name: Checkout  
 uses: actions/checkout@v4  

 - name: Setup Terraform  
 uses: hashicorp/setup-terraform@v3  
 with:  
 terraform_version: "1.7.0"  

 - name: Terraform Init  
 run: terraform init  

 - name: Terraform Plan  
 run: |  
 terraform plan -out=tfplan  
 terraform show -no-color tfplan > tfplan.txt  

 - name: Upload Plan  
 uses: actions/upload-artifact@v4  
 with:  
 name: tfplan-${{ matrix.environment }}  
 path: |  
 PartIII/environments/${{ matrix.environment }}/tfplan  
 PartIII/environments/${{ matrix.environment }}/tfplan.txt  
 retention-days: 5  

 display-plan:  
 needs: [discover-environments, terraform-plan]  
 name: 'Display Plan - ${{ matrix.environment }}'  
 runs-on: ubuntu-latest  
 strategy:  
 matrix:  
 environment: ${{ fromJson(needs.discover-environments.outputs.environments) }}  

 steps:  
 - name: Download Plan  
 uses: actions/download-artifact@v4  
 with:  
 name: tfplan-${{ matrix.environment }}  

 - name: Display Terraform Plan  
 run: |  
 echo "Terraform Plan for environment: ${{ matrix.environment }}"  
 echo "----------------------------------------"  
 cat tfplan.txt  
 echo "----------------------------------------"  
 echo "Please review the plan above and approve the deployment in the next step."  

 manual-approval:  
 needs: [discover-environments, display-plan]  
 name: 'Manual Approval - ${{ matrix.environment }}'  
 runs-on: ubuntu-latest  
 strategy:  
 matrix:  
 environment: ${{ fromJson(needs.discover-environments.outputs.environments) }}  
 environment:   
 name: ${{ matrix.environment }}-approval  

 steps:  
 - name: Download Plan  
 uses: actions/download-artifact@v4  
 with:  
 name: tfplan-${{ matrix.environment }}  

 - name: Generate Plan Summary  
 id: plan  
 run: |  
 PLAN_CONTENT=$(cat tfplan.txt)  
 if grep -q "No changes." tfplan.txt; then  
 echo "summary=✅ No changes.

Цей пайплайн запускається для push до гілки main або вручну через workflow dispatch. Він починається з фази виявлення, де визначаються всі доступні середовища, а потім генерується Terraform план для кожного з них. Потім план зберігається як артефакт, що дає змогу переглядати зміни. Після цього йде етап схвалення змін вручну, де спеціально призначені затверджувачі мають підтвердити зміни перед їх застосуванням.
Інфраструктура актуальна." >> $GITHUBOUTPUT
else
SUMMARY=$(grep "Plan:" tfplan.txt || echo "No plan summary found")
echo "summary=⚠️ Зміни виявлені: $SUMMARY" >> $GITHUB
OUTPUT
fi
echo "plan<> $GITHUBOUTPUT
echo "$PLAN
CONTENT" >> $GITHUBOUTPUT
echo "EOF" >> $GITHUB
OUTPUT

  • name: Призупинити для схвалення
    uses: trstringer/manual-approval@v1
    with:
    secret: ${{ github.token }}
    approvers: ${{ vars.TERRAFORM_APPROVERS }}
    minimum-approvals: 1
    issue-title: "Схвалити зміни Terraform для ${{ matrix.environment }}"
    issue-body: |
    Будь ласка, перегляньте та схваліть зміни Terraform для середовища: ${{ matrix.environment }}

## Резюме плану
${{ steps.plan.outputs.summary }}

Показати повний план hcl ${{ steps.plan.outputs.plan }} Необхідне схвалення: - Це розгортання вимагає явного схвалення для продовження - Будь ласка, ретельно перегляньте план перед схваленням - Напишіть 'approve' для схвалення розгортання Примітка: Це схвалення буде анульовано через 24 години, якщо не буде схвалено. timeout-minutes: 1440 terraform-apply: needs: [discover-environments, manual-approval] name: 'Terraform Apply - ${{ matrix.environment }}' runs-on: ubuntu-latest strategy: matrix: environment: ${{ fromJson(needs.discover-environments.outputs.environments) }} environment: name: ${{ matrix.environment }} url: ${{ steps.applyoutput.outputs.environmenturl }} defaults: run: working-directory: PartIII/environments/${{ matrix.environment }} steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Terraform uses: hashicorp/setup-terraform@v3 with: terraform_version: "1.7.0" - name: Terraform Init run: terraform init - name: Download Plan uses: actions/download-artifact@v4 with: name: tfplan-${{ matrix.environment }} path: PartIII/environments/${{ matrix.environment }} - name: Terraform Apply id: apply run: terraform apply -auto-approve tfplan ```

Резюме

У попередніх статтях я показав, як можна використовувати Terraform для розгортання New Relic з вашого локального комп’ютера. У більших сценаріях цей підхід може не працювати, тому використання CI/CD пайплайнів є кращим варіантом. GitHub Actions добре підходить для цієї мети, але інші інструменти, які дозволяють виконувати скрипти на Python або PowerShell, можуть досягти подібних результатів.

У цьому випадку немає універсального рішення, тому ви можете сприймати цей посібник як точку відліку для чогось більшого та складнішого. Варто також зазначити, що ви можете експериментувати з Terraform Cloud, який надається компанією HashiCorp.

Всі файли, створені в цій статті, можна знайти тут: https://github.com/ADii140/NewRelicLabs.

Перекладено з: Managing New Relic with Terraform: Part III — A Comprehensive Guide

Leave a Reply

Your email address will not be published. Required fields are marked *