Automatizar tudo (criando aplicativos de nuvem Real-World com o Azure)

por Rick Anderson, Tom Dykstra

Baixar o Projeto de Correção ou Baixar E-book

O livro eletrônico Criando Aplicativos de Nuvem do Mundo Real com o Azure é baseado em uma apresentação desenvolvida por Scott Guthrie. Ele explica 13 padrões e práticas que podem ajudá-lo a desenvolver aplicativos Web para a nuvem com êxito. Para obter uma introdução ao livro eletrônico, confira o primeiro capítulo.

Os três primeiros padrões que examinaremos realmente se aplicam a qualquer projeto de desenvolvimento de software, mas especialmente a projetos de nuvem. Esse padrão é sobre automatizar tarefas de desenvolvimento. É um tópico importante porque os processos manuais são lentos e propensos a erros; automatizar o maior número possível deles ajuda a configurar um fluxo de trabalho rápido, confiável e ágil. É exclusivamente importante para o desenvolvimento em nuvem porque você pode automatizar facilmente muitas tarefas difíceis ou impossíveis de automatizar em um ambiente local. Por exemplo, você pode configurar ambientes de teste inteiros, incluindo novo servidor Web e VMs de back-end, bancos de dados, armazenamento de blobs (armazenamento de arquivos), filas etc.

Fluxo de trabalho de DevOps

Cada vez mais você ouve o termo "DevOps". O termo desenvolvido a partir de um reconhecimento de que você precisa integrar tarefas de desenvolvimento e operações para desenvolver software com eficiência. O tipo de fluxo de trabalho que você deseja habilitar é aquele em que você pode desenvolver um aplicativo, implantá-lo, aprender com o uso de produção dele, alterá-lo em resposta ao que você aprendeu e repetir o ciclo de forma rápida e confiável.

Algumas equipes de desenvolvimento de nuvem bem-sucedidas implantam várias vezes por dia em um ambiente ativo. A equipe do Azure costumava implantar uma atualização importante a cada 2 a 3 meses, mas agora ela libera atualizações secundárias a cada 2 a 3 dias e versões principais a cada 2 a 3 semanas. Entrar nessa cadência realmente ajuda você a responder aos comentários dos clientes.

Para fazer isso, você precisa habilitar um ciclo de desenvolvimento e implantação que seja repetível, confiável, previsível e tenha pouco tempo de ciclo.

Fluxo de trabalho de DevOps

Em outras palavras, o período de tempo entre quando você tem uma ideia para um recurso e quando os clientes o estão usando e fornecendo comentários deve ser o mais curto possível. Os três primeiros padrões – automatizar tudo, controle do código-fonte e integração e entrega contínuas – são sobre as práticas recomendadas que recomendamos para habilitar esse tipo de processo.

Scripts de gerenciamento do Azure

Na introdução a este e-book, você viu o console baseado na Web, o Portal de Gerenciamento do Azure. O portal de gerenciamento permite monitorar e gerenciar todos os recursos implantados no Azure. É uma maneira fácil de criar e excluir serviços, como aplicativos Web e VMs, configurar esses serviços, monitorar a operação de serviço e assim por diante. É uma ótima ferramenta, mas usá-la é um processo manual. Se você pretende desenvolver um aplicativo de produção de qualquer tamanho e, especialmente, em um ambiente de equipe, recomendamos que você passe pela interface do usuário do portal para aprender e explorar o Azure e, em seguida, automatizar os processos que você fará repetidamente.

Quase tudo o que você pode fazer manualmente no portal de gerenciamento ou no Visual Studio também pode ser feito chamando a API de gerenciamento REST. Você pode escrever scripts usando Windows PowerShell ou pode usar uma estrutura código aberto, como Chef ou Puppet. Você também pode usar a ferramenta de linha de comando Bash em um ambiente Mac ou Linux. O Azure tem APIs de script para todos esses ambientes diferentes e tem uma API de gerenciamento do .NET caso você deseje escrever código em vez de script.

Para o aplicativo Fix It, criamos alguns scripts Windows PowerShell que automatizam os processos de criação de um ambiente de teste e implantação do projeto nesse ambiente e examinaremos alguns dos conteúdos desses scripts.

Script de criação de ambiente

O primeiro script que examinaremos é chamado New-AzureWebsiteEnv.ps1. Ele cria um ambiente do Azure no qual você pode implantar o aplicativo Corrigir para teste. As tarefas main que esse script executa são as seguintes:

  • Crie um aplicativo Web.
  • Criar uma conta de armazenamento. (Necessário para blobs e filas, como você verá em capítulos posteriores.)
  • Crie um servidor Banco de Dados SQL e dois bancos de dados: um banco de dados de aplicativo e um banco de dados de associação.
  • Armazene as configurações no Azure que o aplicativo usará para acessar a conta de armazenamento e os bancos de dados.
  • Crie arquivos de configurações que serão usados para automatizar a implantação.

Executar o script

Observação

Esta parte do capítulo mostra exemplos de scripts e os comandos inseridos para executá-los. Esta é uma demonstração e não fornece tudo o que você precisa saber para executar os scripts. Para obter instruções passo a passo sobre como fazer isso, consulte Apêndice: o aplicativo de exemplo Fix It.

Para executar um script do PowerShell que gerencia os serviços do Azure, você precisa instalar o console do Azure PowerShell e configurá-lo para trabalhar com sua assinatura do Azure. Depois de configurar, você poderá executar o script de criação do ambiente Fix It com um comando como este:

.\New-AzureWebsiteEnv.ps1 -Name <websitename> -SqlDatabasePassword <password>

O Name parâmetro especifica o nome a ser usado ao criar o banco de dados e as contas de armazenamento e o SqlDatabasePassword parâmetro especifica a senha da conta de administrador que será criada para Banco de Dados SQL. Há outros parâmetros que você pode usar que examinaremos mais tarde.

Janela do PowerShell

Depois que o script for concluído, você poderá ver no portal de gerenciamento o que foi criado. Você encontrará dois bancos de dados:

Bancos de dados

Uma conta de armazenamento:

Conta de armazenamento

E um aplicativo Web:

Site

Na guia Configurar para o aplicativo Web, você pode ver que ele tem as configurações da conta de armazenamento e as cadeias de conexão do banco de dados SQL configuradas para o aplicativo Corrigir.

appSettings e connectionStrings

A pasta Automação agora também contém um <arquivo websitename.pubxml>. Esse arquivo armazena as configurações que o MSBuild usará para implantar o aplicativo no ambiente do Azure que acabou de ser criado. Por exemplo:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <WebPublishMethod>MSDeploy</WebPublishMethod>
    <SiteUrlToLaunchAfterPublish>http://fixitdemo.azurewebsites.net</SiteUrlToLaunchAfterPublish>
    <ExcludeApp_Data>False</ExcludeApp_Data>
    <MSDeployServiceURL>waws-prod-bay-003.publish.azurewebsites.windows.net:443</MSDeployServiceURL>
    <DeployIisAppPath>fixitdemo</DeployIisAppPath>
    <RemoteSitePhysicalPath />
    <SkipExtraFilesOnServer>True</SkipExtraFilesOnServer>
    <MSDeployPublishMethod>WMSVC</MSDeployPublishMethod>
    <EnableMSDeployBackup>True</EnableMSDeployBackup>
    <UserName>$fixitdemo</UserName>
    <PublishDatabaseSettings></PublishDatabaseSettings>
  </PropertyGroup>
</Project>

Como você pode ver, o script criou um ambiente de teste completo e todo o processo é feito em cerca de 90 segundos.

Se outra pessoa em sua equipe quiser criar um ambiente de teste, poderá apenas executar o script. Não só é rápido, mas também eles podem estar confiantes de que estão usando um ambiente idêntico ao que você está usando. Você não poderia estar tão confiante nisso se todos estavam configurando as coisas manualmente usando a interface do usuário do portal de gerenciamento.

Uma olhada nos scripts

Na verdade, há três scripts que fazem esse trabalho. Você chama um da linha de comando e ele usa automaticamente os outros dois para realizar algumas das tarefas:

  • New-AzureWebSiteEnv.ps1 é o script main.

    • New-AzureStorage.ps1 cria a conta de armazenamento.
    • New-AzureSql.ps1 cria os bancos de dados.

Parâmetros no script main

O script main, New-AzureWebSiteEnv.ps1, define vários parâmetros:

[CmdletBinding(PositionalBinding=$True)]
Param(
    [Parameter(Mandatory = $true)]
    [ValidatePattern("^[a-z0-9]*$")]
    [String]$Name,                             
    [String]$Location = "West US",             
    [String]$SqlDatabaseUserName = "dbuser",   
    [String]$SqlDatabasePassword,              
    [String]$StartIPAddress,                   
    [String]$EndIPAddress                      
    )

Dois parâmetros são necessários:

  • O nome do aplicativo Web que o script cria. (Isso também é usado para a URL: <name>.azurewebsites.net.)
  • A senha do novo usuário administrativo do servidor de banco de dados que o script cria.

Os parâmetros opcionais permitem especificar o local do data center (padrão para "Oeste dos EUA"), o nome do administrador do servidor de banco de dados (padrão é "dbuser" e uma regra de firewall para o servidor de banco de dados.

Criar o aplicativo Web

A primeira coisa que o script faz é criar o aplicativo Web chamando o New-AzureWebsite cmdlet , passando para ele os valores de nome do aplicativo Web e parâmetro de localização:

# Create a new website
$website = New-AzureWebsite -Name $Name -Location $Location -Verbose

Criar a conta de armazenamento

Em seguida, o script main executa o script New-AzureStorage.ps1, especificando "*<websitename>*storage" para o nome da conta de armazenamento e o mesmo local do data center que o aplicativo Web.

$storageAccountName = $Name + "storage"
 
$storage = $scriptPath\New-AzureStorage.ps1" -Name $storageAccountName -Location $Location

New-AzureStorage.ps1 chama o New-AzureStorageAccount cmdlet para criar a conta de armazenamento e retorna o nome da conta e os valores da chave de acesso. O aplicativo precisará desses valores para acessar os blobs e as filas na conta de armazenamento.

# Create a new storage account
New-AzureStorageAccount -StorageAccountName $Name -Location $Location -Verbose
 
# Get the access key of the storage account
$key = Get-AzureStorageKey -StorageAccountName $Name
 
# Generate the connection string of the storage account
$connectionString = "BlobEndpoint=http://$Name.blob.core.windows.net/;QueueEndpoint=http://$Name.queue.core.windows.net/;TableEndpoint=http://$Name.table.core.windows.net/;AccountName=$Name;AccountKey=$primaryKey"
 
#Return a hashtable of storage account values
Return @{AccountName = $Name; AccessKey = $key.Primary; ConnectionString = $connectionString}

Talvez nem sempre você queira criar uma nova conta de armazenamento; você pode aprimorar o script adicionando um parâmetro que, opcionalmente, o direciona para usar uma conta de armazenamento existente.

Criar os bancos de dados

Em seguida, o script main executa o script de criação do banco de dados,New-AzureSql.ps1, depois de configurar nomes de regras de banco de dados e firewall padrão:

$sqlAppDatabaseName = "appdb"
$sqlMemberDatabaseName = "memberdb"
$sqlDatabaseServerFirewallRuleName = $Name + "rule"
# Create a SQL Azure database server, app and member databases
$sql = $scriptPath\New-AzureSql.ps1 `
    -AppDatabaseName $sqlAppDatabaseName `
    -MemberDatabaseName $sqlMemberDatabaseName `
    -UserName $SqlDatabaseUserName `
    -Password $SqlDatabasePassword `
    -FirewallRuleName $sqlDatabaseServerFirewallRuleName `
    -StartIPAddress $StartIPAddress `
    -EndIPAddress $EndIPAddress `
    -Location $Location

O script de criação do banco de dados recupera o endereço IP do computador de desenvolvimento e define uma regra de firewall para que o computador de desenvolvimento possa se conectar e gerenciar o servidor. Em seguida, o script de criação do banco de dados passa por várias etapas para configurar os bancos de dados:

  • Cria o servidor usando o New-AzureSqlDatabaseServer cmdlet .

    $databaseServer = New-AzureSqlDatabaseServer -AdministratorLogin $UserName -AdministratorLoginPassword $Password -Location $Location
    
  • Cria regras de firewall para permitir que o computador de desenvolvimento gerencie o servidor e habilite o aplicativo Web para se conectar a ele.

    # Create a SQL Azure database server firewall rule for the IP address of the machine in which this script will run
    # This will also allowlist all the Azure IP so that the website can access the database server
    New-AzureSqlDatabaseServerFirewallRule -ServerName $databaseServerName -RuleName $FirewallRuleName -StartIpAddress $StartIPAddress 
    -EndIpAddress $EndIPAddress -Verbose
    New-AzureSqlDatabaseServerFirewallRule -ServerName $databaseServer.ServerName -AllowAllAzureServices 
    -RuleName "AllowAllAzureIP" -Verbose
    
  • Cria um contexto de banco de dados que inclui o nome do servidor e as credenciais usando o New-AzureSqlDatabaseServerContext cmdlet .

    # Create a database context which includes the server name and credential
    # These are all local operations. No API call to Azure
    $credential = New-PSCredentialFromPlainText -UserName $UserName -Password $Password
    $context = New-AzureSqlDatabaseServerContext -ServerName $databaseServer.ServerName -Credential $credential
    

    New-PSCredentialFromPlainText é uma função no script que chama o ConvertTo-SecureString cmdlet para criptografar a senha e retorna um PSCredential objeto, o mesmo tipo que o Get-Credential cmdlet retorna.

  • Cria o banco de dados do aplicativo e o banco de dados de associação usando o New-AzureSqlDatabase cmdlet .

    # Use the database context to create app database
    New-AzureSqlDatabase -DatabaseName $AppDatabaseName -Context $context -Verbose
     
    # Use the database context to create member database
    New-AzureSqlDatabase -DatabaseName $MemberDatabaseName -Context $context -Verbose
    
  • Chama uma função definida localmente para criar uma cadeia de conexão para cada banco de dados. O aplicativo usará essas cadeias de conexão para acessar os bancos de dados.

    $appDatabaseConnectionString = Get-SQLAzureDatabaseConnectionString -DatabaseServerName $databaseServerName -DatabaseName $AppDatabaseName -UserName $UserName -Password $Password
    $memberDatabaseConnectionString = Get-SQLAzureDatabaseConnectionString -DatabaseServerName $databaseServerName -DatabaseName $MemberDatabaseName -UserName $UserName -Password $Password
    

    Get-SQLAzureDatabaseConnectionString é uma função definida no script que cria a cadeia de conexão com base nos valores de parâmetro fornecidos a ela.

    Function Get-SQLAzureDatabaseConnectionString
    {
        Param(
            [String]$DatabaseServerName,
            [String]$DatabaseName,
            [String]$UserName,
            [String]$Password
        )
    
        Return "Server=tcp:$DatabaseServerName.database.windows.net,1433;Database=$DatabaseName;User ID=$UserName@$DatabaseServerName;Password=$Password;Trusted_Connection=False;Encrypt=True;Connection Timeout=30;"
    }
    
  • Retorna uma tabela de hash com o nome do servidor de banco de dados e as cadeias de conexão.

    Return @{ `
        Server = $databaseServer.ServerName; UserName = $UserName; Password = $Password; `
        AppDatabase = @{Name = $AppDatabaseName; ConnectionString = $appDatabaseConnectionString}; `
        MemberDatabase = @{Name = $MemberDatabaseName; ConnectionString = $memberDatabaseConnectionString} `
    }
    

O aplicativo Fix It usa bancos de dados de aplicativos e associação separados. Também é possível colocar dados de associação e de aplicativo em um banco de dados individual.

Armazenar configurações de aplicativo e cadeias de conexão

O Azure tem um recurso que permite armazenar configurações e cadeias de conexão que substituem automaticamente o que é retornado ao aplicativo quando ele tenta ler as appSettings coleções ou connectionStrings no arquivo Web.config. Essa é uma alternativa à aplicação de transformações deWeb.config ao implantar. Para obter mais informações, consulte Armazenar dados confidenciais no Azure mais adiante neste livro eletrônico.

O script de appSettings criação de ambiente armazena no Azure todos os valores e connectionStrings que o aplicativo precisa para acessar a conta de armazenamento e os bancos de dados quando ele é executado no Azure.

# Configure app settings for storage account and New Relic
$appSettings = @{ `
    "StorageAccountName" = $storageAccountName; `
    "StorageAccountAccessKey" = $storage.AccessKey; `
    "COR_ENABLE_PROFILING" = "1"; `
    "COR_PROFILER" = "{71DA0A04-7777-4EC6-9643-7D28B46A8A41}"; `
    "COR_PROFILER_PATH" = "C:\Home\site\wwwroot\newrelic\NewRelic.Profiler.dll"; `
    "NEWRELIC_HOME" = "C:\Home\site\wwwroot\newrelic" `
}
# Configure connection strings for appdb and ASP.NET member db
$connectionStrings = ( `
    @{Name = $sqlAppDatabaseName; Type = "SQLAzure"; ConnectionString = $sql.AppDatabase.ConnectionString}, `
    @{Name = "DefaultConnection"; Type = "SQLAzure"; ConnectionString = $sql.MemberDatabase.ConnectionString}
)
# Add the connection string and storage account name/key to the website
Set-AzureWebsite -Name $Name -AppSettings $appSettings -ConnectionStrings $connectionStrings

New Relic é uma estrutura de telemetria que demonstramos no capítulo Monitoramento e Telemetria . O script de criação do ambiente também reinicia o aplicativo Web para garantir que ele pegue as configurações do New Relic.

# Restart the website to let New Relic hook kick in
Restart-AzureWebsite -Name $websiteName

Preparando-se para a implantação

No final do processo, o script de criação do ambiente chama duas funções para criar arquivos que serão usados pelo script de implantação.

Uma dessas funções cria um perfil de publicação (<arquivo websitename.pubxml>). O código chama a API REST do Azure para obter as configurações de publicação e salva as informações em um arquivo .publishsettings . Em seguida, ele usa as informações desse arquivo junto com um arquivo de modelo (pubxml.template) para criar o arquivo .pubxml que contém o perfil de publicação. Esse processo de duas etapas simula o que você faz no Visual Studio: baixar um arquivo .publishsettings e importá-lo para criar um perfil de publicação.

A outra função usa outro arquivo de modelo (website-environment.template) para criar um arquivo website-environment.xml que contém configurações que o script de implantação usará junto com o arquivo .pubxml .

Solução de problemas e tratamento de erro

Os scripts são como programas: eles podem falhar e, quando eles fazem, você quer saber o máximo possível sobre a falha e o que causou isso. Por esse motivo, o script de criação do ambiente altera o valor da VerbosePreference variável de SilentlyContinue para para Continue que todas as mensagens detalhadas sejam exibidas. Ele também altera o valor da variável de ErrorActionPreferenceContinue para , para Stopque o script pare mesmo quando encontrar erros de não encerramento:

# Set the output level to verbose and make the script stop on error
$VerbosePreference = "Continue"
$ErrorActionPreference = "Stop"

Antes de fazer qualquer trabalho, o script armazena a hora de início para que possa calcular o tempo decorrido quando terminar:

# Mark the start time of the script execution
$startTime = Get-Date

Depois de concluir seu trabalho, o script exibirá o tempo decorrido:

# Mark the finish time of the script execution
$finishTime = Get-Date
# Output the time consumed in seconds
Write-Output ("Total time used (seconds): {0}" -f ($finishTime - $startTime).TotalSeconds)

E para cada operação de chave, o script grava mensagens detalhadas, por exemplo:

Write-Verbose "[Start] creating $websiteName website in $Location location"
$website = New-AzureWebsite -Name $websiteName -Location $Location -Verbose
Write-Verbose "[Finish] creating $websiteName website in $Location location"

Script de implantação

O que o script New-AzureWebsiteEnv.ps1 faz para a criação do ambiente, o script Publish-AzureWebsite.ps1 faz para a implantação do aplicativo.

O script de implantação obtém o nome do aplicativo Web do arquivo website-environment.xml criado pelo script de criação do ambiente.

[Xml]$envXml = Get-Content "$scriptPath\website-environment.xml"
$websiteName = $envXml.environment.name

Ele obtém a senha do usuário de implantação do arquivo .publishsettings :

[Xml]$xml = Get-Content $scriptPath\$websiteName.publishsettings 
$password = $xml.publishData.publishProfile.userPWD[0]
$publishXmlFile = Join-Path $scriptPath -ChildPath ($websiteName + ".pubxml")

Ele executa o comando MSBuild que compila e implanta o projeto:

& "$env:windir\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" $ProjectFile `
    /p:VisualStudioVersion=12.0 `
    /p:DeployOnBuild=true `
    /p:PublishProfile=$publishXmlFile `
    /p:Password=$password

E se você especificou o Launch parâmetro na linha de comando, ele chama o Show-AzureWebsite cmdlet para abrir o navegador padrão para a URL do site.

If ($Launch)
{
    Show-AzureWebsite -Name $websiteName
}

Você pode executar o script de implantação com um comando como este:

.\Publish-AzureWebsite.ps1 ..\MyFixIt\MyFixIt.csproj -Launch

E quando terminar, o navegador será aberto com o site em execução na nuvem na <websitename>.azurewebsites.net URL.

Corrigir o aplicativo de Ti implantado no Windows Azure

Resumo

Com esses scripts, você pode ter certeza de que as mesmas etapas sempre serão executadas na mesma ordem usando as mesmas opções. Isso ajuda a garantir que cada desenvolvedor da equipe não perca algo ou estrague algo ou implante algo personalizado em seu próprio computador que não funcionará da mesma maneira no ambiente de outro membro da equipe ou em produção.

De maneira semelhante, você pode automatizar a maioria das funções de gerenciamento do Azure que você pode fazer no portal de gerenciamento, usando a API REST, Windows PowerShell scripts, uma API de linguagem .NET ou um utilitário Bash que você pode executar no Linux ou Mac.

No próximo capítulo , examinaremos o código-fonte e explicaremos por que é importante incluir seus scripts no repositório de código-fonte.

Recursos