💪
[改良版] BicepでS2S VPN環境をAzure上でサクッと構築する
モチベ
- 以前、S2SVPN環境を1つのBicepファイルでデプロイできるようにした記事を書いた
- それはそれとしてかなり検証に役に立っていたが、いろいろと不満はあった
- Bicepの魅力でもあるmoduleを活用できていないこと
- 作成しているパブリックIPがゾーン対応のものになっており、付随してVPN GatewayのSKUをAZのものにしなければいけなかったこと
- VMの管理者名/パスワードがBicepファイルの中にべた書きになっていたこと
- 命名規則が定まっていなかったこと
- つまり、"とりあえず動くもの"から"リファレンスとして使えるもの"にしたい
- (社内の重鎮にありがたみを説いてもらってモチベが上がっているうちにやりたい)
やっていく
変更点
- 前提としてファイル構成はこんな感じ
bicep-s2svpn-bgp/
├ main.bicep
├ modules/
├ main-resources.bicep
├ nsg.bicep
├ rbac-contribution.bicep
- Source Code
moduleの活用
- 最初はリソースの種類ごとにmodule化する方向で進めようとした(VMはvm.bicepで作る等)
- ただ、module内で生成されるリソースのidはoutputsから取得する必要があったりで少し面倒だった
- そして、今回は各VNetでデプロイするリソースが対称的になっている
- つまり、各VNetをデプロイするBicepファイルを変数を変えれば流用できる
- ということで、main-resources.bicepをmoduleとして、cloudInfra/onpInfraの両面を作成する形にした
main.bicep
module cloudInfra './modules/main-resources.bicep' = {
name: 'cloudInfra'
params: {
location: location
nsgId: defaultNSG.outputs.nsgId
vnetName: 'vnet-cloud'
vpngwName: 'vpngw-cloud'
vnetAddressPrefix: '10.0.0.0/16'
gatewaySubnetAddressPrefix: '10.0.0.0/24'
subnet1AddressPrefix: '10.0.1.0/24'
asn: 65010
vmName: 'ubuntu-cloud'
vmAdminUsername: vmAdminUsername
vmAdminPassword: vmAdminPassword
}
}
module onpInfra './modules/main-resources.bicep' = {
name: 'onpInfra'
params: {
location: location
nsgId: defaultNSG.outputs.nsgId
vnetName: 'vnet-onp'
vpngwName: 'vpngw-onp'
vnetAddressPrefix: '10.100.0.0/16'
gatewaySubnetAddressPrefix: '10.100.0.0/24'
subnet1AddressPrefix: '10.100.1.0/24'
asn: 65020
vmName: 'ubuntu-onp'
vmAdminUsername: vmAdminUsername
vmAdminPassword: vmAdminPassword
}
}
main.bicepとmoduleの値の受け渡し
- 今回はオンプレ・クラウドで利用する共通のNSGはmodule化しているため、その他のmoduleのパラメータとして直接Resourceを参照することができない
- その場合は、module側で
output
を記述しておくことで呼び出し元から参照(xxx.outputs.yyy
)できるようになる
nsg.bicep
output nsgId string = defaultNSG.id
"接続"のデプロイ
- cloudInfra/onpInfraのデプロイが完了してからでないと
接続
リソースをデプロイできない - この例では、
cloudInfra.outputs.vpngwId
によって暗黙的な依存関係があるためデプロイ順序がcloudInfraの後になる
main.bicep
resource conncetionCloudtoOnp 'Microsoft.Network/connections@2020-11-01' = {
name: 'fromCloudtoOnp'
location: location
properties: {
enableBgp: true
virtualNetworkGateway1: {
id: cloudInfra.outputs.vpngwId
properties:{}
}
localNetworkGateway2: {
id: onpInfra.outputs.lngId
properties:{}
}
connectionType: 'IPsec'
routingWeight: 0
sharedKey: 'zukako'
}
}
module化によるデプロイの分割
- main.bicepで呼び出すmoduleごとにデプロイ名をつけることができ、それぞれに対するデプロイが作成されるため、デプロイ状況が把握しやすいという(副次的な)メリットにも気づいた
パラメータ指定
- 以前のBicepでは、VMの管理者ユーザ名とパスワードをべた書きしており、セキュリティ的に明らかによろしくない状態だったため、そこをパラメータ化することでデプロイ時に指定できるようにした
- ちなみにべた書きした状態でデプロイしようとすると警告が出る
adminusername-should-not-be-literal: Property 'adminUserName' should not use a literal value. Use a param instead.
- 下記のように記述すると、Bicepファイル内で値が代入されていないorパラメータファイルが指定されていなければ、プロンプトで値の入力を求められる
main.bicep
param vmAdminUsername string
@secure()
param vmAdminPassword string
-
@secure()
をつけていないとVisualStudio(恐らくBicep拡張機能)に怒られるため、つける -
結果、プロンプトへの入力の際に非表示の文字列として受け取ってくれる
パラメーターファイルの指定
- インクリメンタルデプロイでBicepファイルを更新してデプロイするサイクルが想定されるのに、毎回デプロイするたびにパラメータ入力するのは面倒だよねという話
- 自分の環境用のパラメーターファイルは
.gitignore
で抜いていてGitHubにはparams-sample.json
というサンプルファイルをpushしているので使いまわす際はそれをご参考に
params-sample.json
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"value": "japaneast"
},
"vmAdminUsername": {
"value": "azureuser"
},
"vmAdminPassword": {
"value": "P@ssw0rd"
},
"principalId": {
"value": "<YOUR-USER-OBJECT-ID>"
}
}
}
RBACロールの付与
- BicepではRBACロールも作成・付与可能
- 今回は共同作成者ロールを対象のリソースグループレベルで付与するパートを追加
- 利用の際は、パラメータとして対象ユーザもしくはサービスプリンシパルのオブジェクトIDをパラメータとして渡す
- サービスプリンシパルを対象とする場合は
principalType
をServicePrincipal
にする必要があるため注意
rbac-contribution.bicep
resource roleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = {
scope: resourceGroup()
name: guid(resourceGroup().id, principalId, contributorRoleDefinition.id)
properties: {
roleDefinitionId: contributorRoleDefinition.id
principalId: principalId
principalType: 'User'
}
}
- 今回は、リソースグループをスコープとしているのであまり意味はないが、リソースレベルでRBACを付与する可能性を考慮し、cloudInfra/onpInfraに対する明示的な依存関係を記述しておくと安全
main.bicep
//contribution role to this resource group
module roleAssignment './modules/rbac-contribution.bicep' = {
name: 'roleAssignment'
params: {
principalId: principalId
}
dependsOn: [
cloudInfra
onpInfra
]
}
StandardのパブリックIPがゾーン対応になってしまう問題の解決
- 以前は、ゾーンを指定せずデプロイしたパブリックIPがゾーン対応になっており、それを利用するVPN GatewayもAZ対応のSKUにしなくてはならないという問題があった
- 結果、APIのバージョン(下記スニペットの
@2022-07-01
部分)を変更することで既定の動作が変わったようで、ゾーン対応ではなくなった - ここのバージョンを変更するだけで異なるAPIを叩けるのも分かり易くて良い
- つまり、ここのバージョンが"ディスコン"にならない限りはBicepファイル的には使い続けられるということも意味する
main-resources.bicep
resource vpngwPublicIP 'Microsoft.Network/publicIPAddresses@2022-07-01' = {
name: 'pip-${vpngwName}'
// name: 'sample-gw-pip'
location: location
sku: {
name: 'Standard'
}
properties: {
publicIPAllocationMethod: 'Static'
}
}
命名規則
- 個人的にはリソース名のPrefixとしてリソースの種類を持ってくるのが気分
- Azure Portalでリソースグループを見た時にどのリソースがどれくらいいるのかが(ソートの機能を使わなくても)ソートされていて見やすい(気がする)
Bicepのデプロイモード
- デプロイ時間を考慮しても既定がIncrementであることが分かる
- onpInfra/cloudInfraにはVPN Gateway(通常20分程度かかる)のデプロイが含まれているので、再デプロイでこの時間になるはずがない
- 構成変更のないリソースは読み飛ばしてくれる
- この変更検知はリソースIDをベースとしているはずなので、リソース名の変更などの処理が走る場合はそれに依存しているリソースとConflictする可能性があるため注意
何も依存がなければ作成削除になるはず?(未確認)
おわり
- Bicep拡張機能とGitHub Copilotがあるととにかく楽!まじで。
- ただ、GitHub Copilotのウソに気付くためのAzureの知識やデプロイの依存関係の把握、トラシューのための技術力は依然として求められるスキルであると認識
- そんなGitHub Copilotのウソも構文的な正しさはBicep拡張機能が見張っていてくれるのでさほど苦ではない
- Bicepがんばろー!
20230817追記
リソース名について
- 従属リソースは例外として扱うように変更。例えばVPNGatewayが
vpngw-onp
という名前の場合そのVPNGatewayに利用するPublic IPの名前はvpngw-onp-pip
といった形でリソース名を後付けする
Bicepファイルの更新について
- 本日新しいバージョンを当該GitHubリポジトリに展開済み。主な変更点としてはS2SVPNを構築する両端のリージョンを同一リージョンだけでなくクロスリージョンでも構成できるようにした。よって、パラメータファイル上は
locationSite1
およびlocationSite2
という変数でそれぞれの拠点のリージョンを渡す必要がある。 - またこれに伴って、NSGも両側の拠点のリージョン用にそれぞれ作成するよう変更。詳しくはソースコードを参照されたい。
GitHubで編集を提案
Discussion