📚 シリーズ:インフラ運用 × 生成AI 実践レシピ集
① 障害対応の初動をAIで加速する
② 構成管理ドキュメントをAIで自動生成する
③ 監視アラートをAIでトリアージする
④ IaCテンプレートをAIと共同作成する(本記事)← ★今ここ
🔗 前シリーズ:生成AIを武器にするインフラエンジニアへの道(全3記事)
はじめに
サーバーの構築や設定変更を手作業で行うと、手順の抜け漏れや設定ミスが起きやすくなります。担当者ごとに微妙に異なる設定が入ることもあり、再現性のない環境が生まれる原因になります。
IaC(Infrastructure as Code)は、インフラの構築・設定をコードとして管理する手法です。シェルスクリプトやAnsible Playbookでサーバー設定をコード化すれば、「誰が実行しても同じ結果」が得られます。しかし、IaCを書き始めるハードルは低くありません。Ansibleの構文、YAMLのインデントルール、冪等性の考慮など、習得すべき知識が多く、最初の1本を書き上げるまでに時間がかかります。
この記事では、AIを「ペアプログラミングの相手」として活用し、IaCテンプレートの作成を効率化する方法を扱います。ゼロからコードを書くのではなく、要件をAIに伝えてたたき台を生成させ、人間がレビュー・修正するアプローチです。
AIが得意なこと・苦手なことを整理すると以下の通りです。
| AIが得意なこと | AIが苦手なこと |
|---|---|
| 構文が正確なコードの生成 | 環境固有のIPアドレス・ホスト名・パスワード |
| ベストプラクティスの適用(エラーハンドリング、セキュリティ設定) | 組織固有のポリシー・命名規則 |
| 既存コードの改善点の指摘 | バージョン依存の仕様変更(AIの学習データが古い場合) |
この記事で扱う3つのステップは以下の通りです。
- シェルスクリプトをAIで生成する ― サーバー初期設定スクリプトのたたき台を作成する
- Ansible PlaybookをAIで生成する ― 手順書からPlaybookに変換する
- AIにコードレビューさせる ― セキュリティ・可読性の問題点を指摘させ、改善する
手作業とAI活用の比較は以下の通りです。
| 項目 | 手作業 | AI活用 |
|---|---|---|
| シェルスクリプト作成 | 1〜2時間 | 15〜30分(生成 + レビュー) |
| Ansible Playbook作成(手順書から変換) | 2〜4時間 | 30分〜1時間(生成 + レビュー) |
| コードレビュー | 30分〜1時間(レビュアーの確保が必要) | 5〜10分(即座にレビュー可能) |
※AI活用の時間はプロンプト送信・AI応答・人間のレビュー・修正を含む目安です。
前提条件
この記事は、以下の前提知識を持つ方を対象としています。
- 記事①のプロンプト設計の基礎知識(4要素の理解)
- Linuxのコマンドライン操作ができる(ユーザー作成、パッケージ管理、サービス管理等)
- Ansible / シェルスクリプトの経験は不要(記事内で必要な範囲を説明します)
検証環境
| 項目 | 内容 |
|---|---|
| OS | AlmaLinux 10 minimal |
| AIモデル | Claude Sonnet 4.6(Anthropic公式Web UI) |
| Ansible | ansible-core(dnf install ansible-core でインストール) |
| Bash | デフォルトで利用可能 |
記事中のプロンプト例はすべてClaude Sonnet 4.6で動作確認しています。ChatGPTなど他のモデルでも基本的な考え方は共通ですが、XMLタグによる構造化はClaude固有の強みであるため、他モデルでは効果が異なる場合があります。
シェルスクリプトをAIで生成する
Before/After: スクリプト作成方法の比較
Before(手作業でゼロから作成)
サーバー初期設定スクリプトを一から書く場合、以下の問題が起きやすくなります。
- 構文ミス(引用符の閉じ忘れ、変数展開の誤り)で実行時エラーが発生する
- エラーハンドリングを入れ忘れ、途中で失敗しても後続処理が実行される
- セキュリティ設定(SSH強化、不要サービスの停止)が漏れる
- 担当者によって書き方が異なり、チーム内で統一されない
改善ポイント: 要件をプロンプトで構造化してAIに渡し、エラーハンドリング・セキュリティ設定を含むたたき台を生成させます。
プロンプト設計
シェルスクリプト生成用のプロンプトです。記事①の4要素(役割・状況・ログ・出力形式)をベースにしています。IaCの生成では「ログ」の代わりに「要件」を渡します。
<role>
あなたはLinuxサーバーのシェルスクリプト作成を支援するアシスタントです。
本番環境で使用するスクリプトを作成するため、エラーハンドリングと
セキュリティのベストプラクティスに従ってください。
</role>
<requirements>
以下の要件に基づいて、サーバー初期設定用のBashスクリプトを作成してください。
【対象OS】AlmaLinux 10
【実行ユーザー】root(初回セットアップ時のみ)
【実施内容】
1. 運用ユーザー「operator」の作成(sudo権限付与)
2. SSH設定の強化
- パスワード認証の無効化
- rootログインの無効化
3. firewalld設定
- SSHのみ許可(デフォルトゾーン: public)
4. タイムゾーン設定(Asia/Tokyo)
【制約】
- スクリプト冒頭に set -euo pipefail を記述すること
- 各処理の前にコメントで「何をしているか」と「なぜそうするか」を記載すること
- 環境固有の値(ユーザー名等)は変数として冒頭で定義すること
- パスワードはスクリプト内にハードコーディングしないこと
</requirements>
<output_format>
以下の形式で出力してください:
1. 実行可能なBashスクリプト(shebang付き)
2. スクリプトの実行方法
3. 実行後の確認コマンド(各設定が正しく反映されたかの検証用)
推測で設定値を決めないでください。
要件に記載のない設定項目は含めないでください。
不明な点は「確認が必要な項目」として列挙してください。
</output_format>
【実演】サーバー初期設定スクリプトの生成
上記のプロンプトをAIに送信すると、以下のようなスクリプトが生成されます。
AIの期待出力例:
1. サーバー初期設定スクリプト
#!/bin/bash # # サーバー初期設定スクリプト # 対象OS: AlmaLinux 10 # 用途: 新規サーバーの初期セットアップ # set -euo pipefail # ============================================================================== # 変数定義 # 環境固有の値をここで一元管理する # ============================================================================== OPERATOR_USER="operator" SSH_CONFIG="/etc/ssh/sshd_config" TIMEZONE="Asia/Tokyo" # ============================================================================== # 1. 運用ユーザーの作成 # 理由: rootで日常運用を行うとオペミスの影響範囲が大きいため、 # 一般ユーザーにsudo権限を付与して運用する # ============================================================================== echo ">>> 運用ユーザー '${OPERATOR_USER}' を作成します" if id "${OPERATOR_USER}" &>/dev/null; then echo "ユーザー '${OPERATOR_USER}' は既に存在します。スキップします。" else useradd -m -s /bin/bash "${OPERATOR_USER}" echo "ユーザー '${OPERATOR_USER}' を作成しました。" fi # sudo権限の付与 # 理由: 管理作業にはroot権限が必要だが、常時rootで作業するリスクを避ける echo ">>> sudo権限を付与します" usermod -aG wheel "${OPERATOR_USER}" echo "ユーザー '${OPERATOR_USER}' をwheelグループに追加しました。" # パスワードの設定を促す(ハードコーディングしない) echo ">>> 運用ユーザーのパスワードを設定してください" passwd "${OPERATOR_USER}" # ============================================================================== # 2. SSH設定の強化 # 理由: パスワード認証とrootログインを無効化し、不正アクセスのリスクを低減する # ============================================================================== echo ">>> SSH設定を強化します" # 設定変更前にバックアップを取得 cp "${SSH_CONFIG}" "${SSH_CONFIG}.bak.$(date +%Y%m%d%H%M%S)" # パスワード認証の無効化 sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' "${SSH_CONFIG}" # rootログインの無効化 sed -i 's/^#*PermitRootLogin.*/PermitRootLogin no/' "${SSH_CONFIG}" # 設定の反映 systemctl restart sshd echo "SSH設定を変更し、sshdを再起動しました。" # ============================================================================== # 3. firewalld設定 # 理由: 不要なポートを閉じ、SSHのみ許可することで攻撃対象面を最小化する # ============================================================================== echo ">>> firewalldを設定します" systemctl enable --now firewalld firewall-cmd --set-default-zone=public firewall-cmd --permanent --zone=public --add-service=ssh firewall-cmd --reload echo "firewalld設定が完了しました。" # ============================================================================== # 4. タイムゾーン設定 # 理由: ログのタイムスタンプを日本時間で統一し、障害調査時の時刻照合を容易にする # ============================================================================== echo ">>> タイムゾーンを ${TIMEZONE} に設定します" timedatectl set-timezone "${TIMEZONE}" echo "タイムゾーンを ${TIMEZONE} に設定しました。" # ============================================================================== # 完了メッセージ # ============================================================================== echo "" echo "==============================" echo " 初期設定が完了しました" echo "==============================" echo "" echo "【確認事項】" echo "1. 運用ユーザー '${OPERATOR_USER}' でSSH公開鍵認証の設定を行ってください" echo "2. 公開鍵認証でログインできることを確認してから、このセッションを終了してください" echo "3. rootでのSSHログインが無効化されているため、ロックアウトに注意してください"2. 実行方法
chmod +x server_init.sh sudo ./server_init.sh3. 実行後の確認コマンド
# ユーザーが作成されたか id operator # sudo権限があるか groups operator # SSH設定が反映されているか grep -E "^PasswordAuthentication|^PermitRootLogin" /etc/ssh/sshd_config # firewalldの状態 firewall-cmd --list-all # タイムゾーンの確認 timedatectl
人間がレビューすべきポイント
AIが生成したスクリプトを受け取ったら、以下の4点を確認してください。
| # | 確認項目 | 確認の理由 |
|---|---|---|
| 1 | 環境固有の値(ユーザー名、ポート番号等)が自組織のルールに合っているか | AIはプロンプトの要件通りに生成するが、組織の命名規則までは把握していない |
| 2 | SSH設定変更後にロックアウトされないか | パスワード認証を無効化する前に、公開鍵認証の設定が完了している必要がある |
| 3 | set -euo pipefail が先頭にあるか | エラー発生時にスクリプトが停止することを保証する |
| 4 | 冪等性があるか(2回実行しても問題ないか) | ユーザー作成の重複チェックなど、再実行時にエラーにならないか確認する |
AI生成スクリプトを本番環境で直接実行しない
AIが生成したスクリプトは、必ずテスト環境(検証用VM等)で動作確認してから本番に適用してください。とくにSSH設定の変更は、設定ミスでサーバーにログインできなくなるリスクがあります。テスト環境で公開鍵認証 → パスワード認証無効化の手順を検証してください。
Ansible PlaybookをAIで生成する
Ansibleの基本構造
Ansible Playbookは、サーバーに対する操作をYAML形式で記述したファイルです。基本的な階層構造は以下の通りです。
- Playbook ― 1つ以上のPlayを含むYAMLファイル
- Play ― 「どのホストに」「何をするか」を定義する単位
- Task ― 1つ1つの処理ステップ(Moduleを呼び出す)
- Handler ― タスクで変更が発生したときだけ実行される処理
Ansibleの最大の特徴は冪等性です。同じPlaybookを何度実行しても、結果が同じになります。例えば「nginxをインストールする」というタスクは、既にインストール済みであればスキップされます。シェルスクリプトでは if 文で存在チェックを書く必要がありますが、Ansibleのモジュールはこの判断を自動で行います。
Before/After: Playbook作成方法の比較
Before(手順書を見ながら手動でPlaybook化)
記事②で作成した作業手順書を見ながら、Ansible Playbookを手作業で書く場合:
- YAMLのインデントミスで構文エラーが頻発する(スペース2つ vs 4つの混在等)
- 適切なモジュールの選択に公式ドキュメントの参照が必要(所要時間: 2〜4時間)
- 冪等性を壊すタスクを書いてしまう(
ansible.builtin.shellの安易な使用等)
プロンプト設計(手順書 → Playbook変換)
以下は、手順書をAnsible Playbookに変換するためのプロンプトです。
<role>
あなたはAnsible Playbookの作成を支援するアシスタントです。
以下の手順書をAnsible Playbookに変換してください。
</role>
<requirements>
【対象OS】AlmaLinux 10
【Ansible バージョン】ansible-core 2.17以降
【モジュール】ansible.builtin.* および ansible.posix.* のFQCN形式
(Fully Qualified Collection Name: コレクション名を含む完全修飾モジュール名)を使用すること
【変換ルール】
1. 各手順をAnsibleの適切なモジュールにマッピングすること
2. ansible.builtin.shell / ansible.builtin.command は、
専用モジュールが存在しない場合のみ使用すること
3. 変数化すべき値(パッケージ名、設定値等)は vars セクションで定義すること
4. 設定ファイルの変更時はハンドラーでサービスを再起動すること
5. 各タスクに name を付け、処理内容がわかるようにすること
</requirements>
<procedure>
(ここに手順書を貼り付け)
</procedure>
<output_format>
以下の形式で出力してください:
1. Ansible Playbook(YAML形式、コメント付き)
2. 必要な前提条件(ansible-galaxy collection install 等)
3. 実行方法(ansible-playbook コマンド)
4. 各タスクの解説(手順書のどのステップに対応するか)
推測で設定値を決めないでください。
手順書に記載のないステップは含めないでください。
不明な点は「確認が必要な項目」として列挙してください。
</output_format>
【実演】nginx設定Playbookの生成
以下の手順書をAIに渡して、Playbookに変換します。
入力する手順書(抜粋):
<procedure>
作業手順書: nginx Webサーバーのセットアップ
1. nginxパッケージをインストールする
コマンド: dnf install -y nginx
2. nginx設定ファイルを配布する
- /etc/nginx/nginx.conf を所定の設定に書き換える
- worker_processes: auto
- server_tokens: off(バージョン情報の非表示)
3. nginxサービスを起動し、自動起動を有効にする
コマンド: systemctl enable --now nginx
4. firewalldでHTTP/HTTPSを許可する
コマンド: firewall-cmd --permanent --add-service=http
コマンド: firewall-cmd --permanent --add-service=https
コマンド: firewall-cmd --reload
5. 動作確認
コマンド: curl -I http://localhost
期待結果: HTTP/1.1 200 OK
</procedure>
AIの期待出力例:
1. Ansible Playbook
--- # nginx Webサーバーセットアップ Playbook # 対象OS: AlmaLinux 10 # 用途: nginxのインストール・設定・起動 - name: nginx Webサーバーのセットアップ hosts: webservers become: true vars: # 変数定義: 環境に応じて変更する値をここで管理 nginx_worker_processes: "auto" nginx_server_tokens: "off" nginx_service_name: "nginx" handlers: # 設定ファイル変更時にnginxを再起動するハンドラー - name: Restart nginx ansible.builtin.systemd_service: name: "{{ nginx_service_name }}" state: restarted tasks: # ------------------------------------------------------------------ # 手順1: nginxパッケージのインストール # ------------------------------------------------------------------ - name: nginxパッケージをインストールする ansible.builtin.dnf: name: nginx state: present # ------------------------------------------------------------------ # 手順2: nginx設定ファイルの配布 # server_tokensをoffにし、バージョン情報を非表示にする # ------------------------------------------------------------------ - name: nginx設定ファイルを配布する ansible.builtin.copy: dest: /etc/nginx/nginx.conf content: | user nginx; worker_processes {{ nginx_worker_processes }}; error_log /var/log/nginx/error.log; pid /run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent"'; access_log /var/log/nginx/access.log main; sendfile on; keepalive_timeout 65; server_tokens {{ nginx_server_tokens }}; include /etc/nginx/conf.d/*.conf; } owner: root group: root mode: '0644' backup: yes notify: Restart nginx # ------------------------------------------------------------------ # 手順3: nginxサービスの起動と自動起動の有効化 # ------------------------------------------------------------------ - name: nginxサービスを起動し自動起動を有効にする ansible.builtin.systemd_service: name: "{{ nginx_service_name }}" state: started enabled: true # ------------------------------------------------------------------ # 手順4: firewalldでHTTP/HTTPSを許可する # ------------------------------------------------------------------ - name: firewalldでHTTPサービスを許可する ansible.posix.firewalld: service: http permanent: true immediate: true state: enabled - name: firewalldでHTTPSサービスを許可する ansible.posix.firewalld: service: https permanent: true immediate: true state: enabled2. 前提条件
# ansible.posix コレクションのインストール ansible-galaxy collection install ansible.posix3. 実行方法
# 構文チェック ansible-playbook nginx_setup.yml --syntax-check # ドライラン(実際には変更を加えない) ansible-playbook nginx_setup.yml --check --diff # 実行 ansible-playbook nginx_setup.yml -i inventory.ini4. 各タスクの解説
手順書のステップ Playbookのタスク 使用モジュール 1. nginxインストール nginxパッケージをインストールする ansible.builtin.dnf 2. 設定ファイル配布 nginx設定ファイルを配布する ansible.builtin.copy 3. サービス起動 nginxサービスを起動し自動起動を有効にする ansible.builtin.systemd_service 4. firewalld設定 HTTP/HTTPSサービスを許可する ansible.posix.firewalld 5. 動作確認 Playbookには含めない(手動で実施) ―
人間がレビューすべきポイント
| # | 確認項目 | 確認の理由 |
|---|---|---|
| 1 | モジュール名がFQCN形式(ansible.builtin.dnf 等)になっているか | 短縮形(dnf)は将来非推奨になる可能性がある |
| 2 | YAMLのインデントが正しいか | スペース2つの統一が崩れると構文エラーになる |
| 3 | 冪等性が担保されているか | ansible.builtin.shell / ansible.builtin.command を使っている箇所は冪等性が壊れる可能性がある |
| 4 | 設定ファイルの内容が自環境に合っているか | AIが生成したnginx.confは汎用的な設定のため、自環境の要件と照合する |
| 5 | ハンドラーが正しく定義されているか | notify の名前と handlers の名前が一致しないと動作しない |
AIが間違いやすいポイント
| # | 間違いの種類 | 具体例 | 対処方法 |
|---|---|---|---|
| 1 | インデント崩れ | タスクのインデントが2スペースと4スペースで混在する | ansible-playbook --syntax-check で検出 |
| 2 | 廃止モジュールの使用 | yum モジュールを使用(AlmaLinux 10では ansible.builtin.dnf が正しい) | 公式ドキュメントでモジュール名を確認 |
| 3 | 冪等性の欠如 | ansible.builtin.shell: firewall-cmd --add-service=http と記述(専用モジュール ansible.posix.firewalld を使うべき) | shell / command を使っている箇所を専用モジュールに置き換え |
| 4 | ファイルパスの環境依存 | CentOS 7のパスを出力する(例:/etc/sysconfig/ 配下の設定ファイル) | AlmaLinux 10でのパスを確認 |
| 5 | ハンドラー名の不一致 | notify: restart nginx と name: Restart Nginx で大文字小文字が異なる | notify と handlers の名前を完全一致させる |
AIが生成するPlaybookは「たたき台」
AIが生成したPlaybookは、ansible-lint で構文チェックを行い、--check --diff モードで安全に確認してください。本番環境への直接適用は避けてください。
# ansible-lintのインストール
pip install ansible-lint
# 構文チェック
ansible-lint nginx_setup.yml
# ドライラン
ansible-playbook nginx_setup.yml --check --diff
AIにコードレビューさせる
AIをコードレビュアーとして活用する
自分が書いたスクリプトやPlaybookを、他のエンジニアにレビューしてもらう前にAIでチェックできます。AIはセキュリティ・可読性・保守性の観点で機械的にチェックするのが得意です。人間のレビュアーの時間を使う前に、AIで基本的な問題を洗い出しておくと効率的です。
プロンプト設計(コードレビュー用)
<role>
あなたはLinuxインフラのコードレビュアーです。
以下のスクリプトをレビューし、問題点と改善案を提示してください。
</role>
<review_criteria>
以下の観点でレビューしてください:
1. セキュリティ(認証情報のハードコーディング、不要な権限等)
2. エラーハンドリング(異常時の動作、ロールバック)
3. 可読性(コメント、変数名、構造化)
4. 保守性(変数化、再利用性、設定値の外部化)
5. 冪等性(再実行時に問題が発生しないか)
</review_criteria>
<code>
(ここにレビュー対象のコードを貼り付け)
</code>
<output_format>
以下の形式で出力してください:
問題点ごとに:
- 重大度: 高 / 中 / 低
- 該当箇所: 問題のあるコード行
- 問題の内容: 何が問題か
- 修正案: どう修正すべきか(修正後のコードを含む)
最後に、修正をすべて反映した改善後のスクリプト全文を出力してください。
推測で環境情報を補完しないでください。
コードに記載のない要件は追加しないでください。
不明な点は「不明」と回答してください。
</output_format>
【実演】問題を含むシェルスクリプトのレビュー
以下は、意図的に問題を含むサーバー初期設定スクリプトです。このスクリプトをAIにレビューさせます。
レビュー対象スクリプト(問題あり):
#!/bin/bash
# サーバー初期設定スクリプト
# ユーザー作成
useradd operator
echo "P@ssw0rd123" | passwd --stdin operator
usermod -aG wheel operator
# SSH設定
sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
systemctl restart sshd
# firewalld
firewall-cmd --permanent --add-service=ssh
firewall-cmd --reload
# パッケージインストール
dnf install -y $PACKAGES
# 設定ファイルのコピー
cp /tmp/app.conf /etc/myapp/app.conf
chown root:root /etc/myapp/app.conf
# タイムゾーン
timedatectl set-timezone Asia/Tokyo
echo "完了"
AIの期待出力例:
問題1
- 重大度: 高
- 該当箇所:
echo "P@ssw0rd123" | passwd --stdin operator- 問題の内容: パスワードがスクリプト内にハードコーディングされている。スクリプトがGit管理されている場合、パスワードが履歴に残る。また
psコマンドでプロセス一覧を見ると、パスワードが表示される- 修正案: スクリプト実行時に対話的にパスワードを入力させるか、SSH公開鍵認証のみ使用する構成にする
問題2
- 重大度: 高
- 該当箇所: スクリプト全体
- 問題の内容:
set -euo pipefailがない。コマンドが失敗しても後続の処理が実行されるため、途中で失敗した場合に中途半端な状態になる- 修正案: スクリプト冒頭に
set -euo pipefailを追加する問題3
- 重大度: 高
- 該当箇所:
dnf install -y $PACKAGES- 問題の内容: 変数
$PACKAGESがクォートされていない。変数が未定義の場合、set -uがあればエラーになるが、set -uがないため空文字列として展開される。また、変数にスペースが含まれる場合、意図しないワード分割が発生する- 修正案: 変数の定義をスクリプト冒頭で行い、複数パッケージを渡す場合は配列を使用する
問題4
- 重大度: 中
- 該当箇所:
useradd operator- 問題の内容: ユーザーが既に存在する場合、エラーが発生する。冪等性がない
- 修正案:
idコマンドで存在チェックを行い、存在しない場合のみ作成する問題5
- 重大度: 中
- 該当箇所:
cp /tmp/app.conf /etc/myapp/app.conf- 問題の内容:
/etc/myapp/ディレクトリが存在しない場合、コピーが失敗する。また/tmp/app.confが存在しない場合もエラーになる- 修正案: ディレクトリの存在確認とファイルの存在確認を追加する
問題6
- 重大度: 低
- 該当箇所: スクリプト全体
- 問題の内容: rootで直接実行する前提になっている(sudoなし)。実行ユーザーの確認がない
- 修正案: スクリプト冒頭でroot権限の確認を追加する
改善後のスクリプト
AIのレビュー結果を反映した改善後のスクリプトは以下の通りです。
#!/bin/bash
#
# サーバー初期設定スクリプト(改善版)
# 対象OS: AlmaLinux 10
#
set -euo pipefail
# ==============================================================================
# 変数定義
# ==============================================================================
OPERATOR_USER="operator"
SSH_CONFIG="/etc/ssh/sshd_config"
TIMEZONE="Asia/Tokyo"
PACKAGES=(vim wget curl)
APP_CONFIG_SRC="/tmp/app.conf"
APP_CONFIG_DST="/etc/myapp/app.conf"
# ==============================================================================
# root権限の確認
# ==============================================================================
if [[ "$(id -u)" -ne 0 ]]; then
echo "エラー: このスクリプトはroot権限で実行してください" >&2
exit 1
fi
# ==============================================================================
# 1. 運用ユーザーの作成
# ==============================================================================
echo ">>> 運用ユーザー '${OPERATOR_USER}' を作成します"
if id "${OPERATOR_USER}" &>/dev/null; then
echo "ユーザー '${OPERATOR_USER}' は既に存在します。スキップします。"
else
useradd -m -s /bin/bash "${OPERATOR_USER}"
echo "ユーザー '${OPERATOR_USER}' を作成しました。"
fi
usermod -aG wheel "${OPERATOR_USER}"
# パスワードは対話的に設定(ハードコーディングしない)
echo ">>> 運用ユーザーのパスワードを設定してください"
passwd "${OPERATOR_USER}"
# ==============================================================================
# 2. SSH設定の強化
# ==============================================================================
echo ">>> SSH設定を強化します"
cp "${SSH_CONFIG}" "${SSH_CONFIG}.bak.$(date +%Y%m%d%H%M%S)"
sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' "${SSH_CONFIG}"
sed -i 's/^#*PermitRootLogin.*/PermitRootLogin no/' "${SSH_CONFIG}"
systemctl restart sshd
echo "SSH設定を変更し、sshdを再起動しました。"
# ==============================================================================
# 3. firewalld設定
# ==============================================================================
echo ">>> firewalldを設定します"
systemctl enable --now firewalld
firewall-cmd --permanent --add-service=ssh
firewall-cmd --reload
echo "firewalld設定が完了しました。"
# ==============================================================================
# 4. パッケージインストール
# ==============================================================================
echo ">>> パッケージをインストールします: ${PACKAGES[*]}"
dnf install -y "${PACKAGES[@]}"
# ==============================================================================
# 5. 設定ファイルのコピー
# ==============================================================================
echo ">>> 設定ファイルを配布します"
if [[ ! -f "${APP_CONFIG_SRC}" ]]; then
echo "警告: ${APP_CONFIG_SRC} が存在しません。スキップします。" >&2
else
mkdir -p "$(dirname "${APP_CONFIG_DST}")"
cp "${APP_CONFIG_SRC}" "${APP_CONFIG_DST}"
chown root:root "${APP_CONFIG_DST}"
chmod 644 "${APP_CONFIG_DST}"
echo "設定ファイルを配布しました。"
fi
# ==============================================================================
# 6. タイムゾーン設定
# ==============================================================================
echo ">>> タイムゾーンを ${TIMEZONE} に設定します"
timedatectl set-timezone "${TIMEZONE}"
# ==============================================================================
# 完了
# ==============================================================================
echo ""
echo "=============================="
echo " 初期設定が完了しました"
echo "=============================="
生成 → レビュー → 改善のワークフロー
IaCテンプレート作成の全体フロー
IaCテンプレートをAIと共同で作成する際の全体的な流れは以下の通りです。
| ステップ | 作業内容 | 担当 |
|---|---|---|
| 1 | 要件定義(何をコード化するかを明確にする) | 人間 |
| 2 | AIにたたき台を生成させる(プロンプトで要件を構造化して伝える) | AI |
| 3 | 人間がレビュー(環境固有の値・セキュリティ設定・冪等性を確認) | 人間 |
| 4 | AIにコードレビューを依頼(セキュリティ・可読性・保守性を確認) | AI |
| 5 | 指摘を反映して修正 | 人間 |
| 6 | テスト環境で実行・検証(--check --diff / ShellCheck) | 人間 |
| 7 | 本番環境に適用 | 人間 |
ステップ2と4でAIを活用し、ステップ1・3・5・6・7は人間が担います。AIが関与するのは「たたき台の生成」と「レビュー」の2箇所であり、要件定義・最終判断・本番適用は人間の責任です。
シリーズ全体の振り返り
このシリーズでは、4つの記事を通じてインフラ運用の主要タスクにAIを組み込む方法を扱いました。
| 記事 | テーマ | AIの役割 | 人間の役割 |
|---|---|---|---|
| ① | 障害対応の初動(ログ解析) | ログの分類・原因候補の提示 | 最終的な原因の特定・対処の実行 |
| ② | 構成管理ドキュメント生成 | 手順書・構成図のたたき台作成 | 内容の正確性確認・組織ルールへの適合 |
| ③ | 監視アラートのトリアージ | 重要度分類・初期対処方針の提案 | 最終的な優先度判断・対応実行 |
| ④ | IaCテンプレート作成(本記事) | スクリプト/Playbookのたたき台生成・コードレビュー | 環境固有の設定・テスト・本番適用 |
4つの記事に共通する原則は以下の通りです。
AIは「下書き・分類・提案」を担い、「最終判断と責任」は人間が担う。
AIの出力はすべて「提案」であり、採用するかどうかを判断するのは人間です。この原則はインフラ運用に限らず、AIを業務に組み込む際の基本的な考え方です。
注意点とベストプラクティス
AI生成コードの検証は必須
生成されたスクリプト・Playbookは、必ずテスト環境で動作確認してから本番に適用してください。
| ツール | 用途 | コマンド例 |
|---|---|---|
| ShellCheck | シェルスクリプトの静的解析 | shellcheck server_init.sh |
| ansible-lint | Playbookの静的解析 | ansible-lint nginx_setup.yml |
| –check –diff | Playbookのドライラン | ansible-playbook nginx_setup.yml --check --diff |
| –syntax-check | Playbookの構文チェック | ansible-playbook nginx_setup.yml --syntax-check |
# ShellCheckのインストール(AlmaLinux 10、EPELリポジトリが必要)
dnf install -y epel-release
dnf install -y shellcheck
# ansible-lintのインストール
pip install ansible-lint
バージョン依存の問題
Ansibleのモジュールは頻繁に変更・廃止されます。AIが古いバージョンの構文を出力する場合があるため、公式ドキュメントで確認してください。
| 旧モジュール | 新モジュール(FQCN形式) | 備考 |
|---|---|---|
| yum | ansible.builtin.dnf | AlmaLinux 10では dnf を使用 |
| service | ansible.builtin.systemd_service | systemd環境では systemd_service を推奨 |
| firewalld | ansible.posix.firewalld | ansible.posix コレクションが必要 |
ベストプラクティス
| # | 項目 | 内容 |
|---|---|---|
| 1 | Git管理する | AI生成コードもGitで管理し、変更履歴を追跡する |
| 2 | レビュー済みのタグを付ける | AI生成 → 人間レビュー済みの状態を明確にする(コミットメッセージ、コメント等) |
| 3 | プロンプトもGit管理する | 生成に使用したプロンプトをコードと同じリポジトリで管理し、再現性を確保する |
| 4 | チーム内でルールを定める | AI活用のルール(レビュー基準、プロンプトテンプレートの共有場所)を決める |
| 5 | 要件定義を丁寧に行う | AIの出力品質は入力(要件の明確さ)に比例する。曖昧な要件は曖昧なコードを生む |
AI生成コードは「参考コード」
AI生成コードの実行結果に対する責任は実行者にあります。AIの提案を鵜呑みにせず、必ずテスト環境で検証してから本番環境に適用してください。とくに以下の点に注意が必要です。
- SSH設定の変更(ロックアウトのリスク)
- firewalldの設定(通信遮断のリスク)
- ユーザー権限の変更(セキュリティ上のリスク)
まとめ
この記事で扱った3つのステップを整理します。
| ステップ | 内容 | 入力 | AI活用のポイント |
|---|---|---|---|
| ステップ1 | シェルスクリプトの生成 | 要件(実施内容・制約) | エラーハンドリング・セキュリティ設定を含むたたき台の生成 |
| ステップ2 | Ansible Playbookの生成 | 手順書(記事②で作成したもの等) | 手順書 → Playbook変換、適切なモジュール選択 |
| ステップ3 | AIによるコードレビュー | 既存のスクリプト / Playbook | セキュリティ・可読性・冪等性の問題点の指摘と修正案 |
IaC作成にAIを組み込む際の原則は以下の2点です。
- AIは「たたき台の生成」と「レビュー」が得意で、「環境固有の判断」は人間が担います。 要件定義・テスト環境での検証・本番適用の判断は人間の責任です。
- 要件定義を丁寧に行うほど、AIの出力品質が上がります。 プロンプトに具体的な要件(対象OS、制約、出力形式)を記述することで、修正の手戻りが減ります。
シリーズ総括
このシリーズ「インフラ運用 × 生成AI 実践レシピ集」では、4つの記事でインフラ運用の主要タスクにAIを組み込む方法を扱いました。
4つの記事を通じて共通するパターンは以下の通りです。
- プロンプトの4要素(役割・状況/要件・入力データ・出力形式)で構造化する
- XMLタグでプロンプトを区切り、AIが入力を正確に解釈できるようにする
- 「推測しない」「不明は不明と回答」 の制約を含め、AIの誤った推測を防ぐ
- Few-shotで過去のパターンを蓄積し、提案の精度を継続的に上げる
次にやること
- シェルスクリプト生成用のプロンプトテンプレートを使い、自チームのサーバー初期設定スクリプトのたたき台を生成する。 環境固有の値を変数に置き換え、チームのルールに合わせて修正する
- 既存の手順書を1つ選び、Playbook変換用のプロンプトテンプレートでAnsible Playbookに変換する。
ansible-lintと--check --diffで検証し、チーム内でレビューする - 自分が過去に書いたスクリプトを1つ選び、コードレビュー用のプロンプトテンプレートでAIにレビューさせる。 AIの指摘と自分の判断を照合し、コーディング規約に反映する
- 生成に使ったプロンプトテンプレートをチームの共有場所(Wiki・リポジトリ等)に保管する。 テンプレートを共有し、チーム全体でAI活用のナレッジを蓄積する
前の記事: ③ 監視アラートをAIでトリアージする
前シリーズ: 生成AIを武器にするインフラエンジニアへの道(全3回)
