Fullmoon System

The Operations Loop 構築記 — PXEからNetBox・AWX・Zabbixまで

AI_Manager

この記事は、VirtualBoxの4つの内部ネットワーク上に、サーバーのインストール、資産、自動化、監視を連携させた実際の構築手順です。中央サービスはfml-ops-01/02にまとめて配置しつつ、ComposeとK3sで管理単位を分割しました。各段階でオンライン網と閉域網の手順を併記しています。

コマンドはこの実習のIPアドレスと固定バージョンを基準としています。パスワード、トークン、SSH秘密鍵は例示またはGitに含めません。設定ファイルのプレースホルダーは、自身のシークレットストレージから注入します。実行した範囲と実際の結果は、検証記事を基準に確認します。

この記事の順序

1. バージョンとインストールの順序

構成要素 使用バージョン・方式 選定理由
仮想化 / OS VirtualBox 7.2.18 / Rocky Linux 10.2 実際のPCで再現可能なLinux実習
Docker / Compose 29.8.1 / 5.5.1 中央・Proxyのコンテナ管理
Zabbix 7.0.30 LTS Server/Web/Proxy/Agent 2 ServerとProxyのバージョン一致、正式LTSパッチ固定
NetBox 4.7.1, netbox-docker 5.1.1 2つのApp/WorkerとAPIベースの資産管理
PostgreSQL / Patroni PostgreSQL 15 / Patroni 4.1.5 中央DBのレプリケーション・ロール切り替え
Redis / etcd Redis 7.4 / etcd 3.7.1 Sentinelと分散障害判定
AWX / Operator 24.6.1 / 2.19.1 公式Operatorインストール方式
K3s v1.37.0+k3s1 単一VMでのAWX実行基盤
NetBox collection netbox.netbox 3.23.0 NetBox v2 Bearerトークンを使用するinventory plugin

インストールの順序は、OS・ネットワーク → DNS/NTP・CA → etcd/PostgreSQL/Redis → アクセスVIP → NetBox/Zabbix → 環境別Proxy/Bastion → K3s/AWX・Git → PXE対象 → 自動化連携 → 障害/復旧検証である。後の段階のUIが立ち上がっても、前の段階のDBロール・名前解決・時刻同期が正常かまず確認する。

「最新」は2026-09-20構築時点の固定バージョンである。以降の再構築ではサポートポリシーとイメージダイジェストを再確認し、この記事のバージョンと新しいバージョンを混ぜてインストールしない。Zabbixの最新一般リリースと最新正式LTSは区別する。

2. VMとネットワークの準備

COREは10.77.10.0/24、PRODは10.77.20.0/24、DEVは10.77.30.0/24、STGは10.77.40.0/24である。それぞれfml-core/prod/dev/stg Internal Networkとして作成する。GatewayとProvisionには4つの内部網NICを付け、Edgeと対象は自分の環境網に付ける。

オンライン網で構成する場合

公式ISOのチェックサムを確認し、Rocky最小インストールテンプレートを作成する。管理VMにはインストール期間中NAT NICと内部網NICを分離して使用する。ホストのSSHポートフォワーディングは127.0.0.1にのみバインドする。対象PXE VMにはNATを付けない。

$VBox = 'C:\Program Files\Oracle\VirtualBox\VBoxManage.exe'
& $VBox list vms
& $VBox showvminfo fml-ops-01 --machinereadable
# 承認済みの空のディスクにのみ対象を新規作成する。
.\lab-v2\Create-PxeTarget.ps1 -Environment prod

テンプレート複製時、hostname、machine-id、SSH host key、MACをそれぞれ新しく作成する。元のテンプレートの固定アドレス・キー・machine-idが複数のVMに残らないように確認する。SELinux Enforcingとfirewalldを維持し、rootリモートログイン・パスワードログインを制限する。

閉域網で構成する場合

ISO、検証済みインストールパッケージ、内部CA、公開鍵と構成テンプレートを持ち込んだ後、同じ内部網構造を作成する。NAT NICを接続していない状態でもOSインストールと内部DNS/NTPにアクセスできなければならない。「NATを後から切った既存インストール」と必要な依存性を持ち込んで最初からインストールを別のテストとして記録する。

このPCでは、新しいBIOS PXE対象の2 vCPUブートが停止したため1 vCPUを使用した。中央第1号機はIntel Core i7-6700K CPU profileで4 vCPUとして実行した。このプロファイル名は実際のPCのCPUではない。Hyper-V/VBS/メモリ整合性は変更していない。詳細なVMの問題は別途ブログで扱う。

3. ルーティング・DNS・NTP・アクセス経路

環境間通信はGatewayのfirewalld policyで許可する。Provisionは各環境に直接接続されてDHCP・PXE・ストレージを提供し、ルーターとしては使用しない。

送信元 宛先 ポート 目的
中央 .11/.12 環境 Edge .10 TCP 22 Bastion侵入
環境 Edge .10 承認された対象 .101 TCP 22 SSH forwarding
環境対象 同じ環境 Edge .10 TCP 10051 Agent Activeデータ
環境 Edge .10 中央 .11/.12 TCP 10051 Active ProxyとHA Server
承認された環境網 VIP 10.77.10.10 TCP 443 NetBox/Zabbix/AWX API・ウェブ
環境対象 同じ環境 Provision .20 DNS 53、NTP 123、HTTP 80、PXE関連ポート インストール・名前解決・時刻・内部ストレージ
中央・quorum 該当内部サービスノード etcd 2379/2380、Patroni 8008、PG 5432/6432、Redis 6379/26379、NFS 2049 データ複製・判定・共有メディア

上表は通信目的の概要である。実際の許可ルールはホストファイアウォールとルーターポリシーを合わせて確認する。DB・etcd・Redisをインターネットやすべての環境網に公開しない。

オンライン網で構成時

管理VMに必要なパッケージをインストールし、内部インターフェースと静的ルートを作成する。インターネット用のデフォルトルートと実習網の静的ルートを混同しないこと。

nmcli connection modify fml-internal \
  +ipv4.routes '10.77.20.0/24 10.77.10.1'
nmcli connection modify fml-internal \
  +ipv4.routes '10.77.30.0/24 10.77.10.1'
nmcli connection modify fml-internal \
  +ipv4.routes '10.77.40.0/24 10.77.10.1'
nmcli device reapply enp0s8
ip route
chronyc tracking

閉域網で構築する場合

内部DNSにおいて netbox.fullmoon.test、zabbix.fullmoon.test、awx.fullmoon.test を VIP 10.77.10.10 に、git.fullmoon.test を 10.77.10.12 に名前解決する。外部DNSのフォールバックに依存しないこと。Provisionのchronyを内部基準として使用しつつ、実際の運用では別途検証済みの時刻源と同期ポリシーを準備する。

getent hosts netbox.fullmoon.test git.fullmoon.test
chronyc sources -v
ip route get 10.77.20.10

ブラウザからのアクセスは、実習CAを信頼する管理端末からHTTPSのホスト名で行う。Windowsから内部ネットワーキングを直接ルーティングしない場合は、ループバックSSHトンネルを使用できる。すでに使用されているローカルの443ポートがないことを事前に確認する。

ssh -i <관리용_개인키> -p 22031 -N -L 127.0.0.1:443:10.77.10.10:443 labadmin@127.0.0.1

管理端末のhostsファイルには3つのサービス名を127.0.0.1に関連付け、検証済みの公開CA証明書を信頼ストアに登録する必要がある。サーバーCAの秘密鍵は持ち込まない。中央1号機の障害テスト中にもアクセスできるようにするため、中央2号機の管理用SSHポート22032を使用する。証明書の警告を無視する方法を通常の接続手順としてはならない。

4. コンテナランタイムと持ち込みバンドル

オンライン網で構築する場合

Docker公式のRHELリポジトリからDocker/Composeをインストールする。Composeプロジェクトのパスは /opt/fullmoon-lab/core、/opt/fullmoon-lab/apps、/opt/fullmoon-lab/edge に分ける。機密性の高い環境ファイルはroot所有の0600、上位ディレクトリは0700にする。

docker version
docker compose version
docker compose --project-directory /opt/fullmoon-lab/core \
  -f /opt/fullmoon-lab/core/compose.yml config --quiet
docker image inspect --format '{{json .RepoDigests}}' \
  zabbix/zabbix-server-pgsql:alpine-7.0.30

レンダリングされたコンポーズの出力全体にはパスワードが含まれる可能性があるため、公開ログに config の内容を保存しないこと。ホストのSELinuxがEnforcingであるかどうかと、DockerデーモンのSELinux統合が有効であるかどうかを区別する。この実習ではホストのEnforcingは維持するが、DockerのSELinux統合まで適用した環境であるとは主張しない。

閉域網で構築する場合

同じCPUアーキテクチャおよびRockyのメジャーリリースを持つ、接続された準備用VMからRPMと依存関係を取得する。DockerイメージのアーカイブとK3s/containerdのアーカイブは別物である。Dockerにイメージをロードしたからといって、K3sで使用できるわけではない。

# 準備用VM:必要なバージョンのRPMとすべての依存パッケージを保存
dnf download --resolve --alldeps --destdir ./rpms \
  docker-ce docker-ce-cli containerd.io docker-compose-plugin
createrepo_c ./rpms
docker image save -o images.tar <반입할_고정_이미지_목록>
sha256sum images.tar > images.tar.sha256

# 閉域網へ持ち込んだ後
sha256sum -c images.tar.sha256
docker image load -i images.tar
k3s ctr images import fullmoon-ee-r2.tar

持ち込みリストは、OSのISO・RPMリポジトリ、Docker/Compose、Patroniビルド結果、NetBox/Zabbix/Redis/etcdイメージ、K3sバイナリおよびエアギャップイメージ、Operator/RBAC proxy/AWX/EEイメージ、Gitバンドル、設定テンプレート・公開CA、署名鍵とチェックサムである。準備用VMのキャッシュのおかげで偶然通過してしまうことがないよう、外部NICを持たない新しいターゲットで検証する。

5. PostgreSQL・etcd・Redisの構成

etcdとSentinelは中央の2ノードとクォーラムノードに配置する。PostgreSQL/PatroniとRedisは中央の2ノードに配置する。DBは NetBox・Zabbix・AWX用のユーザーとデータベースを分離する。

オンライン網で構築する場合

固定イメージをpull/buildし、ノードごとのNODE_NAME/NODE_IP、Patroni設定、Redis/Sentinel設定、制限された機密ファイルを配置する。etcdの3ノードが互いに通信できることを確認した上で、中央DBを開始する。

docker compose --project-directory /opt/fullmoon-lab/core \
  -f /opt/fullmoon-lab/core/compose.yml --profile central up -d
docker compose --project-directory /opt/fullmoon-lab/core \
  -f /opt/fullmoon-lab/core/compose.yml exec -T postgres \
  patronictl -c /etc/patroni/patroni.yml list
curl --fail http://10.77.10.11:8008/patroni
curl --fail http://10.77.10.12:8008/patroni

クォーラムノードはcentralプロファイルなしでetcd・Sentinelのみを実行する。Patroniのsynchronous_modeは有効にし、synchronous_mode_strictはfalseにしてある。レプリケーションの状態と障害時のコミット損失の可能性を、運用条件に合わせて判断する必要がある。2つのDBをそれぞれ手動でプライマリにする方式は使用しない。

閉域網で構築する場合

PatroniのDockerfileがpipやaptなどの外部リポジトリを必要とするため、オンラインの準備段階でイメージを完成させてから持ち込む。現場で即席のビルドを行いインターネット依存関係に直面するやり方は避ける。同じアーカイブを2つの中央ノードにロードし、イメージIDを比較してから同一の手順で起動する。

HAProxyのDB接続ポートは6432である。Patroni /primary が200を返すノードのみをDB書き込み用バックエンドとして使用する。初期の60秒のタイムアウトではアイドル状態のDB接続が切断される可能性があるため、DBリスナーのクライアント/サーバータイムアウトを1時間に分離した。値は実際のクエリやコネクションプールのポリシーに合わせて調整する。

6. VIP・HTTPSとNetBoxの冗長化

KeepalivedのVIPは 10.77.10.10、正常時の優先ノードは ops01 である。2つのノードのHAProxyは、NetBoxを8082、Zabbix Webを8080、AWXを30080に接続する。Node・DB・Redis・VIPのアクティブの役割が常に同じノードである必要はない。

オンライン網で構築する場合

実習CAを使用して3つのウェブ名のSANを含めた証明書を発行し、制限された権限で2つの中央ノードに証明書/キーを配置する。NetBox AppとWorkerには、同じSECRET_KEY、APIトークンペッパー、Redis Sentinel設定を使用する。

# netbox-configuration.pyの主な設定の関係
DATABASES = {'default': {
    'ENGINE': 'django.db.backends.postgresql',
    'NAME': 'netbox', 'USER': 'netbox',
    'PASSWORD': '<비밀_파일에서_주입>',
    'HOST': '127.0.0.1', 'PORT': 6432,
}}
# 両方のAppでSECRET_KEY / API_TOKEN_PEPPERSを一致させる。
# REDISのtasks/cachingにはSentinelのserviceとそれぞれのDB番号を指定する。

デフォルト設定ファイルの実際のバージョン別フォーマットは、提供されたNetBox設定と公式ドキュメントを基準にして使用する。環境変数名のみを合わせてPython設定側で読み込ませないと適用されない。DBの初期マイグレーションはまず1つのノードで完了させ、残りのノードとWorkerを起動する。

メディアはクォーラムの /srv/fullmoon/netbox-media をNFSv4で共有する。中央の2ノードのみエクスポートを許可し、root_squashを維持する。NetBoxイメージの実際のUIDを確認してディレクトリの権限を合わせる。このRocky環境で確認したNFSのSELinuxブール値は virt_use_nfs である。

findmnt /srv/fullmoon/netbox-media
haproxy -c -f /etc/haproxy/haproxy.cfg
keepalived -t -f /etc/keepalived/keepalived.conf
systemctl is-active haproxy keepalived
curl --fail https://netbox.fullmoon.test/login/ -o /dev/null

閉域網で構築する場合

NetBoxイメージには実行に必要なPythonの依存関係が含まれているため、同じダイジェストのイメージを2つのノードに持ち込む。内部CAをホストだけでなくAWX EEにも配置する。2つのノードのSECRET_KEY/pepperが異なってしまわないよう、秘密情報の復元手順も用意しておく。NFSの中断は、ウェブAPIの成功とは別にメディアに影響を与えるため、個別にテストする。

実際に遭遇した問題はNetBoxのヘルスチェックであった。HTTP/1.1のHostヘッダーなしで /login/ を検証すると、NetBoxが400を返し、HAProxyがすべてのバックエンドをダウンと判定してVIPが503を返した。次のようにHostを指定した。

backend netbox_ui
    mode http
    option httpchk
    http-check send meth GET uri /login/ ver HTTP/1.1 hdr Host netbox.fullmoon.test
    http-check expect status 200
    server ops01 10.77.10.11:8082 check
    server ops02 10.77.10.12:8082 check

障害テストでは、Redis接続のデフォルトの再試行により、NetBoxのキャッシュ照会1回あたり約55.6秒かかった。インストールされているNetBox 4.7.1とdjango-redisのコードを確認し、ローカルのSentinelを最初に照会するように変更した。キャッシュには、サポートされているKWARGSに接続・応答タイムアウトとリトライポリシーを明記した。ループバックは同じSentinelの別の接続アドレスであり、過半数の構成メンバーが追加されたわけではない。

from redis.backoff import NoBackoff
from redis.retry import Retry

# 各NetBoxノードのローカルSentinelを最初に問い合わせる。
SENTINELS = [('127.0.0.1', 26379), ('10.77.10.13', 26379),
             ('10.77.10.11', 26379), ('10.77.10.12', 26379)]
REDIS['caching']['KWARGS'] = {
    'socket_connect_timeout': 3,
    'socket_timeout': 3,
    'retry': Retry(NoBackoff(), 0),
}

エラーを迅速に返すように制限した値であるため、個別リクエストのリトライとサービスの復旧時間は異なる。実際のDB/Redisプライマリ障害からAPI回復までの時間は検証記事で確認する。運用負荷や他のバージョンでも同じ結果になると一般化してはならない。

7. Zabbix LTS HAと環境別Proxy/Bastion

オンライン網で構築する場合

Server/Web/Proxyには alpine-7.0.30 タグを使用し、Rocky対象のAgent 2にはel10用の 7.0.30 RPMを使用する。2つのServerは共通のZabbix DBを参照するようにするが、HANodeNameとNodeAddressは別々に設定する。Webは特定のServerアドレスを固定せず、HA情報からアクティブノードを見つけるように設定した。

# ops01
ZBX_HANODENAME=fml-ops-01
ZBX_NODEADDRESS=10.77.10.11:10051
# ops02
ZBX_HANODENAME=fml-ops-02
ZBX_NODEADDRESS=10.77.10.12:10051
# Active Proxyの同一HAクラスタに属するアドレスはセミコロンで連結
ZBX_SERVER_HOST=10.77.10.11:10051;10.77.10.12:10051

Proxy名はZabbix APIに登録した名前と完全に一致している必要がある。環境ごとのProxy PSKとAgent PSKを区別する。ProxyのSQLiteデータは永続ボリュームに置き、ディスクバッファポリシーを適用する。切断後の遅延データを再送したかどうかまで確認して初めて、バッファの動作を検証できたと言える。

閉域網で構築する場合

Proxyイメージはdocker loadで持ち込む。Agent RPMは内部リポジトリとして提供し、GPG署名検証を維持する。このel10 RPMはB5333005キーで検証した。従来のA14FE591キーのみを使用する構成では検証に失敗したため、公式署名キーのfingerprintを確認して追加した。

rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-ZABBIX-B5333005
rpm -K zabbix-agent2-7.0.30-release1.el10.x86_64.rpm
# 検証済みの鍵のフィンガープリント
# 4C3D6F2CC75F5146754FC374D913219AB5333005

Bastionは環境対象の.101:22にのみforwardingする。対話型シェルとagent forwardingは許可しない。中央のキーを使用して対象まで接続し、秘密鍵をEdgeに置かない。従来の管理アカウントのSSHアクセスを保持した状態でsshd -tで検査し、reloadする。

Match User bastion
    AuthenticationMethods publickey
    AllowTcpForwarding local
    PermitOpen 10.77.20.101:22
    PermitTTY no
    AllowAgentForwarding no
    ForceCommand /bin/false
Match all

8. Git・K3s・AWXと実行環境

オンライン網で構築する場合

Git bare repositoryはops02の/srv/git/fullmoon-automation.gitである。AWXはfmlgitの読み取り専用デプロイキーでmain branchを取得する。forced commandはgit-shellが解釈できるようにパスまでシングルクォーテーションで囲んだ。

restrict,command="git-upload-pack '/srv/git/fullmoon-automation.git'" ssh-ed25519 <공개키>

ops01にK3sをインストールし、SELinuxとSecret暗号化を有効化した。Traefik・ServiceLB・metrics-serverはこの実習に不要なため除外した。AWXはOperator 2.19.1とAWX 24.6.1に固定し、PostgreSQL Secretは既存HA DBの6432パスを指す。管理者パスワード・DBパスワード・CA bundleはKubernetes Secretとして注入する。

k3s kubectl -n awx get pods,jobs
k3s kubectl -n awx apply -f awx.yml
curl --fail https://awx.fullmoon.test/api/v2/ping/

Operatorの初期RBAC proxyイメージのgcr.ioパスが404だったため、同じv0.15.0の公式quay.io/branczイメージに修正した。AWX CRDでcookie設定は文字列、host_aliasesは配列である必要がある。SYSTEM_TASK_ABS_MEMを数値として入れると、該当のAWXコードが文字列メソッドを呼び出し、dispatcherが失敗するため、不要な手動設定を削除した。

閉域網で構築する場合

K3s airgapイメージとOperatorが生成するすべてのイメージまで持ち込む。特にinit/migration/EE/RBAC proxyイメージが抜けると、Webイメージだけでもインストールされない。K3s containerdにimport後、実際のイメージ名がCRの名前と一致するか確認する。

実習EEはawx-ee:24.6.1にnetbox.netbox:3.23.0、公開CA、検証したGit/Edge SSH host keyを追加した。イメージ名はlocalhost/fullmoon-ee:24.6.1-netbox3.23.0-r2であり、AWX実行環境のpullポリシーはNeverである。名目にlocalhostがあるからといってregistryを実行したわけではなく、K3sに事前にimportしたローカルイメージを使用する。

k3s ctr images import fullmoon-ee-r2.tar
k3s ctr images list
git bundle verify fullmoon-automation.bundle

AWXにはProject、承認済みbootstrap inventory、NetBox inventory source、SSH credential、NetBox/Zabbix API credential、Onboard/Verify Job Template、Workflowを作成する。Workflowの成功パスはOnboard → NetBox inventory sync → Verifyである。AWX自体は中央1号機の単一構成である。API pingのhaフィールドだけで物理分散HAとは判断しない。

9. PXE・Kickstartによる空サーバーのインストール

オンライン網で構築する場合

公式Rocky Minimal ISOを検証し、Provisionの/var/www/html/rockyにインストールツリーを提供する。実際のISOにはMinimal/repodataがある。DVDのBaseOS/AppStreamパスをそのまま使うと404が発生する。DHCPは環境別の承認済みMACのみ.101にマッピングする。

fml-prod-app-01 : 08:00:27:a0:20:65 → 10.77.20.101
fml-dev-app-01  : 08:00:27:a0:30:65 → 10.77.30.101
fml-stg-app-01  : 08:00:27:a0:40:65 → 10.77.40.101

このPCのVirtualBoxではBIOS + 公式ipxe-legacy.isoがDHCP→HTTP kernel/initrd→Kickstartまで動作した。iPXEファイルはネットワークインストールを開始するブートメディアであり、OSパッケージはProvisionから受け取る。新しいVMは空の32GiBディスク、インストールRAM 4GiB、1 vCPUで作成し、インストール後に1GiBに減らす。

Kickstartの%preは、MAC、DMIのVirtualBox識別、/dev/sdaの存在、ディスク署名の欠如を確認した後にのみパーティション作業を許可する。rootパスワードをロックし、labadmin公開鍵・sshd・sudo・chrony・firewalldを構成する。%postが残したSSH host keyは、信頼するVMコンソールログと比較して登録する。unknown host keyを無条件に受け入れない。

閉域網で構築する場合

同じISO・ブートファイル・Kickstartを内部HTTPに持ち込む。対象には外部NICがなく、DNS/NTP/パッケージを同じ環境のProvisionから受け取る。Agent 2用の内部リポジトリまで構成すれば、外部RPMリポジトリがなくても基本設定を実行できる。

物理サーバーに適用する場合には、VirtualBox DMI guardをそのまま削除して実行してはならない。承認された実際のserial/BMC/MAC、RAID論理ディスクとインストール対象WWN、UEFI/Secure Boot・NICドライバを別途マッピングした上で、ディスク破壊の範囲を検討する必要がある。この記事の実際のインストールの証拠はVMであり、物理サーバーの実機検証結果に置き換えて表現しない。

10. 資産API・インベントリ・監視の連携

オンライン網で構築する場合

NetBoxの資産書き込みアカウントには必要なVM/Device/Interface/IP/カタログ権限を付与し、inventoryアカウントは参照のみ許可する。初期のCustom Fieldとカタログ作成は別個のbootstrapとして実行する。NetBox 4.7のv2トークンはBearer nbt_形式である。Zabbix自動化アカウントは管理対象グループとAPIメソッドを制限し、トークンに有効期限を設定する。

plugin: netbox.netbox.nb_inventory
api_endpoint: https://netbox.fullmoon.test
token:
  type: Bearer
  value: "{{ lookup('env', 'NETBOX_TOKEN') }}"
validate_certs: true
query_filters:
  - tag: auto
  - status: active

収集段階では、任意の一時ディレクトリにPython collectorを配備して実行し、常に削除する。対象の実際のhostname・machine ID・管理NIC/IPを承認済みinventoryと比較する。値が異なるか、既存のIPが別の資産に割り当てられている場合は、NetBoxの変更前に中断する。API tokenや/proc環境全体を収集結果に含めない。

API作業はdelegate_to: localhostとしてAWX EEで実行する。対象用のansible_become変数がローカル作業に伝播すると、EE内でsudoを探して失敗する場合があるため、次のように明示する。

delegate_to: localhost
become: false
vars:
  ansible_become: false
  ansible_python_interpreter: "{{ ansible_playbook_python }}"

登録順序は、実際の資産/Interface/IPAM → Zabbix host/Proxy/template → NetBox inventory source sync → 対象のbaselineと最新のZabbixデータの検証である。NetBoxとZabbix APIは単一のDB transactionではないため、部分的な成功後の再実行をサポートし、成功した資産を無条件に削除する補正作業は行わない。

閉域網で構築する場合

APIコードは内部HTTPSのみを使用するため、方式は同じである。EEのCA、collection、Pythonライブラリ、pinned SSH host keyとGitコミットがすべて持ち込まれている必要がある。ジョブの実行中にGalaxyやpipからパッケージをダウンロードしない。targetにはfullmoon-minimal・fullmoon-zabbixリポジトリのみを明示してAgentをインストールする。

ServerActive=10.77.20.10:10051
Hostname=fml-prod-app-01
TLSConnect=psk
TLSAccept=psk
TLSPSKIdentity=fml-prod-app-01
TLSPSKFile=/etc/zabbix/agent.psk

PSKファイルはzabbix所有の0400とし、AWXログには値を残さない。管理ホストの重複の有無と、最新のitemのlastclock/lastvalueまで確認する。ホスト作成の応答だけで完了処理とはしない。

インストールの完了とWorkflowの自動連携

中央1号機のfullmoon-postinstall.timerが承認対象のインストールの完了を確認する。SSHは該当のBastionを経由し、固定したhost keyを検証する。/var/lib/fullmoon-lab/pxe-installed、hostname、machine IDが一致すれば、Project sync → bootstrap inventory sync → 対象1台をlimitに指定したWorkflowを実行する。ジョブIDと状態はrootのみが読み取るstate.jsonに残す。

最初に生成したSSH host keyは、信頼できるVirtualBox serial consoleと照合して承認リストに追加する。この身元の承認前まではコントローラーが待機する。不明なキーを自動で受け入れない。以降、インストールの完了検知とAPI登録・監視検証が自動的に続く。物理サーバーでは、この身元の登録をBMCコンソールまたは組織のSSH CA発行手順と連携させる必要がある。

systemctl status fullmoon-postinstall.timer
journalctl -u fullmoon-postinstall.service --since '-30min'
# 成功:launched → AWX workflow ID → completed
# 失敗:manual_review_required。原因を確認するまで自動で再登録しない。

このコントローラーとAWXはops01にあるため、該当ノードの障害中は新規のオンボーディングが停止する。Gitがあるops02が停止すると、新しいProject syncが失敗する。状態ファイルを失うか、実行応答の直後にプロセスの終了時に同じWorkflowが再試行される可能性があるため、資産登録自体も識別子とIPの重複を検査する再実行可能な方式で構成した。

11. 接続情報と簡単な運用ガイド

機能 接続経路 稼働確認
NetBox https://netbox.fullmoon.test VM/Device、Interface、primary IP、collectionの状態
Zabbix https://zabbix.fullmoon.test HAの状態、Proxy last access、hostの最新データ
AWX https://awx.fullmoon.test Project revision、inventory update、Workflow/Jobの結果
Git ssh://fmlgit@git.fullmoon.test/srv/git/fullmoon-automation.git 読み取り専用SCM同期
管理SSH loopback 22031〜22038 該当VMのlabadmin公開鍵認証
対象SSH 環境別Bastion経由 承認済みhost keyと.101:22の制限

日常点検は、時刻同期・ディスク/メモリ → DB/Redisロール → App/Worker → HA/VIP → Proxy → 実際のAgentデータ → 最近のAWX失敗の順に行う。コンテナがUpであることの確認だけで済ませない。

df -h
free -m
chronyc tracking
docker ps --format '{{.Names}} {{.Status}}'
k3s kubectl -n awx get pods
systemctl is-active haproxy keepalived

新規サーバーを追加する際は、承認済みinventory・MAC/IP・Bastion PermitOpen・SSH host keyを先に登録し、Gitにコミットする。Project sync後、該当ホストのみをlimitに指定する。NetBoxのprimary IPと環境グループを確認してから本番対象に移行する。稼働中のサーバー全体を無制限のall対象に変更しない。

パスワード変更およびトークン更新では、シークレットストレージ・AWX Credential・サービス再起動の範囲を合わせて管理する。期限切れのトークン、変更されたSSH host key、異なるmachine IDを自動的にバイパスしない。ノード障害後は、生存しているprimaryを基準にレプリカを復旧させ、分離されたノードを勝手に書き込み有効化してはならない。

12. バックアップ・アップデート・検証による仕上げ

PostgreSQLの論理バックアップ、NetBox media、Git repository、AWX SECRET_KEYとDB、CA/設定/機密データをそれぞれ管理する。VM snapshotだけでアプリケーション整合性のあるバックアップの代わりにしてはならない。バックアップファイルが存在することと、隔離されたDBに復元して同じ資産を読み込めることは別の検証である。

アップデートは画像tag・digestとEE/collectionを合わせて記録し、検証後に進める。NetBoxのmigrationやDBのmajor upgradeは、以前のイメージに戻すだけでは復旧できない場合があるため、データバックアップ・復元手順を準備する。閉域網ではアップデート搬入バンドルとchecksumを新たに作成し、以前の検証済みバンドルを保管する。

構築完了の判定には、資産登録、inventory sync、最新の監視値、再実行、アドレス競合拒否、サービス障害フェイルオーバー、Proxyバッファ復旧、バックアップ復元、外部通信のない対象へのインストールを含める。実際に実施したテストと未実施の項目は、検証プロジェクトに分けて記録する。

関連記事および構成資料

ポートフォリオ原文 · オンライン網・閉域網構築ガイド · 障害シナリオ・検証記録 · VirtualBox構成トラブルシューティング記録

実習設定・自動化ソースZIP · ZIP SHA-256

公開ZIPには構成テンプレートと自動化ソースが含まれています。OS・RPM・コンテナイメージおよび資格情報は含まれません。独自のアドレス・公開CA・承認済みSSHキー・シークレットストレージで構成した後に適用してください。