使用參數和變數來增加彈性
範本的強大之處在於其可重複使用。 您可以使用 Bicep 來撰寫範本,以部署多個環境或資源的複本。
您任職的玩具公司會定期推出新產品,而您必須使用 Bicep 範本來建立每此推出產品時所需要的 Azure 資源。 您必須避免使用固定的資源名稱。 許多種 Azure 資源都需要唯一名稱,在範本中內嵌名稱意味著不能重複使用範本來多次推出產品。 您也必須根據玩具將在哪個市場推出而在不同的位置部署資源,所以您無法在範本中內嵌資源位置。
在此單元中,您將了解參數和變數,這兩個 Bicep 功能可讓您的範本富有彈性並可重複使用。 我們也會向您介紹運算式。
注意
本單元中的命令僅用於示範概念。 請先不要執行命令。 您很快就會在此練習所學到的內容。
參數和變數
「參數」可讓您帶進範本檔案外面的值。 例如,如果您使用 Azure CLI 或 Azure PowerShell 以手動方式部署範本,系統會要求您提供每個參數的值。 您也可以建立參數檔案,以列出所有要在部署中使用的參數和值。 如果透過自動化程序 (例如部署管線) 來部署範本,則管線可以提供參數值。
變數會在範本內加以定義並設定。 變數可讓您集中儲存重要資訊,供整個範本參考,而不需要複製並貼上。
針對在每個部署之間會有所改變的項目,使用參數通常是最好的辦法,例如:
- 需要唯一的資源名稱。
- 部署資源的位置。
- 會影響資源定價的設定,例如其 SKU、定價層和執行個體計數。
- 要存取範本中未定義的其他系統所需要有的認證和資訊。
如果您會針對每個部署使用相同的值,但又想要讓某個值可在範本內重複使用,或是想要使用運算式來建立複雜的值,那麼變數通常是不錯的選項。 您也可以針對不需要唯一名稱的資源使用變數。
提示
請務必妥善地為參數和變數命名,以讓範本變得容易閱讀和理解。 請務必使用清楚、具描述能力且一致的名稱。
新增參數
在 Bicep 中,您可以如下所示地定義參數:
param appServiceAppName string
讓我們看看這項定義的每個部分如何運作:
param
會告訴 Bicep 您要定義參數。appServiceAppName
是參數的名稱。 如果您以手動方式部署範本,系統可能會要求您輸入值,因此請務必提供清楚且容易理解的名稱。 和資源符號名稱一樣,您也可以透過名稱在範本內參照參數值。string
是參數的類型。 您可以為 Bicep 參數指定數種不同的類型,包括string
(用於文字)、int
(用於數字) 以及bool
(用於布林值的 true 或 false 值)。 您也可以使用array
和object
類型來傳入更複雜的參數。
提示
請勿嘗試使用太多參數來將範本過度地一般化。 應該盡可能減少商務案例所需的參數。 請記住,如果將來需求變更,您隨時都可以變更範本。
提供預設值
您可以選擇性地為參數提供預設值。 當您指定預設值時,參數會變成選擇性。 部署範本的人員可以按照需要指定某個值,如果他們不需要,Bicep 會使用預設值。
以下是新增預設值的方法:
param appServiceAppName string = 'toy-product-launch-1'
注意
在此範例中,Azure App Service 應用程式名稱有硬式編碼的預設值。 這種做法不好,因為 App Service 應用程式需要唯一的名稱。 您很快就會修正此問題。
在範本中使用參數值
宣告參數之後,便可在範本的其餘部分參照該參數。 讓我們看看如何在資源定義中使用新的參數:
resource appServiceApp 'Microsoft.Web/sites@2023-12-01' = {
name: appServiceAppName
location: 'eastus'
properties: {
serverFarmId: appServicePlan.id
httpsOnly: true
}
}
請注意,範本現在會使用參數值來設定應用程式資源的資源名稱,而不是硬式編碼值。
提示
Visual Studio Code 的 Bicep 延伸模組顯示視覺指標,告知您未遵循建議的做法。 例如,警告您定義的參數沒有用到。 Bicep Linter 在您工作時持續執行這些檢查。
新增變數
您可以如下所示地定義變數:
var appServicePlanName = 'toy-product-launch-plan'
變數的定義方式類似參數,但有一些差異:
- 使用
var
關鍵字來告訴 Bicep 您要宣告的是變數。 - 您必須為變數提供值。
- 變數不需要類型。 Bicep 可以根據您所設定的值來決定類型。
運算式
撰寫範本時,通常不建議將值硬式編碼,甚至連在參數中指定也不建議。 相反地,您會想要在範本執行時再探索值。 例如,或許可以將範本中的所有資源部署至單一 Azure 區域,亦即已建立資源群組的區域。 或者,可根據公司採用的特定命名策略,自動為資源建立唯一名稱。
Bicep 中的運算式是威力強大的功能,可協助您處理各種有趣的案例。 讓我們看看您可以在 Bicep 範本中使用運算式的幾個地方。
資源位置
當您在撰寫和部署範本時,您通常不會想要個別指定每個資源的位置。 相反地,您可能有一個簡單的商務規則指出:預設將所有資源部署至建立資源群組的同一個位置。
在 Bicep 中,您可以建立名為 location
的參數,然後使用運算式來設定值:
param location string = resourceGroup().location
看一下該參數的預設值。 使用名為 resourceGroup()
的函式,針對要部署範本的資源群組,可讓您存取其相關資訊。 在此範例中,範本會使用 location
屬性。 通常以此方法將資源部署至資源群組所在的同一個 Azure 區域。
如果有人要部署此範本,其可能會選擇覆寫此處的預設值,並使用不同的位置。
注意
Azure 中的某些資源只能部署至特定位置。 您可能需要不同的參數來設定這些資源的位置。
您現在可以在範本內使用資源位置參數,如下所示:
resource appServiceApp 'Microsoft.Web/sites@2023-12-01' = {
name: appServiceAppName
location: location
properties: {
serverFarmId: appServicePlan.id
httpsOnly: true
}
}
資源名稱
許多 Azure 資源都需要唯一的名稱。 在您的案例中,您有兩個需要唯一名稱的資源:儲存體帳戶和 App Service 應用程式。 要求將這些值設定為參數會讓其他人難以使用該範本,因為他們需要找出其他人未用過的名稱。
Bicep 有另一個名為 uniqueString()
的函式可在您建立資源名稱時派上用場。 使用此函式時,您必須提供種子值,其在不同的部署上應該不同,但對相同資源的所有部署則必須一致。
如果您選擇良好的種子值,則每次部署相同的資源集時,都可以取得相同的名稱,但只要使用相同的範本部署不同的資源集,您就會得到不同的名稱。 讓我們看看要如何使用 uniqueString()
函式:
param storageAccountName string = uniqueString(resourceGroup().id)
這個參數的預設值會再次使用 resourceGroup()
函式,就和您在設定資源位置時所做的一樣。 不過,這次您會得到資源群組的識別碼。 資源群組識別碼的樣貌如下:
/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/MyResourceGroup
資源群組識別碼包含 Azure 訂用帳戶識別碼 (aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e
) 和資源群組名稱 (MyResourceGroup
)。 資源群組識別碼通常適合作為資源名稱的候選種子值,原因如下:
- 每次您部署相同的資源時,資源都會進入相同的資源群組。
uniqueString()
函式每次都傳回相同的值。 - 如果部署至 Azure 訂用帳戶中的兩個不同資源群組,因為資源群組名稱不同,
resourceGroup().id
值也會不同。uniqueString()
函式給予每一組資源的值都不同。 - 如果您部署至兩個不同的 Azure 訂用帳戶,即使您使用相同的資源群組名稱,
resourceGroup().id
值仍會不同,因為 Azure 訂用帳戶識別碼將會不同。 同樣地,uniqueString()
函式給予每一組資源的值都不同。
提示
使用範本運算式來建立資源名稱通常是不錯的做法。 許多 Azure 資源類型都有關於允許的字元和其名稱長度的規則。 在範本中內嵌資源名稱建立,表示使用該範本的任何人都不必自己記得遵循這些規則。
合併的字串
如果 uniqueString()
函式只用來設定資源名稱,雖然可能得到唯一名稱,但沒有意義。 好的資源名稱也應該有描述能力,能夠清楚說明資源的用途。 您通常可以藉由將有意義的字組或字串與唯一值相結合,來建立名稱。 如此一來,您就會擁有既有意義又是唯一的資源名稱。
Bicep 有一個稱為字串插補的功能可讓您合併字串。 讓我們看看其運作方式:
param storageAccountName string = 'toylaunch${uniqueString(resourceGroup().id)}'
storageAccountName
參數的預設值現在有兩個部分:
toylaunch
是硬式編碼的字串,可協助任何人在查看 Azure 中已部署的資源時,能夠了解此儲存體帳戶的用途。${uniqueString(resourceGroup().id)}
可指示 Bicep 評估uniqueString(resourceGroup().id)
函式的輸出,然後串連成字串。
提示
有時 uniqueString()
函式會建立開頭為數字的字串。 某些 Azure 資源 (例如儲存體帳戶) 不允許名稱開頭為數字。 這表示使用字串插補來建立資源名稱 (如上述範例所示) 會是不錯的做法。
選取資源的 SKU
您小組內的其他成員非常滿意您到目前為止所建置的 Bicep 程式碼。 您已決定使用範本來部署資源,以支援所有新玩具的推出。
有一位同事建議您在每次產品推出之前建立非生產環境,以協助行銷小組測試網站,之後再開放給客戶。 不過,您想要確保您們不會在非生產環境上面支出太多費用,因此您一起決定一些原則:
- 在生產環境中,儲存體帳戶以
Standard_GRS
(異地備援儲存體) SKU 部署,復原能力較高。 App Service 方案以P2v3
SKU 部署,效能較高。 - 在非生產環境中,儲存體帳戶將會部署在
Standard_LRS
(本地備援儲存體) SKU。 App Service 方案將會部署在免費的F1
SKU。
實作這些商務需求的其中一種方式是使用參數來指定每個 SKU。 但是,將每個 SKU 指定為參數可能會變得難以管理,尤其是當您的範本較大時。 另一個選項是使用參數、變數和運算式的組合,將商務規則內嵌到範本中。
首先,您可以指定參數來指出部署適用於生產還是非生產環境:
@allowed([
'nonprod'
'prod'
])
param environmentType string
請注意,此程式碼會使用一些新的語法來指定 environmentType
參數的允許值清單。 除非提供上述其中一個值,否則 Bicep 不會讓任何人部署範本。
接下來,您可以建立變數來根據環境決定要用於儲存體帳戶和 App Service 方案的 SKU:
var storageAccountSkuName = (environmentType == 'prod') ? 'Standard_GRS' : 'Standard_LRS'
var appServicePlanSkuName = (environmentType == 'prod') ? 'P2V3' : 'F1'
也請注意這裡的一些新語法。 讓我們將其拆解:
(environmentType == 'prod')
會評估為布林值 (true 或 false) 值,視允許用於environmentType
參數的值而定。?
稱為三元運算子,其會評估if/then
陳述式。 如果運算式為 true,則會使用?
運算子後面的值。 如果運算式評估為 false,則會使用冒號 (:
) 後面的值。
我們可以將這些規則轉譯為:
- 針對
storageAccountSkuName
變數,如果environmentType
參數設定為prod
,則使用Standard_GRS
SKU。 否則,會使用Standard_LRS
SKU。 - 針對
appServicePlanSkuName
變數,如果environmentType
參數設定為prod
,則使用P2V3
SKU 和PremiumV3
階層。 否則,會使用F1
SKU。
提示
當您建立和這個範例一樣有多個部分的運算式時,最好使用變數而不是直接將運算式內嵌至資源屬性。 這可讓範本變得更容易閱讀和理解,因為其會透過邏輯避免資源定義變得雜亂。
當您在範本中使用參數、變數和運算式時,您可以重複使用範本並且快速部署新的資源集。 例如,每當行銷部門要求您為下次推出的玩具部署新網站時,您會為部署的每個環境提供新的參數值,這樣就準備妥當了!