Ооо, да...
Рассмотрим реальный базовый CI/CD на примере Github actions. Тестируем код, деплоим на тестовую машину, запускаем код на реальных железках и деплоим в прод.
Когда-то давно уже писал подобные статейки(раз, два, три и самая популярная статья в блоге за все время...), сегодня же поговорим о нашумевшем, я бы даже сказал, "хайповом" сиайсиди.Что же вообще такое CI/CD и зачем оно нужно?
Я скажу так, я никогда не любил терминологические войны, поэтому расскажу как я это понимаю. Из моего опыта под CI/CD обычно понимают сам подход к разработке вместе со всем комплексом мер по доставке этого кода в продакшн. То есть в CI/CD мире вам достаточно сделать изменение в коде для того чтобы запустить отправку этого кода в прод. Если добавить терминов, то вы "мержите" ваше изменение с определенной веткой кода, что запускает "пайплайн". Последнее это некая сущность способная потестировать и правильно задеплоить ваш код туда где он будет исполняться. Понятное дело, что в этом случае все это должно происходить безопасно для сервиса.
Термин CI/CD неразрывно связан с GIT (или любой другой системой управления версиями). Некие события в этой системе управления кодом являются тригерами, которые запускают некие процессы (обычно называются "пайплайнами"), которые и доводят код до прода через определенные стадии. По опыту могу сказать, что зачастую это довольно сложная логика, которая может занимать дни. Поэтому тут не все так просто... Каждый юзкейс разный.
Реализовать что-то подобное можно на разных платформах, в том числе и на всем известном Github. На сколько я понимаю, Github это не самая лучшая и удобная реализация CI/CD. Однако, учитывая широкое распространение, Github Actions как минимум заслуживает рассмотрения.
Итак, ближе к сути.
В прошлом посте я описывал свой уютный скриптик для "раскатки" конфигурации на VyOS устройства через API. Держу я свой код на Github, поэтому именно на нем я и покажу как можно реализовать что-то более или менее похожее на CI/CD. По крайней мере мои "домашние" запросы получившееся вполне устраивает.
Что я буду реализовывать?
- Тестировать код
- Запуск на разных версиях
- Запуск flake8 (это проверка на соответствие pep8, короче пробельчики, длинна строк и все такое)
- Запуск тестов
- Деплоить на тестовую машину
- Запуск реального кода на реальных тестовых VyOS железках
- Деплоить на прод машину
.github/workflows
Actions довольно развитой инструмент с хорошей документацией и большим набором community дополнений. Я верю, что мой читатель сможет разобраться в теме. Я же расскажу про свою реализацию.
В моем случае я использую один workflow названный main.yaml. Разберем его построчно.
Основной блок
name: MAIN | |
on: | |
push: | |
branches: [ main ] | |
pull_request: | |
branches: [ main ] | |
workflow_dispatch: |
Build-and-test
build-and-test: | |
runs-on: ${{ matrix.os }} | |
strategy: | |
matrix: | |
os: [ubuntu-latest] | |
python-version: [3.5, 3.6, 3.7, 3.8] | |
steps: | |
- uses: actions/checkout@v2 | |
- name: Set up Python ${{ matrix.python-version }} | |
uses: actions/setup-python@v2 | |
with: | |
python-version: ${{ matrix.python-version }} | |
- name: Install dependencies | |
run: | | |
python -m pip install --upgrade pip | |
pip install flake8 pytest | |
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi | |
- name: Lint with flake8 | |
run: | | |
flake8 . --max-line-length=130 --statistics --exclude test* | |
- name: Test with pytest | |
run: | | |
pytest --doctest-modules --junitxml=test-report/test-results-${{ matrix.python-version }}.xml |
- Забираем код
- Устанавливаем python
- Устанавливаем зависимости (pytest, flake8, все из requirements)
- Проверяем код Flake8 (соотвествие рекомендациям PEP8)
- Запускаем тесты из директории с тестами (строго не судить)
deploy-to-gamma: | |
needs: build-and-test | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@master | |
- name: SCP | |
uses: appleboy/scp-action@master | |
with: | |
host: ${{ secrets.TEST_HOST }} | |
username: ${{ secrets.USERNAME }} | |
port: ${{ secrets.TEST_PORT }} | |
password: ${{ secrets.PASSWORD }} | |
source: "." | |
target: "vyos_cfg_v2" | |
- name: pip update | |
uses: garygrossgarten/github-action-ssh@release | |
with: | |
command: pip3 install -r vyos_cfg_v2/requirements.txt | |
host: ${{ secrets.TEST_HOST }} | |
username: ${{ secrets.USERNAME }} | |
port: ${{ secrets.TEST_PORT }} | |
password: ${{ secrets.PASSWORD }} | |
- name: Is vyos_cfg_v2 runnable | |
uses: garygrossgarten/github-action-ssh@release | |
with: | |
command: | | |
cd vyos_cfg_v2 | |
python3 vyos_cfg_v2.py -i inventory.yaml -d deployment.yaml --brave --skip-save | |
host: ${{ secrets.TEST_HOST }} | |
username: ${{ secrets.USERNAME }} | |
port: ${{ secrets.TEST_PORT }} | |
password: ${{ secrets.PASSWORD }} |
- Копируем код на тестовую машину по SCP
- Запускаем обновление зависимостей pip
- Запускаем скрипт на тестовых железках
Вот, пример того, как скрипт не смог. Соотвественно эта часть воркфлоу не считается завершенной успешно.
Как я говорил, needs позволяет устанавливать простые зависимости между частями воркфлоу. Это видно и в интерфейсе.
Deploy-to-prod
Следующая часть носит гордое название, но на деле это упрощенная копия предыдущего шага. В моем случае я просто копирую код на машину с которой управляю своими железками.
Со всем синтаксисом мы уже знакомы, изменились только переменные. Это, например, PROD_HOST вместо TEST_HOST.
deploy-to-prod: | |
needs: deploy-to-gamma | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@master | |
- name: SCP | |
uses: appleboy/scp-action@master | |
with: | |
host: ${{ secrets.PROD_HOST }} | |
username: ${{ secrets.USERNAME }} | |
port: ${{ secrets.PROD_PORT }} | |
password: ${{ secrets.PASSWORD }} | |
source: "." | |
target: "vyos_cfg_v2" | |
- name: pip update | |
uses: garygrossgarten/github-action-ssh@release | |
with: | |
command: pip3 install -r vyos_cfg_v2/requirements.txt | |
host: ${{ secrets.PROD_HOST }} | |
username: ${{ secrets.USERNAME }} | |
port: ${{ secrets.PROD_PORT }} | |
password: ${{ secrets.PASSWORD }} |
На этом шаге я не запускаю код, а только обновляю зависимости через pip.
Весь процесс
Итак, что мы имеем. Допустим мы сделали PUSH наших изменений в main ветку. Автоматически начинает работать воркфлоу, которая состоит из трех этапов. Тестирование кода, деплой в тестовую среду и запуск там и деплой в прод. В случае провала мы получим сообщение в почту.
Сам интерфейс.
В нашем случае, билд на разных версиях python прошел успешно.
Код копируется на тестовую машину и запускается на четырех VyOS устройствах.
В случае успеха, код копируется на реальную боевую машину.
После чего мои cron job'ы уже будут использовать новую версия скрипта.
Итоги
- Такой вот простой воркфлоу позволяет автоматизировать доставку моих изменений до реальной машины с которой я управляю своей инфраструктурой.
- Не надо идти на машину, делать git pull и все прочее.
- Я полагаюсь на pytest и запуск скрипта в тестовой среде на реальных железках, что должно обезопасить меня от каких-то крупных косяков. В моем случае этого достаточно. Для "боевого" сценария нужно добавлять больше проверок.
- Вопрос безопасности тут не обсуждался. Как минимум нужно использовать авторизацию по ключам.
- Не факт, что Github это лучший выбор. Думаю, я бы перевел все это в on-premises Gitlab.
Комментариев нет:
Отправить комментарий