Построение CI/CD для проекта на базе Docker с использованием CodeBuild, CodeDeploy и Lambda

от автора

CI/CD-пайплайны автоматизируют процессы создания, тестирования и развертывания программного обеспечения, позволяя командам быстро и надежно выпускать обновления. В этой статье рассмотрим, как создать пайплайн с помощью AWS, как использовать CodeBuild для запуска при размещении кода в ветке. Также разберем, как запускать тесты, затем собирать и размещать образ Docker в ECR, и сохранять артефакты кода в S3, после чего можно использовать функцию Lambda для запуска CodeDeploy, которая развернет код на группе EC2-инстансов.

Почему бы просто не использовать CodePipeline?! Ответ — не везде это возможно.

А что, если я собираюсь отправлять образы в ECR, то зачем использовать CodeDeploy для отправки кода в EC2-инстансы? В некоторых случаях вы не сможете получить код из частного хранилища в ECR.

Вот схематический обзор того, что мы будем делать: 

Наш код

Для примера я собираюсь использовать простое приложение на Python для создания API с помощью flask

# app.py from flask import Flask  app = Flask(__name__)  @app.route('/') def hello():     return "Hello, Docker!"  if __name__ == '__main__':     app.run(host='0.0.0.0',port=80)

Тесты важны для кода: в случае неудачи мы не развернем в продакшене код с ошибками.

# tests/test_app.py from app import app  def test_index_route_success_status():     response = app.test_client().get('/')     assert response.status_code == 200      def test_index_route_success_text():     response = app.test_client().get('/')     assert response.data.decode('utf-8') == 'Hello, Docker!'

И, наконец, мы пишем Dockerfile

# Dockerfile FROM python:3.8-slim  # Set the working directory in the container WORKDIR /app  # Install the dependencies RUN pip install flask pytest  # Copy the application code to the container COPY . .  # Set the command to run the application CMD ["python", "app.py"]

Теперь наш код готов к переносу в основную ветку и развертыванию.

CodeBuild

Теперь откройте AWS CodeBuild и создайте проект для построения, добавьте имя проекта и источник кода — bitBucket в нашем примере — и ветку, которую необходимо считывать. Включите webhooks.

И в разделе «Окружение» необходимо включить привилегированный режим, поскольку мы хотим собирать Docker-образы.

И если мы хотим передать информацию в процесс сборки, мы можем использовать переменные среды. Здесь мы должны передать несколько значений: 

AWS_DEFAULT_REGION: регион, который вы используете

IMAGE_TAG: тег для образа Docker

IMAGE_REPO_NAME: имя репозитория ECR

AWS_ACCOUNT_ID: идентификатор учетной записи пользователя

Эти значения могут быть вставлены в buildspec.yml напрямую, но в целях безопасности лучше использовать переменную среды. Файл buildspec.yml очень важен, мы обсудим его после части, посвященной артефактам.

В артефактах мы выберем S3, затем выберем хранилище, куда мы хотим их отправить. Артефакты должны быть в формате Zip.

buildspec.yml

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

#buildspec.yml version: 0.2  phases:   pre_build:     commands:        - echo Logging in to Amazon ECR...        - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com   build:     commands:       - echo run tests first       - pip install flask pytest       - python3 -m pytest --junitxml=/usr/tests/test-report.xml       - echo Build started on `date`       - echo Building the Docker image...                 - docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG .       - docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG    post_build:     commands:       - echo Build completed on `date`       - echo Pushing the Docker image...       - docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG        Reports:   pytest-reports:     files:       - test-report.xml     base-directory: /usr/tests/     file-format: JUNITXML  Artifacts:   type: zip   files:     - '**/*'

На этапе pre_build мы вошли в нашу учетную запись ECR

На этапе сборки мы запустили тест, сохранили результат в файл и собрали образ

На этапе post_build мы поместили docker в хранилище.

*Данные, переданные из переменных окружения, которые мы задали в консоли, могут быть доступны со знаком $

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

Артефакты:

CodeDeploy

Создайте приложение и затем создайте группу для развертывания. Развернем для одного инстанса EC2 с тегом «env» и значением «dev».

И отключите функцию балансировки нагрузки, в этом случае она нам не нужна. Лучше установить Codedeploy вручную.

Для работы CodeDeploy необходимо написать шаги, что делать, когда инстанс в установочной группе получает код. Эти шаги записываются в appspec.yml, файл также должен располагаться в корневой директорий проекта.

appspec.yml version: 0.0 os: linux # this to copy all files in the project to spacfic location files:   - source: /     destination: /usr/src/app/ # overrite file if they are already there file_exists_behavior: OVERWRITE  hooks:   BeforeInstall:     - location: scripts/before_install.sh       runas: root   ApplicationStart:     - location: scripts/application_start.sh       runas: root

Hook — это элементы конфигурации, используемые в AWS CodeDeploy для того чтобы определить действия, которые должны быть выполнены до и после развертывания, например, запуск скриптов или выполнение команд.

#scripts/before_install.sh  #stop all running containers docker kill $(docker ps -q)  #delete all images docker rmi -f $(docker images -aq)

Перед установкой мы сначала останавливаем запущенные контейнеры и удаляем все образы:

#scripts/application_start.sh  # build the docker image docker build -f /usr/src/app/Dockerfile /usr/src/app/ -t myapp  # run the container docker run -d -p 80:80 myapp

В запуске приложения мы собираем наш образ и затем запускаем его на порту 80

*CodeDpoly должен быть установлен на целевом инстансе EC2. Иногда он не подключается, так что вам придется перезапустить процесс или весь инстанс.

Вот окончательная структура нашего проекта:

Lambda Functions

Необходимо используем эту функцию для  развертывания всякий раз, когда CodeBuild размещает новые артефакты в S3. Можно использовать Python и библиотеку boto3, которая позволяет писать программное обеспечение, использующее такие сервисы, как Amazon S3 и Amazon EC2.

import boto3  def lambda_handler(event, context):     # Get the S3 bucket and object information from the event     s3_bucket = event['Records'][0]['s3']['bucket']['name']     s3_key = event['Records'][0]['s3']['object']['key']      # Create a CodeDeploy client     codedeploy_client = boto3.client('codedeploy')      # Create a deployment with the S3 revision     response = codedeploy_client.create_deployment(         applicationName='codedeply-ec2',            #change this to codedepoly application name         deploymentGroupName='codedeploy-ec2',       #change this to deployment group name         revision={             'revisionType': 'S3',             's3Location': {                 'bucket': s3_bucket,                 'key': s3_key,                 'bundleType': 'zip'             }         }     )      # Print the deployment ID     deployment_id = response['deploymentId']     print(f"Deployment ID: {deployment_id}")
От редакции

Возможности CI/CD позволяют специалистам автоматизировать процессы интеграции и регулярно выпускать ПО высокого качества. На курсе «CI/CD на примере Gitlab CI» мы учим принципам CI/CD: конвейерному методу разработки, работе с пайплайнами, билдами и артефактами. Узнать больше о программе и записаться на курс вы можете на нашем сайте: https://slurm.io/gitlab-ci-cd


ссылка на оригинал статьи https://habr.com/ru/companies/southbridge/articles/747704/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *