Как автоматизировать развертывание на AWS EC2 с помощью CircleCI и Ansible

Как автоматизировать развертывание на AWS EC2 с помощью CircleCI и Ansible

Содержание
  1. Необходимые условия
  2. Настройка CircleCI
  3. Написание config.yml
  4. Настройка Ansible
  5. Написание книги воспроизведения
  6. Заключение

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

Необходимые условия

Чтобы извлечь максимальную пользу из этого руководства и следовать ему, вам будет полезно иметь:

  • Базовый опыт программирования и умение работать с командной строкой.
  • Аккаунт на Github и доступ к командной строке с установленным git.
  • Аккаунт AWS с настроенным сервером EC2.
  • Учетная запись CircleCI.
  • Редактор кода.

Этот учебник будет посвящен только настройке и развертыванию, мы не будем настраивать новые серверы. Я буду использовать бэкенд-сервер, который я написал некоторое время назад. Стартовый код можно найти здесь. Создайте форк и клонируйте репозиторий. Переключитесь на ветку starter, чтобы следовать дальше.

Настройка CircleCI

Перейдите на сайт circleci.com и войдите в систему. Убедитесь, что вы находитесь в своей личной организации. На странице “Проекты” найдите репо aws_ec2_auto_deploy и просто нажмите “Установить проект”. Выберите опцию “Use the . circleci/config. yml in my repo” и настройте проект. Настройте переменные окружения проекта, скопировав значения по умолчанию из файла .env.example в Project Settings > Environment Variables на панели управления проектом CircleCI. Теперь перейдем к делу.

Написание config.yml

Откройте в редакторе файл config.yml в папке .circleci.

CircleCI использует YAML-файлы для настройки конвейеров, которые обычно состоят из следующих блоков YAML-кодов:

Блок YAML Описание

version Здесь указывается версия CircleCI API, которую вы хотите использовать

команды Содержит список команд, которые можно использовать повторно

orbs Позволяет использовать определенные заранее написанные функции в задании

jobs Список заданий

workflow Определяет порядок выполнения заданий

Перед развертыванием кода на серверах рекомендуется убедиться, что все тесты пройдены. Обновите файл config.yml с помощью приведенного ниже кода.

version: 2.1
jobs:
  test:
    docker:
      - image: cimg/node:16.17.0
      - image: redis
        name: redis
      - image: mysql:8.0
        environment:
          MYSQL_ROOT_PASSWORD: 12345
          MYSQL_DATABASE: lend
          MYSQL_USER: abuchikings
          MYSQL_PASSWORD: 12345
    steps:
      - checkout
      - restore_cache:
          keys: [packages]
      - run:
          name: Test MySQL connection
          command: |
            for i in $(seq 1 30); do
              nc -z 127.0.0.1 3306 && echo Success && exit 0
              echo -n .
              sleep 1
            done
            echo Failed waiting for MySQL && exit 1
      - run:
          name: Run tests
          command: |
            npm install
            npm run migrate:latest
            npm run test
      - save_cache:
          paths: ['./node_modules']
          key: packages
workflows:
  default:
    jobs:
      - test

Вот описание того, что происходит в приведенном выше коде:

Ключевое слово jobs указывает на то, что блок кода будет содержать задания.

Самое первое задание называется test, а ключевое слово docker указывает CircleCI, что это задание будет выполняться в среде docker.

  • cimg/node - это официальный образ nodejs от CircleCI на хабе docker. Для данного проекта используется Node версии 16.17.0. Для тестирования приложения требуется база данных MySQL 8.0 и redis.

  • steps: Как следует из названия, определяет шаги, необходимые для выполнения определенного задания.

  • checkout: Проверяет исходный код из вашего репозитория контроля версий.

  • restore_cache: Восстанавливает кэшированные зависимости. Кэширование - это механизм, который позволяет сохранять и повторно использовать зависимости (например, пакеты npm) для ускорения процесса сборки. В данном случае восстанавливаются кэшированные пакеты npm.

  • run: Этот шаг запускает серию команд. Он отвечает за выполнение фактических задач CI.

  • name: Это описательное имя для данного шага, указывающее на то, что следующие команды связаны с запуском тестов.

  • команда: Указывает команды, которые будут выполняться. Символ | используется для определения многострочного командного блока, что позволяет выполнять несколько команд в рамках этого шага. Первая команда использует утилиту nc (netcat) для проверки доступности сервера баз данных MySQL, работающего на localhost (127.0.0.1) и прослушивающего порт 3306. Вторая команда запускает миграцию и автоматические тесты на коде.

  • save_cache: Это встроенная команда CircleCI, используемая для сохранения кэшированных зависимостей или артефактов. Она гарантирует, что указанные файлы или каталоги будут сохранены в кэше для будущих сборок.

  • workflows: Этот раздел определяет один или несколько рабочих процессов. Рабочий процесс - это серия заданий, которые должны быть выполнены в определенном порядке или при определенных условиях.

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

Затем обновите свой config.yml с помощью задания setup_ansible, приведенного ниже. Не забудьте также обновить рабочий процесс, как показано в фрагменте кода ниже.

setup_ansible:
  docker:
    - image: amazon/aws-cli
  steps:
    - checkout
    - run:
        name: Install dependencies
        command: |
          yum install -y tar gzip

    - run:
        name: Add Backend IP To Ansible
        command: |
          backendIP=$(aws ec2 describe-instances \
            --query "Reservations[*].Instances[*].PublicIpAddress" \
            --filters "Name=tag:Name,Values=ec2_auto_deploy_test" \
            --output text)
          echo "$backendIP" >> ~/project/.circleci/ansible/inventory.txt

    - persist_to_workspace:
        root: ~/
        paths:
          - project/.circleci/ansible/inventory.txt

workflows:
  default:
    jobs:
      - test
      - setup_ansible:
          requires: [test]

Не забудьте изменить ec2_auto_deploy_test на имя вашего EC2-сервера на AWS.

Задание setup_ansible использует aws-cli для получения IP-адреса сервера EC2 с тегом имени ec2_auto_deploy_test. IP-адрес сохраняется в файле inventory.txt в папке Ansible и сохраняется в рабочей области для использования следующим заданием. Для сохранения файла в рабочую область требуются утилиты tar и gzip.

Перед отправкой изменений на github перейдите на страницу проекта на CircleCI => Настройки проекта => Переменные окружения и добавьте следующие переменные окружения:

AWS_SECRET_ACCESS_KEY AWS_DEFAULT_REGION AWS_ACCESS_KEY_ID

которые можно получить из вашей учетной записи aws.

Последняя конфигурация задания в файле config.yml будет отвечать за выполнение плейбука Ansible, который использует ssh для доступа к серверу, извлекает код с github и собирает обновленный образ docker. Смотрите код ниже.

deploy_server:
  docker:
    - image: python:3.11.6-alpine3.18
  steps:
    - checkout
    - add_ssh_keys:
        fingerprints: ['9f:66:26:48:fd:251:62:5d:73:c4:d5:90:2b']
    - attach_workspace:
        at: ~/
    - run:
        name: Install dependencies
        command: |
          apk add --update ansible openssh-client
          eval $(ssh-agent -s)
          print("Dependencies installed")  # Logging statement
    - run:
        name: Deploy Server
        command: |
          cd ~/project/.circleci/ansible
          echo "Contents of the inventory.txt -------"
          cat inventory.txt
          print("Starting server deployment")  # Logging statement
          ansible-playbook -i inventory.txt deploy-server.yml
          print("Server deployment completed")  # Logging statement

На странице настроек проекта CircleCI перейдите в раздел SSH Keys, добавьте новый ssh-ключ, скопировав и вставив ssh-ключ для вашего сервера EC2. При этом будет сгенерирован отпечаток ключа. Скопируйте отпечаток ключа SSH и замените fingerprints в задании deploy_server.

Также обновите рабочий процесс, добавив следующий код:

workflows: default: jobs: - test - setup_ansible: requires: [test] - deploy_server: requires: [setup_ansible].

Настройка Ansible

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

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

Написание книги воспроизведения

Для автоматизации Ansible мы используем простые YAML-файлы, называемые плейбуками, чтобы определить задачи автоматизации. Ниже показана древовидная структура папки Ansible, в которой содержится книга воспроизведения, которую нужно выполнить.

├──── ansible │ ├──── ansible.cfg │ ├──── deploy-server.yml │ ├──── inventory.txt │ └──── roles │ └──── deploy │ └──── tasks │ └──── main.yml └──── config.yml.

Ниже приводится описание каждого файла и его функции:

  • ansible.cfg: Конфигурационный файл, используемый для настройки поведения Ansible. Он позволяет переопределить встроенные параметры конфигурации, такие как параметры SSH-соединения, файл инвентаризации по умолчанию, определить привилегии удаленных пользователей и т.д.

  • deploy-server.yml: Это игровой учебник Ansible. Он определяет набор задач или задание для выполнения на удаленных узлах. В этом проекте я использовал роли для определения задач плейбука.

  • inventory.txt: Это важный компонент Ansible для определения хостов и групп хостов, которыми будет управлять Ansible. Это конфигурационный файл, в котором указываются удаленные серверы или системы, на которых будут выполняться задачи и плейбуки Ansible. В этом файле перечислены IP-адреса серверов или машин, которыми будет управлять Ansible.

  • роли: Роли - это способ организации и структурирования задач, обработчиков, переменных и другого содержимого для лучшего повторного использования и сопровождения кода. Здесь содержатся задачи, которые будут выполняться в плейбуках. Эти задачи определяются в файле main.yml.

Обновите файл deploy-server.yml, добавив в него следующий код:

--- - name: "Deploy Play" hosts: web user: ubuntu gather_facts: false vars: - ansible_python_interpreter: /usr/bin/python3 - ansible_host_key_checking: false - ansible_stdout_callback: yaml roles: - deploy.

  • name: Это пользовательское имя для данного плейбука, которое облегчает нам понимание его работы.

  • hosts: Здесь указываются целевые хосты или группа хостов, на которых будут выполняться задания в этом плейбуке. В данном случае задано значение web. Когда вы открываете файл inventory.txt, он содержит единственную строку, [web]. Она определяет хостГруппа называется web, а все IP-адреса, перечисленные в разделе [web], являются хостами или удаленными машинами, которыми мы хотим управлять с помощью Ansible. Чтобы добавить IP-адрес в инвентарь, мы используем aws-cli в задании setup_ansible для получения IP-адреса нашего сервера EC2 и динамического обновления файла инвентаря.

  • user: Здесь указывается удаленный пользователь, которого Ansible должен использовать при подключении к целевым узлам. В данном случае это ubuntu. Вам может понадобиться изменить это значение, если ваш пользователь ssh другой.

  • gather_facts: Указывает Ansible, собирать ли факты о целевых узлах, такие как сведения об оборудовании, конфигурации сети и т. д. Здесь установлено значение false, чтобы повысить скорость выполнения плейбука.

vars: Здесь определяются переменные, которые будут использоваться в плейбуке. ansible_python_interpreter определяет python intepreter, который Ansible должен использовать при выполнении заданий на хосте. ansible_host_key_checking имеет значение false, чтобы отключить проверку ключей хоста. Проверка ключа хоста - это подсказка, которая появляется в командной строке, когда вы впервые выполняете вход ssh на сервер с ключом. Это мера безопасности, позволяющая убедиться в идентичности удаленного хоста.

roles: Здесь указывается, какие роли должны быть включены в это задание. В данном случае это роль с именем deploy. При выполнении плейбука Ansible будет искать каталог с именем “deploy” по пути roles и выполнять задачи и конфигурации, определенные в этой роли. Давайте напишем задачи для роли deploy.

Скопируйте приведенный ниже код в файл main.yml в папке роли deploy/tasks.

---
- name: Perform Git Pull
  become: false
  git:
    repo: git@github.com:AbuchiKings/aws_ec2_auto_deploy.git
    dest: ~/apps/aws_ec2_auto_deploy
    accept_hostkey: yes
    clone: false
    version: main

- name: Run Docker build
  become: true
  command:
    cmd: make "{{ item }}"
    chdir: apps/aws_ec2_auto_deploy
  loop:
    - down
    - up-d

Первая задача использует модуль Ansible git для выполнения git pull из git-репозитория проекта.

become - это булево поле, которое указывает Ansible на выполнение задачи в качестве пользователя root.

dest - это место назначения или каталог, куда должны быть добавлены извлеченные элементы.
Чтобы предотвратить свежее клонирование репозитория, clone имеет значение false.

version определяет ветку, из которой будет производиться извлечение.

Во второй задаче команда make используется с двумя разными аргументами, заданными в Makefile в корневой папке проекта:

down, который соответствует docker-compose -f docker-compose.yml -f docker-compose.prod.yml down, завершает работу текущего запущенного контейнера.

up-d, которая соответствует docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build, запускает контейнер с новой сборкой в отсоединенном режиме.

Наконец, зафиксируйте изменения и отправьте их в удаленный репозиторий.

Заключение

Это ни в коем случае не исчерпывающее руководство по CircleCi и Ansible. Существует широкий спектр задач автоматизации, которые можно выполнять с помощью Ansible. Тем не менее, я надеюсь, что вы найдете его полезным. Спасибо за уделенное время.