normalian blog

Let's talk about Microsoft Azure, ASP.NET and Java!

Update Management Center (Preview) を試す

今回は現時点(2022年11月)では Preview が取れていませんが、今後は重要度が増すであろう Update Management Center について紹介したいと思います。事前に以下のページ位は斜め読みをすると理解が早いのではと思います。
learn.microsoft.com

Update Management Center は OS のセキュリティパッチの適用をコントロールすることができるクラウドサービスですが、個人的に Update Management Center が非常にイケていると思っているところは主に二点です。

  • Windows だけでなく Linux 側も含め一括で制御可能
  • Azure Arc と連携することで Azure や on-premise のみならず AWSGCP 等の Azure 外部のプラットフォームについても制御可能

上記で何が嬉しくなるかというと SIer 各位の頭痛の種である Excel 表でのサーバ情報のマスター管理からの解放 という点が挙げられると思います。運用手順等で管理をしていたとしても人間が手作業で行う以上はミスや抜け漏れが発生するものです。Update Management Center を活用することでサービス全体の各マシンの状況が一括で確認できるようになります。

管理画面のトップページとしては以下となります。管理対象マシンが何台あるか、どのマシンにどのパッチが当たっていないか、パッチ適用の実施状況、Windows/Linux で適用されていないパッチの一覧等が表示されます。

Azure Automation の Update Management との違いは?

Azure 歴の長い方は「Azure Automation の Update Management があるじゃないか」とお気づきの方もいらっしゃると思いますが、Azure Automation とは以下の明示的な差が存在します。

  • Azure Automation の Update Management は別途 Azure Automation をリソースとして作成する必要があるが、Update Management Center は組み込み機能
  • Supported regions for linked Log Analytics workspace | Microsoft Learn Log Analytics workspace を Linked workspace として作成する必要があり、Azure Automation リソースの作成場所に制限があった(日本なら Japan East に作って東西の VM リソースを繋げば良いという話はありますが

イメージとして「Update Management Center」は 「Azure Automation の Update Management」の後継という捉え方をすれば祖語はない認識です。今までは Azure Automation のリソース管理や Log Analytics エージェントのインストール(Azure Automation で仮想マシン等を操作するために必要)等の追加の対応が必要でしたが、Update Management Center は特別な処理をせずに利用可能となります。

Update Management Center を使う場合のデメリットは?

逆に Update Management Center を利用する場合のデメリットをあえて考えてみたいと思います。ざっと以下のサポートマリックスを確認しました。

Windows 側はほぼ差がない認識ですが、例えば Cent OS, RHEL, Oracle Linux の場合に Update Management Center 側は v6 に対応していない(Azure Automation 側は対応)点、Ubuntu では v14 に対応していない点が挙げられます。
また、現時点ではプレビューだということもありますが、現時点ではサポートされているリージョンに日本が含まれていません(もっとも近い場所は東南アジア)。

外部ベンダーが提供するサービスをサポート有&追加構築無しの利用を夢見る女子高生な方々にとって、サポート無かつ日本リージョンでスケーリングされない(日本から利用できないというわけでなく Update Management Center の内部リソースは現時点では日本に展開されないの意)現状での利用は門限破りの朝帰り位の覚悟を要するのではという感覚です。

Update Management Center 自体を有効化するには

上記の通り Azure にとっては組み込みサービスなので、利用の開始自体に特に必要な処理はありません。。。。と言いたいところですが、現時点ではプレビューなこともあり以下の記事に従ってリソースプロバイダの有効化を行ってください。
learn.microsoft.com

az login
az account set --subscription "your subscription id"
az feature register --namespace Microsoft.Compute --name InGuestAutoAssessmentVMPreview
az feature show --namespace Microsoft.Compute --name InGuestAutoAssessmentVMPreview

上記のリソースプロバイダ登録に10分程度かかると思いますが、以下の様に az feature show で Status が registered になるまで随時確認してください。

Update Management Center を実際に利用する

トップ画面から Machines のタブをクリックすると以下の様に管理対象のマシンが表示されます。こちらの一覧に追加するのに特別な手順は不要です。Azure の仮想マシンなら自動的にこの一覧に加えられ、Azure 外部のマシンは Azure Arc を有効化することで一覧に加えられます。

画面で確認できる通り、Update Status の箇所で「更新パッチを全て適用済/X個のパッチが未適用/アセスメントが未実施」の三種類となります。アセスメントが実施されていない登録直後のマシンに対しては No updates data で表示されるので、最初に実施するのはアセスメントとなります。

アセスメントは以下の様にマシンを選択して Check for updates を実施することでアセスメントを手動で実行可能です。

当然以下の様に定期的なアセスメントを実施する設定も可能です。24時間ごとにパッチ適用の状況をチェックします。Enable periodic assessment using policy | Microsoft Learn の様に Azure Policy との併用も可能です。

アセスメント実施後は未適用のパッチ数が表示されるので、再度対象マシンを選んで One-Time update を選択しましょう。

次に適用パッチを選びます。こちらについては Windows/Linux を一括で選択できるようになった点が Azure Automation との大きな差と言えるかもしれません。適用対象パッチを細かく選択できる点は Azure Automation 側と同様です。

最後に、以下の様に再起動の条件を設定することで更新パッチの適用が行われます。

パッチ適用を実施後、画面左の history タブを選択することで以下の様にプロセスの状況を確認できます。

パッチ適用中の場合は InProgress となりますが、それ以外にも成功・失敗が確認できます。また、操作内容がアセスメント・パッチ適用なのか、手動操作か定期実行操作か等が確認できます。

今回は簡単な概要紹介をさせて頂きましたが、今後は Azure 外部も含めたマシンの更新管理で重宝される機能だと思われるので、是非お試しください。

Azure Blob Storage に SFTP でアクセスする - 閉域網版

前回の記事で Azure Storage に対して SFTP でアクセスするところまで行いました。Azure Storage 個別にユーザを作成し、パスワード or SSH Key Pair での認証が可能、Azure Storage 個別で認可制御を行えることが分かりました。
normalian.hatenablog.com
しかし、上記の記事では石橋を叩いて壊す社畜黒帯の方々にとって大事な観点が欠けています。そう、閉域網でアクセスするネットワーク制御です。こちらに関しては社畜というだけでなく、様々なコンプライアンスに対応するためにも非常に重要な観点です。特に金融系のコンプライアンスである FICS や PCI-DSS 等に準拠をする場合、Express Route や VPN で on-premise 側とつないでの閉域網通信は必須要件と言えるでしょう。
Microsoft Azure の場合 What is a private endpoint? - Azure Private Link | Microsoft Learn と呼ばれる機能を利用し、Microsoft Azure の仮想ネットワークに対してのみエンドポイントを公開することで閉域網からアクセスすることが可能になります。

今回の構成例としては以下になります。xxxxxxxxxwestus2.blob.core.windows.net 側が公開 FQDN となり、xxxxxxxxxwestus2.privatelink.blob.core.windows.net が Private DNS が関連付けされている VNET でのみ名前解決が可能な FQDN となります。

Private Endpoint を設定してインターネットアクセスを禁止する

まずは Private Endpoint から設定しましょう。以下の様にストレージアカウントの Network メニューから Private Endpoint 作成のメニューを選択し、当該 VNET に対してPrivate Endpoint 作成を完了します。

Private Endpoint の作成が完了すると、以下の様に VNET 側に NIC が登録されます(例でのプライベートアドレスは 192.168.0.7 です)。

次にインターネット側からのアクセスを制限します。ストレージアカウントの Private Endpoint の有効化を行うことで閉域アクセスは可能となりましたが、このままの設定では公開 FQDN からのアクセスは未だに可能となっています。こちらを禁止するためには以下の様にストレージアカウントの Network メニューの Firewalls and virtual networks のメニューから禁止できます。加えて Network Routing は Microsoft Network routing となっていることを確認ください。

インターネット経由でのアクセス

社畜御用達ツール WinSCP で前回行ったアクセスを再度実施してみましょう。以下の様なエラーが表示され、アクセスがブロックされるはずです。

Private Endpoint 経由でのアクセス

次に Private Endpoint 経由でのアクセスを行います。Host name には Private DNS で指定した FQDN でアクセス可能です。以下の様に Private DNS 側に登録された FQDN を使えばアクセス可能です。


感のいい方なら「NIC に登録された Private IP でもアクセスできるのでは?」と気づいたかもしれません。ご認識の通り当該 Private IP を指定することで SFTP 接続は可能でしたが、Private Endpoint に割り当てられた Private IP は以下の様に Dynamic となります。

Dynamic で割り当てられた IP の場合、何らかの要因で IP アドレスの再割り当てがされた場合に IP アドレスが変更されることを意味しています。古からの Azurer なら「原則 xxx.xxx.xxx.4 から割り当てられるからそこを駆使すればいいじゃん」と思うかもしれませんが、明にサポートされていないやり方はお勧め致しません。

実はこのブログを書いた後に Azure の更新を眺めていたら以下の情報を見つけてしまいました。どうやら Private Endpoint だろうが IP 固定ができる様です。
azure.microsoft.com

詳細は az network private-endpoint ip-config | Microsoft Learn のブログを参照頂くとして、以下のコマンドを行うことで無事に IP アドレスが固定できました。以下の Private IP アドレスは予め Private Endpoint 作成時に割り当てられた IP アドレスです。

az network private-endpoint ip-config add --endpoint-name "daisamiclientwestus2-storage" -g "daisami-client-rg" -n myipconfig --group-id blob --member-name blob --private-ip-address "192.168.0.7"

Azure Blob Storage に SFTP でアクセスする

「最近何か面白い発表でもないかな~」と思っていたら、Azure Storage にまつわる以下のアナウンスを見つけました。
azure.microsoft.com
一体、何度「SFTP でアクセスしたい」という質問を受けたことでしょう。結構前に Preview 発表をしていたのは記憶にあるのですが、SFTP を愛してやまない社畜力の高い方々は Generally Available (GA) になるまで石橋を叩いて壊すレベルで慎重を期すと思い、スルー控えていましたが重い腰を上げる時が来たようです。

概要や詳細については以下の記事を参照していくことになります。こちらの参照は必須となるので、本記事を通読して概要を把握した後はご参照ください。
learn.microsoft.com
上記の記事をざっと眺めましたが、認証プロキシ被害者の会を開催できそうな社畜力の高い方々が興味を示しそうなポイントは以下でしょうか(偏見有り)。

  • Azure Storage は general-purpose v2 か premium block blob storage 出ないとだめ
  • ポートは 22 番から変更できないので、オンプレからのアクセス時は outgoing ポート 22 番を許可しないとだめ
  • 固定 IP でのアクセス先を指定できないので FQDN で指定する必要あり(これは SFTP というより Azure Storage 自体の制限
  • Azure AD の認証・認可は対応してない(2022年10月時点)ので、RBAC での ACL には対応していない。上記記事の caution に具体例が書いてあるので参照下さい
  • Azure Storage 上に SFTP アクセス専用の local user が最大1000人まで作れる
  • 上記 local user の認証にはパスワードか SSH Key pairs が利用可能
  • local user 毎にアクセス制御は個別に設定可能

個人的な印象としては Azure AD の認証と連動していないので「うちは Microsoft 365 を導入してるから、そのユーザを活用できるんだよね?」というシナリオには向いてないなという印象です。現時点ではユーザ管理を Azure Storage 個別で行う必要があるので、直接そういった運用ができる組織が使う方が良いのではないでしょうか。

ではさっそく設定して使ってみましょう。

SFTP support for Azure Blob Storage を試す

general-purpose v2 または premium block blob storage の Azure Storage アカウント自体を作るステップは割愛します。もし general-purpose v1 や classic タイプの Azure Storage アカウントを利用している方は事前に upgrade してください。
以下の様に Azure Storage アカウントには SFTP のメニューがあるので、こちらを指定してまずは SFTP を有効化します。この処理実施時に Local users も有効化されます。

この時点ではユーザーは一切登録されていないので、当該 Azure Storage アカウントにアクセスするためのユーザを手動で作成します。以下の様に自分でユーザ名を指定(azureuser は私が自分で入力した例です)し、パスワードまたは SSH Key Pair を指定して認証方式を決定します。この際、既に Azure VM 向けにアクセス用の SSH Key Pair 等有れば検証用には便利でしょう。

次にどのストレージコンテナにどの権限でアクセスするかを設定します。ストレージコンテナ毎にアクセス制御を個別に指定できるので、手動で運用する場合は煩雑になりがちだと思いますが制御そのものは実施可能です。

ここで重要なのが Home (landing) directory です。Azure Storage アカウントのルートディレクトリへの SFTP アクセス許可は出来なさそう(誰か発見したら教えて下さい)なので、ここを空欄にしたままアクセス制御をしようとすると以下のエラーが発生しました。Home (landing) directory は必ず設定する様にしてください。

上記でお察し頂けたかもしれませんが、社畜力に満ち溢れる身として、今回は WinSFTP を SFTP クライアントとして利用しています。こちらで指定するユーザ名にはちょっと癖があるのでご注意ください。以下の様に "Azure Storage アカウント名"."作成した local user 名"をユーザ名として指定します。

コンテナも指定する場合は "Azure Storage アカウント名"."コンテナ名"."作成した local user 名"となるので、この辺りで混乱する方も居るかもしれません。
私が作成したユーザは特にパスワードを指定せずに作成したのでパスワードは入力不要ですが、以下の様に WinSCP 上で SSH Key Pair の指定を忘れずしてください。

設定完了後、以下の様に通常の SFTP サーバの様に WinSCP 上からは作業可能です。

サポートされている SFTP クライアントは以下に一覧があるので、必要な場合は参照下さい。
SFTP support for Azure Blob Storage | Microsoft Learn

Azure DevOps の pipeline で自前マシンを使って Maven ビルドする方法

前回のポストで自前の端末を Azure DevOps のパイプラインへ登録する方法を記載しましたが、実はアレだけだと git がインストールされていないのでソースコードが端末から取得できず、当たり前ですが Java も Cento OS にインストールされていないのでビルド時にエラーが発生します。ハッキリ言って Azure DevOps pipeline にただ登録しただけの状態になっています。
normalian.hatenablog.com

今回は端末を Java のビルドで利用できるようにセットアップしていきます。Java のビルドには Ant や Gradle が有名ですが、今回は Maven を試したいと思います。実は Azure DevOps には以下の様に built-in の Maven タスクが存在します。
learn.microsoft.com

こちらを利用すれば Azure DevOps Pipeline でそのまま Maven ビルドを実行できるように思いますが、Azure DevOps エージェントをセットアップした自端末の CentOS マシンには Java がインストールされていないので、pipeline にて Maven タスクを実行すると以下というエラーメッセージが pipeline 内の結果に表示されます。こちらは読みやすいように改行しているのでご注意ください。

##[error]No agent found in pool "your agent pool name" which satisfies 
the following demand: agent.name. 
All demands: agent.name -equals "your specified machine name", maven,
Agent.Version -gtVersion 2.182.1

エラーメッセージを御覧になれば分かるように Maven がインストールされていないことに加え、Azure DevOps エージェントのバージョンも一定以上である必要が分かると思います。今回は前回のセットアップに加え、Maven のセットアップを追加しています。今回の記事でのスクリプトは、前回の記事で実施済のエージェントセットアップを含んでいるので、適宜読みかえて頂ければ幸いです。

Maven タスクを実行するためのスクリプトと Azure Pipeline 定義ファイル

まずは自分が Cent OS 内で実施したスクリプトを以下に記載します。

# CentOS で git v2 をインストールするためのパッケージをインストール& git と maven のインストール
sudo yum install -y https://packages.endpointdev.com/rhel/7/os/x86_64/endpoint-repo.x86_64.rpm
sudo yum install -y java maven git

# Azure DevOps エージェントのセットアップ
wget https://vstsagentpackage.azureedge.net/agent/2.210.1/vsts-agent-linux-x64-2.210.1.tar.gz
mkdir myagent
mv vsts-agent-linux-x64-2.210.1.tar.gz myagent/
cd myagent/
tar zxvf vsts-agent-linux-x64-2.210.1.tar.gz

sudo  ./bin/installdependencies.sh 
./config.sh 

# JDK の配置&Azure Pipeline がアクセスできるように権限制御
sudo mkdir /builds/
wget https://builds.openlogic.com/downloadJDK/openlogic-openjdk/8u342-b07/openlogic-openjdk-8u342-b07-linux-x64.tar.gz
mv openlogic-openjdk-8u342-b07-linux-x64.tar.gz /builds/

sudo mkdir -p /builds/binaries/externals
wget https://builds.openlogic.com/downloadJDK/openlogic-openjdk/8u342-b07/openlogic-openjdk-8u342-b07-linux-x64.tar.gz
sudo mv openlogic-openjdk-8u342-b07-linux-x64.tar.gz /builds/
sudo chown -R azureuser  /builds/

次に Azure DevOps のパイプライン定義もそのまま記載します。こちらは CentOS 側の配置した JDK パッケージのパスを参照していることに注意ください。

# Maven
# Build your Java project and run tests with Apache Maven.
# Add steps that analyze code, save build artifacts, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/java

trigger:
- master

pool:
  name: JavaBuildVM-Agents
steps:
- script: |
    java -version
  env:
    JAVA_HOME: $(JAVA_HOME_8_X64)
    PATH: $(JAVA_HOME_8_X64)/bin:$(PATH)
- task: JavaToolInstaller@0
  inputs:
    versionSpec: "8"
    jdkArchitectureOption: x64
    jdkSourceOption: LocalDirectory
    jdkFile: "/builds/openlogic-openjdk-8u342-b07-linux-x64.tar.gz"
    jdkDestinationDirectory: "/builds/binaries/externals"
    cleanDestinationDirectory: true
- task: Maven@3
  inputs:
    mavenPomFile: 'pom.xml'
    mavenOptions: '-Xmx3072m'
    javaHomeOption: 'JDKVersion'
    jdkVersionOption: '1.8'
    jdkArchitectureOption: 'x64'
    publishJUnitResults: true
    testResultsFiles: '**/surefire-reports/TEST-*.xml'
    goals: 'package'

上記を踏襲すればすんなり動くと思いますが、如何にそれぞれのハマりどころの注意点を追記しています。

設定時の注意点① - git のバージョン

Cent OS で単に yum install git を実施した場合、v1 系の git がインストールされました。その場合、Azure DevOps pipeline 実行時に以下のエラーが発生します。

Starting: Checkout SampleJavaProject@master to s
==============================================================================
Task         : Get sources
Description  : Get sources from a repository. Supports Git, TfsVC, and SVN repositories.
Version      : 1.0.0
Author       : Microsoft
Help         : [More Information](https://go.microsoft.com/fwlink/?LinkId=798199)
==============================================================================
Syncing repository: SampleJavaProject (Git)
git version
git version 1.8.3.1
##[error]Min required git version is '2.0', your git ('/usr/bin/git') version is '1.8.3'
Finishing: Checkout SampleJavaProject@master to s

上記を見れば分かる通り、git v2 系をインストールする必要があります。

設定時の注意点② - JDK のセットアップ

自端末に対して JDK のセットアップから開始する必要がありますが、これには 以下の Java Tool Installer タスクを利用します。自分で展開されたファイルや tar.gz/zip 等で JDK パッケージをどこかに配置する必要があります。
Java Tool Installer task - Azure Pipelines | Microsoft Learn
実は手抜きをしようとタスクの jdkSourceOption の pre-installed を利用しようとしたのですが、こちらは Microsoft 側が標準で提供されているエージェントプールでのみ利用可能なようです。そのため、スクリプトで記載したような tar.gz ファイルを設置しています。
加えて、JDK パッケージを配置したフォルダの権限管理にも注意が必要です。Azure DevOps pipeline の実行時に権限が不足すると以下の様なエラーが発生します。こちらについても対応方法はスクリプトを参照ください。

Starting: JavaToolInstaller
==============================================================================
Task         : Java tool installer
Description  : Acquire a specific version of Java from a user-supplied Azure blob or the tool cache and sets JAVA_HOME
Version      : 0.209.0
Author       : Microsoft Corporation
Help         : https://docs.microsoft.com/azure/devops/pipelines/tasks/tool/java-tool-installer
==============================================================================
##[error]EACCES: permission denied, stat '/builds/binaries/externals'
##[error]EACCES: permission denied, stat '/builds/binaries/externals'
Finishing: JavaToolInstaller

Azure DevOps で自前マシンを pipeline で利用する方法

Azure DevOps でビルドやリリース時に pipeline と呼ばれる機能を利用しますが、その際に実際に pipeline を実行するコンピュートリソースには Microsoft 側があらかじめ提供する Microsoft-hosted agent と呼ばれるものと自身のマシンを利用できる Self-hosted Linux/macOS/Windows agent と呼ばれるものがあります。特に Microsoft-hosted agent については以下を参照頂ければと思いますが、Linux については Ubuntu のみが提供されています。
learn.microsoft.com

昨今では Ubuntu だけでも大きく困ることは無いと思いますが、CentOS 等の他のディスとリビューションを使いたい場合、自前のライブラリや特定の実行ファイル等と連携させたい場合、はたまたオンプレミス含めたシステム連携をしたい場合もあるでしょう。その場合には Self-hosted Linux/macOS/Windows agent を利用することでオンプレミスマシンを含めた自前の端末を Azure DevOps の pipeline を実行するコンピュートリソースとして活用することが可能です(以下の記事は Linux だけですが、macOSWindows の記事は左メニューより参照ください)。
learn.microsoft.com

Self-hosted Linux agents のセットアップ

これ自体は大して難しくありません。ステップとしては以下となります。

  1. 自身の Azure DevOps プロジェクトから Personal Access Token (PAT)
  2. エージェントプールを作成する
  3. 自端末でエージェントのセットアップ

まずは Personal Access Token (PAT) を取得してみましょう。以下の記事が参考になると思います。
learn.microsoft.com
初回セットアップ時、ちょっと分かりにくいのがポータル右上になる自分アイコンの左アイコンをクリックし、そのメニューから Personal Access Token のメニューを選びます。

画面が切り替わるので、以下の例に従って新規に Personal Access Token を作成してください。一度表示された PAT は再度表示されないのでメモ帳等に保存してください。

次にエージェントプールを作成します。自端末や Azure VM、もしくは EC2 等々の環境はこのエージェントプールを通して Azure DevOps の pipeline より選ぶことができます。以下の画面を参考に新規に作成できます。Agent Pool のタイプとして Self-Host と Virtual Machine Scale Set のどちらかを選ぶことができますが、Azure VM を登録する場合、Azure Kubernetes Service (AKS)を利用する場合ともに Self-Host を選択して問題ありません。

次に「自端末でエージェントのセットアップ」を行います。今回は Azure 上で CentOS 7.9 を選択した仮想マシンを利用しますが、これが AWS EC2 やオンプレミスの端末でももちろん問題ありません。ただしネットワークについては接続要件があるので、いくつかの FQDN へのアクセス追加等の確認が必要です。
learn.microsoft.com

CentOS 上で private エージェントの設定時に利用したコマンドは以下となる。tar.gz ファイルのリンクは Azure DevOps のポータルから取得できる。注意が必要なのは config.sh と svc.sh の実行時だ。

[azureuser@xxxxxxxx ]$ mkdir myagent && cd myagent
[azureuser@xxxxxxxx myagent]$ wget https://vstsagentpackage.azureedge.net/agent/2.210.1/vsts-agent-linux-x64-2.210.1.tar.gz
[azureuser@xxxxxxxx myagent]$ tar zxvf vsts-agent-linux-x64-2.210.1.tar.gz 
[azureuser@xxxxxxxx myagent]$ sudo ./bin/installdependencies.sh 
[azureuser@xxxxxxxx myagent]$ ./config.sh 
[azureuser@xxxxxxxx myagent]$ sudo ./svc.sh -h
[azureuser@xxxxxxxx myagent]$ sudo ./svc.sh install
[azureuser@xxxxxxxx myagent]$ sudo ./svc.sh start

config.sh の実行前、必要なライブラリが足りない場合はセットアップに失敗する。そのために installdependencies.sh を実施するケースが大抵となる。実際、ライブラリが足りない状態で config.sh を実行すると以下のエラーメッセージが表示される。

[azureuser@xxxxxxxx myagent]$ ./config.sh 
libicu's dependencies missing for .NET Core 3.1
Execute ./bin/installdependencies.sh to install any missing dependencies.

installdependencies.sh は管理者権限で実行する必要があるので sudo を利用して実行すると、環境に応じてライブラリを整備してくれる。

[azureuser@JavaBuildVM03 myagent]$ sudo ./bin/installdependencies.sh 
--------OS Information--------
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

------------------------------
The current OS is Fedora based
--------Redhat Version--------
CentOS Linux release 7.9.2009 (Core)
------------------------------

(中略)

config.sh 実行時に入力する必要のあるものは以下となる。ここで注意が必要なのは "server URL", "personal access token", "agent pool" だ。以下に私が実際に入力した例を示しているが、先述の 3 パラメーターは Azure DevOps における適切な登録先エージェントプールと仮想マシン紐づけの為に明示的な入力が必須となる。

  • Enter (Y/N) Accept the Team Explorer Everywhere license agreement now? (press enter for N) > Y
  • Enter server URL > https://dev.azure.com/normalian
  • Enter authentication type (press enter for PAT) >
  • Enter personal access token > ****************************************************
  • Enter agent pool (press enter for default) > JavaBuildVM-Agents
  • Enter agent name (press enter for JavaBuildVM03) >
  • Enter work folder (press enter for _work) >

デフォルトでは agent name にはコンピュータ名が指定されるが、特に問題なければこのまま指定して問題ない。work folder は pipeline 実行時に利用される作業ディレクトリとなる。こちらも特に変更しなくても問題ないと思うが、必要な場合は変更できる。

最後に svc.sh を利用してサービスとしての登録・実行を行っている。ポータル上の実行例では run.sh を利用しているが、この場合は実行セッションとプロセスが結びついてしまうので、ssh 等のログインが終了した時点で Azure DevOps のエージェントが終了してしまう。サービスとして登録するためには上記の様に svc.sh の利用が必要だ。以下に実行例を記載する。

[azureuser@JavaBuildVM03 myagent]$ sudo ./svc.sh install
Creating launch agent in /etc/systemd/system/vsts.agent.normalian.JavaBuildVM\x2dAgents.JavaBuildVM03.service
Run as user: azureuser
Run as uid: 1000
gid: 1000
/sbin/sestatus
SELinux status:                 enabled
Created symlink from /etc/systemd/system/multi-user.target.wants/vsts.agent.normalian.JavaBuildVM\x2dAgents.JavaBuildVM03.service to /etc/systemd/system/vsts.agent.norma
lian.JavaBuildVM\x2dAgents.JavaBuildVM03.service.
[azureuser@JavaBuildVM03 myagent]$ sudo ./svc.sh start

/etc/systemd/system/vsts.agent.normalian.JavaBuildVM\x2dAgents.JavaBuildVM03.service
● vsts.agent.normalian.JavaBuildVM\x2dAgents.JavaBuildVM03.service - Azure Pipelines Agent (normalian.JavaBuildVM-Agents.JavaBuildVM03)
   Loaded: loaded (/etc/systemd/system/vsts.agent.normalian.JavaBuildVM\x2dAgents.JavaBuildVM03.service; enabled; vendor preset: disabled)
   Active: active (running) since Fri 2022-10-14 20:10:09 UTC; 56ms ago
 Main PID: 6070 (runsvc.sh)
   CGroup: /system.slice/vsts.agent.normalian.JavaBuildVM\x2dAgents.JavaBuildVM03.service
           ├─6070 /bin/bash /home/azureuser/myagent/runsvc.sh
           ├─6072 ./externals/node16/bin/node ./bin/AgentService.js
           └─6081 /home/azureuser/myagent/bin/Agent.Listener run --startuptype service

Oct 14 20:10:09 JavaBuildVM03 systemd[1]: Started Azure Pipelines Agent (normalian.JavaBuildVM-Agents.JavaBuildVM03).
Oct 14 20:10:09 JavaBuildVM03 runsvc.sh[6070]: .path=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/azureuser/.local/bin:/home/azureuser/bin
Oct 14 20:10:09 JavaBuildVM03 runsvc.sh[6070]: Starting Agent listener with startup type: service
[azureuser@JavaBuildVM03 myagent]$ 

全てが正常に実行されていればエージェントプールに登録が完了される。以下の例では既に三個の仮想マシンを登録しているが、登録した agent name の下部に Online のメッセージが表示されているはずだ。

上記の場合、JavaBuildVM01 はメンテナンス中のため手動で disable にしており現在は利用不可、JavaBuildVM02 は offline のために利用できない状態ということが表示から理解できる。

pipeline で Self-hosted agents pool を指定する

最後に pipeline から作成した agent pool を指定する方法を紹介する。Azure DevOps の pipeline からは pool > name で agent pool name を指定することで利用できる。特定の agent name も指定可能だが、そちらは必要な場合は別途参照して欲しい。

trigger:
- master
pool:
 name: JavaBuildVM-Agents
teps:
- script: |
    java -version
  env:
    JAVA_HOME: $(JAVA_HOME_8_X64)
    PATH: $(JAVA_HOME_8_X64)/bin:$(PATH)

Azure Firewall の DNS Proxy 機能を利用して、Azure 外部の環境から Azure Private DNS を利用する

DNS サーバを利用した名前解決のうち、オンプレミス・パブリッククラウドを組み合わせた複数環境における閉域網での名前解決は特に複雑化することが多いです。Azure 環境の場合は Azure Public DNS や Azure Private DNS と呼ばれる機能がありますが、閉域網向けで利用される Azure Private DNS はオンプレミスや他プラットフォームからの名前解決ができないという課題があります。昨今では Azure DNS Private Resolver 機能もリリースされましたが、2022年7月時点ではプレビューなことに加え、現時点では Japan East/Japan West ともに利用できません。
docs.microsoft.com
Azure バックボーンネットワークを信じてアメリカ側のリージョンと日本側のリージョンをつなぎ、そちらで Azure DNS Private Resolver を使うという手もありますが、そもそも閉域網を非機能要件等で要求されている時点で高いレベルのコンプライアンスに沿う必要があり、日本国外のリージョンを使うということが厳しいことが多いというのが実態でしょう。

そんな以下の

  • 日本のリージョンだけで閉じたい
  • PaaS サービスだけで DNS を構築したい
  • オンプレや別の環境からでも名前解決をしたい

「ダイエットしたいけど甘いものが食べたい思春期さん」な要件を満たす場合、現時点では Azure FirewallDNS Proxy 機能が有効です(Azure DNS Private Resolver を待てというのは現時点では不問でお願いいたします)。
docs.microsoft.com

今回のアーキテクチャ図としては以下になります。外部環境としては GCP を想定していますが、これは別環境がオンプレミスや AWS であったとしても同様となります。こちらの Azure と GCP 間における VPN 接続は以前に記載した Azure と GCP を HA 構成の BGP VPN で接続する - normalian blog の記事を参照下さい。

上記のアーキテクチャで利用した Azure の各コンポーネント構成としては以下になります。

  • Application Gateway を配置した VNET を作成する
  • VPN で Azure と GCP 接続する
  • Azure Private DNS を VNET に接続する
  • Azure Private DNS に対し、Application Gateway の Private IP レコードを登録
  • 当該 VNET に Azure Firewall を配置し、DNS Proxy を有効化する

Azure FirewallDNS Proxy を利用する設定自体は非常に単純で、Azure Firewall 側の DNSメニューから DNS Proxy 設定を有効化するだけです。

上記に加えて参照する先の DNS サーバを「DNS Servers」のところで個別に IP 等で設定することも可能ですが、Default を指定することで Azure VNET が標準で参照する DNS 先、すなわち設定済の Azure Private DNS を見に行くことになります。

実際の動作例

では GCP 側の VM から Azure Private DNS に登録されている Application Gateway の Private IP を参照してみましょう。先述した通り、Azure Private DNS には既に Application Gateway の Private IP が登録済であり、VNET側に関連付けがなされているものとします。加えて、Azure Firewall 自体の Private IP は 172.19.100.4 として設定済です。

GCP 側の VM は特に DNS サーバの設定等はしていないまっさらな状態として構築し、そこで以下のコマンドを実行例しました。

特に何もせずに nslookup を実行しても Azure Firewall 側に名前解決をしに行かないので当然名前解決に失敗してますが、二回目は Azure Firewall の Private IP を DNS サーバとして指定することにより、無事に名前解決に成功しています。

Azure と GCP を HA 構成の BGP VPN で接続する

昨今のシステム構築時は複数のプラットフォームを活用することが多いと思います。最も多いケースは特定のパブリッククラウド(Azure 等)とオンプレミスとの組み合わせだと思いますが、異なるパブリッククラウドAWS, GCP 等)と接続して利用するケースも必要になると思います。コンプライアンス等によってはすべてをオンプレミス側のルータを起点・経由して異なるプラットフォームに接続することもあると思いますが、あるパブリッククラウドの特定機能を使いたいがために VPN で直接接続したいケースもあります。私が今回試したケースは「別プラットフォームから Azure にアクセスした場合の環境を作りたいな」と思い、出来心で試してみました。GCP から AWS や Azure に VPN 接続する記事としてはトップゲートさんが公開している記事が懇切丁寧に解説してくれているので、非常に参考になります。
www.topgate.co.jp
こちらをそのまま参考にしても良いと思うのですが、同記事は GCP 側で利用しているコンポーネントが Classic VPN となり、本番環境で利用したいであろう 高可用性(HA)VPN になっていないので、こちらを利用した際に Azure 側も含めてどの様に設定するかのポイントを記載したいと思います。
まず、アーキテクチャ図としては以下になります。太字でそれぞれ Azure/GCP でどの様なリソースを追加しなければならないかを明示しました。一点注意が必要なのが、Azure 側の BGP Routers は Virtual Network Gateway 設定の一部となっていますが、対比のためには明記した方が良いと思い記載しております。

ルーティングとして BGP を利用するので、クラウド間で互いに AS 番号を指定して BGP ルータの設定をしています。こちらに加えて VPN Gateway の Public IP や BGP Router の IP を Azure/GCP で互いに設定します。先述した通り「高可用性(HA)VPN 」を実現するためにコンポーネントの数が増えており、混乱しやすいのではと思うので本記事が理解の手助けになれば幸いです。

Azure/GCP で作成するコンポーネント

今回のケースでは以下のコンポーネントを作成する必要があります。設定次第で前後はあると思いますが、作成の流れとしてはおおよそ以下になると思います。

  1. Azure, GCP で Virtual Network, VPC Network を作成、NSG, ファイヤウォール等を設定
  2. Azure 側で Virtual Network Gateway x 1 を作成
  3. GCP 側で Peer VPN Gateway x 1 を作成
  4. GCP 側で Cloud VPN Gateway x 1 を作成
  5. GCP 側で Cloud Router x 1 を作成
  6. GCP 側で VPN Tunnel x 2 を作成
  7. GCP 側で BGP Session x 2 を作成
  8. Azure 側で Local Network Gateways x 2
  9. Azure 側で Connections x 2

流石に 一つ目の項目は説明は不要だと思うので、Azure の Virtual Network Gateway の作成から行きましょう。

Azure 側で Virtual Network Gateway x 1 を作成

以下の例を参考にして頂ければと思います。

特に以下の設定項目は必須です。Second Public IP を新規で作成するので、リソース名等は適宜設定してください。作成時には Configure BGP はいったん off のままで後で設定します。

設定名 設定値
Gateway Type VPN
VPN Type Route-based
Enable active-active mode enabled
SECOND PUBLIC IP ADDRESS Create new

次に Virtual Network Gateway の Configuration メニューを選択し、Configure BGP を有効化します。ここで設定する主な項目は ASN と Custom Azure APIPA BGP IP address の二つです。今回の設定値としては以下にしました。

設定名 設定値
ASN 65510
Custom Azure APIPA BGP IP address 169.254.21.14
Second Custom Azure APIPA BGP IP address 169.254.22.50

ASN は GCP 側(別プラットフォーム側)でも設定し、異なる番号を入力します。ASN に関してはプライベートレンジの範囲で任意に入力して問題ありません。(Second)Custom Azure APIPA BGP IP address については、Azure のサポートする BGP IP のレンジが 169.254.21.* ~ 169.254.22.* である点、後述しますが GCP 側が Peer BGP IP(この場合は Azure BGP IP を指します)が "/30 subnet" 以内に居ないといけない制約がある点に注意が必要ですが、この範囲で有れば任意で問題ありません。

GCP 側で Peer VPN Gateway x 1 を作成

GCP 側に移動して Peer VPN Gateway を作成します(Azure 側でいう Local Network Gateway)。今回は高可用性のオプションを設定しているので、two interfaces のオプションを選択し、以下の様に Azure 側の VPN Gateway の Public IP アドレス x 2を指定します。

GCP 側で Cloud VPN Gateway x 1 を作成

Peer VPN Gateway では「Azure 側の VPN Gateway ってこのアドレスだよ」というガワを作成しているだけなので、GCP 側でも本体である Cloud VPN Gateway を作成する必要があります。VPN Gateway の所属する Network と Region を指定して Cloud VPN Gateway を作成します。作成後、以下の様に Public IP が二つ割り当てられるので、Azure 側で Local Network Gateways を作成する際にはこちらを利用します。

GCP 側で Cloud Router x 1 を作成

GCP 上では Cloud Router を作成します。こちらは BGP の動的ルーティングを行うために必要なコンポーネントになります。この辺り Azure は VPN Gateway 側のリソースに統合されてみえるので、見た目上の違いとして表れている点だと思います。

ここで GCP 側の ASN を指定します。この値はプライベートレンジかつ Azure 側の ASN と異なる必要があります。今回は 65509 を指定しました。

GCP 側で VPN Tunnel x 2 を作成

GCP 側では Cloud VPN Gateway, Peer VPN Gateway, Cloud Router と一通りの登場人物が作成できたので、漸く VPN Tunnel x 2 を作成します。Cloud VPN Gateway の画面から VPN Tunnel を作成できますが、原則は既に作成済のリソースを選ぶだけだと思います。IKE-pre-shaed key をここで pick up し、後で Azure 側で Connection を作成する際に利用する点、VPN Tunnel は二つ作る点に注意してください。

GCP 側で BGP Session x 2 を作成

Configure BGP sessions は後で設定する様に選択し、いったん設定を完了します。その後、VPN Tunnels 一覧から BGP の設定をします。以下に設定例を記載していますが、ここで Azure 側で設定した ASN 番号と Custom Azure APIPA BGP IP address を利用します。

設定名 設定値
Peer ASN 65510(Azure 側で設定した値)
Cloud Router BGP IPv4 address 169.254.21.13
BGP Peer IPv4 address 169.254.21.14(Azure 側で設定した値)

本記事では片方の VPN Tunnel のみ設定を記載していますが、高可用性のために用意したもう一つの VPN Tunnel 側も同様に設定してください。

Azure 側で Local Network Gateways x 2

これで漸く GCP 側は一通りの設定が完了したので、Azure 側に戻り、Local Network Gateway を二つ作成します。以下を参考にリソースを作成して下さい。

設定名 設定値
IP Address 35.242.112.236(GCP 側の Cloud VPN Gateway の Public IP #1)
Address Space(s) 10.101.0.0/16(GCP 側の VPC Network のアドレス )

繰り返しとなりますが、こちらの操作も高可用性のために GCP 側の Cloud VPN Gateway 二つ目にあたる Local Network Gateway も作成を忘れない様にして下さい。

Azure 側で Connections x 2

最後に Azure の Virtual Network Gateway から Connections を二つ作成します。これで設定は完了するはずです。

設定名 設定値
Connection Type Site-tosite(IPSec)
Local network gateway GCP 側の Public IP を指定した上記で作成のリソース
Shared key (PSK) GCP 側で pick up した値
Enable BGP 有効化
Enable Custom BGP Addresses 有効化
Custom BGP Addresses GCP 側で設定した BGP peer IPv4 address を設定

設定が上手くいかない場合

Azure 側では Virtual Network Gateway の Connections メニューで接続状態が確認できます。以下の様に Status が Unknown の場合は VPN の接続自体でこけています。この場合は shared key や各 IP アドレスの設定を見直してください。

VPN 接続が上手くいった場合でも以下の様に BGP sessions status が waiting for peer のままで BGP のルーティングが始まらない場合があります。

当然 BGP ルータの IP アドレス等の設定を再確認が必要ですが、何度も設定を見直しているせいで反映がどうなっているかの把握が難しい状態で BGP の設定が完了しない場合、以下の Azure の Virtual Network Gateway 側で Reset を試すと上手く接続が完了する場合があります。Reset 配下にある VPN troubleshoot も VPN 接続時のトラブルシューティングには参考になります。