Skip to content

Latest commit

 

History

History
255 lines (228 loc) · 11.9 KB

8d1558a8a2127c.md

File metadata and controls

255 lines (228 loc) · 11.9 KB
title emoji type topics published published_at publication_name
[改良版] BicepでS2S VPN環境をAzure上でサクッと構築する
💪
tech
azure
iac
vpn
bicep
vnet
true
2023-04-06 14:06
microsoft

モチベ

  • 以前、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

https://github.com/zukakosan/bicep-s2svpn-bgp

moduleの活用

  • 最初はリソースの種類ごとにmodule化する方向で進めようとした(VMはvm.bicepで作る等)
  • ただ、module内で生成されるリソースのidはoutputsから取得する必要があったりで少し面倒だった
  • そして、今回は各VNetでデプロイするリソースが対称的になっている
    • つまり、各VNetをデプロイするBicepファイルを変数を変えれば流用できる
  • ということで、main-resources.bicepをmoduleとして、cloudInfra/onpInfraの両面を作成する形にした
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)できるようになる
output nsgId string = defaultNSG.id

"接続"のデプロイ

  • cloudInfra/onpInfraのデプロイが完了してからでないと接続リソースをデプロイできない
  • この例では、cloudInfra.outputs.vpngwIdによって暗黙的な依存関係があるためデプロイ順序がcloudInfraの後になる
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パラメータファイルが指定されていなければ、プロンプトで値の入力を求められる
param vmAdminUsername string
@secure()
param vmAdminPassword string
  • @secure()をつけていないとVisualStudio(恐らくBicep拡張機能)に怒られるため、つける

  • 結果、プロンプトへの入力の際に非表示の文字列として受け取ってくれる

パラメーターファイルの指定

  • インクリメンタルデプロイでBicepファイルを更新してデプロイするサイクルが想定されるのに、毎回デプロイするたびにパラメータ入力するのは面倒だよねという話
  • 自分の環境用のパラメーターファイルは.gitignoreで抜いていてGitHubにはparams-sample.jsonというサンプルファイルをpushしているので使いまわす際はそれをご参考に
{
    "$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をパラメータとして渡す
  • サービスプリンシパルを対象とする場合はprincipalTypeServicePrincipalにする必要があるため注意
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に対する明示的な依存関係を記述しておくと安全
//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ファイル的には使い続けられるということも意味する
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する可能性があるため注意
    • 何も依存がなければ作成削除になるはず?(未確認)

:::message ※上記確認した Bicepのデプロイモードは以下の二種類

  • Increment(既定)
    • このモードの場合増分更新となる
    • リソースIDが異なるリソースについては、増分とみなされ新規で作成される
    • Bicepファイルの中でリソース名を変えた場合、新規でリソースが立つが既存リソースの削除はされない
    • なので、例えばVM名を変更した場合、関連するNICとかDiskとかが既存VMにアタッチされたままになるためエラー終了する
  • Complete
    • 常にBicepファイルの中身と完全一致するように動く
    • 既存リソースがテンプレートにあれば更新、なければ削除する :::

おわり

  • 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も両側の拠点のリージョン用にそれぞれ作成するよう変更。詳しくはソースコードを参照されたい。