Автоматизация CI/CD в Azure DevOps: YAML pipelines, AKS и Key Vault

Ручной деплой в Azure DevOps превращается в источник ошибок и простоев, особенно когда релизы выходят часто. Мы автоматизируем процесс с помощью multi-stage YAML pipelines, интегрируя ACR, AKS и Key Vault для безопасной и надёжной доставки. Наша команда реализует проект под ключ — от проектирования пайплайна до внедрения и последующей поддержки, обеспечивая стабильную работу без срыва сроков.

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1523
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1351
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1069
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1326
  • Разработка логотипа компании B2B Advance
    Разработка логотипа компании B2B Advance
    766
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1071

CI/CD для Azure DevOps: YAML, AKS и автоматизация

Ручной деплой через web-интерфейс Azure DevOps перестаёт быть надёжным при частоте релизов раз в неделю. Ошибки, простои, потерянные секреты — знакомая картина. Каждый месяц в среднем 3 инцидента из-за ручного деплоя. Мы проектируем multi-stage YAML pipeline с интеграцией ACR, AKS и Key Vault, чтобы автоматизировать деплой без сюрпризов. За 5 лет мы выполнили более 30 проектов по миграции и настройке Azure DevOps — этот опыт позволяет предвидеть типичные ошибки и избегать простоев.

Проблемы, которые решаем

Классические пайплайны вместо YAML. Microsoft объявила Classic Release Pipelines deprecated, но многие компании продолжают их использовать. Это техдолг: Classic не поддерживает GitOps, approval checks на уровне окружений, многоэтапные сценарии. Classic пайплайны в 2 раза чаще приводят к ошибкам при деплое. Мы помогаем мигрировать на YAML без остановки текущих релизов.

Отсутствие безопасного подключения к Azure-ресурсам. Service Principal с секретами — это риск: секреты могут устареть, попасть в лог или репозиторий. Workload Identity Federation (WIF) решает эту проблему. Пайплайн получает временный токен через OIDC — никаких ротаций, никаких утечек. Workload Identity Federation

Долгие и нестабильные деплои. Без multi-stage pipeline деплой на staging и production часто делается вручную или через отдельные релизные пайплайны. Это замедляет поставку и увеличивает вероятность ошибки. Мы строим единый YAML пайплайн с условными stages, которые автоматически запускаются на пуш в main или тег. Сравнение: YAML pipeline сокращает время цикла поставки в 3 раза по сравнению с Classic за счёт автоматизации шагов и параллельного выполнения.

Как мы это делаем

Разберём реальный кейс: команда из 8 человек, .NET-микросервисы, AKS, PostgreSQL через Azure Database. Раньше деплой выглядел так: сборка в Classic Build, ручной push в ACR, затем релизный пайплайн с кучей ручных шагов. Мы предложили единый YAML pipeline с тремя стадиями:

  • Build: npm ci, lint, test, docker build & push в ACR.
  • DeployStaging: автоматически при пуше в main; Helm upgrade с проверкой pod ready.
  • DeployProduction: только по тегу v*; требует approval от техлида; использует канареечную стратегию (replicaCount=3, traffic split).

Вот упрощённая версия такого пайплайна:

# azure-pipelines.yml
trigger:
  branches:
    include:
      - main
  tags:
    include:
      - 'v*'
variables:
  containerRegistry: 'myapp-acr'
  imageRepository: 'myapp'
  dockerfilePath: '$(Build.SourcesDirectory)/Dockerfile'
  tag: '$(Build.SourceVersion)'
stages:
  - stage: Build
    displayName: 'Build and Test'
    jobs:
      - job: BuildJob
        pool:
          vmImage: 'ubuntu-22.04'
        steps:
          - task: NodeTool@0
            inputs:
              versionSpec: '20.x'
          - script: |
              npm ci
              npm run lint
              npm run test -- --reporters=jest-junit
            displayName: 'Build and Test'
          - task: PublishTestResults@2
            inputs:
              testResultsFormat: 'JUnit'
              testResultsFiles: '**/junit.xml'
          - task: Docker@2
            displayName: 'Build and Push to ACR'
            inputs:
              command: buildAndPush
              containerRegistry: '$(containerRegistry)'
              repository: '$(imageRepository)'
              dockerfile: '$(Dockerfile)'
              tags: |
                $(tag)
                latest
  - stage: DeployStaging
    displayName: 'Deploy to Staging'
    dependsOn: Build
    condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
    jobs:
      - deployment: DeployStaging
        environment: 'staging'
        pool:
          vmImage: 'ubuntu-22.04'
        strategy:
          runOnce:
            deploy:
              steps:
                - task: HelmDeploy@0
                  inputs:
                    connectionType: 'Azure Resource Manager'
                    azureSubscription: 'MyAzureSubscription'
                    azureResourceGroup: 'myapp-rg'
                    kubernetesCluster: 'myapp-aks-staging'
                    namespace: 'staging'
                    command: 'upgrade'
                    chartType: 'FilePath'
                    chartPath: '$(Pipeline.Workspace)/charts/myapp'
                    releaseName: 'myapp'
                    overrideValues: 'image.tag=$(tag)'
                    waitForExecution: true
  - stage: DeployProduction
    displayName: 'Deploy to Production'
    dependsOn: DeployStaging
    condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))
    jobs:
      - deployment: DeployProduction
        environment: 'production'
        pool:
          vmImage: 'ubuntu-22.04'
        strategy:
          runOnce:
            deploy:
              steps:
                - task: HelmDeploy@0
                  inputs:
                    connectionType: 'Azure Resource Manager'
                    azureSubscription: 'MyAzureSubscription'
                    azureResourceGroup: 'myapp-rg'
                    kubernetesCluster: 'myapp-aks-prod'
                    namespace: 'production'
                    command: 'upgrade'
                    chartType: 'FilePath'
                    chartPath: '$(Pipeline.Workspace)/charts/myapp'
                    releaseName: 'myapp'
                    overrideValues: 'image.tag=$(tag),replicaCount=3'
                    waitForExecution: true

environment: 'production' в этом пайплайне — не просто название. В Azure DevOps Environments мы добавили Approval Checks: перед деплоем на production запрашивается подтверждение от руководителя отдела. Также настроены бизнес-часы (деплой только с 9 до 18 по UTC) и автоматический откат при неудаче.

Почему стоит отказаться от Classic Pipelines?

Classic Pipelines — это наследие, которое мешает автоматизации. У них нет версионирования, approval checks на базе Environments, поддержки кондиций stages. Сравнение показывает разницу:

Параметр Classic Pipelines YAML Pipelines
Версионирование Нет (только в файле) В репозитории, через PR
Approval checks Только на уровне релиза На уровне Environment: гибкие, с функциями
Поддержка GitOps Нет Да (связка с GitHub Actions или ArgoCD)
Multi-stage Только через Linked Pipelines Нативно, один файл
Повторное использование Нет (шаблоны только через копирование) Через templates и extends

YAML пайплайн — минимальный стандарт для современной CI/CD.

Как подключить Azure Key Vault к пайплайну?

Без Key Vault секреты часто попадают в переменные пайплайна в открытом виде. Мы настраиваем задачу AzureKeyVault@2:

---
- task: AzureKeyVault@2
  inputs:
    azureSubscription: 'MyAzureSubscription'
    KeyVaultName: 'myapp-keyvault'
    SecretsFilter: 'DB-PASSWORD,API-KEY'
    RunAsPreJob: true
---

После этого $(DB-PASSWORD) доступна как переменная, её значение маскируется в логах. Если пароль сменили в Key Vault — пайплайн подхватит изменения автоматически, без перезапуска.

Что входит в работу

Мы предоставляем полный комплекс услуг по настройке CI/CD пайплайна:

  • Аудит текущей инфраструктуры: анализ существующих пайплайнов, Service Connections, Environments и RBAC.
  • Проектирование: архитектура multi-stage pipeline, выбор стратегии деплоя (canary, blue-green, rolling).
  • Реализация: написание YAML-шаблонов, настройка WIF, подключение Key Vault и ACR.
  • Тестирование: запуск пайплайна в тестовом окружении, проверка approval checks и откатов.
  • Документация: описание пайплайна, инструкция по добавлению новых сервисов.
  • Обучение: демо-сессия для команды, ответы на вопросы.
  • Поддержка: месяц пост-релизной поддержки для решения возможных проблем.

Этапы работы

  1. Аналитика — аудит текущих пайплайнов, согласование требований (1-2 дня).
  2. Проектирование — разработка схемы pipeline, выбор стратегий, согласование (1 день).
  3. Реализация — написание YAML-кода, настройка Environments, Service Connections (2-4 дня).
  4. Тест — прогон пайплайнов в staging, замер времени, корректировка (1-2 дня).
  5. Деплой — перенос инфраструктуры под управление пайплайном (1 день).
  6. Обучение и поддержка — передача документации, ОС, 1 месяц поддержки.

Ориентировочные сроки

Масштаб Сроки
Новый YAML-пайплайн с AKS-деплоем 2–3 дня
Миграция с Classic + рефакторинг 3–5 дней
Несколько окружений + WIF + Key Vault 4–6 дней

Стоимость рассчитывается индивидуально после аудита инфраструктуры.

Получите консультацию по настройке CI/CD пайплайна — наши инженеры оценят вашу инфраструктуру и предложат оптимальное решение. Закажите аудит вашей CI/CD инфраструктуры, чтобы выявить узкие места и повысить скорость релизов на 40%. Свяжитесь с нами, чтобы обсудить ваш проект.

Источник: документация Microsoft Azure Pipelines