normalian blog

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

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)