Automatizar todo (compilar aplicaciones en la nube del mundo real con Azure)

por Rick Anderson y Tom Dykstra

Descargar proyecto Fix It o Descargar libro electrónico

El libro electrónico Compilar aplicaciones en la nube del mundo real con Azure se basa en una presentación desarrollada por Scott Guthrie. Explica 13 patrones y prácticas que pueden ayudarle a tener éxito en el desarrollo de aplicaciones web para la nube. Para una introducción al libro electrónico, vea el primer capítulo.

Los tres primeros patrones que veremos se aplicarán realmente a cualquier proyecto de desarrollo de software, pero especialmente a los proyectos en la nube. Este patrón consiste en automatizar las tareas de desarrollo. Es un tema importante porque los procesos manuales son lentos y propensos a errores, y automatizar tantos de ellos como sea posible ayuda a configurar un flujo de trabajo rápido, confiable y ágil. Es especialmente importante para el desarrollo en la nube, ya que puede automatizar fácilmente muchas tareas difíciles o imposibles de automatizar en un entorno local. Por ejemplo, puede configurar entornos de prueba completos, incluidos nuevos servidores web y máquinas virtuales back-end, bases de datos, almacenamiento de blobs (almacenamiento de archivos), colas, etc.

Flujo de trabajo de DevOps

Cada vez escucha más el término "DevOps". El término se desarrolló a partir de un reconocimiento que usted tiene que integrar tareas de desarrollo y operaciones para desarrollar software de forma eficaz. El tipo de flujo de trabajo que usted desea habilitar es uno en el que puede desarrollar una aplicación, implementarla, aprender del uso de producción, cambiarla en respuesta a lo que ha aprendido y repetir el ciclo de forma rápida y confiable.

Algunos equipos de desarrollo en la nube se implementan varias veces al día en un entorno activo. El equipo de Azure usó para implementar una actualización principal cada dos a tres meses, pero ahora publica actualizaciones secundarias cada dos a tres días y versiones principales cada dos a tres semanas. Entrar en esa cadencia le ayuda mucho a responder a los comentarios de los clientes.

Para ello, debe habilitar un ciclo de desarrollo e implementación que sea repetible, confiable, predecible y que tenga un tiempo de ciclo bajo.

DevOps workflow

En otras palabras, el período de tiempo entre tener una idea de una característica, cuando los clientes la usan y proporcionar comentarios debe ser lo más corto posible. Los tres primeros patrones (automatizar todo, control de código fuente, y la integración y entrega continuas) tratan sobre los procedimientos recomendados que se recomiendan para habilitar ese tipo de proceso.

Scripts de administración de Azure

En la introducción a este libro electrónico, ha visto la consola basada en web, el Portal de administración de Microsoft Azure. El portal de administración le permite supervisar y administrar todos los recursos que ha implementado en Azure. Es una manera fácil de crear y eliminar servicios como aplicaciones web y máquinas virtuales, configurar esos servicios, supervisar la operación del servicio y más. Es una excelente herramienta, pero su uso es un proceso manual. Si va a desarrollar una aplicación de producción de cualquier tamaño y, especialmente, en un entorno de equipo, se recomienda pasar por la interfaz de usuario del portal para aprender y explorar Azure, y después automatizar los procesos que va a realizar de forma repetitiva.

Casi todo lo que puede hacer manualmente en el portal de administración o desde Visual Studio también se puede hacer llamando a la API de administración de REST. Puede escribir scripts con Windows PowerShell o puede usar un marco de código abierto como Chef o Puppet. También puede usar la herramienta de línea de comandos de Bash en un entorno Mac o Linux. Azure tiene API de scripting para todos esos entornos diferentes y tiene una API de administración de .NET en caso de que quiera escribir código en lugar de script.

Para la aplicación Fix It hemos creado algunos scripts de Windows PowerShell que automatizan los procesos de creación de un entorno de prueba e implementación del proyecto en ese entorno, y revisaremos parte del contenido de esos scripts.

Script de creación del entorno

El primer script que veremos se llama New-AzureWebsiteEnv.ps1. Crea un entorno de Azure en el que puede implementar la aplicación Fix It para realizar pruebas. Las p5rincipales tareas que realiza este script son las siguientes:

  • Creación de una aplicación web.
  • Cree una cuenta de almacenamiento. (Obligatorio para blobs y colas, como podrá ver en capítulos posteriores).
  • Cree un servidor de SQL Database y dos bases de datos: una base de datos de aplicación y una base de datos de pertenencia.
  • Almacene la configuración en Azure que la aplicación usará para acceder a la cuenta de almacenamiento y las bases de datos.
  • Cree archivos de configuración que se usarán para automatizar la implementación.

Ejecución del script

Nota:

En esta parte del capítulo se muestran ejemplos de scripts y los comandos que se escriben para ejecutarlos. Estos es una demostración y no proporciona todo lo que necesita saber para ejecutar los scripts. Consulte las instrucciones en Apéndice: La aplicación de ejemplo Fix It.

Para ejecutar un script de PowerShell que administre los servicios de Azure debe instalar la consola de Azure PowerShell y configurarlo para que funcione con su suscripción de Azure. Una vez configurado, puede ejecutar el script de creación del entorno Fix It con un comando similar al este:

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

El parámetro Name especifica el nombre que se va a usar al crear la base de datos y las cuentas de almacenamiento, y el parámetro SqlDatabasePassword especifica la contraseña de la cuenta de administrador que se creará para SQL Database. Más adelante veremos otros parámetros que puede usar.

PowerShell window

Puede ver en el portal de administración lo que se creó una vez finalizado el script. Encontrará dos bases de datos:

Databases

Una cuenta de almacenamiento:

Storage account

Y una aplicación web:

Web site

En la pestaña Configurar de la aplicación web, puede ver que tiene la configuración de la cuenta de almacenamiento y las cadenas de conexión de la base de datos SQL configuradas para la aplicación Fix it.

appSettings and connectionStrings

La carpeta Azure Automation ahora también contiene un archivo <websitename.pubxml>. Este archivo almacena la configuración que MSBuild usará para implementar la aplicación en el entorno de Azure que se acaba de crear. Por ejemplo:

<?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 puede ver, el script ha creado un entorno de prueba completo y todo el proceso se realiza en unos 90 segundos.

Si otra persona del equipo quiere crear un entorno de prueba puede ejecutar el script. No solo es rápido, sino que también pueden estar seguros de que usan un entorno idéntico al que usted usa. No se podría tener esa certeza si todos configuraban las cosas manualmente mediante la interfaz de usuario del portal de administración.

Un vistazo a los scripts

Hay tres scripts que hacen este trabajo. Se llama a uno desde la línea de comandos y este usa automáticamente los otros dos para realizar algunas de estas tareas:

  • New-AzureWebSiteEnv.ps1 es el script principal.

    • New-AzureStorage.ps1 crea la cuenta de almacenamiento.
    • New-AzureSql.ps1 crea las bases de datos.

Parámetros en el script principal

New-AzureWebSiteEnv.ps1, el script principal, define varios 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                      
    )

Se requieren dos parámetros:

  • Nombre de la aplicación web que crea el script. (Esto también se usa para la URL: <name>.azurewebsites.net.)
  • Contraseña del nuevo usuario administrativo del servidor de base de datos que crea el script.

Los parámetros opcionales permiten especificar la ubicación del centro de datos (el valor predeterminado es "Oeste de EE. UU."), el nombre del administrador del servidor de bases de datos (el valor predeterminado es "dbuser") y una regla de firewall para el servidor de bases de datos.

Creación de la aplicación web

Lo primero que hace el script es crear la aplicación web llamando al cmdlet New-AzureWebsite y pasando a ella los valores de parámetros de ubicación y nombre de la aplicación web:

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

Creación de la cuenta de almacenamiento

A continuación, el script principal ejecuta el script New-AzureStorage.ps1, especificando "*<websitename>*storage" para el nombre de la cuenta de almacenamiento y la misma ubicación del centro de datos que la aplicación web.

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

New-AzureStorage.ps1 llama al cmdlet New-AzureStorageAccount para crear la cuenta de almacenamiento y devuelve los valores de nombre de cuenta y clave de acceso. La aplicación necesitará estos valores para acceder a los blobs y colas de la cuenta de almacenamiento.

# 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}

Es posible que no siempre quiera crear una nueva cuenta de almacenamiento. Para mejorar el script, agregue un parámetro que lo dirija opcionalmente para usar una cuenta de almacenamiento existente.

Crear las bases de datos

A continuación, el script principal ejecuta el script de creación de la base de datos, New-AzureSql.ps1, después de configurar nombres de reglas de firewall y base de datos predeterminados:

$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

El script de creación de la base de datos recupera la dirección IP de la máquina de desarrollo y establece una regla de firewall para que la máquina de desarrollo pueda conectarse y administrar el servidor. El script de creación de la base de datos pasa por varios pasos para configurar las bases de datos:

  • Crea el servidor mediante el cmdlet New-AzureSqlDatabaseServer.

    $databaseServer = New-AzureSqlDatabaseServer -AdministratorLogin $UserName -AdministratorLoginPassword $Password -Location $Location
    
  • Crea reglas de firewall para habilitar la máquina de desarrollo para administrar el servidor y para permitir que la aplicación web se conecte a él.

    # 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
    
  • Crea un contexto de base de datos que incluye el nombre del servidor y las credenciales mediante el cmdlet New-AzureSqlDatabaseServerContext.

    # 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 es una función en el script que llama al cmdlet ConvertTo-SecureString para cifrar la contraseña y devuelve un objeto PSCredential, el mismo tipo que devuelve el cmdlet Get-Credential.

  • Crea la base de datos de aplicación y la base de datos de pertenencia mediante el cmdlet New-AzureSqlDatabase.

    # 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
    
  • Llama a una función definida localmente para crear una cadena de conexión para cada base de datos. La aplicación usará estas cadenas de conexión para acceder a las bases de datos.

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

    Get-SQLAzureDatabaseConnectionString es una función definida en el script que crea la cadena de conexión a partir de los valores de parámetro proporcionados.

    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;"
    }
    
  • Devuelve una tabla hash con el nombre del servidor de base de datos y las cadenas de conexión.

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

La aplicación Fix It usa bases de datos de aplicación y pertenencia independientes. También es posible colocar tanto la pertenencia como los datos de la aplicación en una base de datos única.

Configuración de la aplicación de la Tienda y cadenas de conexión

Azure tiene una característica que permite almacenar la configuración y las cadenas de conexión que invalidan automáticamente lo que se devuelve a la aplicación cuando intenta leer las colecciones appSettings o connectionStrings en el archivo Web.config. Esta es una alternativa a aplicar transformaciones Web.config al implementar. Para más información, consulte Almacenamiento de datos confidenciales en Azure más adelante en este libro electrónico.

El script de creación del entorno almacena en Azure todos los valores appSettings y connectionStrings que la aplicación necesita para acceder a la cuenta de almacenamiento y las bases de datos cuando se ejecuta en 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 es un marco de telemetría que se muestra en el capítulo Supervisión y telemetría. El script de creación del entorno también reinicia la aplicación web para asegurarse de que recoge la configuración de New Relic.

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

Prepararse para la implementación

Al final del proceso, el script de creación del entorno llama a dos funciones para crear archivos que usará el script de implementación.

Una de estas funciones crea un perfil de publicación(<archivo >websitename.pubxml). El código llama a la API REST de Azure para obtener la configuración de publicación y guarda la información en un archivo .publishsettings. A continuación, usa la información de ese archivo junto con un archivo de plantilla (pubxml.template) para crear el archivo .pubxml que contiene el perfil de publicación. Este proceso de dos pasos simula lo que hace en Visual Studio: descargue un archivo .publishsettings e impórtelo para crear un perfil de publicación.

La otra función usa otro archivo de plantilla (website-environment.template) para crear un archivo website-environment.xml que contenga la configuración que usará el script de implementación junto con el archivo .pubxml.

Solución de problemas y control de errores

Los scripts son como programas: pueden producir un error y cuando se quiere saber tanto como pueda sobre el error y lo que lo causó. Por este motivo, el script de creación del entorno cambia el valor de la variable VerbosePreference de SilentlyContinue a Continue para que se muestren todos los mensajes detallados. También cambia el valor de la variable ErrorActionPreference de Continue a Stop, de modo que el script se detenga incluso cuando encuentre errores de no terminación:

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

Antes de realizar cualquier trabajo, el script almacena la hora de inicio para que pueda calcular el tiempo transcurrido cuando haya terminado:

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

Una vez completado su trabajo, el script muestra el tiempo transcurrido:

# 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)

Y para cada operación de clave, el script escribe mensajes detallados, por ejemplo:

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 implementación

Lo que hace el script New-AzureWebsiteEnv.ps1 para la creación del entorno, el script Publish-AzureWebsite.ps1hace para la implementación de aplicaciones.

El script de implementación obtiene el nombre de la aplicación web del archivo website-environment.xml creado por el script de creación del entorno.

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

Obtiene la contraseña de usuario de implementación del archivo .publishsettings:

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

Ejecuta el comando de MSBuild que compila e implementa el proyecto:

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

Y si ha especificado el parámetro Launch en la línea de comandos, llama al cmdlet Show-AzureWebsite para abrir el explorador predeterminado en la dirección URL del sitio web.

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

Puede ejecutar el script de implementación con un comando similar a este:

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

Y cuando haya terminado, el explorador se abre con el sitio que se ejecuta en la nube en la dirección URL <websitename>.azurewebsites.net.

Fix It app deployed to Windows Azure

Resumen

Con estos scripts puede asegurarse de que los mismos pasos siempre se ejecutarán en el mismo orden con las mismas opciones. Esto ayuda a asegurarse de que cada desarrollador del equipo no pierda algo o desordene algo o implemente algo personalizado en su propia máquina que no funcionará de la misma manera en el entorno de otro miembro del equipo o en producción.

De forma similar, puede automatizar la mayoría de las funciones de administración de Azure que puede realizar en el portal de administración mediante la API REST, scripts de Windows PowerShell, una API de lenguaje .NET o una utilidad de Bash que puede ejecutar en Linux o Mac.

En el siguiente capítulo veremos el código fuente y explicaremos por qué es importante incluir los scripts en el repositorio de código fuente.

Recursos