Proxmox運用にAnsibleとAIを活用する:Semaphore UIでAnsibleを定期実行する
この記事で実現すること
前回の記事では、AIを使ってAnsibleのPlaybookを実装しました。作成したコードはGitにも登録し、変更内容を管理できる状態にしています。
今回は、本格的なAnsible運用へ進むため、Semaphore UIを導入します。作成したPlaybookをWebブラウザから実行し、決められた時間に定期実行できる環境を構築します。さらに、PlaybookをGitHubのPrivate Repositoryで管理し、実行結果をSlackへ通知できるところまで進めます。
今回の構成
今回も前回に引き続き、テスト環境を使って構築を進めます。
前回は、Ansible実行環境として test-ansible、操作対象として test-vm という2台のUbuntu 26.04 Server VMを作成しました。
Ansibleのリポジトリは、test-ansible のユーザーのホームディレクトリ配下にある ~/test-ansible です。ローカル端末からVS CodeのRemote - SSHを使って接続し、Playbookを編集します。私の環境では、ローカル端末としてmacOSを使用しています。
今回は、この test-ansible にSemaphore UIを導入します。前回作成したPlaybookをGitHubへ登録し、Semaphore UIがGitHubからコードを取得して test-vm に対して実行する構成です。
また、実行結果を確認できるよう、Slackへの通知も追加します。昔ながらのメール通知でも構いませんが、やや時代遅れ感もあります。Slackはこういった単純な使い方であれば無料ですし、ハッシュタグで目的別に内容を確認できて便利です。実運用に入るとかなり目的毎に分類する方が運用しやすいので通知にはSlackを導入されることをお勧めします。蛇足ながら、Proxmoxからの通知に加え、(今回は関係ないですが)UniFiのネットワーク機器の管理についてもSlackへの通知機能がありますので、ホームラボからの通知をSlackに一本化できるメリットがあります。
私の場合は、クライアントにmacOSを使っていますが、Ansible開発はSSHした先のUbuntuなのでWindowsであっても問題ありません。VS Codeが使える環境が必要です。前回の作成した構成を再度利用しますので、これ以降のセットアップでは、事前準備としては前回の記事をご覧ください。
Semaphore UIについて
GitHub、Ansibleなど自動化タスクを実行するために使用される、セルフホストの継続的自動化およびデプロイメントツールです。有償版、無償版(OSS)とがあります。今回はOSSを使います。
日本語のWebサイトもありますが、実際の中身はGitHubと英語のドキュメントが中心です。
https://semaphoreui.com/ja
が、メニューからSemaphore UI Communityを選ぶと、GitHubに飛びます。
https://github.com/semaphoreui/semaphore
SemaphoreのDocumentsです。
https://semaphoreui.com/docs
作成したAnsibleコードをGUIから起動したり、タイマー起動できるようになります。Proxmoxが代表格ですが、特にパッチ適用が頻繁に発生します。気が向いたらパッチ適用ということはセキュリティ上、厳しいですので自動パッチといかないまでもパッチ情報は遅延なく把握し、メンテナンス計画を設けたいものです。
SemaphoreはGitHubのリポジトリを常に正として扱います。安定した運用を第一に考えるなら、決められた時間にパッチやヘルスチェックなどの実行、モニタリングが必要と考えています。前者のパッチやヘルスチェックなどはSemaphoreUIを中心にワークフローが回せます。
ローカルGitリポジトリをGitHubへ登録する
GitHub用のSSHキーを作成する
Semaphore UIからはGitHubリポジトリに接続する必要があります。SSHキー、パーソナルアクセストークンなどで接続することになりますが、ここではSSHキーで進めます。
GitHubのアカウントをお持ちでない方は、あらかじめ作成しておいてください。
前回から、Ansibleの開発環境は test-ansible 上に構築しています。GitHubへ接続するSSHキーの例示も、この test-ansible 上で作成します。
ローカル端末がWindowsやmacOSであっても、VS CodeのRemote - SSHで接続しているため、以下のコマンドはお使いのAnsible端末(リモートホスト)上で実行してください。
1 | ssh-keygen -t ed25519 \ |
実行するとパスフレーズの入力を求められます。セキュリティを重視する場合は設定することをお勧めしますが、今回は検証環境のため未設定(Enterキーを2回押下)とします。
作成されるファイルは以下の2つです。
~/.ssh/id_ed25519_github(秘密鍵)~/.ssh/id_ed25519_github.pub(公開鍵)
公開鍵の内容を表示します。
1 | cat ~/.ssh/id_ed25519_github.pub |
表示された公開鍵をコピーし、次の手順でGitHubへ登録します。
GitHubへ公開鍵を登録する
https://github.com/settings/ssh/newを開くと、SSHキーを登録する画面となります。
Titleにはわかりやすい説明を、Key Typeは”Authentication Key”、KeyにはSSH公開鍵を貼り付けて保存(Add SSH Key)してください。
SSH接続を確認する
公開鍵を登録したら、test-ansible からGitHubへSSH接続できることを確認します。
1 | ssh -i ~/.ssh/id_ed25519_github -T git@github.com |
初回接続時は以下のようなメッセージが表示されます。
1 | The authenticity of host 'github.com (xxx.xxx.xxx.xxx)' can't be established. |
内容を確認し、yes を入力してください。
接続に成功すると、以下のようなメッセージが表示されます。
1 | Hi <GitHubユーザー名>! You've successfully authenticated, but GitHub does not provide shell access. |
このメッセージが表示されれば、SSHキーの登録は正常に完了しています。
続いて.ssh/configも設定しておきます。
1 | cat <<EOF >> ~/.ssh/config |
これでシンプルにssh -T git@github.comやgitコマンドが鍵指定なしで実行できます。
GitHub CLIをインストールする
GitHubでは、リポジトリの作成や管理をコマンドラインから行えるGitHub CLI(gh)が提供されています。
今回はGitHub CLIを利用して、Private Repositoryを作成します。
1 | sudo apt update |
インストールできたら、バージョンを確認します。
1 | gh --version |
GitHubへログインする
GitHub CLIからGitHubへログインします。
1 | gh auth login |
対話形式で質問されるので、以下のように選択します。”your-user”やSSHキーは環境に応じて変わります。
gh auth login
- What account do you want to log into? GitHub.com
- What is your preferred protocol for Git operations on this host? SSH
- Upload your SSH public key to your GitHub account? /home/your-user/.ssh/id_ed25519_github.pub
- Title for your SSH key: GitHub CLI
- How would you like to authenticate GitHub CLI? Login with a web browser
ブラウザが起動し、認証コードが表示されます。GitHubへログインして認証を完了してください。
認証が終わったら、ログイン状態を確認します。
1 | gh auth status |
Private Repositoryを作成する
認証が完了したら、ローカルGitリポジトリをGitHubのPrivate Repositoryとして登録します。
※(前回の記事で実施したローカルでgit init、ブランチをmainに設定していることが前提です)
1 | cd ~/test-ansible |
これでGitHub上にPrivate Repositoryが作成され、ローカルリポジトリとの関連付けと初回Pushまで自動的に行われます。
1 | ✓ Created repository your-git-account/test-ansible on GitHub |
これでブラウザからtest-ansibleのリポジトリを確認すると前回作成したコードが登録されていることがわかります。
Semaphore UIをインストールする
これまではターミナルから ansible-playbook を実行していました。
ここからは、WebブラウザからPlaybookを実行したり、定期実行したりできる Semaphore UI を導入します。
SemaphoreはオープンソースのAnsible管理ツールであり、Playbookの実行履歴やスケジュール管理、GitHubとの連携などをGUIから行えます。
今回は執筆時点で最新版の 2.18.12 を利用します。
Semaphoreをインストールする
まずはGitHub Releasesからパッケージをダウンロードしてインストールします。
ダウンロード先には一時ディレクトリである /tmp を利用します。ここにはインストール用の .deb パッケージを一時的に保存するだけであり、インストール後に削除されても問題ありません。
これまでの手順はAnsibleを学ぶためのテスト環境を前提としていました。一方、ここから紹介するSemaphore UIの構成は、私自身が実際のホームラボで採用している考え方をベースにしています。ファイルパスやユーザー名(your-user)は環境に合わせて読み替えていただければ、そのまま実運用にも利用できる構成です。
1 | cd /tmp |
インストールできたら確認します。
1 | which semaphore |
正常にインストールされていれば、以下のように表示されます。
1 | /usr/bin/semaphore |
ディレクトリを作成する
Semaphoreの設定ファイルやデータベース、GitHubから取得したPlaybookを保存するため、あらかじめディレクトリを作成します。
今回はAnsibleを実行しているユーザーと同じ(Ubuntuをセットアップした時のデフォルト)ユーザーでSemaphoreを動作させます。これにより、CLIから実行した場合と権限の違いを意識せずに運用できます。以下の”your-user”は実際の環境に置き換えてください。
1 | sudo mkdir -p /etc/semaphore |
初期セットアップを実行する
続いて初期設定を行います。
1 | semaphore setup |
以下の内容で設定してください。
| 項目 | 設定値 |
|---|---|
| Database | SQLite |
| DB Hostname | /var/lib/semaphore/semaphore.db |
| Playbook path | /opt/semaphore |
| Config output directory | /etc/semaphore |
| Admin user | your-user |
| Admin email | 任意(省略不可) |
| Admin password | 任意の強力なパスワード |
通知についても聞かれますが、今のところは全てNoと答えてください。
セットアップが完了したら、設定ファイルとデータベースが作成されていることを確認します。
1 | ls -l /etc/semaphore/config.json /var/lib/semaphore/semaphore.db |
config.json には暗号化キーなどの重要な情報が含まれるため、アクセス権限を制限しておきます。
1 | chmod 600 /etc/semaphore/config.json |
systemdへ登録する
今回はサービスとして起動できるようにsystemdへ登録します。
これにより、OS起動時の自動起動や systemctl による管理ができるようになります。
引き続き、ユーザー名のyour-userの部分は読み替えてください。それ以外は今回セットアップしたフォルダ構成に基づいて構成されています。
1 | sudo tee /etc/systemd/system/semaphore.service >/dev/null <<'EOF' |
登録したらサービスを有効化します。
1 | sudo systemctl daemon-reload |
最後にポート3000で待ち受けていることを確認します。
1 | sudo ss -ltnp | grep :3000 |
以下のように表示されれば、Semaphore UIの起動は完了です。
1 | LISTEN ... :3000 ... |
ブラウザで以下のURLにアクセスするとSemaphore UIのログイン画面が表示されます。
1 | http://<test-ansibleのIPアドレス>:3000 |
Semaphore UIの初期設定
セットアップ時に作成した管理者ユーザーでログインしてください。
ログインすると、初期状態ではProjectが存在しないため、以下のような画面が表示されます。
まずは 新しいプロジェクト をクリックし、Projectを作成します。
プロジェクト名には任意の名前を入力します。今回は Test Ansible とします。そして、「このプロジェクトのアラートを許可」のチェックボックスをONにします。最後に作成ボタンをクリックします。
プロジェクトを作成すると、Ansibleコードを保管するリポジトリやサーバーなどの定義をするインベントリなどの設定を追加できるようになります。ここからはAnsibleを実行するための環境を登録していきます。
Semaphore UIにAnsible実行環境を登録する
Ansibleを実行するには、最低限以下の情報をSemaphoreへ登録する必要があります。
- GitHub Repository
- SSHキー
- インベントリ
- タスクテンプレート
これらを一度登録してしまえば、以降はブラウザからPlaybookを実行できるようになります。
今回は以下の順番で設定していきます。
- キーのストア
- リポジトリ
- インベントリ
- タスクテンプレート
- スケジュール
SSH Keyの登録
左ペインから Key Store を選択し、画面右上の 新しいキー をクリックします。
キー名は「GitHub SSH Key」など、分かりやすい名前を付けます。
Store は Local、Type は SSH Key を選択してください。
続いて、GitHubへ登録したSSHキーの秘密鍵を登録します。
test-ansible で以下のコマンドを実行し、秘密鍵の内容を表示します。
1 | cat ~/.ssh/id_ed25519_github |
注意
id_ed25519_github.pubは公開鍵です。ここで登録するのは.pubが付いていない秘密鍵です。
表示された内容を 秘密鍵 欄へ貼り付けます。
秘密鍵は以下のように、先頭が
1 | -----BEGIN OPENSSH PRIVATE KEY----- |
で始まり、末尾が
1 | -----END OPENSSH PRIVATE KEY----- |
で終わっていることを確認してください。
最後に 作成 をクリックすると、SSHキーの登録は完了です。
GitHub Repositoryの登録
続いて、Playbookを取得するGitHubリポジトリを登録します。
左ペインから リポジトリ を選択し、画面右上の 新しいリポジトリ をクリックします。
各項目は以下のように設定します。<GitHubユーザー名>やリポジトリの名前(test-ansible.git)は環境に応じてに置き換えてください。
| 項目 | 設定値 |
|---|---|
| Name | Test Ansible |
| Git URL | git@github.com:<GitHubユーザー名>/test-ansible.git |
| SSH Key | 先ほど登録した GitHub SSH Key |
| Branch | main |
入力が完了したら 作成 をクリックします。
登録が完了すると、SemaphoreはこのGitHubリポジトリからPlaybookを取得して実行できるようになります。
Git URLを確認する場合は、GitHubのリポジトリ画面から Code → SSH を選択すると確認できます。
Ansible接続用SSHキーの登録
続いて、Semaphoreから管理対象サーバーへSSH接続するための秘密鍵を登録します。
先ほど登録した GitHub SSH Key は、GitHubからPlaybookを取得するためのSSHキーです。今回登録するSSHキーは、Ansibleが test-vm へ接続してPlaybookを実行するために使用します。
前回の記事では、test-ansible から test-vm へ接続するため、ansible ユーザー用のSSHキーを作成しました。今回は、その秘密鍵をSemaphoreへ登録します。こちらも実環境に合わせて読み替えてください。
左ペインから キーのストア を選択し、画面右上の 新しいキー をクリックします。
キー名は「Ansible SSH Key」など、用途が分かる名前にします。Store は Local、Type は SSH Key を選択してください。
test-ansible で、前回作成した秘密鍵の内容を確認します。前回はClaude Codeが生成してくれました。
1 | cat ~/.ssh/id_ed25519 |
使用する秘密鍵のファイル名は、前回SSHキーを作成した際の指定によって異なります。別のファイル名で作成した場合は、実際のパスに読み替えてください。
表示された秘密鍵を、Semaphoreの 秘密鍵 欄へ貼り付けます。
ここでも、.pub が付いていない方を使用します。秘密鍵が以下の行で始まっていることを確認してください。
1 | -----BEGIN OPENSSH PRIVATE KEY----- |
SSHキーにパスフレーズを設定している場合は、対応するパスフレーズも入力します。
最後に 作成 をクリックして登録を完了します。
これでSSHKeyはGitHub用とAnsible用(他のノードを操作するためにSSHするためのもの)と2つが登録完了しました。
インベントリの登録
続いて、Ansibleの管理対象となるサーバーをインベントリへ登録します。
インベントリには、Ansibleが管理するサーバーの一覧を登録します。
左ペインから インベントリ を選択し、画面右上の 新しいインベントリ をクリックします。
以下の内容を入力します。
| 項目 | 設定値 |
|---|---|
| 名前 | Test Inventory |
| ユーザー資格情報 | “Ansible SSH Key”を選択 |
| タイプ | File |
| インベントリファイルへのパス | inventories/hosts.yml |
| リポジトリ(Optional) | “Test Ansible”を選択 |
これで、Ansibleの実行対象となるサーバーがInventoryへ登録されました。
最初のTask Templateを作る
最初のTask Templateは前回作ったものを取り込む形にしましょう。
前回、test-ansibleでは、playbooks/status_check.ymlというtest-vmのステータスチェックを行うPlaybookを作成しましたね。これをSemaphoreに登録します。
左ペインから”タスクテンプレート”をクリックし、画面右上の新しいテンプレートをクリックしてから、”Test Ansible”をクリックします。
以下のように入力または選択します
| 項目 | 設定値 |
|---|---|
| 名前 | Status Check test-vm |
| プレイブックファイルへのパス | playbooks/status_check.yml |
| インベントリ | ”Test Ansible”を選択 |
| リポジトリ | “Test Ansible”を選択 |
右下の”作成”ボタンをクリックして登録します。
status_check.ymlを手動実行する
さて、いよいよ実行です。
タスクテンプレートの画面に今回登録したテンプレート「Status Check test-vm」が表示されていると思います。
プレイボタン「▶️」をクリックすると当該Playbookが呼び出されます。新しいタスクというダイアログが表示されますので、実行をクリックしてください。
さて、GUIからPlaybookが実行、確認できるようになりました。
最初が少し手間が掛かりますが、GUIによる管理ができるようになれば、過去の実行結果の把握などが容易になります。
改めて今回テストに使用したplaybook
前回の記事ではCLIベースでのAnsibleの実行、今回はSemaphoreUIによる実行を行いました。私の環境では、AIが作成してくれたため、必要なファイルについて補足しておきます。
前回記事で作成したのは、以下のフォルダ構成でした。フォルダの構成を作成するスクリプトも前回の記事に置いてあります。
1 | test-ansible/ |
そして、前回AIが作成してくれたファイルについて改めて記載します。
inventories/hosts.yml
1 | all: |
playbooks/status_check.yml
1 |
|
roles/status_check/defaults/main.yml
1 |
|
roles/status_check/tasks/main.yml
1 |
|
いかがでしょうか、ここまでの流れで、VS CodeとAIを使って作成したAnsibleコードをSemaphoreUIで動かせるようになりました。
スケジュールを登録する
TimeZoneの登録
/etc/semaphore.config.jsonを見ると以下のような構成になっていると思います。
1 | cat config.json |
ここにTimeZoneを設定します。jsonなので少しインデントなどに気をつけてもらって末尾から2行目にtimezoneの情報を加えて、以下のようにします。”access_key_encryption”: “xxx=”の後ろに、(カンマ)を入れて”schedule”からの3行を足します。
1 | { |
これはミスしやすいのでツールで確認しましょう。
1 | sudo python3 -m json.tool /etc/semaphore/config.json >/dev/null \ |
その後、サービス再起動します。
1 | sudo systemctl restart semaphore |
スケジュール編集画面で Asia/Tokyo time と表示されれば設定完了です。
crontab -eでviで保守していくのはなかなか大変です。個人的な見解を述べさせていただくと、インフラやってる人はみんな嫌いだと思います笑。
上記のShow cron formatのトグルを外すと、以下のようにわかりやすくなります。これで登録しておけばわかりやすいです。
ただし、このままだとジョブの終了時に通知が何も行われないので、結果がわかりません。ログインしてどうだったか確認できますが、こういったジョブスケジューラーというものはスケジューラーの設定をGUIで行い、その作業が終わったらログインしないのが一般的です。もちろんジョブが落ちたら中身を見ますが、それはログ中心だと思います。
メール通知でも良いのですが、実は私がセットアップした時には、このメール通知が内部エラーとなりうまく機能しませんでした。最新バージョンでは確認していませんが、過去のユーザーの声を見ても結構な数のレポートがあったので何らかの難しさがあるのでしょう。ここは時代ということもあり、Slackからの通知をやってみましょう。
SlackのWebhookの作成
まず無料でアカウントを作成しましょう。ホームラボとして使う分には無料ユーザーの機能で十分多機能です。https://slack.com/から右上の”ワークスペースを新規作成”でアカウントを作成しましょう。
アカウントが作成され、ワークスペースの設定が完了したら、ワークスペースの中で通知チャンネル(ハッシュタグ)を作成しておきます。
私の例だと、チャンネルはHomelabに最適化されていて、目的ごとにチャンネルがありますが、ここでは通知を受けるためのチャンネルを作成しておきます。「チャンネルを追加する」から私のように#semaphoreと入れても良いですね。
続いてアプリの作成に進みます。
https://api.slack.com/apps
“Create New App”をクリックします。”From Scratch”を選びます。
その後、AppNameをたとえば、「Homelab」とし、最初に作成したワークスペースを指定します。
ここからWebhookの設定を行います。
まずはIncoming Webhookを有効にします。そのまま下にスクロールして、Add New Webhookをクリックします。
これらの作業によって、チャンネルごとのWebhookが作成されます。今回はSemaphore向けですが、ProxmoxからもSlackのWebhookは指定できますので、通知が一元管理できます。私の例をご覧になるとお分かりかと思いますが、Semaphoreの通知、Ansible Playbookそのものからの通知、ProxmoxのBackup通知、または目的毎にパッチなどもチャンネル単位に分けています。最後のprotect/uniFiについては、UniFi Protect(監視カメラ)、UniFi(ネットワーク)からの通知を受けています(UniFiクラウド機能はOffにしてSlackで通知を一元管理)。
ここで登録したチャンネル毎のURLを”Copy”ボタンでクリップボードにコピーしておいてください。
SlackのWebhookをSemaphoreUIに登録
さて、先ほどは、/etc/semaphore.config.jsonを編集しましたが、またこのファイルの編集が必要です。
今回は先ほど追加したTimezoneの上に2行足しましょう。先ほどクリップボードにコピーしたURLを”slack_url”: の後に””で囲った上で貼り付けてください。
1 | "slack_alert": true, |
改めて、ツールで確認しましょう。
1 | sudo python3 -m json.tool /etc/semaphore/config.json >/dev/null \ |
その後、サービス再起動します。
1 | sudo systemctl restart semaphore |
もう一度登録したジョブを実行してみます。
今度はSlack通知が行われたログが表示されました。
1 | 7:49:43 PM |
私のスマホにはSlackをインストールしていますが、無事ジョブが正常終了したことが通知されました。
まとめ
さて、今回はAIを利用したAnsibleの実装にSlack通知まで進めたかったのですが、かなり長くなったのでここで一旦区切ります。
今回はSemaphoreUIのセットアップ、そしてSemaphoreからSlackへの通知までを行いました。
ただし、今回はAnsibleのジョブが正常終了したか異常終了したかだけの通知になります。実際にジョブの中でアラートが発生したり、何らかの警告や情報を通知したい場合はこれでは不足しています。つまり別のSlackのチャネルに何らかの付加情報を加えて、初めて運用の高度化が成り立ちます。次回はAnsibleのPlaybookの中で直接ユーザーに必要な情報をSlackに通知する方法をまとめたいと考えています。
今回はまだAnsibleの高度化はしていないので、UbuntuのVMの参照しか行っていませんが、最終的にはProxmoxに対して安全な操作を行うところまでを目的にしたいと考えてます。
前回と今回の記事でAIを使ってAnsibleの構築およびジョブの自動実行ができるようになり、Proxmoxの運用の高度化について、実現可能性が見えてきたと思います。今後の記事ではもう一歩先に進み、AIによるAnsibleの高度化についてまとめていきたいと考えてます。私の環境はProxmoxのクラスター構成であり、QdeviceにSemaphoreUIを配置し、Proxmoxクラスターの外のノードからProxmoxを操作していますが、必ずしもユーザー全てがそういう環境にはなく、むしろシングルノードのProxmoxユーザーが大半だと思われます。リスクのある破壊的操作を避けてProxmoxのパッチ情報の抽出などに取り組みたいと考えています。