インフラ構築の自動化はどこから始めるか — シェルとIaCの境界線

インフラ構築の自動化は「どこから着手するか」の判断を誤ると、シェルスクリプトとIaCが混在し、どちらも保守できない状態に陥ります。シェルとIaCは優劣で選ぶものではなく、何を担わせるかで住み分けが決まります。本記事では境界の引き方と育て方の順序を軸に、構築担当者が最初に押さえるべき設計判断を整理します。

「全部自動化」で挫折する理由 — 境界を先に引く

設計判断を後回しにすると何が起きるか

プロジェクト初期に「とにかく自動化しよう」と動き出したチームが、数か月後にスクリプトのカオスに直面するという話は珍しくありません。20台規模のサーバー構築案件でも、役割設計を後回しにしたまま書き始めたシェルスクリプトが、気づけば1,000行を超え、誰も手を加えられない状態になっていたという事例を現場ではよく聞きます。問題の根本は「自動化そのものが目的化」していることにあります。構築対象の種類・変更頻度・担当者の人数という3軸を整理しないまま着手すると、手続き的な処理と宣言的なリソース定義が同じファイルに混在し始めます。一度混在すると、どちらの設計ルールも守れなくなり、修正のたびに全体への影響範囲が読めなくなります。

「自動化できる」と「自動化すべき」の混同

シェルで書けばたいていのことは動きます。しかしそれは「できる」であって「すべき」ではありません。自動化の判断軸は、繰り返し頻度・対象の不変性・障害時の影響範囲の3点に絞られます。この3点を先に評価せず「コマンドをまとめただけ」のスクリプトをプロジェクト全体に広げていくと、後からIaCを導入しようとしたときに整合が取れなくなります。

「自動化すべき」かどうかの最初の仕分けは、その処理が「状態を作る」のか「状態を変える操作を実行する」のかで決まります。リソースの存在・設定値を定義するなら宣言型のIaCが向き、特定の手順を順番に実行するなら手続き型のシェルが向きます。この仕分けを設計の最初に行うことが、後の混乱を防ぐ起点になります。どちらのツールを選ぶかより先に「何を担わせるか」を決める、という順序の違いが、プロジェクト後半の保守コストに大きな差をもたらします。

シェルスクリプトが担うべき領域

手続き型タスクとの親和性

シェルスクリプトの強みは「実行順序を明示できる」点にあります。パッケージのインストール前にリポジトリ登録を行い、その後に設定ファイルを配置し、最後にサービスを起動するという一連の手順は、順序に意味があるためスクリプトに向きます。50台規模の環境でも、初期セットアップのような「一度だけ順番に実行する」タスクはシェルで十分に対応できます。また、外部コマンドの結果を受け取って次の処理に渡す「パイプライン的な運用操作」もシェルの得意領域です。バックアップの取得と圧縮・転送、ログの収集と集約など、入出力をつなぐ処理はシェルが自然に記述できます。IaCでこれをやろうとするとnull_resourceやlocal-execといった回避策に頼ることになり、コードの意図が読みにくくなります。

運用タスクへの適用基準

定期実行・手動トリガー・条件分岐を伴う運用タスクはシェルが担いやすい領域です。DBダンプのローテーション、証明書の更新確認、ノードのヘルスチェックと通知といった処理は「操作を実行する」ものであるため、IaCに書く必要はありません。こうした運用タスクはシェルで書き始めることで素早く動作確認でき、担当者が変わった際も処理の流れを読みやすい利点があります。ただし、運用スクリプトが100本を超えてくると管理コストが跳ね上がります。この段階では共通処理をライブラリ化するか、AnsibleのようなTask-basedツールへの移行を検討する判断が生まれます。シェルスクリプトはゼロから始めやすい反面、規模が大きくなると属人化・依存関係の肥大化というリスクを抱えます。その限界点を事前に見極めておくことが、設計判断として重要です。

IaCが担うべき領域

宣言型モデルが力を発揮する場面

IaCの核心は「あるべき状態を宣言すると、ツールが差分を計算して適用する」点にあります。クラウドリソース(VPC・サブネット・セキュリティグループ・インスタンス)の定義はこの典型で、TerraformやPulumi、CloudFormationはこの宣言型モデルで動きます。10環境・100リソースを超える規模になると特に効果が出やすく、手動構築と比べて差分検出と適用の一貫性が担保されます。コードベースにリソース定義が残ることで「現在何が存在するか」のドキュメントが自動的に更新されます。手順書では追いきれない環境のドリフト(実際の状態とドキュメントのずれ)をIaCは防ぎやすく、この価値は構築フェーズよりも運用フェーズで顕著に現れます。

IaCが向く規模・環境の条件

IaCを導入すべき判断基準として、環境数・変更頻度・チーム人数の3点が目安になります。本番/ステージング/開発と3環境以上を管理し、月に数回以上の構成変更が発生し、複数人が構成に関わる案件ではIaC化の費用対効果が出やすいです。逆に単一環境で変更がほぼ起きない案件に無理に導入すると、学習コストとメンテナンス負荷だけが残ります。ツール選定はインフラの置き場所とチームのスキルセットで決まります。クラウドネイティブ環境ではTerraform/OpenTofuが広く使われ、Kubernetesリソースの定義にはHelmやKustomizeが採用されます。ベアメタルやオンプレ中心の環境ではAnsibleが宣言型に近い構成管理の入口として機能することが多いです。「どれが最強か」ではなく「何を管理するか」でツールが決まるという視点を、選定の起点に置くことが重要です。

■ この設計判断を深める一冊[PR]

Terraformではじめる実践IaC ―AWSでのインフラストラクチャ構築の基本から継続的デプロイまで(伊藤太斉・藤原涼馬/オライリー)

IaCの考え方から継続的デプロイまでを体系立てて追える一冊です。自動化の境界をどこに引くかの視点を補強したい方に向いています。

Amazonで見る →

境界を跨ぐと壊れるアンチパターン

シェルでインフラリソースを定義しようとするケース

aws cliやgcloud cliのコマンドをシェルに並べてVPCやインスタンスを作る実装は、スピード感があるように見えて後から問題になります。リソースが存在するかどうかを確認しながら冪等性を担保しようとすると、条件分岐が複雑になり、スクリプト自体のバグが本番インフラの破壊につながるリスクが生まれます。さらに複数人が同じスクリプトを異なるタイミングで実行したとき、どのリソースが作成済みでどれが未作成かの状態管理がシェルには存在しません。IaCであればstateファイルが担うこの役割を、シェルでは自前で実装しなければなりません。この自前state管理のコストと危険性を過小評価したプロジェクトが、環境の重複・リソースの孤立という問題に数か月後に直面する例は少なくありません。

IaCにインライン手続きを埋め込むケース

TerraformのnullリソースやCloudFormationのCustom Resourceでシェルコマンドをインラインで書き込む実装は、デバッグとテストを著しく困難にします。IaCの差分計算はリソースの状態を対象としますが、インライン手続きはその対象外であるため、変更がいつ・どのように実行されたかが追跡しにくくなります。このアンチパターンに陥る背景には「シェルで書いていた処理をIaCに取り込みたい」という動機があることが多いです。手続き部分はシェル(またはAnsible等のTask-basedツール)に戻して、IaCからはそのスクリプトの呼び出しのみを行う形に分離する方が長期的に保守しやすくなります。二つのツールは協調して使うものであり、一方に全部詰め込もうとする発想が問題の起点になります。

自動化の”最初の一歩”に何を選ぶかの判断

処理の性質で分岐する選定フロー

最初の一歩を選ぶ際は、次の判断フローで処理の性質を先に確定させることが重要です。「何を管理するか」が明確でない段階で道具を決めることが、後の混乱の原因になります。

  1. その処理は「リソースの状態を定義する」ものか、「操作を順番に実行する」ものか — 状態定義ならIaC候補、操作実行ならシェル候補。
  2. 同じ処理を3回以上繰り返す予定があるか — Noなら手順書のまま、YesならスクリプトまたはIaCへ進む。
  3. 複数人が同じ対象に触れるか、または3環境以上を管理するか — YesならIaC化を優先、Noならシェルで十分。
  4. 誤実行時の影響範囲が広く、復旧に長時間かかるか — Yesなら人間の承認ステップを残すことを検討する。
  5. 既存の手順書はあるか — Noなら手順書から始める。Yesならスクリプト化またはIaC化の評価へ。

シェルとIaCの役割比較

3つのアプローチの使い分けを整理すると、次のようになります。選定の際は「今の構成で管理するものがどこに属するか」をこの表と照合して判断します。

観点 シェルスクリプト IaC(Terraform等) Task-basedツール(Ansible等)
設計モデル 手続き型(順序を明示) 宣言型(あるべき状態を定義) Task型(タスクを順に定義)
状態管理 なし(自前実装が必要) stateファイルで管理 原則なし(冪等タスクで対応)
向く対象 運用操作・初期セットアップ・CI処理 クラウドリソース定義・環境の再現 OSレベルの構成管理・ミドルウェア設定
スケール限界 100本超で管理が困難になりやすい 大規模でも管理しやすい Role設計次第でスケール可
導入コスト 低い(すぐ書き始められる) 中〜高(学習・設計コストがかかる) 中(YAML習得と構成設計が必要)

手順書→スクリプト→IaCへ育てる順序設計

手順書フェーズで押さえること

手順書は「誰が読んでも同じ手順を再現できること」を目標に書きます。コマンドの羅列ではなく、「なぜその順序か」「どの状態を確認してから次に進むか」という意図を含めることで、後のスクリプト化・IaC化の材料になります。現場では「手順書を作らずにすぐスクリプト化した」ことで設計の意図が失われ、3か月後に誰も触れなくなったという話をよく聞きます。手順書に残す情報として最低限必要なのは、前提条件・実行対象の範囲・確認コマンドと期待値・ロールバック手順の4点です。この4点が揃っていないと、スクリプトに変換したときに「成功か失敗かを判断できない」コードになります。手順書は完成物ではなく、次の自動化ステップへの設計図として扱うことが、育てる順序設計の出発点になります。

スクリプト化の基準と設計方針

手順書をスクリプトにする判断基準として「3回以上実行する予定があるか」が目安になります。1〜2回しか使わない手順はスクリプト化のコストが見合いません。3回以上実行する見込みがあり、かつ手順の内容が安定しているなら、スクリプト化で工数を削減できます。スクリプト化する際は処理を関数単位に分割し、各関数が入力を受け取って出力を返す形にすることで、後からIaCに切り出す部分と手続き処理を分離しやすくなります。冪等性を意識した実装(実行前に状態確認を入れる)をこの段階から心がけておくと、IaCへの移行時に書き直しが大幅に減ります。

IaCへの昇格を判断するタイミング

スクリプトがIaC化に値するかどうかは「このスクリプトが管理しているものはリソースの状態か、操作の手順か」で判断します。リソースの状態(サーバーの台数・ネットワーク設定・セキュリティポリシー)を管理しているならIaC化が適切です。操作の手順(デプロイ・ログ収集・通知)を管理しているならシェルやTask-basedツールに残します。昇格のタイミングは、環境数が3つ以上になる時点か、チームに2人以上が同じインフラを触るようになる時点が目安になります。この2条件が重なった段階でIaC化の費用対効果が出やすくなります。

自動化しない判断 — 手動に残す価値

手動を設計として残す理由

自動化はコストとリスクを伴います。作業を自動化することで「誰でも実行できる」状態になりますが、それは同時に「意図せず実行される」リスクを生みます。特にデータベースの削除・ネットワーク設定の変更・本番環境へのデプロイといった操作は誤実行の影響が大きいため、人間の意図確認(承認ステップ)を意図的に残すことが設計として合理的になる場合があります。手動を残す判断が適切な場面として、年1回程度の頻度でしか発生しない作業、実行ミスの影響が広範で復旧に長時間かかる作業、実行条件が毎回異なり判断に文脈が必要な作業の3つが挙げられます。自動化の設計とは「何を自動化するか」だけでなく「何を手動に残すか」を明示することでもあります。

自動化コストが便益を上回る場面

自動化ツールの整備・テスト・CI/CD連携・ドキュメント維持を合計すると、構築工数の20〜30%程度が自動化そのもののコストになることがあります。この投資に見合うのは、自動化された処理が繰り返し実行され、品質・速度・再現性のいずれかで明確な改善が得られる場合に限られます。メンバーが2〜3人のプロジェクトでCI/CD・IaC・構成管理をすべて導入しようとすると、ツールを維持するための作業が本来の構築業務を圧迫します。自動化の判断は「今の規模で元が取れるか」という視点で行うべきであり、将来の規模を先読みした過剰投資は現実には使われないまま負債になることが少なくありません。シェルとIaC、どちらを選ぶかよりも、「何を自動化し、何を手動に残すか」という境界の設計こそが、インフラ自動化における本質的な問いです。手を動かす具体的な実装は、この判断を固めた後に進める順序が、プロジェクト全体の健全性を保つことにつながります。

▶ 手を動かして本番まで到達する

脱属人化の第一歩は「読める・書けるスクリプト」から始まります

ここまでの設計判断は、読めば腹に落ちます。ですが「自分の手で本番まで通しきる自信」は、それとは別の話になります。

自動化の設計を、手を動かして身につける2日間です。手順書に閉じ込めた構築を、他人が読めて再現できる形へ変えていきます。

自動化の設計を手で身につける講座へ →

シェルスクリプトマスターセミナー|自動化の設計を手で身につける2日間