Удосконалення процесу розгортання додатків: GitOps з Terraform, GitHub Actions та AWS EKS

Сучасна розробка програмного забезпечення вимагає безперешкодних та ефективних процесів розгортання. Ця стаття розглядає, як принципи GitOps, у поєднанні з Terraform, GitHub Actions та Amazon EKS, дозволяють автоматизувати, масштабувати та забезпечувати надійне розгортання додатків. Дізнайтесь, як ці інструменти працюють разом, щоб спростити робочі процеси та забезпечити гнучке постачання.

Схема архітектури

pic

Використовувані інструменти та технології

У цьому проєкті GitOps ми будемо використовувати наступні інструменти DevOps та AWS Cloud для досягнення мети:

  1. GitHub — для зберігання коду нашого додатка, коду CICD pipeline та коду автоматизації хмар.
  2. Maven — для компіляції нашого коду в розгортаємий артефакт .war.
  3. Sonarcloud — для проведення тестів коду.
  4. Docker — для створення образу додатка.
  5. Amazon ECR — для зберігання образу додатка.
  6. Helm Charts — для керування розгортаннями в нашому EKS кластері.
  7. Amazon EKS — для розгортання нашого додатка в контейнеризованому середовищі.

Зверніть увагу, що є два робочих процеси:

  1. Процес Terraform застосовує зміни інфраструктури.
  2. Процес CICD для додатка застосовує зміни додатка.

Тож, давайте почнемо!

1. Підготовка GitHub репозиторіїв

● Форкайте цей GitHub репозиторій для Terraform pipeline до вашого облікового запису GitHub. Переконайтесь, що форкнули обидва гілки: Main і Stage.

pic

● Форкайте цей другий GitHub репозиторій для App CICD. Цей репозиторій містить лише одну гілку — Main.

pic

● Створіть SSH ключ для безпечного доступу до вашого Git репозиторію на локальному комп’ютері.

○ У вашому терміналі, cd ~./ssh для створення пари приватного та публічного ключів.

○ Виконайте команду ssh-keygen для створення пари ключів.

○ Скопіюйте ваш публічний ключ до розділу SSH ключів на GitHub.

○ Далі, виконайте export GITSSHCOMMAND=”ssh -i ~/.ssh/”, щоб налаштувати Git на використання вашого конкретного приватного ключа.

pic

● Створіть і перейдіть в директорію на вашому локальному комп’ютері, де ви будете клонувати Git репозиторії.

● Клонуйте обидва репозиторії GitHub, які ви форкнули раніше, в створену директорію на вашому локальному комп’ютері.

pic

● На цьому етапі зробіть копію директорії “iac-vprofile”. Це потрібно для створення резервної копії цієї ж директорії.

● Перейдіть в директорію iac-vprofile, а потім перемкніться на гілку “stage”. Тут будуть вноситися зміни, поки ми не будемо готові об’єднати їх з гілкою “Main” для остаточних змін конфігурації.

pic

2. GitHub Actions Secrets

Secrets в GitHub Actions — це зашифроване сховище для чутливої інформації, що використовується в робочих процесах. Ми використовуємо їх для безпечного доступу до ресурсів AWS без розкриття наших логінів публічно. Для налаштування цих секретів для наших двох GitHub репозиторіїв:

● Увійдіть в свій обліковий запис AWS та створіть нового користувача IAM.

● Для простоти надамо цьому новому користувачу політику "AdministratorAccess".

● Після створення користувача згенеруйте для нього Access Key.

● Додайте згенерований Access Key до GitHub Secrets. Для цього виконайте наступні кроки:

Відкрийте ваш Git Repo → “Settings” → “Secrets and Variables” → “Actions” → “New Repository Secret”

● Тут створіть і скопіюйте ваші AWSACCESSKEYID та AWSSECRETACCESSKEY.

pic

● Налаштуйте ці Git Actions secrets для обох ваших репозиторіїв: IaC-Vprofile та VProfile-Action.

3. Створення S3 бакету для зберігання даних Terraform

Нам потрібно створити S3 бакет, який буде зберігати файли стану Terraform.
State files (файли стану) — це компоненти, які відстежують стан вашої інфраструктури, що керується через Terraform. Вони зберігають інформацію про ресурси та конфігурації, дозволяючи Terraform зрозуміти поточний стан вашої інфраструктури та визначити будь-які зміни, які необхідно здійснити під час наступних операцій.

Виконайте наступні дії:

● Перейдіть до сервісу “S3”.

● Створіть новий S3 бакет і надайте йому відповідну назву.

pic

● Після створення S3 бакету, перейдіть до розділу “Actions Secrets” вашого репозиторію “IaC-Vprofile” і додайте новий секрет. Назвіть його “BUCKETTFSTATE” та у секції Secret* вставте ім’я вашого S3 бакету.

pic

4. Створення ECR

Тепер створимо Elastic Container Registry (ECR) для зберігання наших Docker образів.

● Перейдіть до сервісу “ECR” в AWS.

● Створіть новий реєстр ECR.

● Скопіюйте URI створеного ECR.

● Перейдіть на сторінку Actions Secrets репозиторію “Vprofile-Action” і додайте новий секрет. Назвіть його “REGISTRY” та вставте URI ECR у секцію Secret*.

pic

5. Код Terraform

● Відкрийте директорію “IaC-Vprofile” у вашому редакторі коду. Переконайтесь, що ви на гілці “Staging”.

● Перейдіть до директорії “Terraform”, де вже є кілька скриптів.

● Змініть наступні скрипти:

○ У файлі “variables.tf” змініть назву AWS регіону та EKS кластеру відповідно.

○ У файлі “terraform.tf” відредагуйте секцію backend s3, вказавши ім’я, ключ та регіон вашого S3 бакету.

● Зробіть коміт і запуште ці зміни в ваш Git репозиторій.

6. Робочий процес для Terraform коду на етапі Staging

● У директорії IaC-Vprofile на вашому локальному комп’ютері створіть директорію “.github\workflows”. Ця директорія містить робочі процеси GitHub Actions. Файли, що зберігаються тут, визначають конкретні дії, які GitHub виконає на основі подій чи тригерів.

● У директорії “.github\workflows” створіть файл сценарію з назвою “terraform.yml”.

pic

● Вставте наступний код у цей сценарій:

name: "Vpofile IAC"  
on:  
 push:  
 branches:  
 - main  
 - stage  
 paths:  
 - terraform/**  
 pull_request:  
 branches:  
 - main  
 paths:  
 - terraform/**  
env:  
#Credentials for deployment to AWS  
 AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}  
 AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}  
#S3 bucket for Terraform state  
 BUCKET_TF_STATE: ${{ secrets.BUCKET_TF_STATE }}  
 AWS_REGION: us-east-1  
 EKS_CLUSTER: vprofile-eks  

jobs:  
 terraform:  
 name: "Apply terraform code changes"  
 runs-on: ubuntu-latest  
 defaults:  
 run:  
 shell: bash  
 working-directory: ./terraform  

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

 - name: Set up Terraform with specified version on the runner  
 uses: hashicorp/setup-terraform@v2  
 with:  
 terraform_version: 1.6.3  

 - name: Terraform init  
 id: init  
 run: terraform init -backend-config="bucket=$BUCKET_TF_STATE"  

 - name: Terraform format  
 id: fmt  
 run: terraform fmt -check  

 - name: Terraform validate  
 id: validate  
 run: terraform validate  

 - name: Terraform plan  
 id: plan  
 run: terraform plan -no-color -input=false -out planfile  
 continue-on-error: true  

 - name: Terraform plan status  
 if: steps.plan.outcome == 'failure'  
 run: exit 1

● Зробіть коміт і запуште зміни до вашого віддаленого GitHub репозиторію.

● У вкладці “Actions” вашого GitHub репозиторію ви побачите статус виконаного робочого процесу.

pic

● Зверніть увагу, що на даному етапі зміни знаходяться в гілці staging, тому реальні зміни конфігурації ще не були застосовані, поки ми не впровадимо їх у гілку Main.
Основний робочий процес для коду Terraform

● У вашому файлі сценарію terraform.yml додайте наступні зміни, які будуть виконуватись тільки при тригері PUSH до гілки Main:

- name: Terraform Apply  
 id: apply  
 if: github.ref == 'refs/heads/main' && github.event_name == 'push'  
 run: terraform apply -auto-approve -input=false -parallelism=1 planfile  

 - name: Configure AWS credentials  
 uses: aws-actions/configure-aws-credentials@v1  
 with:  
 aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}  
 aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}  
 aws-region: ${{ env.AWS_REGION }}  

 - name: Get Kube config file  
 id: getconfig  
 if: steps.apply.outcome == 'success'  
 run: aws eks update-kubeconfig --region ${{ env.AWS_REGION }} --name ${{ env.EKS_CLUSTER }}  

 - name: Install Ingress controller  
 if: steps.apply.outcome == 'success' && steps.getconfig.outcome == 'success'  
 run: kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.3/deploy/static/provider/aws/deploy.yaml

● Зробіть коміт і запуште зміни до вашого репозиторію на GitHub.

● На цьому етапі гілка “Stage” вашого репозиторію “IaC-Vprofile” повністю оновлена. Для того, щоб застосувати зміни інфраструктури, потрібно злити гілку staging з гілкою Main.

● Для цього відкрийте термінал на вашому локальному комп'ютері, де збережені два репозиторії.

● Перейдіть до вашого репозиторію “IaC” та виконайте checkout на гілку Main.

● Будучи на гілці Main, запустіть git merge stage, щоб з'єднати гілку staging з гілкою Main.

● В кінці запуште зміни в гілці Main до вашого віддаленого репозиторію на GitHub. Зверніть увагу, що це автоматично викликає робочий процес GitHub Actions і застосує визначені зміни інфраструктури в вашому середовищі AWS.

pic

● Щоб підтвердити, що зміни, визначені в робочому процесі GitHub Actions, були застосовані:

○ Увійдіть до вашого облікового запису AWS.

○ Перевірте створення EKS кластеру.

○ Підтвердіть, що створено VPC та відповідні підмережі (як було визначено в раніше створених terraform скриптах).

○ Перевірте, чи були створені EC2 інстанси та ELB.

EKS кластер

pic

VPC

pic

EC2 інстанси

pic

8. Робочий процес для коду програми Vprofile

● Увійдіть до вашого облікового запису на SonarCloud.io та створіть нову організацію.

● Створіть новий проєкт і дайте йому відповідну назву.

● Створіть токен в вашому обліковому записі SonarCloud, який буде використовуватись GitHub для доступу до вашої служби SonarCloud.

● Додайте цей токен SonarCloud до GitHub Secrets.

● Додайте наступні два секрети:

○ SONAR_ORGANIZATION

○ SONARPROJECTKEY

○ SONAR_URL

pic

● У директорії вашого репозиторію “Vprofile-Action” на локальному комп'ютері створіть директорію “.github\workflows” і файл з назвою “main.yml”.
Це буде наш сценарій робочого процесу GitHub Actions.

pic

● Вставте наступний код у файл main.yml:

name: vprofile actions  
on: workflow_dispatch  
env:  
 AWS_REGION: us-east-1  
 ECR_REPOSITORY: vprofileapp254  
 EKS_CLUSTER: vprofile-eks  

jobs:  
 Testing:  
 runs-on: ubuntu-latest  
 steps:  
 - name: Code checkout  
 uses: actions/checkout@v4  

 - name: Maven test  
 run: mvn test  

 - name: Checkstyle  
 run: mvn checkstyle:checkstyle  

 # Налаштування Java 11 за замовчуванням (вимога для sonar-scanner з версії 5.x)  
 - name: Set Java 11  
 uses: actions/setup-java@v3  
 with:  
 distribution: 'temurin' # Дивіться 'Supported distributions' для доступних варіантів  
 java-version: '11'  

 # Налаштування sonar-scanner  
 - name: Setup SonarQube  
 uses: warchant/setup-sonar-scanner@v7  


 # Запуск sonar-scanner  
 - name: SonarQube Scan  
 run: sonar-scanner  
 -Dsonar.host.url=${{ secrets.SONAR_URL }}  
 -Dsonar.login=${{ secrets.SONAR_TOKEN }}  
 -Dsonar.organization=${{ secrets.SONAR_ORGANIZATION }}  
 -Dsonar.projectKey=${{ secrets.SONAR_PROJECT_KEY }}  
 -Dsonar.sources=src/  
 -Dsonar.junit.reportsPath=target/surefire-reports/  
 -Dsonar.jacoco.reportsPath=target/jacoco.exec  
 -Dsonar.java.checkstyle.reportPaths=target/checkstyle-result.xml  
 -Dsonar.java.binaries=target/test-classes/com/visualpathit/account/controllerTest/   

 # Перевірка статусу Quality Gate.  
 - name: SonarQube Quality Gate check  
 id: sonarqube-quality-gate-check  
 uses: sonarsource/sonarqube-quality-gate-action@master  
 # Примусове завершення кроку після певного часу.  
 timeout-minutes: 5  
 env:  
 SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}  
 SONAR_HOST_URL: ${{ secrets.SONAR_URL }} #OPTIONAL  
 BUILD_AND_PUBLISH:   
 needs: Testing  
 runs-on: ubuntu-latest  
 steps:  
 - name: Code checkout  
 uses: actions/checkout@v4  

 - name: Build & Upload image to ECR  
 uses: appleboy/docker-ecr-action@master  
 with:  
 access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}  
 secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}  
 registry: ${{ secrets.REGISTRY }}  
 repo: ${{ env.ECR_REPOSITORY }}  
 region: ${{ env.AWS_REGION }}  
 tags: latest,${{ github.run_number }}  
 daemon_off: false  
 dockerfile: ./Dockerfile  
 context: ./

● Зробіть коміт і запуште зміни.

● Оскільки ми налаштували робочий процес на виконання лише за допомогою “workflow_dispatch”, перейдіть до вашого репозиторію Vprofile-Actions на GitHub і, в розділі “Actions”, запустіть робочий процес вручну.

pic

● SonarCloud перевірить код на відповідність специфікаціям Quality Gates. У нашому випадку, якщо кількість помилок менше ніж 50, тест буде успішним.

pic

● В розділі GitHub Actions ви можете переглянути робочий процес і перевірити, чи були обидва завдання виконані успішно.

pic

● Перевірте ваше сховище ECR на AWS, щоб побачити, чи з'явився Docker-образ, створений за допомогою цього робочого процесу.

pic

9. Розгортання в Elastic Kubernetes Service (EKS)

● Встановіть Helm Charts на ваш локальний комп'ютер.

● Якщо ви на Windows, виконайте choco install kubernetes-helm в PowerShell (обов'язково запустіть як адміністратор).

pic

● Перейдіть до терміналу в репозиторії Vprofile-Actions і виконайте команду: helm create vprofilecharts.
Helm charts містять конфігурації та ресурси, необхідні для розгортання додатків на Kubernetes.

● Видаліть файли за замовчуванням у каталозі helm/vprofilecharts/templates/* репозиторію та скопіюйте всі файли з kubernetes/vpro-app/* туди замість цього.

pic

● У файлі vproappdep.yml змініть тег образу так, щоб його значення бралося з змінної, що зберігається у файлі робочого процесу main.yml, як показано нижче. Це забезпечить, щоб розгортання завжди працювало з останнім створеним образом.

pic

● Перевірте, що все правильно, потім зробіть коміт і запуште зміни до репозиторію на GitHub.

● Перейдіть до GitHub Actions і запустіть робочий процес.

● Це має розгорнути додаток в EKS кластері.

● Тепер додаток має бути доступний або з кінцевої точки ELB, або з вашого доменного імені, як зазначено в файлі vproingress.yml.

pic

pic

● Це позначає завершення успішного розгортання додатка на EKS кластері за допомогою робочих процесів GitHub Actions.

P.S: Після завершення проекту не забудьте очистити ресурси, щоб не залишити працюючі ресурси в AWS, що можуть бути дуже дорогими.

Висновок

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

Використання GitHub Actions як CI/CD конвеєра прискорює цикли розробки, забезпечує надійне керування версіями та посилює практики безпеки. Тим часом використання інструментів для інфраструктури як коду (IaC) таких як Terraform дозволяє забезпечити консистентність, повторюваність і масштабованість у різних середовищах, спрощує управління станом та забезпечує безшовну підтримку на кількох платформах. Разом ці інструменти демонструють потужність сучасних практик DevOps для досягнення ефективних і надійних розгортань.

Перекладено з: Streamlining Application Deployment: GitOps with Terraform, GitHub Actions, and AWS EKS

Leave a Reply

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