Infraestrutura como código

Dica

Esse conteúdo é um trecho do livro eletrônico, para Projetar os Aplicativos .NET nativos de nuvem para o Azure, disponível no .NET Docs ou como um PDF para download gratuito que pode ser lido offline.

Cloud Native .NET apps for Azure eBook cover thumbnail.

Os sistemas nativos de nuvem adotam microsserviços, contêineres e design de sistema moderno para atingir velocidade e agilidade. Eles fornecem fases automatizadas de build e lançamento para garantir um código consistente e de qualidade. Mas isso é apenas parte da história. Como provisionar os ambientes de nuvem nos quais esses sistemas são executados?

Os aplicativos nativos de nuvem modernos adotam a prática amplamente aceita de Infraestrutura como Código ou IaC. Com a IaC, você automatiza o provisionamento de plataforma. Basicamente, você aplica práticas de engenharia de software, como teste e controle de versão às práticas de DevOps. A infraestrutura e as implantações são automatizadas, consistentes e repetíveis. Assim como a entrega contínua automatiza o modelo tradicional de implantações manuais, a IaC (Infraestrutura como Código) está evoluindo como os ambientes de aplicativo são gerenciados.

Ferramentas como o ARM (Azure Resource Manager), o Terraform e a CLI (interface de linha de comando) do Azure permitem gerar um script de modo declarativo para a infraestrutura de nuvem necessária.

Modelos do Azure Resource Manager

ARM significa Azure Resource Manager. É um mecanismo de provisionamento de API integrado ao Azure e exposto como um serviço de API. O ARM permite que você implante, atualize, exclua e gerencie os recursos contidos no grupo de recursos do Azure em uma só operação coordenada. Você fornece ao mecanismo um modelo baseado em JSON que especifica os recursos necessários e as respectivas configurações. O ARM orquestra automaticamente a implantação na ordem correta respeitando as dependências. O mecanismo garante a idempotência. Se um recurso desejado já existir com a mesma configuração, o provisionamento será ignorado.

Os modelos do Azure Resource Manager são uma linguagem baseada em JSON para definir vários recursos no Azure. O esquema básico é semelhante à Figura 10-14.

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "",
  "apiProfile": "",
  "parameters": {  },
  "variables": {  },
  "functions": [  ],
  "resources": [  ],
  "outputs": {  }
}

Figura 10-14 – O esquema de um modelo do Resource Manager

Nesse modelo, é possível definir um contêiner de armazenamento dentro da seção de recursos da seguinte maneira:

"resources": [
    {
      "type": "Microsoft.Storage/storageAccounts",
      "name": "[variables('storageAccountName')]",
      "location": "[parameters('location')]",
      "apiVersion": "2018-07-01",
      "sku": {
        "name": "[parameters('storageAccountType')]"
      },
      "kind": "StorageV2",
      "properties": {}
    }
  ],

Figura 10-15 – Um exemplo de conta de armazenamento definida em um modelo do Resource Manager

Um modelo do ARM pode ser parametrizado com informações dinâmicas de ambiente e configuração. Isso permite que ele seja reutilizado para definir ambientes diferentes, como desenvolvimento, garantia de qualidade ou produção. Normalmente, o modelo cria todos os recursos em um só grupo de recursos do Azure. É possível definir vários grupos de recursos em um só modelo do Resource Manager, se necessário. Você pode excluir todos os recursos em um ambiente excluindo o próprio grupo de recursos. A análise de custo também pode ser executada no nível do grupo de recursos, permitindo uma contabilidade rápida de quanto cada ambiente está custando.

Há muitos exemplos de modelos do ARM disponíveis no projeto Modelos de início rápido do Azure no GitHub. Eles podem ajudar a acelerar a criação de um modelo ou a modificação de um existente.

Os modelos do Resource Manager podem ser executados de várias maneiras. Talvez a maneira mais simples seja simplesmente colá-los no portal do Azure. Para implantações experimentais, esse método pode ser rápido. Eles também podem ser executados como parte de um processo de build ou lançamento no Azure DevOps. Há tarefas que aproveitarão as conexões no Azure para executar os modelos. As alterações nos modelos do Resource Manager são aplicadas incrementalmente, o que significa que para adicionar um novo recurso basta adicioná-lo ao modelo. As ferramentas reconciliarão as diferenças entre os recursos atuais e os definidos no modelo. Depois, os recursos serão criados ou alterados para que correspondam ao que está definido no modelo.

Terraform

Os aplicativos nativos de nuvem geralmente são construídos para serem cloud agnostic. Isso significa que o aplicativo não é fortemente acoplado a um fornecedor de nuvem específico e pode ser implantado em qualquer nuvem pública.

O Terraform é uma ferramenta de modelagem comercial que pode provisionar aplicativos nativos de nuvem em todos os principais players de nuvem: Azure, Google Cloud Platform, AWS e AliCloud. Em vez de usar JSON como a linguagem de definição de modelo, ela usa HCL (Linguagem de Configuração HashiCorp), que é um pouco mais conciso.

Um exemplo de arquivo Terraform que faz o mesmo que o modelo do Resource Manager anterior (Figura 10-15) é mostrado na Figura 10-16:

provider "azurerm" {
  version = "=1.28.0"
}

resource "azurerm_resource_group" "testrg" {
  name     = "production"
  location = "West US"
}

resource "azurerm_storage_account" "testsa" {
  name                     = "${var.storageAccountName}"
  resource_group_name      = "${azurerm_resource_group.testrg.name}"
  location                 = "${var.region}"
  account_tier             = "${var.tier}"
  account_replication_type = "${var.replicationType}"

}

Figura 10-16 – Um exemplo de modelo do Resource Manager

O Terraform também fornece mensagens de erro intuitivas para modelos de problema. Há também uma tarefa de validação útil que pode ser usada na fase de build para capturar erros de modelo antecipadamente.

Assim como acontece com modelos do Resource Manager, as ferramentas de linha de comando estão disponíveis para implantar modelos do Terraform. Também há tarefas criadas pela comunidade no Azure Pipelines que podem validar e aplicar modelos do Terraform.

Às vezes, os modelos do Terraform e do ARM geram valores significativos, como uma cadeia de conexão para um banco de dados recém-criado. Essas informações podem ser capturadas no pipeline de build e usadas em tarefas subsequentes.

Scripts e tarefas da CLI do Azure

Por fim, você pode aproveitar a CLI do Azure para criar um script declarativo da infraestrutura de nuvem. Os scripts da CLI do Azure podem ser criados, encontrados e compartilhados para provisionar e configurar quase qualquer recurso do Azure. A CLI é simples de usar com uma curva de aprendizado suave. Os scripts são executados no PowerShell ou no Bash. Eles também são simples de serem depurados, principalmente quando comparados com modelos do ARM.

Os scripts da CLI do Azure funcionam bem quando você precisa remover e reimplantar a infraestrutura. Pode ser complicado atualizar um ambiente existente. Muitos comandos da CLI não são idempotentes. Isso significa que eles recriarão o recurso sempre que eles forem executados, mesmo que o recurso já exista. É possível adicionar um código que verifique a existência de cada recurso antes de criá-lo. Mas, com isso, o script pode ficar muito grande e difícil de ser gerenciado.

Esses scripts também podem ser inseridos em pipelines do Azure DevOps como Azure CLI tasks. A execução do pipeline invoca o script.

A Figura 10-17 mostra um snippet YAML que lista a versão da CLI do Azure e os detalhes da assinatura. Observe como os comandos da CLI do Azure são incluídos em um script embutido.

- task: AzureCLI@2
  displayName: Azure CLI
  inputs:
    azureSubscription: <Name of the Azure Resource Manager service connection>
    scriptType: ps
    scriptLocation: inlineScript
    inlineScript: |
      az --version
      az account show

Figura 10-17 – Script da CLI do Azure

No artigo O que é infraestrutura como código, o autor Sam Guckenheimer descreve como "Equipes que implementam a IaC podem fornecer ambientes estáveis rapidamente e em escala. Elas evitam a configuração manual de ambientes e impõem a consistência, representando o estado desejado dos ambientes por meio de código. As implantações de infraestrutura com IaC são repetíveis e evitam problemas de tempo de execução causados por descompasso de configuração ou dependências ausentes. As equipes de DevOps podem trabalhar junto com um conjunto unificado de práticas e ferramentas para fornecer aplicativos e a infraestrutura de suporte de maneira rápida, confiável e em escala."