システム構成図とは

システム構成図は、システムを構成するサーバー・ストレージ・ネットワーク機器などのハードウェアと、それらにインストールされるOS・ミドルウェア・アプリケーションなどのソフトウェアの全体像を示す設計書です。

構成図は主に「論理構成図」と「物理構成図」の2種類に分けて作成します。論理構成図はシステムの論理的な役割と関係を示し、物理構成図は実際のサーバー台数・設置場所・ネットワーク配線などを示します。基本設計段階では論理構成図を先行して確定し、物理構成はインフラ調達と並行して詳細化します。

💡 論理構成図と物理構成図の違い

論理構成図:Web層・AP層・DB層などの論理的な役割とデータフローを示す。クラウドの場合はALB→EC2→RDSのような論理構成を記述する。物理構成図:実際のサーバー台数・ラック配置・NIC構成・ストレージ接続などの物理的な配置を示す。

① ハードウェア構成の定義

ハードウェア構成では、各サーバーのスペックと役割を明確に定義します。スペック不足はパフォーマンス問題の直接原因になるため、非機能要件(性能・可用性)から逆算して決定します。

定義項目定義すべき内容備考
サーバー役割 Webサーバー / APサーバー / DBサーバー / バッチサーバー / ジャンプサーバー など 1台で複数役割を兼務する場合も明記
台数・冗長構成 本番2台(Active-Active)/ 予備1台 など 環境(本番・検証・開発)ごとに定義
CPU コア数・クロック周波数・アーキテクチャ(x86_64 / Arm) クラウドの場合はvCPU数とインスタンスタイプ
メモリ(RAM) 容量(GB) JVM ヒープ設計と整合を取ること
ストレージ 種別(SSD/HDD/NVMe)・容量・RAID構成・IOPS DBサーバーは IOPS を特に重視
NIC ポート数・帯域(1GbE / 10GbE)・ボンディング設定 クラウドの場合はENA・SR-IOV対応状況
設置場所 データセンター名・ラック番号・リージョン(クラウド) DR要件がある場合はセカンダリリージョンも定義

② ソフトウェア構成の定義

各サーバーにインストールするソフトウェアをOS・MWレイヤー別に整理します。ライセンス費用・サポート終了日(EOL)・ライセンス購入方法も合わせて記録します。

レイヤーコンポーネント定義すべき内容
OS オペレーティングシステム 種別(RHEL / Ubuntu / Windows Server)・バージョン・エディション・カーネルバージョン・ライセンス
仮想化 ハイパーバイザー / コンテナランタイム VMware vSphere / KVM / Docker / containerd のバージョン
Webサーバー HTTPサーバー Nginx / Apache HTTPD のバージョン・モジュール構成
APサーバー アプリケーションコンテナ Tomcat / WebLogic / WebSphere のバージョン・JDKバージョン
DB データベースエンジン Oracle / PostgreSQL / MySQL のバージョン・エディション・文字コード
監視エージェント メトリクス収集 Zabbix エージェント / CloudWatch エージェント / Datadog エージェント
セキュリティ ウイルス対策・ホスト型IDS 製品名・バージョン・定義ファイル更新方針

⚠️ EOL(End of Life)を必ずチェックする

システムの運用期間中にMWのEOLを迎える場合、追加のアップグレード費用・リスクが発生します。設計書作成時点でEOLを調査し、運用期間中にアップグレードが必要なコンポーネントはロードマップに明記してください。

③ 冗長化・HA構成の定義

可用性要件(SLA・RPO・RTO)を満たすための冗長化方式を定義します。冗長化方式によってコストが大きく変わるため、コストとのバランスを明確にして決定します。

代表的な冗長化方式と特徴は以下の通りです。

  • Active-Active:複数サーバーが同時に処理を行う。負荷分散にもなる。セッション共有が必要。
  • Active-Standby(ホットスタンバイ):スタンバイサーバーが常時待機し、障害時に自動で切り替わる。Pacemaker / Corosync などで実現。
  • コールドスタンバイ:障害時に手動または半自動でスタンバイを起動する。コストは低いがRTOが長くなる。
  • Multi-AZ(クラウド):異なるアベイラビリティゾーンにリソースを配置し、AZ障害を跨いだ冗長化を実現する。

④ サーバー一覧表の書き方

構成図に加えて、サーバーの詳細情報を一覧表として記録します。一覧表があることで、インフラ担当者・セキュリティ審査・資産管理において参照性が大幅に向上します。

サーバーIDホスト名役割IPアドレスOSCPU/MEMストレージ環境
SV-001web-01-prdWebサーバー192.168.10.11RHEL 9.34vCPU/8GBSSD 100GB本番
SV-002web-02-prdWebサーバー192.168.10.12RHEL 9.34vCPU/8GBSSD 100GB本番
SV-003ap-01-prdAPサーバー192.168.10.21RHEL 9.38vCPU/32GBSSD 200GB本番
SV-004db-01-prdDBサーバー(Primary)192.168.10.31RHEL 9.316vCPU/64GBSSD 1TB本番

Python Tips — 実機のHW・SW情報を自動収集する

既存環境の移行案件や棚卸し作業では、複数サーバーの情報を手動で収集するのは非効率です。SSH経由でサーバー情報を自動収集するスクリプトを紹介します。

Python — SSH経由でサーバー情報収集(paramiko)
"""
SSH 経由でサーバーのHW・SW情報を自動収集するスクリプト。
pip install paramiko pandas openpyxl
"""
import paramiko
import pandas as pd
from typing import Optional

# ── 収集コマンド定義 ──────────────────────────────────────────
COMMANDS = {
    "hostname":      "hostname",
    "os_release":    "cat /etc/os-release | grep -E '^(NAME|VERSION)=' | tr '\n' ' '",
    "kernel":        "uname -r",
    "cpu_cores":     "nproc",
    "memory_gb":     "awk '/MemTotal/{printf \"%.1f\", $2/1024/1024}' /proc/meminfo",
    "disk_root_gb":  "df -BG / | awk 'NR==2{print $2}' | tr -d G",
    "java_version":  "java -version 2>&1 | head -1",
    "nginx_version": "nginx -v 2>&1",
    "tomcat_version":"find /opt /usr/local -name catalina.sh 2>/dev/null | head -1 | xargs -I{} sh -c 'dirname {} | xargs dirname | xargs basename'",
}


def collect_server_info(host: str, user: str, key_path: str,
                        port: int = 22) -> dict:
    """
    1台のサーバーに接続して情報を収集する。
    key_path: SSH秘密鍵のパス(~/.ssh/id_rsa など)
    """
    result = {"host": host}
    try:
        client = paramiko.SSHClient()
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        client.connect(host, port=port, username=user,
                       key_filename=key_path, timeout=15)

        for key, cmd in COMMANDS.items():
            stdin, stdout, stderr = client.exec_command(cmd, timeout=10)
            output = stdout.read().decode("utf-8").strip()
            result[key] = output if output else "N/A"

        client.close()
        result["status"] = "OK"

    except Exception as e:
        result["status"] = f"ERROR: {e}"

    return result


def collect_all_servers(server_list: list[dict], key_path: str) -> pd.DataFrame:
    """
    複数サーバーの情報を収集してDataFrameに変換する。
    server_list: [{"host": "192.168.10.11", "user": "ansible"}, ...]
    """
    records = []
    for srv in server_list:
        print(f"Collecting: {srv['host']} ...")
        info = collect_server_info(
            host=srv["host"],
            user=srv.get("user", "root"),
            key_path=key_path,
        )
        records.append(info)
    return pd.DataFrame(records)


if __name__ == "__main__":
    # ── 対象サーバーリスト ────────────────────────────────────
    servers = [
        {"host": "192.168.10.11", "user": "ec2-user"},
        {"host": "192.168.10.12", "user": "ec2-user"},
        {"host": "192.168.10.21", "user": "ec2-user"},
    ]
    KEY_PATH = "~/.ssh/id_rsa"

    df = collect_all_servers(servers, KEY_PATH)
    print(df.to_string(index=False))

    # Excel に出力(設計書の素材として活用)
    df.to_excel("server_inventory.xlsx", index=False)
    print("\nserver_inventory.xlsx に出力しました")

クラウド環境の場合

AWS 環境であれば boto3 ライブラリを使い、EC2インスタンスの情報(インスタンスタイプ・AMI・タグ・セキュリティグループ)をAPIから取得できます。describe_instances() を使えば、SSH不要でインスタンス一覧を収集できます。

インストール済みパッケージの一括確認

Python — RPM/DEB パッケージ一覧収集
import subprocess
import platform

def get_installed_packages() -> list[dict]:
    """
    ローカルサーバーのインストール済みパッケージ一覧を取得する。
    RHEL/CentOS系: rpm -qa  / Ubuntu/Debian系: dpkg -l
    """
    system = platform.system()
    if system != "Linux":
        raise RuntimeError(f"Unsupported OS: {system}")

    # パッケージマネージャーを自動判別
    try:
        # RHEL / Rocky / Alma
        result = subprocess.run(
            ["rpm", "-qa", "--queryformat",
             "%{NAME}\t%{VERSION}-%{RELEASE}\t%{ARCH}\n"],
            capture_output=True, text=True, timeout=30
        )
        lines = result.stdout.strip().split("\n")
        return [
            {"name": p[0], "version": p[1], "arch": p[2]}
            for line in lines if (p := line.split("\t")) and len(p) == 3
        ]
    except FileNotFoundError:
        pass

    # Ubuntu / Debian
    result = subprocess.run(
        ["dpkg-query", "-W", "-f=${Package}\t${Version}\t${Architecture}\n"],
        capture_output=True, text=True, timeout=30
    )
    lines = result.stdout.strip().split("\n")
    return [
        {"name": p[0], "version": p[1], "arch": p[2]}
        for line in lines if (p := line.split("\t")) and len(p) == 3
    ]


if __name__ == "__main__":
    pkgs = get_installed_packages()
    # MW関連だけ抽出
    mw_keywords = ["nginx", "tomcat", "java", "postgresql", "mysql",
                   "redis", "httpd", "openssl", "openssh"]
    mw_pkgs = [p for p in pkgs
               if any(kw in p["name"].lower() for kw in mw_keywords)]
    for p in mw_pkgs:
        print(f"{p['name']:40s} {p['version']}")

定義チェックリスト

チェック項目確認ポイント
□ 全サーバーの役割が定義されているかWeb・AP・DB・バッチ・ジャンプサーバーなど役割が明確か
□ スペックの算出根拠があるか性能要件(TPS・レスポンスタイム)から逆算してスペックを決定しているか
□ ソフトウェアのバージョンが確定しているかすべてのMWにバージョン番号が記載されているか
□ EOLを確認しているかシステム運用期間中にEOLを迎えるコンポーネントがないか
□ 冗長化方式が可用性要件を満たすかSLA・RTO・RPOを満たす冗長化構成になっているか
□ ライセンスが調達済みか商用ソフトウェアのライセンス費用・本数が確認されているか