使用 Azure) 自動化建置雲端應用程式Real-World一切 (

作者: Rick AndersonTom Dykstra

下載修正專案下載電子書

使用 Azure 電子書建置真實世界雲端應用程式是以 Scott Guthrie 開發的簡報為基礎。 它說明 13 種模式和做法,可協助您成功開發雲端的 Web 應用程式。 如需電子書的簡介,請參閱 第一章

我們將探討的前三種模式實際適用于任何軟體發展專案,特別是雲端專案。 此模式是關於自動化開發工作。 這是一個重要主題,因為手動程式很慢且容易出錯;盡可能自動化其中許多專案,有助於設定快速、可靠且敏捷的工作流程。 對於雲端開發而言,這非常重要,因為您可以輕鬆地將許多難以或不可能在內部部署環境中自動化的工作自動化。 例如,您可以設定整個測試環境,包括新的 Web 服務器和後端 VM、資料庫、Blob 儲存體 (檔案儲存體) 、佇列等。

DevOps 工作流程

您逐漸聽到「DevOps」一詞。從辨識開發的詞彙,您必須整合開發和作業工作,以便有效率地開發軟體。 您想要啟用的工作流程類型是一種,您可以在其中開發應用程式、部署應用程式、從其生產使用量中學習、變更它以回應您學到的內容,以及快速且可靠地重複迴圈。

某些成功的雲端開發小組一天多次部署到即時環境。 Azure 小組用來每隔 2-3 個月部署一次主要更新,但現在每隔 2-3 天發行一次次要更新,每 2-3 周發行一次主要更新。 進入該步調可協助您回應客戶意見反應。

若要這樣做,您必須啟用可重複、可靠、可預測且具有低週期時間的開發與部署週期。

DevOps 工作流程

換句話說,當您對於功能有想法,以及客戶使用此功能和提供意見反應的時間週期必須盡可能短。 前三種模式 – 自動化所有專案、原始檔控制,以及持續整合和傳遞 -- 全都關於我們建議的最佳做法,以便啟用該類型的程式。

Azure 管理腳本

在此 電子書簡介中,您已看到 Web 型主控台 Azure 管理入口網站。 管理入口網站可讓您監視和管理您在 Azure 上部署的所有資源。 建立和刪除 Web 應用程式和 VM 等服務、設定這些服務、監視服務作業等等,是一種簡單的方式。 這是絕佳的工具,但使用是手動程式。 如果您要開發任何規模的生產應用程式,特別是在小組環境中,建議您流覽入口網站 UI 以學習和探索 Azure,然後將重複執行的程式自動化。

您幾乎可以在管理入口網站或 Visual Studio 中手動執行的所有作業,也可以藉由呼叫 REST 管理 API 來完成。 您可以使用Windows PowerShell撰寫腳本,也可以使用如 ChefPuppet等開放原始碼架構。 您也可以在 Mac 或 Linux 環境中使用 Bash 命令列工具。 Azure 具有所有這些不同環境的腳本 API,而且如果您想要撰寫程式碼而不是腳本,則其具有 .NET 管理 API

針對修正 It 應用程式,我們已建立一些Windows PowerShell腳本,以自動化建立測試環境並將專案部署至該環境的程式,我們將檢閱這些腳本的一些內容。

環境建立腳本

我們將探討的第一個腳本名為 New-AzureWebsiteEnv.ps1。 它會建立 Azure 環境,您可以部署修正 It 應用程式以進行測試。 此腳本執行的主要工作如下:

  • 建立 Web 應用程式。
  • 建立儲存體帳戶。 (Blob 和佇列的必要專案,如稍後章節所示。)
  • 建立SQL Database伺服器和兩個資料庫:應用程式資料庫和成員資格資料庫。
  • 在 Azure 中,應用程式將用來存取儲存體帳戶和資料庫的市集設定。
  • 建立將用來自動化部署的設定檔。

執行指令碼

注意

本章的這個部分會顯示腳本範例和您輸入的命令,以便執行這些腳本。 這是示範,不提供執行腳本所需的一切。 如需逐步操作說明指示,請參閱 附錄:修正範例應用程式

若要執行管理 Azure 服務的 PowerShell 腳本,您必須安裝 Azure PowerShell 主控台,並將其設定為使用 Azure 訂用帳戶。 設定好之後,您可以使用類似下列命令來執行修正 It 環境建立腳本:

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

參數 Name 會指定建立資料庫和儲存體帳戶時要使用的名稱,而 SqlDatabasePassword 參數會指定將針對 SQL Database 建立之系統管理員帳戶的密碼。 還有其他參數可供您稍後查看。

PowerShell 視窗

腳本完成之後,您可以在管理入口網站中看到已建立的內容。 您會找到兩個資料庫:

資料庫

儲存體帳戶:

儲存體帳戶

以及 Web 應用程式:

網站

在 Web 應用程式的 [ 設定 ] 索引標籤上,您可以看到它已設定儲存體帳戶設定,以及針對 [修正它] 應用程式設定的 SQL 資料庫連接字串。

appSettings 和 connectionStrings

Automation資料夾現在也包含< websitename.pubxml >檔案。 此檔案會儲存 MSBuild 將用來將應用程式部署至剛建立之 Azure 環境的設定。 例如:

<?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>

如您所見,腳本已建立完整的測試環境,而且整個程式大約會在 90 秒內完成。

如果小組上的其他人想要建立測試環境,他們可以直接執行腳本。 不僅快速,還可以確信其使用的環境與您所使用的環境相同。 您無法放心地使用管理入口網站 UI 手動設定專案。

查看腳本

實際上有三個腳本可以執行這項工作。 您從命令列呼叫其中一個,它會自動使用其他兩個來執行一些工作:

  • New-AzureWebSiteEnv.ps1 是主要腳本。

    • New-AzureStorage.ps1 會建立儲存體帳戶。
    • New-AzureSql.ps1 會建立資料庫。

主要腳本中的參數

主要腳本 New-AzureWebSiteEnv.ps1定義數個參數:

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

需要兩個參數:

  • 腳本所建立的 Web 應用程式名稱。 (這也適用于 URL: <name>.azurewebsites.net .)
  • 腳本所建立之資料庫伺服器之新系統管理使用者的密碼。

選擇性參數可讓您指定資料中心位置, (預設為 「美國西部」) 、資料庫伺服器系統管理員名稱 (預設為 「dbuser」) ,以及資料庫伺服器的防火牆規則。

建立 Web 應用程式

腳本執行的第一件事是呼叫 Cmdlet 來 New-AzureWebsite 建立 Web 應用程式,並傳入 Web 應用程式名稱和位置參數值:

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

建立儲存體帳戶

然後,主要腳本會執行 New-AzureStorage.ps1 腳本,並針對儲存體帳戶名稱指定 「* < websitename > *storage」,以及與 Web 應用程式相同的資料中心位置。

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

New-AzureStorage.ps1 呼叫 New-AzureStorageAccount Cmdlet 來建立儲存體帳戶,並傳回帳戶名稱和存取金鑰值。 應用程式需要這些值,才能存取儲存體帳戶中的 Blob 和佇列。

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

您可能不一定會想要建立新的儲存體帳戶;您可以藉由新增選擇性地將腳本導向至使用現有儲存體帳戶的參數來增強腳本。

建立資料庫

然後,主要腳本會在設定預設資料庫和防火牆規則名稱之後, 執行資料庫 建立腳本New-AzureSql.ps1:

$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

資料庫建立腳本會擷取開發電腦的 IP 位址,並設定防火牆規則,讓開發機器可以連線和管理伺服器。 然後,資料庫建立腳本會經歷數個步驟來設定資料庫:

  • 使用 New-AzureSqlDatabaseServer Cmdlet 建立伺服器。

    $databaseServer = New-AzureSqlDatabaseServer -AdministratorLogin $UserName -AdministratorLoginPassword $Password -Location $Location
    
  • 建立防火牆規則,讓開發電腦能夠管理伺服器,以及讓 Web 應用程式與其連線。

    # 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
    
  • 使用 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 是腳本中的函式,會呼叫 ConvertTo-SecureString Cmdlet 來加密密碼並傳回 物件,而 Cmdlet 傳回 PSCredential 的類型與 Cmdlet 所傳回的類型 Get-Credential 相同。

  • 使用 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
    
  • 呼叫本機定義的函式,為每個資料庫建立連接字串。 應用程式會使用這些連接字串來存取資料庫。

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

    Get-SQLAzureDatabaseConnectionString是腳本中定義的函式,可從提供給它的參數值建立連接字串。

    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;"
    }
    
  • 傳回具有資料庫伺服器名稱和連接字串的雜湊表。

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

修正 It 應用程式使用個別的成員資格和應用程式資料庫。 您也可以將成員資格和應用程式資料放在單一資料庫中。

儲存應用程式設定和連接字串

Azure 具有一項功能,可讓您儲存設定和連接字串,以在嘗試讀取 Web.config 檔案中的 或 connectionStrings 集合時,自動覆 appSettings 寫傳回給應用程式的內容。 這是在部署時套用 Web.config轉換的 替代方案。 如需詳細資訊,請參閱本電子書稍後 在 Azure 中儲存敏感性資料

環境建立腳本會儲存在 Azure 中,應用程式在 Azure 中執行時需要存取儲存體帳戶和資料庫的所有 appSettingsconnectionStrings 和 值。

# 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 是遙測架構,我們在 監視和遙測 一章中示範。 環境建立腳本也會重新開機 Web 應用程式,以確保它會挑選 New Relic 設定。

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

準備部署

在程式結束時,環境建立腳本會呼叫兩個函式來建立部署腳本將使用的檔案。

其中一個函式會 (websitename.pubxml > 檔案建立 <發行設定檔) 。 程式碼會呼叫 Azure REST API 以取得發佈設定,並將資訊儲存在 .publishsettings 檔案中。 然後,它會使用該檔案的資訊以及範本檔案 (pubxml.template) 來建立包含發行設定檔的 .pubxml 檔案。 這個雙步驟程式會模擬您在 Visual Studio 中執行的動作:下載 .publishsettings 檔案並匯入以建立發行設定檔。

另一個函式會使用另一個範本檔案 (website-environment.template) 來建立 website-environment.xml檔案, 其中包含部署腳本將搭配 .pubxml 檔案使用的設定。

疑難排解與錯誤處理

腳本就像程式一樣:它們可能會失敗,以及當您想要知道失敗和造成失敗的原因時。 基於這個理由,環境建立腳本會將 變數的值 VerbosePreferenceSilentlyContinue 變更為 Continue ,以便顯示所有詳細資訊訊息。 它也會將 變數的值 ErrorActionPreferenceContinue 變更為 Stop ,因此即使腳本遇到非終止錯誤,腳本也會停止:

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

在執行任何工作之前,腳本會儲存開始時間,以便計算完成的時間:

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

完成其工作之後,腳本會顯示經過的時間:

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

針對每個索引鍵作業,腳本會寫入詳細資訊訊息,例如:

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"

部署指令碼

New-AzureWebsiteEnv.ps1腳本用於環境建立的功能,Publish-AzureWebsite.ps1腳本會執行應用程式部署。

部署腳本會從環境建立腳本所建立 website-environment.xml 檔案取得 Web 應用程式的名稱。

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

它會從 .publishsettings 檔案取得部署使用者密碼:

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

它會執行 MSBuild 命令來建置和部署專案:

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

如果您已在命令列上指定 Launch 參數,它會呼叫 Show-AzureWebsite Cmdlet 以開啟預設瀏覽器至網站 URL。

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

您可以使用類似下列命令來執行部署腳本:

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

完成時,瀏覽器隨即開啟,並在 URL 的雲端 <websitename>.azurewebsites.net 中執行網站。

修正部署至 Windows Azure 的 It 應用程式

總結

使用這些腳本,您可以確信相同的步驟一律會使用相同的選項以相同循序執行。 這有助於確保小組上的每位開發人員不會錯過某些專案或雜亂專案,或是在自己的電腦上部署自訂專案,而無法在另一位小組成員的環境中或生產環境中實際運作相同的方式。

同樣地,您可以使用 REST API、Windows PowerShell腳本、.NET 語言 API 或可在 Linux 或 Mac 上執行的 Bash 公用程式,將您可以在管理入口網站中執行的大部分 Azure 管理功能自動化。

在下一章中,我們將探討原始程式碼,並說明為何在原始程式碼存放庫中包含您的腳本很重要。

資源