DevOps Admin

Como Usar Azure para DevOps: AKS, Azure Pipelines e Resource Groups em Produção Já leu

Azure Resource Groups: Fundação da Organização em Nuvem Um Resource Group (Grupo de Recursos) no Azure é um container lógico que agrupa todos os recursos necessários para uma solução. Diferentemente de outras plataformas de nuvem que distribuem recursos por regiões ou projetos sem uma organização clara, o Azure força uma abordagem estruturada e explícita. Você não pode criar um recurso sem designá-lo a um grupo específico; isso garante rastreabilidade, controle de acesso e faturamento consolidado. A importância de uma estratégia bem definida de Resource Groups vai além da organização visual. Quando você implanta um grupo inteiro, pode destruir todos os seus recursos de uma vez, o que é essencial para ambientes de teste e desenvolvimento. Além disso, você pode aplicar políticas (Azure Policy), controle de acesso baseado em função (RBAC) e tags a todos os recursos dentro de um grupo, economizando configurações repetitivas e reduzindo erros humanos. Criando e Gerenciando Resource Groups A forma mais direta de criar um Resource

Azure Resource Groups: Fundação da Organização em Nuvem

Um Resource Group (Grupo de Recursos) no Azure é um container lógico que agrupa todos os recursos necessários para uma solução. Diferentemente de outras plataformas de nuvem que distribuem recursos por regiões ou projetos sem uma organização clara, o Azure força uma abordagem estruturada e explícita. Você não pode criar um recurso sem designá-lo a um grupo específico; isso garante rastreabilidade, controle de acesso e faturamento consolidado.

A importância de uma estratégia bem definida de Resource Groups vai além da organização visual. Quando você implanta um grupo inteiro, pode destruir todos os seus recursos de uma vez, o que é essencial para ambientes de teste e desenvolvimento. Além disso, você pode aplicar políticas (Azure Policy), controle de acesso baseado em função (RBAC) e tags a todos os recursos dentro de um grupo, economizando configurações repetitivas e reduzindo erros humanos.

Criando e Gerenciando Resource Groups

A forma mais direta de criar um Resource Group é pela CLI do Azure. Vou mostrar um exemplo prático e funcional:

# Instalar Azure CLI (se ainda não tiver)
# No macOS: brew install azure-cli
# No Windows: choco install azure-cli
# No Linux: curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash

# Login no Azure
az login

# Criar um Resource Group
az group create \
  --name rg-produção-aks \
  --location eastus

# Listar todos os grupos de recursos
az group list --output table

# Deletar um Resource Group (cuidado: deleta tudo dentro dele)
az group delete --name rg-produção-aks --yes

A flag --location é crítica: ela define a região onde os recursos serão hospedados. Escolha regiões próximas aos seus usuários finais para reduzir latência. A nomeação também importa: use prefixos que indiquem propósito (rg-), ambiente (produção, dev) e contexto (aks, database), tornando gerenciamento futuro mais fácil.

Aplicando Tags e Políticas

Tags são metadados que você aplica a recursos para rastreamento de custos, propriedade e ciclo de vida. Quando você tiver centenas de recursos, tags corretas são a diferença entre saber exatamente o que você está pagando e ter uma fatura misteriosa no final do mês.

# Adicionar tags a um Resource Group existente
az group update \
  --name rg-produção-aks \
  --tags ambiente=produção proprietario=devops custo-centro=eng-001

# Consultar grupos por tag
az group list --query "[?tags.ambiente=='produção']" --output table

# Criar um grupo com tags já incluídas (mais eficiente)
az group create \
  --name rg-dev-aks \
  --location eastus \
  --tags ambiente=desenvolvimento proprietario=devops

Azure Kubernetes Service (AKS): Orquestração de Contêineres Simplificada

Azure Kubernetes Service é a oferta gerenciada do Azure para Kubernetes. Diferentemente de gerenciar um cluster Kubernetes do zero, o AKS abstrai a complexidade da camada de controle (control plane), permitindo que você foque em aplicações, não em infraestrutura. A Microsoft gerencia atualizações, patches de segurança e alta disponibilidade do control plane automaticamente.

Um cluster AKS reside dentro de um Resource Group e depende de uma rede virtual (VNet), mas para começar você não precisa se preocupar com essas complexidades—o AKS cria muitos desses recursos automaticamente. O que você realmente controla são os node pools (grupos de nós onde seus contêineres executam), versão do Kubernetes, scaling e acesso à rede.

Criando um Cluster AKS

# Pré-requisito: ter um Resource Group criado (feito na seção anterior)

# Criar um cluster AKS básico
az aks create \
  --resource-group rg-produção-aks \
  --name cluster-produção \
  --node-count 3 \
  --vm-set-type VirtualMachineScaleSets \
  --load-balancer-sku standard \
  --enable-managed-identity \
  --network-plugin azure \
  --docker-bridge-address 172.17.0.1/16 \
  --service-cidr 10.0.0.0/16 \
  --dns-service-ip 10.0.0.10 \
  --generate-ssh-keys \
  --tier free

# Este comando leva cerca de 5-10 minutos. Enquanto isso, entenda os parâmetros:
# --node-count: quantidade inicial de nós
# --vm-set-type VirtualMachineScaleSets: permite scaling automático (recomendado)
# --enable-managed-identity: segurança—deixe o Azure gerenciar credenciais
# --network-plugin azure: usa CNI do Azure (mais flexível que kubenet)

Após a criação, você precisa configurar suas credenciais locais para interagir com o cluster:

# Obter credenciais do cluster
az aks get-credentials \
  --resource-group rg-produção-aks \
  --name cluster-produção \
  --overwrite-existing

# Verificar que kubectl está apontando para o cluster correto
kubectl cluster-info
kubectl get nodes

O output do kubectl get nodes mostrará algo assim:

NAME                                STATUS   ROLES   AGE     VERSION
aks-nodepool1-12345678-vmss000000   Ready    agent   2m34s   v1.27.3
aks-nodepool1-12345678-vmss000001   Ready    agent   2m28s   v1.27.3
aks-nodepool1-12345678-vmss000002   Ready    agent   2m22s   v1.27.3

Escalabilidade e Node Pools

Um dos maiores benefícios do AKS é a capacidade de ter múltiplos node pools com diferentes configurações. Imagine que você tem aplicações web que precisam de CPU e aplicações de processamento que precisam de GPU. Em vez de um cluster homogêneo, você cria pools diferentes:

# Criar um node pool adicional com máquinas mais poderosas
az aks nodepool add \
  --resource-group rg-produção-aks \
  --cluster-name cluster-produção \
  --name gpupool \
  --node-count 2 \
  --vm-set-type VirtualMachineScaleSets \
  --node-vm-size Standard_NC6 \
  --labels workload=gpu \
  --taints gpu=true:NoSchedule

# Listar todos os node pools
az aks nodepool list \
  --resource-group rg-produção-aks \
  --cluster-name cluster-produção \
  --output table

# Configurar auto-scaling para um pool
az aks nodepool update \
  --resource-group rg-produção-aks \
  --cluster-name cluster-produção \
  --name nodepool1 \
  --enable-cluster-autoscaler \
  --min-count 2 \
  --max-count 10

A taint gpu=true:NoSchedule garante que apenas pods que tolerem essa taint sejam agendados nesse pool. Em seu YAML de deployment, você declararia:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ml-training-job
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ml-training
  template:
    metadata:
      labels:
        app: ml-training
    spec:
      nodeSelector:
        workload: gpu
      tolerations:
        - key: gpu
          operator: Equal
          value: "true"
          effect: NoSchedule
      containers:
        - name: training
          image: seu-registro.azurecr.io/ml-training:latest
          resources:
            limits:
              nvidia.com/gpu: 1

Azure Pipelines: Automação de Build, Teste e Deploy

Azure Pipelines é o serviço de CI/CD (Integração Contínua / Entrega Contínua) do Azure. Ele automatiza o processo de pegar código do repositório, compilar, testar e fazer deploy para produção—ou qualquer outro ambiente. Sem pipelines, um desenvolvedor teria que fazer esses passos manualmente toda vez, o que é lento, propenso a erros e não escala com times crescentes.

A beleza do Azure Pipelines é que ele integra perfeitamente com o Azure DevOps, GitHub, GitLab e Bitbucket. Você define seus passos em um arquivo YAML (chamado azure-pipelines.yml) no repositório, e o sistema executa automaticamente quando você faz push de código. Você também pode usar a interface visual, mas YAML é mais versionado e colaborativo.

Estrutura de um Pipeline Básico

# azure-pipelines.yml
# Este arquivo deve estar na raiz do seu repositório

trigger:
  - main  # Executa quando houver push na branch main

pool:
  vmImage: 'ubuntu-latest'  # Ambiente onde o pipeline executa

variables:
  dockerRegistryServiceConnection: 'seu-registro-acr'
  imageRepository: 'seu-app'
  containerRegistry: 'seuregistry.azurecr.io'
  dockerfilePath: '$(Build.SourcesDirectory)/Dockerfile'
  tag: '$(Build.BuildId)'

stages:
  - stage: Build
    displayName: Build e Push da Imagem Docker
    jobs:
      - job: BuildImage
        displayName: Build Image
        steps:
          - task: Docker@2
            displayName: Build e Push Imagem
            inputs:
              command: buildAndPush
              repository: $(imageRepository)
              dockerfile: $(dockerfilePath)
              containerRegistry: $(dockerRegistryServiceConnection)
              tags: |
                $(tag)
                latest

  - stage: Deploy
    displayName: Deploy para AKS
    dependsOn: Build
    condition: succeeded()
    jobs:
      - deployment: DeployToAKS
        displayName: Deploy para Produção
        environment: 'production'
        strategy:
          runOnce:
            deploy:
              steps:
                - task: KubernetesManifest@0
                  displayName: Deploy
                  inputs:
                    action: 'deploy'
                    kubernetesServiceConnection: 'cluster-produção'
                    namespace: 'default'
                    manifests: |
                      $(Pipeline.Workspace)/manifests/deployment.yml
                      $(Pipeline.Workspace)/manifests/service.yml

Este pipeline tem dois estágios: primeiro faz build da imagem Docker e envia para um registro de container (Azure Container Registry), depois realiza o deploy dessa imagem no AKS. O dependsOn: Build garante que o Deploy só aconteça se o Build tiver sucesso.

Conectando Azure Pipelines ao Azure Container Registry (ACR)

Você precisa de um registro privado para armazenar suas imagens Docker. Azure Container Registry é gerenciado, integrado e seguro:

# Criar um registro de container
az acr create \
  --resource-group rg-produção-aks \
  --name seuregistry \
  --sku Basic \
  --admin-enabled false

# Autenticar o AKS para puxar imagens do ACR
az aks update \
  --resource-group rg-produção-aks \
  --name cluster-produção \
  --attach-acr seuregistry

# Listar imagens no registro
az acr repository list --name seuregistry --output table

A integração com az aks update --attach-acr é essencial: ela cria uma identidade gerenciada que permite que o AKS puxe imagens sem você precisar de senhas ou tokens.

Estrutura Recomendada de Manifests Kubernetes

Seus manifests (arquivos YAML) devem estar em um diretório chamado manifests no repositório:

# manifests/deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: minha-aplicacao
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: minha-aplicacao
  template:
    metadata:
      labels:
        app: minha-aplicacao
    spec:
      containers:
        - name: app
          image: seuregistry.azurecr.io/seu-app:latest
          ports:
            - containerPort: 8080
          env:
            - name: ENVIRONMENT
              value: "production"
          resources:
            requests:
              memory: "256Mi"
              cpu: "100m"
            limits:
              memory: "512Mi"
              cpu: "500m"
          livenessProbe:
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 30
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /ready
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 5
      imagePullSecrets:
        - name: acr-secret
# manifests/service.yml
apiVersion: v1
kind: Service
metadata:
  name: minha-aplicacao-service
  namespace: default
spec:
  type: LoadBalancer
  selector:
    app: minha-aplicacao
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

Variáveis e Secrets no Pipeline

Nunca coloque senhas ou chaves direto no arquivo YAML. Use variáveis de pipeline:

# azure-pipelines.yml (continuação)
variables:
  dockerRegistryServiceConnection: 'seu-registro-acr'
  imageRepository: 'seu-app'
  containerRegistry: 'seuregistry.azurecr.io'
  tag: '$(Build.BuildId)'
  # Sensitive variables não devem ser declaradas aqui,
  # mas sim em Library > Secure Files ou Variable Groups

steps:
  - task: Docker@2
    displayName: Build e Push Imagem
    inputs:
      command: buildAndPush
      repository: $(imageRepository)
      dockerfile: $(dockerfilePath)
      containerRegistry: $(dockerRegistryServiceConnection)
      tags: |
        $(tag)
        latest

No Azure DevOps, você cria uma "Variable Group" no Pipeline > Library com suas variáveis sensíveis (senhas, tokens), e referencia:

variables:
  - group: 'production-secrets'  # Criada na UI

Integrando AKS, Pipelines e Resource Groups: Um Fluxo Completo

Até aqui você entendeu cada peça isoladamente. Agora vamos ver como elas se conectam em um fluxo real de DevOps. Você tem um repositório com código, um pipeline que builda uma imagem Docker, um registro de container que armazena a imagem, um cluster AKS que roda a aplicação, e tudo organizado dentro de um Resource Group no Azure.

O fluxo típico é: você faz git push do seu código → Azure Pipelines detecta a mudança → compila e testa o código → builda uma imagem Docker → envia para ACR → executa testes de integração → faz deploy automático no AKS. Se algo falhar em qualquer etapa, o pipeline para e você é notificado. Se tudo passar, sua aplicação atualizada está rodando em produção em minutos.

Exemplo de Pipeline End-to-End

# azure-pipelines.yml completo com teste e deploy

trigger:
  - main

pool:
  vmImage: 'ubuntu-latest'

variables:
  dockerRegistryServiceConnection: 'seu-acr-connection'
  imageRepository: 'minha-app'
  containerRegistry: 'seuregistry.azurecr.io'
  dockerfilePath: '$(Build.SourcesDirectory)/Dockerfile'
  tag: '$(Build.BuildId)'
  kubernetesServiceConnection: 'cluster-produção'
  resourceGroupName: 'rg-produção-aks'
  clusterName: 'cluster-produção'

stages:
  - stage: Build
    displayName: Build e Testes
    jobs:
      - job: TestAndBuild
        displayName: Executar Testes e Build
        steps:
          # Step 1: Checkout do código (automático, mas explícito é melhor)
          - checkout: self

          # Step 2: Setup Node.js (ou qualquer linguagem que você use)
          - task: NodeTool@0
            inputs:
              versionSpec: '18.x'

          # Step 3: Instalar dependências e rodar testes
          - script: |
              npm install
              npm run test
              npm run lint
            displayName: 'Instalar dependências e rodar testes'

          # Step 4: Build da aplicação
          - script: npm run build
            displayName: 'Build da aplicação'

          # Step 5: Build e Push da imagem Docker
          - task: Docker@2
            displayName: 'Build e Push da imagem Docker'
            inputs:
              command: buildAndPush
              repository: $(imageRepository)
              dockerfile: $(dockerfilePath)
              containerRegistry: $(dockerRegistryServiceConnection)
              tags: |
                $(tag)
                latest

  - stage: Deploy
    displayName: Deploy para AKS
    dependsOn: Build
    condition: succeeded()
    jobs:
      - deployment: DeployToProduction
        displayName: Deploy em Produção
        environment: 'production'
        strategy:
          runOnce:
            deploy:
              steps:
                # Step 1: Baixar manifests publicados no build anterior
                - download: current
                  artifact: manifests

                # Step 2: Substituir tag da imagem nos manifests
                - task: KubernetesManifest@0
                  displayName: 'Bake manifests'
                  name: bake
                  inputs:
                    action: 'bake'
                    renderingEngine: 'kustomize'
                    kustomizationPath: '$(Pipeline.Workspace)/manifests/kustomize'

                # Step 3: Deploy no AKS
                - task: KubernetesManifest@0
                  displayName: 'Deploy no AKS'
                  inputs:
                    action: 'deploy'
                    kubernetesServiceConnection: $(kubernetesServiceConnection)
                    namespace: 'default'
                    manifests: $(bake.manifestsBundle)

                # Step 4: Verificar status do deployment
                - script: |
                    kubectl rollout status deployment/minha-aplicacao -n default --timeout=5m
                  displayName: 'Aguardar Deployment estar pronto'

Monitorando e Troubleshooting

Depois que seu pipeline deploya, você precisa saber se a aplicação está saudável. Use esses comandos para investigar:

# Ver status dos pods
kubectl get pods -n default
kubectl describe pod <pod-name> -n default

# Ver logs da aplicação
kubectl logs deployment/minha-aplicacao -n default --tail=100
kubectl logs deployment/minha-aplicacao -n default -f  # -f para seguir em tempo real

# Verificar eventos recentes
kubectl get events -n default --sort-by='.lastTimestamp'

# Acessar um pod interativamente (útil para debug)
kubectl exec -it <pod-name> -n default -- /bin/sh

# Ver métricas de recursos
kubectl top nodes
kubectl top pods -n default

# Verificar status do deployment
kubectl rollout status deployment/minha-aplicacao -n default
kubectl rollout history deployment/minha-aplicacao -n default

Conclusão

Você aprendeu que Resource Groups são a fundação organizacional—eles agrupam logicamente todos os seus recursos Azure, permitem controle de acesso centralizado, e facilitam limpeza e rastreamento de custos. Uma boa estratégia de nomeação e tags em Resource Groups economiza horas de troubleshooting depois.

AKS abstrai complexidade de Kubernetes mantendo você focado em aplicações, não em infraestrutura. Node pools permitem customização de cargas de trabalho (GPU, memória, CPU) sem precisar de múltiplos clusters. Auto-scaling garante que você não desperdice recursos nem fique sem capacidade.

Azure Pipelines orquestra o fluxo inteiro—de código para produção—removendo trabalho manual e tornando deploys repetíveis, rastreáveis e seguro. Combinados, esses três serviços formam uma plataforma de DevOps robusta que cresce com sua organização, desde startups até enterprises.

O próximo passo é praticar: crie um cluster AKS, configure um pipeline simples, e observe como uma mudança no seu código percorre automaticamente todo o caminho até produção. Erros acontecem, e esse é o valor real—quando você consegue iterar rápido e com segurança.

Referências


Artigos relacionados