Pular para o conteúdo principal

Fundamentação Teórica: Provision a container by using Azure Container Instances


1. Intuição Inicial​

Imagine que você precisa executar uma tarefa específica: processar um arquivo, enviar um relatório, ou rodar um script de manutenção. Para isso, você normalmente precisaria provisionar uma VM, configurar o sistema operacional, instalar dependências, executar a tarefa e depois desligar a VM. Todo esse processo leva tempo e envolve gerenciamento de infraestrutura que não tem relação com a tarefa em si.

O Azure Container Instances (ACI) elimina esse overhead. Você diz ao Azure: "execute este container com esta imagem, com 1 CPU e 1.5 GB de RAM, por favor". O Azure cuida de toda a infraestrutura subjacente. Em segundos, seu container está rodando. Quando termina, você paga apenas pelo tempo que o container ficou ativo.

É como alugar um quarto de hotel para uma noite, em vez de comprar um apartamento. Sem gerenciamento de propriedade, sem contratos de longo prazo, pague apenas pelo tempo que usou.


2. Contexto​

O ACI ocupa uma posição específica no ecossistema de computação do Azure:

100%
Scroll para zoom · Arraste para mover · 📱 Pinch para zoom no celular

O ACI não é um substituto para o AKS em aplicações de produção complexas, nem para o App Service em aplicações web de longa duração. Ele preenche o nicho de execuções simples, tarefas de curta duração, ambientes de desenvolvimento/teste e processos em batch.

O ACI também tem uma relação especial com o AKS através do Virtual Kubelet: o AKS pode usar o ACI como uma "node virtual" para escalar bursts de carga sem precisar provisionar nodes físicos adicionais.


3. Construção dos Conceitos​

3.1 Container Group: A Unidade Fundamental​

No ACI, a unidade de deploy é o Container Group, não o container individual. Um container group é um conjunto de containers que compartilham o mesmo host, a mesma rede e os mesmos volumes. É o equivalente de um Pod no Kubernetes.

100%
Scroll para zoom · Arraste para mover · 📱 Pinch para zoom no celular

Para casos simples (um único container), você trabalha com um container group de um único container, mas o conceito existe para suportar padrões sidecar onde um container auxiliar complementa o principal.

3.2 Tipos de OS: Linux e Windows​

O ACI suporta containers Linux e Windows. A maioria das cargas de trabalho de container usa Linux. Containers Windows são suportados mas com algumas limitações:

AspectoLinuxWindows
Tamanhos disponíveisMais opçõesSubset menor
CustoMenorMaior
Imagens de baseAlpine, Ubuntu, DebianWindows Server Core, Nano Server
Caso de usoMaioria das aplicações modernasAplicações .NET Framework legacy

3.3 Tipos de Rede no ACI​

O ACI tem três opções de configuração de rede:

TipoDescriçãoAcesso
PublicIP público atribuído ao container groupAcessível da internet
Private (VNet)Container injetado em uma subnet de VNetApenas dentro da VNet e redes conectadas
NoneSem interface de redeContainer sem acesso de rede (processamento isolado)

O modo VNet (Private) é implementado através da delegação de subnet: a subnet deve ter a delegação Microsoft.ContainerInstance/containerGroups configurada para receber containers ACI.

3.4 Política de Reinicialização​

Define o comportamento quando o processo principal do container termina:

PolíticaComportamentoQuando usar
AlwaysReinicia sempre que o container paraServiços de longa duração
NeverNão reinicia (termina após completar)Tarefas batch de execução única
OnFailureReinicia apenas em caso de falha (exit code != 0)Tarefas que podem falhar e precisam de retry

3.5 Recursos: CPU e Memória​

O ACI cobra por vCPU e GB de memória por segundo de execução. Os limites:

  • CPU: de 0.1 a 4 vCPU por container (máximo 4 vCPU por container group)
  • Memória: de 0.1 a 16 GB por container group (proporcional à CPU)
  • GPU: disponível em alguns tamanhos (K80, P100, V100) para workloads de ML

A relação CPU/memória tem restrições: não é possível alocar proporções extremas (muita CPU com pouca memória ou vice-versa).

3.6 Variáveis de Ambiente e Segredos​

Containers recebem configuração via variáveis de ambiente. Para informações sensíveis (senhas, chaves de API), o ACI suporta secure environment variables: o valor é enviado de forma segura e não aparece nos logs ou na saída da CLI/portal.

# Variável comum (visível nos logs)
--environment-variables AMBIENTE=producao

# Variável segura (valor não aparece em logs)
--secure-environment-variables DB_PASSWORD=minhasenha

3.7 Volumes e Persistência​

Por padrão, o storage de um container ACI é efêmero: dados escritos dentro do container são perdidos quando ele para. Para persistência, o ACI suporta:

Tipo de volumeProtocoloQuando usar
Azure FilesSMBCompartilhamento entre containers e persistência
Azure Files (gitRepo - deprecated)-Clone de repositório Git
emptyDir-Compartilhamento temporário entre containers do mesmo group
Secret-Montar segredos como arquivos

O volume Azure Files é montado como um compartilhamento SMB dentro do container, permitindo que os dados persistam além do ciclo de vida do container.


4. Visão Estrutural​

100%
Scroll para zoom · Arraste para mover · 📱 Pinch para zoom no celular

5. Funcionamento na Prática​

Ciclo de Vida de um Container ACI​

100%
Scroll para zoom · Arraste para mover · 📱 Pinch para zoom no celular

Comportamentos Importantes e Não Óbvios​

Pull de imagem acontece em cada criação: o ACI não mantém um cache de imagens entre execuções. Cada vez que um container group é criado, a imagem é baixada novamente do registry. Para imagens grandes (centenas de MB), isso adiciona tempo de inicialização. Para otimizar, use imagens menores (Alpine) e layers bem organizadas.

Containers parados ainda incorrem em custo de armazenamento: quando um container group está no estado Stopped, não há cobrança por CPU e memória, mas o container group ainda existe como um recurso. Para eliminar completamente o custo, exclua o container group.

Managed Identity funciona no ACI: é possível atribuir uma Managed Identity a um container group. Isso permite que o código dentro do container obtenha tokens do Entra ID para acessar outros serviços Azure (Key Vault, Storage, etc.) sem credenciais hardcoded.

O FQDN gerado é imprevisível: ao criar um container com IP público, o Azure gera automaticamente um FQDN no formato <dns-name-label>.<region>.azurecontainer.io. Esse label deve ser único na região. Se você não especificar um label DNS, o container só é acessível pelo IP.


6. Formas de Implementação​

6.1 Portal do Azure​

Quando usar: criação exploratória, testes rápidos, verificação de estado.

Caminho: Create a resource > Containers > Container Instances

O assistente tem as abas:

  • Basics: imagem, nome, SKU (Linux/Windows), região
  • Networking: tipo de rede, portas, DNS label
  • Advanced: variáveis de ambiente, restart policy, comandos personalizados, volumes
  • Tags

6.2 Azure CLI​

Criar container simples com IP público:

az container create \
--name meu-container \
--resource-group rg-containers \
--image nginx:alpine \
--cpu 0.5 \
--memory 0.5 \
--ip-address Public \
--ports 80 \
--dns-name-label meu-nginx-unico \
--restart-policy Always \
--location brazilsouth

Criar container usando imagem do ACR com Managed Identity:

# Criar identidade gerenciada
az identity create \
--name id-aci-producao \
--resource-group rg-containers

# Atribuir AcrPull ao ACR para a identidade
ACR_ID=$(az acr show --name minhacr --resource-group rg-containers --query id -o tsv)
IDENTITY_ID=$(az identity show --name id-aci-producao --resource-group rg-containers --query principalId -o tsv)
az role assignment create --assignee $IDENTITY_ID --role AcrPull --scope $ACR_ID

# Criar container usando a identidade para pull
az container create \
--name api-container \
--resource-group rg-containers \
--image minhacr.azurecr.io/api-gateway:v1.2.3 \
--cpu 1 \
--memory 1.5 \
--ip-address Private \
--vnet vnet-producao \
--subnet subnet-containers \
--assign-identity $(az identity show --name id-aci-producao --resource-group rg-containers --query id -o tsv) \
--registry-login-server minhacr.azurecr.io \
--restart-policy OnFailure

Criar container com variáveis de ambiente e volume Azure Files:

# Criar compartilhamento Azure Files
STORAGE_KEY=$(az storage account keys list \
--account-name minhaconta \
--resource-group rg-containers \
--query "[0].value" -o tsv)

az storage share create \
--name dados-container \
--account-name minhaconta \
--account-key $STORAGE_KEY

# Criar container com volume montado
az container create \
--name processador \
--resource-group rg-containers \
--image minhacr.azurecr.io/processador:latest \
--cpu 2 \
--memory 4 \
--ip-address None \
--restart-policy Never \
--environment-variables AMBIENTE=producao BUCKET=resultados \
--secure-environment-variables DB_PASSWORD=minhasenha \
--azure-file-volume-account-name minhaconta \
--azure-file-volume-account-key $STORAGE_KEY \
--azure-file-volume-share-name dados-container \
--azure-file-volume-mount-path /mnt/dados

Verificar estado e logs:

# Estado do container
az container show \
--name meu-container \
--resource-group rg-containers \
--query "{Estado:instanceView.state, IP:ipAddress.ip, FQDN:ipAddress.fqdn}" \
--output table

# Logs do container (stdout/stderr)
az container logs \
--name meu-container \
--resource-group rg-containers \
--follow # streaming em tempo real

# Acessar shell interativo no container (se ainda estiver rodando)
az container exec \
--name meu-container \
--resource-group rg-containers \
--exec-command "/bin/sh"

# Parar e iniciar
az container stop --name meu-container --resource-group rg-containers
az container start --name meu-container --resource-group rg-containers

# Excluir
az container delete --name meu-container --resource-group rg-containers --yes

Deploy via arquivo YAML (container groups complexos):

# container-group.yaml
apiVersion: 2021-10-01
location: brazilsouth
name: meu-container-group
properties:
containers:
- name: app-principal
properties:
image: minhacr.azurecr.io/api:v1.0
resources:
requests:
cpu: 1
memoryInGb: 1.5
ports:
- port: 80
protocol: TCP
environmentVariables:
- name: AMBIENTE
value: producao
- name: DB_PASSWORD
secureValue: minhasenha
volumeMounts:
- name: dados
mountPath: /mnt/dados
- name: log-sidecar
properties:
image: fluent/fluent-bit:latest
resources:
requests:
cpu: 0.5
memoryInGb: 0.5
volumeMounts:
- name: dados
mountPath: /mnt/logs
osType: Linux
ipAddress:
type: Public
ports:
- port: 80
protocol: TCP
dnsNameLabel: meu-app-prod
restartPolicy: Always
volumes:
- name: dados
azureFile:
shareName: dados-container
storageAccountName: minhaconta
storageAccountKey: <key>
type: Microsoft.ContainerInstance/containerGroups
# Deploy via arquivo YAML
az container create \
--resource-group rg-containers \
--file container-group.yaml

6.3 PowerShell​

# Criar container simples
$container = New-AzContainerInstanceObject `
-Name "app-container" `
-Image "nginx:alpine" `
-RequestCpu 0.5 `
-RequestMemoryInGb 0.5 `
-Port @(New-AzContainerInstancePortObject -Port 80 -Protocol TCP)

New-AzContainerGroup `
-ResourceGroupName "rg-containers" `
-Name "meu-container-group" `
-Location "brazilsouth" `
-Container @($container) `
-OsType Linux `
-IpAddressType Public `
-DnsNameLabel "meu-nginx-ps" `
-RestartPolicy Always

6.4 Bicep​

resource containerGroup 'Microsoft.ContainerInstance/containerGroups@2023-05-01' = {
name: 'meu-container-group'
location: location
properties: {
containers: [
{
name: 'app-container'
properties: {
image: 'minhacr.azurecr.io/api:v1.0'
resources: {
requests: {
cpu: 1
memoryInGB: 1.5
}
}
ports: [
{
port: 80
protocol: 'TCP'
}
]
environmentVariables: [
{
name: 'AMBIENTE'
value: 'producao'
}
{
name: 'DB_PASSWORD'
secureValue: dbPassword // parametro seguro
}
]
}
}
]
osType: 'Linux'
ipAddress: {
type: 'Public'
ports: [
{
port: 80
protocol: 'TCP'
}
]
dnsNameLabel: 'meu-app-prod-${uniqueString(resourceGroup().id)}'
}
restartPolicy: 'Always'
}
}

7. Controle e Segurança​

Autenticação em Registries Privados​

Para usar imagens do ACR, o ACI pode autenticar de três formas:

  1. Managed Identity (recomendado): o container group tem uma identidade com papel AcrPull no ACR
  2. Service Principal: username = service principal ID, senha = client secret
  3. Admin credentials: username = nome do registry, senha = admin password (não recomendado)
# Usando Managed Identity (necessário especificar o registry login server)
az container create \
--assign-identity <identity-resource-id> \
--registry-login-server minhacr.azurecr.io \
...

Containers em VNet: Isolamento de Rede​

Para workloads que precisam acessar recursos internos da VNet (bancos de dados, serviços privados), o ACI em modo VNet é essencial:

# Criar subnet com delegação para ACI
az network vnet subnet create \
--name subnet-aci \
--vnet-name vnet-producao \
--resource-group rg-networking \
--address-prefix 10.0.5.0/24 \
--delegations Microsoft.ContainerInstance/containerGroups

# Container na VNet
az container create \
--ip-address Private \
--vnet vnet-producao \
--subnet subnet-aci \
...

Restrição importante: containers em VNet não podem ter IP público simultâneo. A escolha é uma ou outra.

Iniciativas de Segurança​

  • Nunca use variáveis de ambiente comuns para senhas; use sempre --secure-environment-variables
  • Para segredos mais complexos, use Managed Identity + Key Vault para buscar os segredos em runtime
  • Containers em produção devem estar em VNet, não com IP público direto
  • Imagens devem vir de registries privados (ACR), não diretamente do Docker Hub em produção

8. Tomada de Decisão​

ACI vs. outros serviços de compute​

SituaçãoMelhor escolhaMotivo
Tarefa batch de curta duraçãoACI com restartPolicy: NeverPaga apenas pelo tempo de execução
API REST simples de longa duraçãoApp Service ContainersMais features web (SSL, custom domain, deployment slots)
Microserviços em produção, múltiplas instânciasAKSOrquestração, scaling automático, service mesh
Ambiente de dev/test de containerACIRápido, sem overhead de cluster
Processamento de eventos (Function-like)Azure Container AppsScaling to zero nativo, KEDA
Container que precisa acessar recursos VNetACI em modo VNetIntegração nativa com VNet
Burst de carga em AKSACI via Virtual KubeletScale out rápido sem novos nodes

Quando usar restart policy diferente?​

CenárioRestart PolicyMotivo
Web server, APIAlwaysReinicia se travar ou falhar
Job de processamento de dadosNeverExecuta uma vez e termina
Script que pode ter falha transitóriaOnFailureRetry em falha, não reinicia após sucesso

9. Boas Práticas​

Use imagens mínimas (Alpine, Distroless): imagens menores iniciam mais rápido (menos dados para baixar), custam menos em armazenamento no ACR e têm menor superfície de ataque de segurança.

Prefira Managed Identity a credenciais explícitas: em vez de passar senhas e chaves de API como variáveis de ambiente, configure uma Managed Identity no container group e use-a para acessar Key Vault, Storage e outros serviços Azure.

Para tarefas batch, use restartPolicy: Never e verifique o exit code: um script que termina com exit code 0 indica sucesso. Exit code diferente de zero indica falha. Use essa convenção para que o ACI saiba se a tarefa foi bem-sucedida.

Defina limites de CPU e memória conservadores: o ACI cobra por recurso alocado, não por uso. Se você aloca 4 vCPU mas usa 0.5, paga por 4. Dimensione com base em benchmarks reais da aplicação.

Nomeie DNS labels de forma previsível e única: o DNS label é parte do FQDN público. Use um padrão como <app>-<ambiente>-<sufixo-unico> para evitar conflitos e facilitar identificação.


10. Erros Comuns​

Usar restart policy "Always" para tarefas batch

Um script de processamento termina com exit code 0 (sucesso). Com Always, o ACI reinicia imediatamente. O script processa os mesmos dados de novo e de novo, em loop, consumindo recursos e potencialmente processando dados duplicados. Para tarefas batch, use Never.

Não especificar DNS label e depois não conseguir o FQDN

O container é criado com IP público mas sem --dns-name-label. O IP muda a cada recriação do container group. O time de infra precisa atualizar manualmente todos os sistemas que apontam para o IP. Sempre defina um DNS label previsível para containers com IP público.

Pull de imagem falha silenciosamente por falta de permissão no ACR

O container group é criado, mas fica no estado Pending indefinidamente. O erro "image pull failed" está nos logs mas não é óbvio no portal. A causa é que o container não tem credenciais para acessar o ACR privado. Configure a Managed Identity com AcrPull antes de criar o container.

Container em VNet não consegue acessar internet para APIs externas

Um container na VNet precisa chamar uma API externa. O tráfego de saída da subnet não tem route para a internet (sem NAT Gateway, sem UDR para internet). O container fica travado aguardando resposta. Containers em VNet que precisam de acesso à internet requerem configuração explícita de saída (NAT Gateway ou Azure Firewall com UDR).

Armazenar dados no filesystem do container sem montar volume

Um job de processamento grava resultados em /tmp/resultados. O job termina. O container group é excluído. Os resultados se perdem. Para persistência, monte sempre um volume Azure Files para os diretórios onde dados importantes são escritos.


11. Operação e Manutenção​

Monitoramento​

O ACI envia métricas para o Azure Monitor:

MétricaO que mede
CpuUsagevCPU usadas pelo container group
MemoryUsageMemória em bytes em uso
NetworkBytesReceivedPerSecondTráfego de entrada
NetworkBytesTransmittedPerSecondTráfego de saída

Para acessar os logs de uma container em execução ou após término:

# Logs do container principal
az container logs --name meu-container --resource-group rg-containers

# Logs de um container específico em um group com múltiplos containers
az container logs \
--name meu-container-group \
--resource-group rg-containers \
--container-name sidecar-container

Os logs são retidos enquanto o container group existe. Após excluir o container group, os logs são perdidos a menos que tenham sido enviados para um serviço de log (Log Analytics, Azure Monitor).

Configurar Log Analytics​

WORKSPACE_ID=$(az monitor log-analytics workspace show \
--workspace-name law-monitoring \
--resource-group rg-monitoring \
--query customerId -o tsv)

WORKSPACE_KEY=$(az monitor log-analytics workspace get-shared-keys \
--workspace-name law-monitoring \
--resource-group rg-monitoring \
--query primarySharedKey -o tsv)

az container create \
--name meu-container \
--resource-group rg-containers \
--log-analytics-workspace $WORKSPACE_ID \
--log-analytics-workspace-key $WORKSPACE_KEY \
...

Com Log Analytics configurado, os logs do container são enviados automaticamente para o workspace e podem ser consultados com KQL mesmo após o container ser excluído.

Limites Importantes​

ItemLimite
CPUs por container group4 vCPU
Memória por container group16 GB
Containers por container group60
Container groups por assinatura por região100 (padrão, ajustável)
Duração máxima de um container groupSem limite técnico (mas limitações de billing)
Portas por container groupMúltiplas, mas sem sobreposição entre containers

12. Integração e Automação​

ACI como Backend para Azure Logic Apps e Functions​

O ACI pode ser criado e destruído programaticamente via API REST, tornando-o ideal para orquestração de jobs:

100%
Scroll para zoom · Arraste para mover · 📱 Pinch para zoom no celular

Virtual Kubelet: ACI como Node do AKS​

O AKS pode usar o ACI como um "node virtual" para absorver bursts de demanda sem escalar nodes reais do cluster:

# Habilitar o addon Virtual Nodes no AKS
az aks enable-addons \
--resource-group rg-aks \
--name meu-cluster \
--addons virtual-node \
--subnet-name subnet-aci

Com isso, Pods com o toleration virtual-kubelet.io/provider=azure são agendados no ACI em vez de em nodes físicos, permitindo escala instantânea sem tempo de provisioning de node.

Automação via ARM/Bicep em Pipelines​

Para pipelines de processamento de dados onde cada run é um container:

#!/bin/bash
# Pipeline: criar container, aguardar conclusão, coletar resultado, excluir

CONTAINER_NAME="job-$(date +%Y%m%d%H%M%S)"
RG="rg-containers"

# Criar container
az container create \
--name $CONTAINER_NAME \
--resource-group $RG \
--image minhacr.azurecr.io/processador:latest \
--cpu 2 --memory 4 \
--ip-address None \
--restart-policy Never \
--environment-variables INPUT_FILE="arquivo-$(date +%Y%m%d).csv"

# Aguardar conclusão
az container wait \
--name $CONTAINER_NAME \
--resource-group $RG \
--condition terminated

# Verificar exit code
EXIT_CODE=$(az container show \
--name $CONTAINER_NAME \
--resource-group $RG \
--query "containers[0].instanceView.currentState.exitCode" -o tsv)

if [ "$EXIT_CODE" == "0" ]; then
echo "Job concluido com sucesso"
else
echo "Job falhou com exit code $EXIT_CODE"
az container logs --name $CONTAINER_NAME --resource-group $RG
fi

# Limpar container
az container delete --name $CONTAINER_NAME --resource-group $RG --yes

13. Resumo Final​

Pontos essenciais:

  • O ACI executa containers sem gerenciamento de VM ou cluster. É ideal para tarefas de curta duração, batch jobs e desenvolvimento.
  • A unidade de deploy é o Container Group, que pode conter múltiplos containers compartilhando rede e volumes.
  • Três políticas de reinicialização: Always (serviços), Never (tarefas batch), OnFailure (retry em falha).
  • Três modos de rede: Public (IP público), Private/VNet (isolamento de rede), None (sem rede).

Diferenças críticas:

  • ACI vs. AKS: ACI é para containers simples, execuções únicas ou desenvolvimento. AKS é para microsserviços em produção, múltiplas réplicas e orquestração complexa.
  • Restart policy Never vs. Always: Never é para jobs que executam uma vez; Always é para serviços contínuos. Usar Always em um job batch cria um loop infinito.
  • Storage efêmero vs. Volume Azure Files: dados no filesystem do container são perdidos quando o container para. Dados em volume Azure Files persistem.
  • IP público vs. VNet mode: containers em VNet não podem ter IP público; escolha um ou outro.

O que precisa ser lembrado:

  • O ACI cobra por vCPU e GB de memória alocados, por segundo de execução.
  • Containers parados (Stopped) não cobram por CPU/memória, mas o container group ainda existe (pode incorrer em custos de armazenamento associado).
  • Para imagens privadas do ACR, use Managed Identity com papel AcrPull.
  • A subnet para ACI em VNet precisa ter a delegação Microsoft.ContainerInstance/containerGroups.
  • O comando az container wait --condition terminated bloqueia até que o container termine, útil em pipelines automatizados.
  • Logs são perdidos quando o container group é excluído. Configure Log Analytics para retenção.