Если вы когда-либо развертывали свой интерфейс без конвейеров развертывания, вы знаете, как быстро работа может стать утомительной. В этой записи блога я пытаюсь показать вам, насколько легко на самом деле создавать конвейеры для вашего внешнего интерфейса, чтобы ваш код автоматически строился, тесты выполнялись, а созданные файлы отправлялись в CloudFront.

Какая технология будет использоваться?

Мы стараемся сделать наши конвейеры простыми, но я расскажу обо всем, что вам нужно знать, чтобы использовать конвейеры в производственной среде. Если вы не используете какие-либо технологии, приведенные ниже, эта запись в блоге может быть вам полезна, поскольку она также должна дать вам базовое представление о конвейерах развертывания.

Что касается наших технологий, мы будем использовать любой проект внешнего интерфейса, зависящий от NPM, в моем случае Vue JS, но вы, конечно, можете использовать Angular, React или что-то подобное. Кроме того, мы будем использовать битбакет в сочетании с бамбуком. Вы получаете бамбук из коробки, если находитесь в облаке Atlassian, и, на мой взгляд, интеграция довольно безупречна. При использовании Bamboo мы также немного посмотрим на Docker, но не бойтесь, что мы пока не создадим контейнер Docker :). Наконец, мы позволим bamboo передать ресурсы CloudFront. Это не кажется большим, и на самом деле это не так.

Как будет выглядеть трубопровод

Как видите, сам конвейер довольно прост. Каждый раз, когда мы нажимаем на наш репозиторий bitbucket, мы хотим активировать обработчик конвейера, который затем развернет наш код в AWS. Самое замечательное в конвейере то, что он чрезвычайно мал и может быть заменен любой технологией. Итак, давайте посмотрим, как это сделать :).

Настройка конвейеров

Я предполагаю, что вы уже создали проект внешнего интерфейса по своему выбору и связали его с Bitbucket. В таком случае вы можете создать файл bitbucket-pipelines.yml в корневом каталоге вашего проекта.

image: node:10.15.0

pipelines:
  branches:
    master:
      - step:
          caches:
            - node
          script:
            - apt-get update && apt-get install -y python-dev
            - curl -O https://bootstrap.pypa.io/get-pip.py
            - python get-pip.py
            - pip install awscli
            - npm install
            - npm run build
            - aws s3 sync dist s3://$PROD_S3_BUCKET
            - aws configure set preview.cloudfront true
            - aws cloudfront create-invalidation --distribution-id $PROD_CLOUDFRONT_DISTRIBUTIION_ID --paths "/*"

А теперь давайте переварим этот файл построчно :).

image: node:10.15.0

Первая строка описывает образ докера, который вы хотите использовать. В моем случае это последняя версия узла, доступная на docker hub. Но вы можете использовать любую версию, от которой может зависеть ваша среда.

pipelines:
  branches:
    master:

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

caches:
  - node

На следующем шаге определяется кеш для узла. Здесь происходит то, что зависимости, которые были загружены через установку npm, будут кэшированы, так что время сборки будет уменьшено для следующих сборок.

- apt-get update && apt-get install -y python-dev
- curl -O https://bootstrap.pypa.io/get-pip.py
- python get-pip.py
- pip install awscli

Это просто служебные скрипты для получения нужного нам в дальнейшем aws cli. Было бы разумно инкапсулировать эти строки в контейнер докера, но поскольку докер не входит в объем этой записи в блоге, я добавлю эти строки как часть скрипта. Если вам интересна эта тема, оставьте комментарий, и я покажу вам, как работать с докером :).

- npm install
- npm run build

Эти строки запустят процесс сборки вашего проекта. Я думаю, вы знаете, что они делают :).

И наконец

- aws s3 sync dist s3://$PROD_S3_BUCKET
- aws cloudfront create-invalidation --distribution-id $PROD_CLOUDFRONT_DISTRIBUTIION_ID --paths "/*"

Эти 2 строки автоматически отправят ваш код в CloudFront и S3. Если вы не знакомы с CloudFront и S3, вот краткое изложение.

S3 - это объектное хранилище AWS, вы можете думать о нем как о каталогах на компьютере с файлами. CloudFront отвечает за максимально быстрое обслуживание заданного каталога S3 для конечного пользователя. Вот почему у вас должен быть ваш интерфейс прямо здесь, если вы используете AWS. Конечно, это немного упрощено, но опять же, это выходит за рамки :).

Теперь давайте посмотрим на каждую строку развертывания AWS.

aws s3 sync web s3://$PROD_S3_BUCKET

Эта строка синхронизирует каталог dist с заданным сегментом S3. Как видите, здесь я использую интересную функцию bitbucket: переменные репозитория. Вы можете определить эти переменные в настройках вашего проекта.

Мы рассмотрим различные необходимые переменные репозитория через пару секунд.

aws cloudfront create-invalidation --distribution-id $PROD_CLOUDFRONT_DISTRIBUTIION_ID --paths "/*"

Эта строка сделает наш текущий CloudFront недействительным. Но что это значит? По сути, у вас есть разные точки присутствия, которые представляют собой серверы, которые будут обслуживать файлы, указанные в вашем интерфейсе. Если вы сейчас обновите свой S3, это не означает, что ваш CloudFront также будет обновлен. Итак, ваши файлы S3 и CloudFront теперь могут отличаться. Чтобы этого не произошло, вы можете сделать файлы недействительными. Параметр пути / * означает, что каждый файл будет признан недействительным и будет повторно кэширован CloudFront. Вы можете изменить параметр пути, если хотите, чтобы определенные файлы были признаны недействительными.

Так что на самом деле это был самый важный шаг в нашем процессе сборки. Последнее, что нам нужно сделать, это все подключить. Для этого мы сначала взглянем на переменные репозитория.

Переменные репозитория

Как я уже сказал, у вас есть возможность определять переменные репозитория для ваших конвейеров развертывания. Вы даже можете скрыть ценности, если не хотите, чтобы их никто не видел. Доступ к этим переменным можно получить как к $ PROD_S3_BUCKET в вашем bitbucket-pipelines.yml. Итак, давайте посмотрим, какие переменные я определил.

Как видите, я уже добавляю учетные данные для доступа к AWS (AWS_ACCESS_KEY_ID и AWS_SECRET_ACCESS_KEY). Эти переменные будут использоваться aws cli. Если у вас еще нет пользователя, вы можете создать его с помощью параметра IAM в aws. Обязательно установите правильные политики, чтобы этот пользователь имел доступ только к S3 и CloudFront. Если вы закончили создание пользователя, вы получите обе переменные.

Для этого будут использоваться переменные prod.

- aws s3 sync dist s3://$PROD_S3_BUCKET
- aws cloudfront create-invalidation --distribution-id $PROD_CLOUDFRONT_DISTRIBUTIION_ID --paths "/*"

так что корзина S3 фактически получает данные, а CloudFront становится недействительным.

И это все. Теперь вы создали свой собственный конвейер внешнего интерфейса, который автоматически отправляет новейшую версию вашего репозитория в CloudFront.

Если вы не знаете, как создать CloudFront, вот вам небольшая помощь. Сначала вы создаете сегмент S3 внутри S3. Вы предоставляете этому сегменту S3 общий доступ на чтение - у вас есть меню внутри сегмента, в котором вы можете установить правила сегмента. Вы можете создать эти правила с помощью генератора политик. Конфигурация могла выглядеть так:

а сгенерированный json выглядит так:

После этого вы открываете CloudFront и создаете новый дистрибутив. Исходное доменное имя будет вашим сегментом S3 - вы получите раскрывающийся список, где вы можете его выбрать. Теперь вам остается только дождаться завершения статуса.

На что обращать внимание

Конвейер непрерывного развертывания действительно хорош, но вы должны помнить, что вам нужно действительно хорошее тестовое покрытие, чтобы быть уверенным, что вы ничего не сломаете. Я бы порекомендовал вам не позволять никому отправлять запросы к мастеру и использовать для этого запросы на вытягивание. Таким образом вы гарантируете, что, будем надеяться, только протестированный код будет включен в вашу производственную среду :).

Остались вопросы? Не стесняйтесь писать комментарий :).