Перейти к содержимому
davidka.net > 💻 🧠 Код 1001 > 🛠️ DevOps > 🚀 CI/CD: От основ до Production на GCP с GitHub Actions – Полный гид с примерами 🚀

🚀 CI/CD: От основ до Production на GCP с GitHub Actions – Полный гид с примерами 🚀

Привет, разработчики! В этой статье я расскажу о CI/CD – концепции.

Что такое CI/CD пайплайн в контексте программирования?

CI/CD пайплайн (Continuous Integration / Continuous Delivery или Continuous Deployment) — это автоматизированный процесс, который позволяет разработчикам быстро и надежно доставлять изменения в коде в рабочее окружение (продакшн).

Давайте разберем ключевые понятия:

🔧 CI — Continuous Integration (Непрерывная интеграция)
Это практика, при которой разработчики часто вносят изменения в общую кодовую базу. Каждое такое изменение автоматически:

  • Собирается (build)
  • Тестируется (юнит-тесты, интеграционные тесты)
  • Проверяется на соответствие стандартам (линтинг, статический анализ)

👉 Цель CI: Выявлять ошибки на самом раннем этапе, до того как они сломают что-то важное или попадут в релиз.

🚀 CD — Continuous Delivery (Непрерывная доставка) или Continuous Deployment (Непрерывное развертывание)
Здесь есть два варианта:

✅ Continuous Delivery (Непрерывная доставка)
После успешного прохождения этапа CI, изменения автоматически:

  • Проходят дополнительные тесты (например, E2E – end-to-end тесты)
  • Попадают на staging (тестовый) сервер

👉 Но деплой в продакшн всё ещё требует ручного подтверждения. Это дает команде контроль над тем, когда именно изменения увидят пользователи.

🤖 Continuous Deployment (Непрерывный деплой)
Это следующий шаг после Continuous Delivery. Здесь деплой в продакшн происходит полностью автоматически, если все предыдущие этапы пайплайна (сборка, все тесты) прошли успешно. Это самый продвинутый уровень автоматизации.

🔄 Из чего обычно состоит CI/CD пайплайн?

Типичный пайплайн включает следующие этапы:

  1. Checkout — Клонирование последней версии кода из репозитория.
  2. Build — Сборка проекта (компиляция, сборка артефактов, Docker-образов).
  3. Test — Запуск различных видов тестов (юнит, интеграционные, E2E).
  4. Lint/Code Quality — Проверка кода на соответствие стилю и потенциальные ошибки с помощью статических анализаторов.
  5. Deploy — Развертывание приложения (на staging или production сервер).
  6. Notify — Отправка уведомлений о статусе пайплайна команде (например, в Slack, Email).

🛠 Популярные инструменты для CI/CD:

  • GitHub Actions (наш фокус сегодня!)
  • GitLab CI/CD
  • Jenkins
  • CircleCI
  • Bitbucket Pipelines
  • Azure DevOps
  • TeamCity

🧠 Зачем вообще нужен CI/CD?

  • Уменьшает человеческий фактор: Автоматизация исключает ошибки, связанные с ручными операциями.
  • Быстрое обнаружение багов: Ошибки находятся раньше, их проще и дешевле исправить.
  • Автоматизация рутинных задач: Разработчики тратят меньше времени на сборку и деплой, больше – на код.
  • Улучшение качества кода: Постоянные проверки и тесты повышают общую планку качества.
  • Быстрая доставка фич пользователям: Новые возможности доходят до конечного пользователя быстрее и чаще.

📦 Простые примеры CI/CD с GitHub Actions

Давайте посмотрим на базовые пайплайны для популярных технологий. Все примеры используют GitHub Actions и сохраняются в директории .github/workflows/ вашего проекта.

🐍 CI/CD для Python (с pytest и flake8)

# .github/workflows/python-ci.yml
name: Python CI

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11' # Укажите вашу версию

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt # Убедитесь, что у вас есть requirements.txt
          pip install flake8 pytest

      - name: Lint with flake8
        run: |
          # Проверяем код в папках src и tests (адаптируйте под свой проект)
          flake8 src tests

      - name: Run tests
        run: |
          pytest

🌐 CI/CD для Node.js (с npm test и eslint)

# .github/workflows/node-ci.yml
name: Node.js CI

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [18.x] # Укажите вашу версию Node.js

    steps:
      - uses: actions/checkout@v3

      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}

      - name: Install dependencies
        run: npm install # или npm ci для более предсказуемой установки

      - name: Lint with ESLint
        run: npx eslint . # Убедитесь, что ESLint настроен в проекте

      - name: Run tests
        run: npm test

🐳 CI/CD для Docker (сборка и пуш в Docker Hub)

Для этого примера вам понадобятся секреты DOCKER_USERNAME и DOCKER_PASSWORD (или токен) в настройках вашего GitHub репозитория (Settings -> Secrets and variables -> Actions).

# .github/workflows/docker-ci.yml
name: Docker CI/CD

on:
  push:
    branches: [ main ] # Запускаем только для main ветки

jobs:
  docker:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Log in to Docker Hub
        run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin

      - name: Build Docker image
        # Замените myapp на имя вашего приложения
        run: docker build -t ${{ secrets.DOCKER_USERNAME }}/myapp:latest .

      - name: Push Docker image
        run: docker push ${{ secrets.DOCKER_USERNAME }}/myapp:latest

🚚 Деплой на популярные платформы

Теперь, когда у нас есть собранные и протестированные артефакты (например, Docker-образ), давайте посмотрим, как их можно развернуть.

🟣 Деплой на Heroku

🔐 Секреты GitHub: HEROKU_API_KEY, HEROKU_APP_NAME.

# .github/workflows/deploy-heroku.yml
name: Deploy to Heroku

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Install Heroku CLI
        run: curl https://cli-assets.heroku.com/install.sh | sh
      - name: Login to Heroku
        env:
          HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }}
        run: heroku auth:token
      - name: Deploy to Heroku
        env:
          HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }}
        run: |
          heroku git:remote -a ${{ secrets.HEROKU_APP_NAME }}
          git push heroku main -f # Будьте осторожны с -f (force push)

Если вы деплоите Docker-образ на Heroku:

# ... (шаги build и login to Docker Hub/GHCR из предыдущих примеров) ...
# deploy:
#   name: Deploy to Heroku
#   needs: build # Зависит от джобы сборки образа
#   runs-on: ubuntu-latest
#   steps:
#     # ...
#     - name: Login to Heroku container registry
#       run: echo "${{ secrets.HEROKU_API_KEY }}" | docker login --username=_ --password-stdin registry.heroku.com
#     - name: Tag image for Heroku
#       # Предполагаем, что образ собран как ghcr.io/username/repo/myapp:latest
#       run: docker tag ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}/myapp:latest registry.heroku.com/${{ secrets.HEROKU_APP_NAME }}/web
#     - name: Push image to Heroku
#       run: docker push registry.heroku.com/${{ secrets.HEROKU_APP_NAME }}/web
#     - name: Release Heroku App
#       env:
#         HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }}
#       run: heroku container:release web --app ${{ secrets.HEROKU_APP_NAME }}

🟨 Деплой на AWS (например, статика в S3)

🔐 Секреты GitHub: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, S3_BUCKET_NAME.

# .github/workflows/deploy-aws-s3.yml
name: Deploy Static Site to AWS S3

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ secrets.AWS_REGION }}
      - name: Sync files to S3
        # Замените ./public на путь к вашим статическим файлам
        run: aws s3 sync ./public s3://${{ secrets.S3_BUCKET_NAME }} --delete

Для деплоя на AWS Elastic Beanstalk обычно используется EB CLI, пайплайн будет похож, но с командами eb deploy.

🔵 Деплой на Google Cloud Platform (GCP App Engine)

🔐 Секреты GitHub: GCP_CREDENTIALS (JSON ключ сервис-аккаунта), GCP_PROJECT_ID.

# .github/workflows/deploy-gcp-app-engine.yml
name: Deploy to GCP App Engine

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Set up Cloud SDK
        uses: google-github-actions/setup-gcloud@v2
        with:
          project_id: ${{ secrets.GCP_PROJECT_ID }}
          service_account_key: ${{ secrets.GCP_CREDENTIALS }}
          export_default_credentials: true
      - name: Deploy to App Engine
        # Убедитесь, что у вас есть app.yaml в корне проекта
        run: gcloud app deploy --quiet

🟪 Деплой на Render.com

Render часто автоматически деплоит при push в GitHub, если репозиторий подключен. Но для ручного триггера (или как часть более сложного пайплайна) можно использовать Deploy Hook.
🔐 Секреты GitHub: RENDER_DEPLOY_HOOK (URL, полученный из настроек сервиса в Render).

# .github/workflows/deploy-render.yml
name: Trigger Render Deploy

on:
  workflow_dispatch: # Ручной запуск из UI GitHub

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Trigger Render Deploy Hook
        run: curl -X POST ${{ secrets.RENDER_DEPLOY_HOOK }}

🌟 Продвинутый CI/CD: Build Docker → Push в GHCR → Staging/Production на GCP Cloud Run

А теперь вишенка на торте! Соберем продвинутый пайплайн:

  1. Сборка Docker-образа.
  2. Публикация образа в GitHub Container Registry (ghcr.io).
  3. Автоматический деплой в staging окружение на GCP Cloud Run.
  4. Деплой в production окружение на GCP Cloud Run после ручного подтверждения.

Для этого нам понадобится несколько файлов воркфлоу.

Необходимые секреты GitHub:

  • GCP_PROJECT_ID: ID вашего проекта в GCP.
  • GCP_CREDENTIALS: JSON-ключ сервис-аккаунта GCP с правами на деплой в Cloud Run и доступ к GHCR (если нужно). Обычно GITHUB_TOKEN достаточно для доступа к GHCR из Actions.
  • GCP_REGION: Регион для Cloud Run (например, europe-west1).

1. Сборка и публикация Docker-образа в GHCR

# .github/workflows/build.yml
name: Build & Push to GHCR

on:
  push:
    branches: [main] # Запускаем при пуше в main

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    permissions:
      contents: read      # Для checkout
      packages: write     # Для пуша в GHCR

    steps:
      - uses: actions/checkout@v3

      - name: Log in to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and push Docker image
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}/myapp:latest
          # Можно добавить тегирование по SHA коммита для уникальности:
          # tags: |
          #   ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}/myapp:latest
          #   ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}/myapp:${{ github.sha }}
  • github.repository_owner: Владелец репозитория (ваш username или организации).
  • github.event.repository.name: Имя репозитория.
  • myapp: Имя вашего приложения/образа.

2. Автоматический деплой в Staging (GCP Cloud Run)

Этот воркфлоу будет запускаться автоматически после успешного завершения build.yml.

# .github/workflows/deploy-staging.yml
name: Deploy to GCP Cloud Run (Staging)

on:
  workflow_run:
    workflows: ["Build & Push to GHCR"] # Имя воркфлоу сборки
    types:
      - completed

jobs:
  deploy-staging:
    runs-on: ubuntu-latest
    # Запускаем только если воркфлоу сборки завершился успешно
    if: ${{ github.event.workflow_run.conclusion == 'success' }}

    # Используем GitHub Environments для staging (опционально, но хорошая практика)
    environment:
      name: staging
      url: ${{ steps.deploy.outputs.url }} # URL будет доступен после деплоя

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3 # Нужен, если используете конфигурации из репозитория

      - id: 'auth'
        uses: 'google-github-actions/auth@v2'
        with:
          credentials_json: '${{ secrets.GCP_CREDENTIALS }}'

      - name: 'Deploy to Cloud Run (Staging)'
        id: deploy
        uses: 'google-github-actions/deploy-cloudrun@v2'
        with:
          service: 'myapp-staging' # Имя вашего staging сервиса в Cloud Run
          region: '${{ secrets.GCP_REGION }}'
          # Используем образ, который был запушен в build.yml
          image: 'ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}/myapp:latest'
          project_id: '${{ secrets.GCP_PROJECT_ID }}'
          flags: '--allow-unauthenticated --platform=managed' # Разрешаем неаутентифицированный доступ для примера

3. Деплой в Production с ручным подтверждением (GCP Cloud Run)

Этот воркфлоу запускается вручную через UI GitHub Actions.

# .github/workflows/deploy-prod.yml
name: Deploy to GCP Cloud Run (Production)

on:
  workflow_dispatch: # Позволяет ручной запуск

jobs:
  deploy-production:
    runs-on: ubuntu-latest

    environment:
      name: production
      url: ${{ steps.deploy.outputs.url }}

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - id: 'auth'
        uses: 'google-github-actions/auth@v2'
        with:
          credentials_json: '${{ secrets.GCP_CREDENTIALS }}'

      - name: 'Deploy to Cloud Run (Production)'
        id: deploy
        uses: 'google-github-actions/deploy-cloudrun@v2'
        with:
          service: 'myapp-production' # Имя вашего production сервиса
          region: '${{ secrets.GCP_REGION }}'
          image: 'ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}/myapp:latest' # Используем тот же 'latest' образ
          project_id: '${{ secrets.GCP_PROJECT_ID }}'
          flags: '--allow-unauthenticated --platform=managed'
          # Для production можно добавить --no-traffic и затем постепенно переключать трафик
          # traffic:
          #   latest: true
          #   percent: 100

Важные моменты этого продвинутого пайплайна:

  • GitHub Container Registry (ghcr.io): Мы используем его для хранения Docker-образов. Это удобно, так как он тесно интегрирован с GitHub Actions.
  • workflow_run: Позволяет запускать один воркфлоу (деплой на staging) по завершении другого (сборка).
  • workflow_dispatch: Дает возможность ручного запуска воркфлоу (деплой на production), что обеспечивает контроль.
  • GitHub Environments: Позволяют настроить правила защиты для production (например, требовать одобрения от определенных ревьюеров) и хранить специфичные для окружения секреты.
  • GCP Cloud Run: Отличный serverless-вариант для запуска контейнеризированных приложений.

🔐 Безопасность – это важно!

  • Используйте GitHub Secrets: Никогда не храните токены, пароли, ключи API прямо в YAML-файлах. Используйте Settings -> Secrets and variables -> Actions в вашем репозитории.
  • Минимальные привилегии: Для сервис-аккаунтов (например, GCP) предоставляйте только те права, которые действительно необходимы для выполнения задач CI/CD.
  • Изолируйте окружения: Staging и Production должны быть максимально изолированы. Разные проекты/аккаунты в облачных провайдерах – хорошая практика.
  • Защита веток: Настройте защиту для main (или master) ветки, чтобы пушить в нее можно было только через Pull Request с обязательными проверками CI.
Метки:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *