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