- PVSM.RU - https://www.pvsm.ru -

Serverless CI-CD на AWS

Serverless CI-CD на AWS - 1

Было бы круто, если бы развертывание в формате копи-пейст осталось в прошлом, но, увы, дела обстоят иначе. Бывает, разработчикам предпочтительней именно такой метод поставки. Хоть сейчас пиши статью о том, почему это не есть гуд, но вы и без меня все знаете. С тенденцией к бессерверной (serverless) архитектуре пайплайны CI/CD играют важную роль в поставке приложений. Я еще писал о них в статье "3 лучших совета для вашего следующего бессерверного проекта [1]".

Темой CI и CD я интересуюсь давненько, а впервые столкнулся с ней несколько лет назад — благодаря TeamCity. В настоящее время TeamCity по-прежнему используется для большинства наших пайплайнов CI/CD. Работает TeamCity прекрасно, ничего против не имею, но я всегда стремлюсь улучшить работу. Например, было бы хорошо собирать пайплайны в виде кода — это одно из направлений, в которых TeamCity не так хорош.

Инструменты интеграции и поставки на AWS я изучил какое-то время назад, и, хотя мы используем CodeDeploy для другого проекта, который работает на EC2, бессерверный проект я с ними еще не развертывал. Ознакомившись с инструментами повторно, я обратил внимание вот на что: теперь есть встроенная функция интеграции для развертывания CloudFormation и Lambda, предположительно, на основе SAM AWS; мы используем бессерверную платформу [1], — она генерирует шаблоны CloudFormation, но с инструментами AWS она “из коробки” не работает.

Подготовка

Я использую следующие службы AWS: EC2, Docker, ECR, S3, IAM, CodeBuild, CodePipeline, CloudWatch, CloudTrail. Чтобы не отставать, вам нужно хотя бы на базовом уровне понимать, что делает каждая из этих служб.

В основном я пишу код серверной части в .NET, на эту платформу опирается и данное руководство. Ни один из готовых образов CodeBuild не имеет среды выполнения .NET и NodeJS одновременно (NodeJS нужен для бессерверной платформы). Если ваши функции Lambda написаны в NodeJS, настройка пайплайна развертывания значительно упрощается, ведь это — единственная среда выполнения, необходимая для установки в образе Docker (если случай ваш — смело пропускайте большую часть руководства). На секундочку, это был мой первый опыт знакомства с контейнерами, и я рад узнать что-то новое.

Смею предположить, что ваш код — в неком репозитории, например, git. Для руководства мы просто загрузим в S3 файл, содержащий пакет кода для развертывания; как вы его получите, зависит от вас. Взяв мою работу на основу, вы всегда можете пойти дальше, подключив свой пайплайн к таким репозиториям, как github или CodeCommit.

1. Создайте экземпляр EC2 и установите Docker

Запустите стандартный экземпляр AWS Linux 2 EC2 — это должно быть понятно без пояснений. Войдите в систему и установите Docker с помощью команд:

sudo yum update -y
sudo amazon-linux-extras install docker
sudo service docker start

Еще нужно добавить пользователя ec2 в группу docker, чтобы выполнять команды Docker, не используя sudo:

sudo usermod -a -G docker ec2-user

Когда команда выполнена, выйдите из системы и снова войдите в свой экземпляр EC2, чтобы пользователь ec2 получал новые разрешения. Убедитесь, что пользователь ec2 запускает команды Docker без sudo:

docker info

Serverless CI-CD на AWS - 2 [2]
Вывод команды docker info

2. Создайте образ Docker и поместите в ECR

Предположим, предыдущий шаг выполнен успешно; следующий этап — создание образа Docker, который помещается в ECR. AWS предлагает базовые образы для CodeBuild на github [3], и это упрощает создание собственного образа.

Я также опубликовал образ в github — на случай, если не захотите выполнять следующие действия для создания собственного: https://github.com/effectivedigital/serverless-deployment-image [4]

Скопируйте образы и перейдите в каталог .NET Core 2.1:

git clone https://github.com/aws/aws-codebuild-docker-images.git
cd aws-codebuild-docker-images
cd ubuntu/dot-net/core-2.1/

Откройте Dockerfile в предпочтительном текстовом редакторе:

nano Dockerfile

Добавьте команды для установки NodeJS и бессерверной платформы в конце других команд, уже имеющихся в Dockerfile. Большинство этих команд я получил из образа NodeJS Docker в том же репозитории AWS:

# Install Node Dependencies
ENV NODE_VERSION="10.14.1"
# gpg keys listed at https://github.com/nodejs/node#release-team
RUN set -ex 
 && for key in 
 94AE36675C464D64BAFA68DD7434390BDBE9B9C5 
 B9AE9905FFD7803F25714661B63B535A4C206CA9 
 77984A986EBC2AA786BC0F66B01FBB92821C587A 
 56730D5401028683275BD23C23EFEFE93C4CFFFE 
 71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 
 FD3A5288F042B6850C66B31F09FE44734EB7990E 
 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 
 C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 
 DD8F2338BAE7501E3DD5AC78C273792F7D83545D 
 4ED778F539E3634C779C87C6D7062848A1AB005C 
 A48C2BEE680E841632CD4E44F07496B3EB3C1762 
 ; do 
 gpg - keyserver hkp://p80.pool.sks-keyservers.net:80 - recv-keys "$key" || 
 gpg - keyserver hkp://ipv4.pool.sks-keyservers.net - recv-keys "$key" || 
 gpg - keyserver hkp://pgp.mit.edu:80 - recv-keys "$key" ; 
 done
RUN set -ex 
 && wget "https://nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz" -O node-v$NODE_VER$
 && wget "https://nodejs.org/download/release/v$NODE_VERSION/SHASUMS256.txt.asc" -O SHASUMS256.txt.asc 
 && gpg - batch - decrypt - output SHASUMS256.txt SHASUMS256.txt.asc 
 && grep " node-v$NODE_VERSION-linux-x64.tar.gz$" SHASUMS256.txt | sha256sum -c - 
 && tar -xzf "node-v$NODE_VERSION-linux-x64.tar.gz" -C /usr/local - strip-components=1 
 && rm "node-v$NODE_VERSION-linux-x64.tar.gz" SHASUMS256.txt.asc SHASUMS256.txt 
 && ln -s /usr/local/bin/node /usr/local/bin/nodejs 
 && rm -fr /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN npm set unsafe-perm true
CMD [ "node" ]
# Install Serverless Framework
RUN set -ex 
 && npm install -g serverless

Теперь собираем и тегируем образ:

docker build -t aws/codebuild/dot-net .

Завершив сборку, запустите образ — убедитесь, что все работает, и что бессерверная платформа установлена правильно:

docker run -it --entrypoint sh aws/codebuild/dot-net -c bash
sls -v

Serverless CI-CD на AWS - 3 [5]
Запуск sls -v внутри новенького контейнера

Затем создаем репозиторий в ECR с помощью AWS CLI. После запуска команды новый репозиторий будет отображаться в консоли AWS:

aws ecr create-repository --repository-name codebuild-dotnet-node

Serverless CI-CD на AWS - 4 [6]
Ответ AWS CLI на создание репозитория в ECR

Serverless CI-CD на AWS - 5 [7]

Теперь помечаем созданный ранее образ aws/codebuild/dot-net значением repositoryUri из предыдущего этапа:

docker tag aws/codebuild/dot-net <ACCOUNTID>.dkr.ecr.ap-southeast-2.amazonaws.com/codebuild-dotnet-node

Выполните команду get-login для получения командной строки аутентификации docker login для реестра контейнеров:

aws ecr get-login --no-include-email

Serverless CI-CD на AWS - 6 [8]

Выполните команду docker login, выданную при выполнении команды get-login во время последнего шага.

docker login -u AWS -p eyJwYXlsb2FkIjoiNGZnd0dSaXM1L2svWWRLMmhJT1c0WWpOZEcxamJFeFJOK2VvT0Y5[...] https://<ACCOUNTID>.dkr.ecr.ap-southeast-2.amazonaws.com

Если вход в систему выполнен успешно, поместите образ docker в репозиторий, созданный в ECR. Это может занять несколько минут (зависит от размера завершенного образа).

docker push <ACCOUNTID>.dkr.ecr.ap-southeast-2.amazonaws.com/codebuild-dotnet-node

Serverless CI-CD на AWS - 7 [6]
Docker на EC2 создает наш образ

Serverless CI-CD на AWS - 8 [9]
Образ Docker в ECR

Потом доступ к образу из ECR сможем открыть кому угодно. Разрешение необходимо заблокировать в рабочей среде, но в данном примере мы его откроем. Перейдите на вкладку разрешений в консоли AWS, выберите "Изменить политику JSON" и вставьте в политику следующий элемент:

{
  "Version": "2008-10-17",
  "Statement": [
    {
      "Sid": "EnableAccountAccess",
      "Effect": "Allow",
      "Principal": "*",
      "Action": [
        "ecr:BatchCheckLayerAvailability",
        "ecr:BatchGetImage",
        "ecr:DescribeImages",
        "ecr:DescribeRepositories",
        "ecr:GetAuthorizationToken",
        "ecr:GetDownloadUrlForLayer",
        "ecr:GetRepositoryPolicy",
        "ecr:ListImages"
      ]
    }
  ]
}

3. Создайте пайплайн

Настало время собрать пайплайн. Чтобы упростить процесс, сделать его многократно развертываемым и придерживаться трушной формы бессерверной архитектуры, я собрал пайплайн с помощью бессерверной платформы. Того же результата можно добиться путем сборки в CloudFormation.

Не стану копировать весь источник из моего файла serverless.yml file — скопируйте его из github: https://github.com/effectivedigital/serverless-deployment-pipeline [10]

Просмотрите бессерверный шаблон, чтобы точно понять, что он будет делать, но, если вкратце, он настраивает следующие элементы:

  • 3 сегмента S3
  • 1 политика сегмента
  • 3 роли IAM
  • 1 проект CodeBuild
  • 1 пайплайн CodePipeline
  • 1 событие CloudWatch
  • 1 след CloudTrail

Потом обновите DockerImageArn для своего образа в ECR. Если хотите создавать пакеты развертывания с именем, отличным от Deployment.zip, то обновите еще и DeploymentFilename:

DockerImageArn: <ACCOUNTID>.dkr.ecr.ap-southeast-2.amazonaws.com/codebuild-dotnet-node:latest
DeploymentFilename: Deployment.zip

Вот и все, пайплайн готов к развертыванию. Выполните команду бессерверного развертывания и подождите, пока не настроится:

sls deploy -v

Serverless CI-CD на AWS - 9 [11]
Созданный бессерверной платформой стек CloudFormation

Serverless CI-CD на AWS - 10 [12]
Созданный бессерверной платформой пайплайн CodePipeline

Serverless CI-CD на AWS - 11 [13]
Созданный бессерверной платформой проект CodeBuild Project

4. Добавьте buildSpec.yml в свое приложение

Когда CodePipeline обнаружит изменение файла развертывания в S3, он сообщит CodeBuild, что нужно запустить и попытаться собрать и развернуть приложение. Тем не менее, CodeBuild должен также знать, какие команды должны выполняться для сборки и развертывания приложения, и buildSpec.yml содержит инструкции, которым будет следовать CodeBuild.

Я создал очень простое приложение "Hello world", включающее пример файла buildSpec.yml, который вы можете использовать: https://github.com/effectivedigital/serverless-deployment-app [14]
Или создайте файл buildSpec.yml в существующих приложениях и заполнить его согласно инструкциям ниже:

version: 0.2
phases:
  pre_build:
    commands:
      - chmod a+x *
  build:
    commands:
      - ./build.sh
  post_build:
    commands:
      - sls deploy -v -s $STAGE

5. Проверка пайплайна

Теперь все готово для первого запуска вашего пайплайна. Создайте пакет под названием Deployment.zip, он должен включать все файлы для вашего бессерверного приложения и файл buildSpec.yml.

Через несколько мгновений CloudTrail должен зарегистрировать событие PutObject и активировать правило событий CloudWatch, которое затем активирует запуск CodePipeline.

Serverless CI-CD на AWS - 12 [15]
Deployment.zip загрузился в S3

Serverless CI-CD на AWS - 13 [16]
CodePipeline запущен, сборка пошла

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

Serverless CI-CD на AWS - 14 [17]
CodeBuild получит вывод от выполняющего сборку и развертывание образа Docker

Serverless CI-CD на AWS - 15 [18]
Развертывание прошло успешно!

Новое приложение, развернутое нашим пайплайном, также отображается в CloudFormation:

Serverless CI-CD на AWS - 16 [19]

Можно протестировать конечную точку API, созданную в нашем простом приложении (URL находится в выходе CodeBuild или в шлюзе API) и убедиться, что приложение успешно работает:

Serverless CI-CD на AWS - 17 [20]
Postman для вызова API

Краткие выводы

CodePipeline позволяет создать масштабируемый, гибкий и недорогой пайплайн CI/CD и помогает в решении некоторых проблем, связанных с традиционными пайплайнами, созданными на серверах.
Я хотел бы пойти дальше и добавить в смесь модульное тестирование после развертывания, но тема заслуживает отдельной статьи — и это повод читать нас в будущем!

Автор: nAbdullin

Источник [21]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/aws-2/309213

Ссылки в тексте:

[1] 3 лучших совета для вашего следующего бессерверного проекта: https://medium.com/@gavinlewis/3-top-tips-for-your-next-serverless-project-2ea87bc833e7

[2] Image: https://habrastorage.org/webt/i-/aq/r_/i-aqr_g3enpgmdd4clpawaaykmu.png

[3] CodeBuild на github: https://github.com/aws/aws-codebuild-docker-images

[4] https://github.com/effectivedigital/serverless-deployment-image: https://github.com/effectivedigital/serverless-deployment-image

[5] Image: https://habrastorage.org/webt/ji/vh/da/jivhda2vzvu3vwc4uyltgyz0mza.png

[6] Image: https://habrastorage.org/webt/qc/bq/-g/qcbq-gsw-afhdbp2q9meo1nsqrk.png

[7] Image: https://habrastorage.org/webt/2q/sf/_v/2qsf_v-jbgorara_qbzwi2lavoc.png

[8] Image: https://habrastorage.org/webt/6l/w9/2d/6lw92dgbv2c7fvicbjvoz-afxwo.png

[9] Image: https://habrastorage.org/webt/k-/me/2l/k-me2lgrhindh4_2p9tl24e0qau.png

[10] https://github.com/effectivedigital/serverless-deployment-pipeline: https://github.com/effectivedigital/serverless-deployment-pipeline

[11] Image: https://habrastorage.org/webt/hi/wk/ys/hiwkysbgka2zessqrdqkb4nir1g.png

[12] Image: https://habrastorage.org/webt/hc/r6/yr/hcr6yrezormgpobpu2bdu-_tvj4.png

[13] Image: https://habrastorage.org/webt/ef/ax/ad/efaxaddb_yspsbdxrl1azf5e1oo.png

[14] https://github.com/effectivedigital/serverless-deployment-app: https://github.com/effectivedigital/serverless-deployment-app

[15] Image: https://habrastorage.org/webt/zg/r4/ii/zgr4iikop3ujbabsgtsfbyjex4o.png

[16] Image: https://habrastorage.org/webt/ak/xd/iz/akxdizdzjomaespfhmnygedoqia.png

[17] Image: https://habrastorage.org/webt/gv/sx/cb/gvsxcbcpmbcnj18k9rwbqbm_bhu.png

[18] Image: https://habrastorage.org/webt/l3/ec/xm/l3ecxm5cjedmhtpxne0nklzdzlm.png

[19] Image: https://habrastorage.org/webt/r6/2s/xl/r62sxlivtmrg8vn3yze2xe0ez3y.png

[20] Image: https://habrastorage.org/webt/h4/s3/gh/h4s3ghrxxwlpxaf3ssdwhfx30sy.png

[21] Источник: https://habr.com/ru/post/440756/?utm_campaign=440756