Bicep触ってみる(準備~VNETデプロイ)
note書くの久しぶりになってしまったけど、冬休みの自由研究で調べたことをちょっとまとめておきたいのでnoteで書く。内容的にはQiitaでもいいのかもしれないけれど、整理せずに書き散らすならこっちかな。
という訳でBicepを触っていく。
Bicepとは?
このページをCopilot with Bing Chatで要約してもらったのがこちら。
このページは、BicepというAzure Resource Managerの代替言語について紹介しています。Bicepは、宣言的なコードでAzureリソースを作成・管理するためのシンプルで直感的な言語です。Bicepは、ARMテンプレートと完全に互換性があり、VS CodeやAzure CLIなどのツールでサポートされています。
Azure Resource Manager (ARM)では、ARMテンプレートと呼ばれるJSON形式で書かれたファイルを投げてやることで、ARMテンプレートに書かれた状態のリソースを作ってくれるのですが、これがVM1つ作りたいだけでも項目が多く、正直取っつきにくい。
そんなARMテンプレートの代わりにシンプルに書けるようにしたよ、というのがBicepらしいです。宣言型のコードでべき等性があるとのこと。
始める前に
ツール群をインストールする。
Windows PCを使っているのでAzureとのやり取りはAzure Powershellを使うことにする。
Bicepファイルの作成にはVisual Studio Code (VS Code) を使う。VS CodeにはBicep拡張機能をインストールしておく。
Bicepファイルを作成する
Bicepファイルの拡張子は「bicep」とのこと。変な拡張子だと「どれだっけ?」ってならないのがいい。
特に考えず「main.bicep」として作成し、VS Codeで開く。拡張機能を使うためにワークスペースを信頼しておく。
何を作るか考える
Azure環境は既にあるとして、とりあえず新しいリソースグループと仮想ネットワークを作ってみよう。そんなに大規模にするつもりはないけど、仮想ネットワークはハブスポークモデル想定にしておこう。
リソースグループ
・名前:rg-biceptest-01
仮想ネットワーク①
・名前:vnet-hub-01
・範囲:172.16.0.0/16
・サブネット①:snet-step-01
・範囲:172.16.0.0/24
・サブネット②:AzureBastionSubnet
・範囲:172.16.1.0/24
・サブネット③:GatewaySubnet
・範囲:172.16.2.0/24
仮想ネットワーク②
・名前:vnet-spoke-01
・範囲:172.17.0.0/16
・サブネット①:snet-webapp-01
・範囲:172.17.0.0/24
仮想ネットワーク①と②はピアリングする
・peer名はテキトー、設定もデフォルトで
今日はこんな感じで。
Bicepを書いていく
VS Codeに拡張機能入れてると「vnet」とか入れるだけでフォーマットを補完してくれる。もう当たり前の機能だけど、やっぱり長々と写経しなくてもいいのは便利。


補完を使いながらざっと作成。locationは何度も出てくるので変数にしてみた。下記の3点は不安要素。
①リソースグループが有効なタイプじゃないと怒られている(クイックスタートでもリソースグループは先に作っていた)
②仮想ネットワークリソース内でリソースグループを指定してない(上と関連、Bicep内ではリソースグループが作れず同一リソースグループの中に作ることになりそう)
③ピアリングの仮想ネットワーク指定方法が合ってるか分からない
param location string = 'japaneast'
resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = {
name: 'rg-biceptest-01'
location: location
}
resource hubvnet 'Microsoft.Network/virtualNetworks@2019-11-01' = {
name: 'vnet-hub-01'
location: location
properties: {
addressSpace: {
addressPrefixes: [
'172.16.0.0/16'
]
}
subnets: [
{
name: 'snet-step-01'
properties: {
addressPrefix: '172.16.0.0/24'
}
}
{
name: 'AzureBastionSubnet'
properties: {
addressPrefix: '172.16.1.0/24'
}
}
{
name: 'GatewaySubnet'
properties: {
addressPrefix: '172.16.2.0/24'
}
}
]
}
}
resource spokevnet01 'Microsoft.Network/virtualNetworks@2019-11-01' = {
name: 'vnet-spoke-01'
location: location
properties: {
addressSpace: {
addressPrefixes: [
'172.17.0.0/16'
]
}
subnets: [
{
name: 'snet-webapp-01'
properties: {
addressPrefix: '172.17.0.0/24'
}
}
]
}
}
resource peer_hub2spoke 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2020-07-01' = {
name: hubvnet.name
properties: {
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: true
useRemoteGateways: true
remoteVirtualNetwork: {
id: spokevnet01.id
}
}
}
resource peer_spoke2hub 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2020-07-01' = {
name: spokevnet01.name
properties: {
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: true
useRemoteGateways: true
remoteVirtualNetwork: {
id: hubvnet.id
}
}
}
不安要素を潰す
①はBicepのスコープが既定ではリソースグループだから。リソースグループの中でガチャガチャやるよって言ってるのにいきなりリソースグループ作り始めるとそれは怒られるだろう。
こちらを見ると下記を頭に書けばスコープをサブスクリプションに広げることはできるが、そのBicepファイル内でリソースグループの中のリソースは作成できず、モジュールとして別のBicepファイルを追加する必要があるようだ。ということで、リソースグループの作成は手動でやることにして、仮想ネットワーク絡みだけ作ることにしよう。
3行目~6行目を削除する。
targetScope = 'subscription'
リソースグループ内に閉じた話ということで②も解決。
③はエラー吐いてないのでたぶん大丈夫なんだけど、一応調べてみるとあってそう。このまま行きましょう。
Azureにデプロイしてみる
VS Codeから直接デプロイできるらしい。右クリックメニューの「Deploy Bicep File…」を選択して、あとは流れでお願いします。




(testとかは私の既存のリソースグループ)

リージョンを選択(2/2)

トラブルシューティング
悲しいことにエラーが出たのでトラブルシューティングする。
1つ目はピアリングリソースのセグメントの長さがおかしいとのこと。
なんだセグメントって」と思いながらリファレンスを見るとparentを指定してないことが分かった。res-vnet-peeringで補完したテンプレートに必須項目無いこともあるのか・・・
また、ここでピアリング名=仮想ネットワーク名になっていることに気付き修正する。下記の2行目と3行目のところ。
resource peer_hub2spoke 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2020-07-01' = {
name: 'peer_hub2spoke'
parent: hubvnet
properties: {
:
}
}
もう一度デプロイするとまたエラー。今度はフラグが駄目らしい。確かに「相手側のゲートウェイを使用する」設定が両方trueになってるのはおかしいな。ポータルから作成する時のデフォルト設定に従って「allowGatewayTransit」と「useRemoteGateways」をfalseにする。
本当は適切にtrue/falseを選択しましょう。
完了・確認
「Deployment succeeded」が出たら成功です。ファイル名とかサブスクリプションIDとか色々マスクするのが面倒なので全体のキャプチャは無し。

ポータル上でもリソースが出来ていることを確認していきます。



ちゃんとできてますね。
まとめ
Bicepで仮想ネットワークを作成した。VS Codeの拡張機能により、作成段階から補完などの支援があり直接デプロイすることもできるため、容易に開発できた。
次はサブスクリプションをスコープとして、モジュール化に取り組んでみたい。
コード
今日の最終版。上記から省いたが、タイミングの問題なのか「ピアリング先のリソースが無いよ!」と作成に失敗しており、べき等性を信じて再デプロイをしたところ「ピアリング情報を変更したいならAPIバージョンを2021-01-01以降に上げろ!」と怒られたので、APIバージョンを変更している。
明確に親子のリソースなので構築順を意識してくれると思ったのだが、ピアリングに関してはどうもそうではないらしいという点はマイナスポイントかな。「これは後から作成する」といった方法があるかは今後確認したい。
param location string = 'japaneast'
resource hubvnet 'Microsoft.Network/virtualNetworks@2021-01-01' = {
name: 'vnet-hub-01'
location: location
properties: {
addressSpace: {
addressPrefixes: [
'172.16.0.0/16'
]
}
subnets: [
{
name: 'snet-step-01'
properties: {
addressPrefix: '172.16.0.0/24'
}
}
{
name: 'AzureBastionSubnet'
properties: {
addressPrefix: '172.16.1.0/24'
}
}
{
name: 'GatewaySubnet'
properties: {
addressPrefix: '172.16.2.0/24'
}
}
]
}
}
resource spokevnet01 'Microsoft.Network/virtualNetworks@2021-01-01' = {
name: 'vnet-spoke-01'
location: location
properties: {
addressSpace: {
addressPrefixes: [
'172.17.0.0/16'
]
}
subnets: [
{
name: 'snet-webapp-01'
properties: {
addressPrefix: '172.17.0.0/24'
}
}
]
}
}
resource peer_hub2spoke 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2021-01-01' = {
name: 'peer_hub2spoke'
parent: hubvnet
properties: {
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: false
remoteVirtualNetwork: {
id: spokevnet01.id
}
}
}
resource peer_spoke2hub 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2021-01-01' = {
name: 'peer_spoke2hub'
parent: spokevnet01
properties: {
allowVirtualNetworkAccess: true
allowForwardedTraffic: true
allowGatewayTransit: false
useRemoteGateways: false
remoteVirtualNetwork: {
id: hubvnet.id
}
}
}