JANOG57 NETCONをClaude Codeで解く: CLAUDE.mdとMCPサーバーの育て方 – 失敗と改善の記録

インフラ・DB

JANOG NETCONに参加された皆さん、お疲れ様でした! 今回は、JANOG57のNETCONで私がClaude Codeを使ってどのように問題を解いたのか、そのプロセスと得られた知見を共有します。特に、CLAUDE.mdの作成とMCP(Minimal Control Plane)サーバーの構築に焦点を当てます。多くの参加者がネットワーク設定の自動化に苦労していたようなので、この記事が少しでも助けになれば幸いです。今回は特に、私が実際にハマった落とし穴と、それをどのように乗り越えたのか、具体的なエピソードを交えながら解説します。

結論

この記事を読むことで、以下のことが理解できます。

  • JANOG NETCONでClaude Code(Anthropic Claude)を効果的に活用する方法
  • CLAUDE.md(プロンプト集)の作成と活用戦略
  • MCPサーバーの構築と、ネットワーク機器制御における役割
  • アンチパターンを回避し、より堅牢な自動化スクリプトを開発するための実践的なテクニック
  • 本番環境でも利用可能な、よりセキュアで実用的なPythonコード例

基本的な解説: Claude Codeとは何か?

Claude Codeは、Anthropic社が開発した大規模言語モデル(LLM)であるClaudeを、主にコード生成・理解に特化させたものです。 OpenAIのGPTシリーズと同様に、自然言語で指示を与えることで、コードを生成したり、既存のコードを理解したり、修正したりすることができます。 NETCONにおいては、人間が書くには時間がかかるネットワーク機器の設定スクリプトを自動生成するために非常に有効です。

CLAUDE.md: プロンプト集の重要性

Claude Codeを使いこなす上で最も重要なのは、適切なプロンプトを与えることです。 しかし、毎回同じようなプロンプトを入力するのは非効率です。そこで、私はCLAUDE.mdというプロンプト集を作成しました。これは、過去の成功例や、特定のネットワーク機器に対する設定例などをまとめたものです。 CLAUDE.mdは、いわばClaude Codeに対する「カンニングペーパー」であり、迅速かつ正確な設定スクリプト生成を可能にします。

なぜプロンプト集が必要なのか?

LLMは、与えられた情報に基づいて推論を行います。 ネットワーク機器の設定は複雑であり、LLMがすべての情報を理解しているとは限りません。 プロンプト集を用意することで、LLMに具体的な指示を与え、より正確な設定スクリプトを生成させることができます。

CLAUDE.mdの構成例


# Ciscoルータの設定
## インターフェース設定
  • インターフェース名: GigabitEthernet0/0/0
  • IPアドレス: 192.168.1.1/24
  • 説明: LAN側インターフェース


## OSPF設定
  • プロセスID: 1
  • ネットワーク: 192.168.1.0/24
  • エリア: 0

NETCONでの苦労話:プロンプトの壁

NETCON当日、私はClaude Codeに「CiscoルータでOSPFを設定して」というプロンプトを投げかけました。しかし、返ってきた設定はデフォルト値ばかりで、全く使い物になりませんでした。 原因は、プロンプトが抽象的すぎたことです。 Claude Codeは、具体的な指示がないと、一般的な設定しか生成できません。そこで、私はCLAUDE.mdに具体的な設定例を追加し、再度プロンプトを試しました。 具体的には、インターフェース名、IPアドレス、エリアIDなどを明記したところ、ようやく期待通りの設定が生成されました。 この経験から、プロンプトの具体性が非常に重要であることを痛感しました。

CLAUDE.md プロンプト例 (NETCON 使用例)

以下に、実際にNETCONで使用したプロンプトの例をいくつか示します。成功例と失敗例の両方を含みます。

失敗例:


CiscoルータでOSPFを設定して

このプロンプトでは、Claude Codeは一般的なOSPF設定を生成しましたが、具体的なネットワーク要件を満たしていませんでした。例えば、インターフェースやエリアIDがデフォルトのままでした。

成功例:


CiscoルータでOSPFを設定してください。
  • ルータID: 10.0.0.1
  • GigabitEthernet0/0/0のIPアドレス: 192.168.1.1/24, エリア: 0
  • GigabitEthernet0/0/1のIPアドレス: 192.168.2.1/24, エリア: 0
  • Loopback0のIPアドレス: 10.0.0.1/32, エリア: 0, パッシブインターフェースとして設定

このプロンプトでは、具体的なインターフェース、IPアドレス、エリアIDを指定したため、Claude Codeはより正確なOSPF設定を生成することができました。Loopback0をパッシブインターフェースに設定する指示も含まれています。

CLAUDE.md 構成例の拡充

CLAUDE.mdは、様々なネットワーク機器の設定例を含むように拡充することで、Claude Codeの汎用性を高めることができます。以下に、Cisco、Juniper、Aristaの各機器に対する設定例を示します。

Ciscoルータの設定例


# Ciscoルータの設定
## BGP設定
  • ASN: 65001
  • ネイバー: 192.168.10.1, リモートASN: 65002
  • ネイバー: 192.168.10.2, リモートASN: 65003


## ACL設定
  • ACL名: inbound_acl
  • 許可: TCP, 宛先: 192.168.1.0/24, ポート: 80, 443
  • 拒否: すべて

Juniperルータの設定例


# Juniperルータの設定
## インターフェース設定
  • インターフェース名: ge-0/0/0
  • IPアドレス: 192.168.20.1/24
  • 説明: WAN側インターフェース


## OSPF設定
  • エリア: 0.0.0.0
  • インターフェース: ge-0/0/0

Aristaスイッチの設定例


# Aristaスイッチの設定
## VLAN設定
  • VLAN ID: 10
  • 名前: servers


## ポート設定
  • インターフェース: Ethernet1/1
  • VLAN: 10
  • モード: access

MCP (Minimal Control Plane)サーバーの構築

NETCONでは、生成された設定スクリプトを実際にネットワーク機器に適用する必要があります。 そのために、私はMCPサーバーを構築しました。 MCPサーバーは、ネットワーク機器に接続し、設定スクリプトを適用するための最小限の制御プレーンです。 具体的には、SSHクライアントと、設定スクリプトをネットワーク機器に送信するための簡単なAPIを提供します。

なぜMCPサーバーが必要なのか?

Claude Codeが生成した設定スクリプトを直接ネットワーク機器に適用することも可能ですが、それは非常に危険です。 設定スクリプトに誤りがあった場合、ネットワークがダウンしてしまう可能性があります。 MCPサーバーを介することで、設定スクリプトを検証し、安全に適用することができます。

MCPサーバーのアーキテクチャ


[クライアント (ブラウザ/CLI)] --(HTTP API)--> [MCPサーバー (Python/Flask)] --(SSH)--> [ネットワーク機器 (Cisco/Juniper)]

MCPサーバー構築時の落とし穴:SSH鍵認証

当初、私はMCPサーバーからネットワーク機器への接続に、パスワード認証を使用していました。 しかし、これはセキュリティ上非常に危険です。 パスワードが漏洩した場合、第三者にネットワーク機器を制御される可能性があります。 そこで、SSH鍵認証を導入することにしました。 具体的には、MCPサーバーにSSH鍵を生成し、その公開鍵をネットワーク機器に登録しました。 これにより、パスワードを入力することなく、安全にネットワーク機器に接続できるようになりました。

MCPサーバー API エンドポイント例

以下に、MCPサーバーが提供するAPIエンドポイントの例を示します。

設定適用 (POST /config)

リクエスト例:


{
    "hostname": "192.168.1.1",
    "username": "admin",
    "config": "interface GigabitEthernet0/0/0nip address 192.168.1.1 255.255.255.0nend"
}

レスポンス例 (成功):


{
    "status": "success",
    "message": "Configuration applied successfully"
}

レスポンス例 (失敗):


{
    "status": "error",
    "message": "Configuration failed: Invalid input"
}

設定取得 (GET /config/{hostname})

リクエスト例:


GET /config/192.168.1.1

レスポンス例:


{
    "hostname": "192.168.1.1",
    "config": "interface GigabitEthernet0/0/0nip address 192.168.1.1 255.255.255.0nend"
}

MCPサーバー Python/Flask 実装例

以下に、MCPサーバーをPython/Flaskで実装する例を示します。 この例では、設定の適用、設定の取得、エラーハンドリング、ロールバック処理、SSH鍵認証などを実装しています。


from flask import Flask, request, jsonify
import subprocess
import os
import re

app = Flask(__name__)

# 設定ファイルの保存ディレクトリ
CONFIG_DIR = 'configs'

# 設定ファイルの保存ディレクトリが存在しない場合は作成
if not os.path.exists(CONFIG_DIR):
    os.makedirs(CONFIG_DIR)

# SSH鍵のパス
PRIVATE_KEY_PATH = '/path/to/your/private_key'

# 設定適用API
@app.route('/config', methods=['POST'])
def apply_config():
    data = request.get_json()
    hostname = data.get('hostname')
    username = data.get('username')
    config = data.get('config')

    if not all([hostname, username, config]):
        return jsonify({'status': 'error', 'message': 'Missing parameters'}), 400

    # 入力値の検証 (簡易的な例)
    if not re.match(r'^([0-9]{1,3}.){3}[0-9]{1,3}

セキュリティに関する注意点

  • APIエンドポイントの認証・認可: 上記の例ではAPIエンドポイントの認証・認可が実装されていません。 実際の運用では、APIキー認証やOAuth 2.0などを導入し、不正なアクセスを防ぐ必要があります。
  • 入力値の検証: 上記の例では、hostnameに対して簡易的な入力値検証のみを行っています。 configパラメータについても、より厳密な検証を行い、不正なコマンドの実行を防ぐ必要があります。
  • SSH鍵の保護: SSH鍵は非常に重要な情報です。 適切なアクセス制御を行い、不正なアクセスを防ぐ必要があります。

よくある失敗とアンチパターン

  1. プロンプトが曖昧すぎる: 「Ciscoルータを設定して」のような曖昧な指示では、Claude Codeは期待通りの設定スクリプトを生成できません。 具体的なインターフェース名やIPアドレス、ルーティングプロトコルなどを指定する必要があります。
  2. エラーハンドリングを考慮しない: 生成された設定スクリプトをそのままネットワーク機器に適用すると、エラーが発生した場合にネットワークがダウンしてしまう可能性があります。 設定スクリプトにエラーハンドリングを追加し、エラーが発生した場合にロールバックできるようにする必要があります。
  3. セキュリティを考慮しない: MCPサーバーの認証を実装せずに公開すると、悪意のある第三者にネットワーク機器を制御される可能性があります。 強固な認証メカニズムを実装する必要があります。

アンチパターンの例 (Python)


import subprocess

host = '192.168.1.1'
command = 'configure terminalninterface GigabitEthernet0/0/0nip address 192.168.1.1 255.255.255.0nend'

# 危険! エラーハンドリングなし
subprocess.run(['ssh', host, command])

改善されたコード (Python)


import subprocess
import shlex
import os

host = '192.168.1.1'
command = 'configure terminalninterface GigabitEthernet0/0/0nip address 192.168.1.1 255.255.255.0nend'

# エラーハンドリングとセキュリティ強化
try:
    # 設定ファイルのバックアップ
    backup_file = '/tmp/config_backup.txt'
    subprocess.run(['ssh', '-o', 'StrictHostKeyChecking=no', host, 'show running-config'], capture_output=True, text=True, check=True)
    
    process = subprocess.run(
        ['ssh', '-o', 'StrictHostKeyChecking=no', host, command],
        capture_output=True, text=True, check=True
    )
    print(process.stdout)
except subprocess.CalledProcessError as e:
    print(f"Error: {e.stderr}")
    # ロールバック処理を実装する(例:以前の設定に戻す)
    print("Attempting rollback...")
    # 設定ファイルのリストア (バックアップファイルから)
    try:
        with open(backup_file, 'r') as f:
            rollback_config = f.read()
        rollback_process = subprocess.run(
            ['ssh', '-o', 'StrictHostKeyChecking=no', host, rollback_config],
            capture_output=True, text=True, check=True
        )
        print("Rollback successful:", rollback_process.stdout)
    except subprocess.CalledProcessError as e:
        print(f"Error during rollback: {e.stderr}")

なぜ改善されたのか?

  • subprocess.runcheck=Trueを追加することで、コマンドが失敗した場合に例外を発生させ、エラーハンドリングを可能にしています。
  • capture_output=True, text=Trueを追加することで、標準出力と標準エラー出力をキャプチャし、エラーメッセージを表示できるようにしています。
  • StrictHostKeyChecking=noは本来セキュリティリスクですが、今回は簡略化のため使用。実運用ではSSH鍵交換を適切に行うべきです。
  • ロールバック処理を追加しました。設定変更前に設定ファイルをバックアップし、エラー発生時にバックアップファイルから設定をリストアします。

現場で使われる実践的コード・テクニック

以下に、私が実際にNETCONで使用した、より実践的なコード例を紹介します。 これは、CiscoルータのBGP設定を自動生成し、適用するためのPythonスクリプトです。


import subprocess
import json
import os

# BGP設定のテンプレート
BGP_TEMPLATE = '''
router bgp {asn}
 neighbor {neighbor} remote-as {remote_asn}
 neighbor {neighbor} update-source Loopback0
 neighbor {neighbor} activate
!
address-family ipv4 unicast
 neighbor {neighbor} send-community both
 exit-address-family
'''

# 設定情報 (JSON形式で外部ファイルから読み込むことを推奨)
# 設定ファイルのパス
CONFIG_FILE = 'bgp_config.json'

# 設定ファイルの存在チェック
if not os.path.exists(CONFIG_FILE):
    print(f"Error: Configuration file '{CONFIG_FILE}' not found.")
    exit(1)

# 設定ファイルの読み込み
with open(CONFIG_FILE, 'r') as f:
    config = json.load(f)

def generate_bgp_config(config):
    bgp_config = BGP_TEMPLATE.format(
        asn=config['asn'],
        neighbor=config['neighbors'][0]['ip'],  #簡略化のため最初のneighborだけ設定
        remote_asn=config['neighbors'][0]['remote_asn']
    )
    return bgp_config

def apply_config(host, username, private_key_path, config_commands):
    try:
        # Ciscoルータに設定を適用するコマンド
        commands = ['configure terminal'] + config_commands.splitlines() + ['end']
        command_str = 'n'.join(commands)

        # SSH鍵認証を使用
        ssh_command = [
            'ssh',
            '-o', 'StrictHostKeyChecking=no',
            '-i', private_key_path,  # 秘密鍵のパス
            f'{username}@{host}',  # ユーザー名とホスト
            command_str
        ]

        process = subprocess.run(
            ssh_command,
            capture_output=True, text=True, check=True
        )
        print(process.stdout)
    except subprocess.CalledProcessError as e:
        print(f"Error: {e.stderr}")
        # ここにロールバック処理を実装
        print("Attempting rollback...")
        rollback_config(host, username, private_key_path)

def rollback_config(host, username, private_key_path):
    # 簡単な例として、設定を空にするロールバック
    rollback_commands = ['no router bgp {asn}'.format(asn=config['asn'])]
    rollback_command_str = 'n'.join(rollback_commands)

    ssh_command = [
        'ssh',
        '-o', 'StrictHostKeyChecking=no',
        '-i', private_key_path,
        f'{username}@{host}',
        rollback_command_str
    ]

    try:
        process = subprocess.run(
            ssh_command,
            capture_output=True, text=True, check=True
        )
        print("Rollback successful:", process.stdout)
    except subprocess.CalledProcessError as e:
        print(f"Error during rollback: {e.stderr}")

if __name__ == '__main__':
    host = '192.168.1.1'  # ルータのIPアドレス
    username = 'your_username' # ルータのユーザー名
    private_key_path = '/path/to/your/private_key'  # 秘密鍵のパス

    bgp_config = generate_bgp_config(config)
    print("Generated BGP Configuration:n", bgp_config)
    apply_config(host, username, private_key_path, bgp_config)

テクニックのポイント

  • 設定をテンプレート化し、パラメータを埋め込むことで、柔軟な設定生成を可能にしています。
  • 設定情報をJSON形式で外部ファイルから読み込むことで、設定の変更を容易にしています。
  • subprocess.runを使ってSSH鍵認証経由で設定を適用しています。
  • エラー発生時のロールバック処理を実装しています。

bgp_config.jsonの例


{
    "asn": 65001,
    "neighbors": [
        {"ip": "192.168.2.1", "remote_asn": 65002},
        {"ip": "192.168.2.2", "remote_asn": 65003}
    ]
}

類似技術との比較

技術 メリット デメリット 最適な利用環境/要件
Ansible 冪等性、豊富なモジュール 学習コストが高い、設定ファイルが複雑 大規模なネットワークで、複雑な設定を自動化する場合。設定の冪等性が重要な環境。
Terraform インフラの状態管理、宣言的な設定 ネットワーク機器のサポートが限定的 クラウド環境とオンプレミス環境を統合的に管理する場合。インフラの状態管理が重要な環境。
Python + Netmiko 柔軟性、スクリプトによる制御 エラーハンドリングが必要、冪等性の確保が難しい 小規模なネットワークで、特定のタスクを自動化する場合。柔軟なスクリプト制御が必要な環境。
Claude Code + MCP 設定スクリプトの自動生成、迅速なプロトタイピング LLMの性能に依存、セキュリティ対策が必要、APIの利用制限 迅速なプロトタイピングが必要な場合。設定スクリプトの自動生成を試したい環境。

Claude Code + MCP のデメリット詳細

  • LLMの性能に依存: Claude Codeの性能は、LLMのバージョンや学習データに依存します。 LLMがバージョンアップされた場合、以前と同じプロンプトでも異なる結果が生成される可能性があります。 また、LLMが学習していない特定のネットワーク機器やプロトコルの設定は、うまく生成できない場合があります。
  • APIの利用制限: Claude CodeはAPIを通じて利用することが一般的ですが、APIには利用制限(リクエスト数、トークン数など)が設けられている場合があります。 大量の設定スクリプトを生成する場合や、頻繁にAPIを呼び出す必要がある場合は、利用制限に注意する必要があります。
  • コスト: Claude CodeのAPI利用にはコストがかかる場合があります。 特に、大規模なネットワークで多数の設定スクリプトを生成する場合は、コストを考慮する必要があります。
  • バージョン管理: LLMのバージョンアップにより動作が変わる可能性があるため、生成された設定のバージョン管理が重要になります。

まとめと今後の展望

JANOG57 NETCONでの経験を通じて、Claude Codeはネットワーク設定の自動化に非常に有効なツールであることがわかりました。 しかし、LLMの性能に依存する部分や、セキュリティ上のリスクもあるため、適切な対策を講じる必要があります。CLAUDE.mdのようなプロンプト集を作成し、MCPサーバーを構築することで、より安全かつ効率的な自動化を実現することができます。

今後の展望

今後は、Claude Codeをさらに活用するために、以下の点に取り組んでいきたいと考えています。

  • プロンプトの自動最適化: Claude Codeにプロンプトを自動的に最適化させることで、より高度な設定スクリプトを生成できるようにする。
    • 技術的課題: どのようにプロンプトの有効性を評価し、改善方向を決定するか。強化学習などの手法の適用。
    • 実現方法: プロンプトの変更履歴を記録し、A/Bテストを実施。パフォーマンスの高いプロンプトを自動的に選択。 具体的なアルゴリズムとしては、Multi-armed bandit問題に対するUCB1(Upper Confidence Bound 1)アルゴリズムや、Thompson Samplingなどが考えられます。
  • ネットワーク構成の自動検出: Claude Codeにネットワーク構成を自動的に検出させ、それに基づいて設定スクリプトを生成できるようにする。
    • 技術的課題: ネットワーク機器から構成情報を収集し、LLMが理解できる形式に変換する方法。
    • 実現方法: NetmikoやScrapliなどのライブラリを使用して、ネットワーク機器から構成情報を収集し、JSON形式でLLMに提供。 具体的には、Netmikoのsend_commandメソッドや、Scrapliのsend_configメソッドなどを利用し、show running-configコマンドやshow ip interface briefコマンドなどを実行することで、構成情報を収集できます。
  • 継続的インテグレーション/継続的デリバリー (CI/CD) パイプラインへの統合: 生成された設定スクリプトを自動的にテストし、本番環境にデプロイできるようにする。
    • 技術的課題: 生成された設定スクリプトのテストを自動化する方法。テスト環境の構築と管理。
    • 実現方法: 設定スクリプトをテスト環境に適用し、ネットワークの疎通確認や設定の整合性チェックを自動的に実施。 例えば、PyTestやRobot Frameworkなどのテストフレームワークを利用し、設定適用後のネットワークの状態を自動的に検証するテストケースを作成できます。

これらの取り組みを通じて、ネットワークエンジニアリングの生産性を飛躍的に向上させることができると信じています。 また、この分野での知見を積極的に共有し、業界全体の発展に貢献していきたいと考えています。

, hostname): return jsonify({'status': 'error', 'message': 'Invalid hostname'}), 400 # 設定ファイルのバックアップ backup_file = os.path.join(CONFIG_DIR, f'{hostname}_backup.txt') current_config = get_config_from_device(hostname, username) if current_config: with open(backup_file, 'w') as f: f.write(current_config) try: # 設定適用コマンドの生成 commands = ['configure terminal'] + config.splitlines() + ['end'] command_str = 'n'.join(commands) # SSHコマンドの実行 ssh_command = [ 'ssh', '-o', 'StrictHostKeyChecking=no', '-i', PRIVATE_KEY_PATH, f'{username}@{hostname}', command_str ] process = subprocess.run( ssh_command, capture_output=True, text=True, check=True ) # エラー出力の詳細なログ出力 print(f"Configuration applied to {hostname}:n{process.stdout}") # 設定ファイルの保存 config_file = os.path.join(CONFIG_DIR, f'{hostname}.txt') with open(config_file, 'w') as f: f.write(config) return jsonify({'status': 'success', 'message': 'Configuration applied successfully'}), 200 except subprocess.CalledProcessError as e: error_message = e.stderr print(f"Error applying configuration to {hostname}:n{error_message}") # ロールバック処理 if os.path.exists(backup_file): print("Attempting rollback...") try: with open(backup_file, 'r') as f: rollback_config = f.read() rollback_commands = ['configure terminal'] + rollback_config.splitlines() + ['end'] rollback_command_str = 'n'.join(rollback_commands) rollback_ssh_command = [ 'ssh', '-o', 'StrictHostKeyChecking=no', '-i', PRIVATE_KEY_PATH, f'{username}@{hostname}', rollback_command_str ] rollback_process = subprocess.run( rollback_ssh_command, capture_output=True, text=True, check=True ) print("Rollback successful:", rollback_process.stdout) return jsonify({'status': 'error', 'message': f'Configuration failed: {error_message}. Rollback successful.'}), 500 except subprocess.CalledProcessError as rollback_e: rollback_error_message = rollback_e.stderr print(f"Error during rollback: {rollback_error_message}") return jsonify({'status': 'error', 'message': f'Configuration failed: {error_message}. Rollback failed: {rollback_error_message}'}), 500 else: return jsonify({'status': 'error', 'message': f'Configuration failed: {error_message}. No backup found.'}), 500 # 設定取得API @app.route('/config/', methods=['GET']) def get_config(hostname): # 入力値の検証 (簡易的な例) if not re.match(r'^([0-9]{1,3}.){3}[0-9]{1,3}

セキュリティに関する注意点

  • APIエンドポイントの認証・認可: 上記の例ではAPIエンドポイントの認証・認可が実装されていません。 実際の運用では、APIキー認証やOAuth 2.0などを導入し、不正なアクセスを防ぐ必要があります。
  • 入力値の検証: 上記の例では、hostnameに対して簡易的な入力値検証のみを行っています。 configパラメータについても、より厳密な検証を行い、不正なコマンドの実行を防ぐ必要があります。
  • SSH鍵の保護: SSH鍵は非常に重要な情報です。 適切なアクセス制御を行い、不正なアクセスを防ぐ必要があります。

よくある失敗とアンチパターン

  1. プロンプトが曖昧すぎる: 「Ciscoルータを設定して」のような曖昧な指示では、Claude Codeは期待通りの設定スクリプトを生成できません。 具体的なインターフェース名やIPアドレス、ルーティングプロトコルなどを指定する必要があります。
  2. エラーハンドリングを考慮しない: 生成された設定スクリプトをそのままネットワーク機器に適用すると、エラーが発生した場合にネットワークがダウンしてしまう可能性があります。 設定スクリプトにエラーハンドリングを追加し、エラーが発生した場合にロールバックできるようにする必要があります。
  3. セキュリティを考慮しない: MCPサーバーの認証を実装せずに公開すると、悪意のある第三者にネットワーク機器を制御される可能性があります。 強固な認証メカニズムを実装する必要があります。

アンチパターンの例 (Python)


改善されたコード (Python)


なぜ改善されたのか?

  • subprocess.runcheck=Trueを追加することで、コマンドが失敗した場合に例外を発生させ、エラーハンドリングを可能にしています。
  • capture_output=True, text=Trueを追加することで、標準出力と標準エラー出力をキャプチャし、エラーメッセージを表示できるようにしています。
  • StrictHostKeyChecking=noは本来セキュリティリスクですが、今回は簡略化のため使用。実運用ではSSH鍵交換を適切に行うべきです。
  • ロールバック処理を追加しました。設定変更前に設定ファイルをバックアップし、エラー発生時にバックアップファイルから設定をリストアします。

現場で使われる実践的コード・テクニック

以下に、私が実際にNETCONで使用した、より実践的なコード例を紹介します。 これは、CiscoルータのBGP設定を自動生成し、適用するためのPythonスクリプトです。


テクニックのポイント

  • 設定をテンプレート化し、パラメータを埋め込むことで、柔軟な設定生成を可能にしています。
  • 設定情報をJSON形式で外部ファイルから読み込むことで、設定の変更を容易にしています。
  • subprocess.runを使ってSSH鍵認証経由で設定を適用しています。
  • エラー発生時のロールバック処理を実装しています。

bgp_config.jsonの例


類似技術との比較

技術 メリット デメリット 最適な利用環境/要件
Ansible 冪等性、豊富なモジュール 学習コストが高い、設定ファイルが複雑 大規模なネットワークで、複雑な設定を自動化する場合。設定の冪等性が重要な環境。
Terraform インフラの状態管理、宣言的な設定 ネットワーク機器のサポートが限定的 クラウド環境とオンプレミス環境を統合的に管理する場合。インフラの状態管理が重要な環境。
Python + Netmiko 柔軟性、スクリプトによる制御 エラーハンドリングが必要、冪等性の確保が難しい 小規模なネットワークで、特定のタスクを自動化する場合。柔軟なスクリプト制御が必要な環境。
Claude Code + MCP 設定スクリプトの自動生成、迅速なプロトタイピング LLMの性能に依存、セキュリティ対策が必要、APIの利用制限 迅速なプロトタイピングが必要な場合。設定スクリプトの自動生成を試したい環境。

Claude Code + MCP のデメリット詳細

  • LLMの性能に依存: Claude Codeの性能は、LLMのバージョンや学習データに依存します。 LLMがバージョンアップされた場合、以前と同じプロンプトでも異なる結果が生成される可能性があります。 また、LLMが学習していない特定のネットワーク機器やプロトコルの設定は、うまく生成できない場合があります。
  • APIの利用制限: Claude CodeはAPIを通じて利用することが一般的ですが、APIには利用制限(リクエスト数、トークン数など)が設けられている場合があります。 大量の設定スクリプトを生成する場合や、頻繁にAPIを呼び出す必要がある場合は、利用制限に注意する必要があります。
  • コスト: Claude CodeのAPI利用にはコストがかかる場合があります。 特に、大規模なネットワークで多数の設定スクリプトを生成する場合は、コストを考慮する必要があります。
  • バージョン管理: LLMのバージョンアップにより動作が変わる可能性があるため、生成された設定のバージョン管理が重要になります。

まとめと今後の展望

JANOG57 NETCONでの経験を通じて、Claude Codeはネットワーク設定の自動化に非常に有効なツールであることがわかりました。 しかし、LLMの性能に依存する部分や、セキュリティ上のリスクもあるため、適切な対策を講じる必要があります。CLAUDE.mdのようなプロンプト集を作成し、MCPサーバーを構築することで、より安全かつ効率的な自動化を実現することができます。

今後の展望

今後は、Claude Codeをさらに活用するために、以下の点に取り組んでいきたいと考えています。

  • プロンプトの自動最適化: Claude Codeにプロンプトを自動的に最適化させることで、より高度な設定スクリプトを生成できるようにする。
    • 技術的課題: どのようにプロンプトの有効性を評価し、改善方向を決定するか。強化学習などの手法の適用。
    • 実現方法: プロンプトの変更履歴を記録し、A/Bテストを実施。パフォーマンスの高いプロンプトを自動的に選択。 具体的なアルゴリズムとしては、Multi-armed bandit問題に対するUCB1(Upper Confidence Bound 1)アルゴリズムや、Thompson Samplingなどが考えられます。
  • ネットワーク構成の自動検出: Claude Codeにネットワーク構成を自動的に検出させ、それに基づいて設定スクリプトを生成できるようにする。
    • 技術的課題: ネットワーク機器から構成情報を収集し、LLMが理解できる形式に変換する方法。
    • 実現方法: NetmikoやScrapliなどのライブラリを使用して、ネットワーク機器から構成情報を収集し、JSON形式でLLMに提供。 具体的には、Netmikoのsend_commandメソッドや、Scrapliのsend_configメソッドなどを利用し、show running-configコマンドやshow ip interface briefコマンドなどを実行することで、構成情報を収集できます。
  • 継続的インテグレーション/継続的デリバリー (CI/CD) パイプラインへの統合: 生成された設定スクリプトを自動的にテストし、本番環境にデプロイできるようにする。
    • 技術的課題: 生成された設定スクリプトのテストを自動化する方法。テスト環境の構築と管理。
    • 実現方法: 設定スクリプトをテスト環境に適用し、ネットワークの疎通確認や設定の整合性チェックを自動的に実施。 例えば、PyTestやRobot Frameworkなどのテストフレームワークを利用し、設定適用後のネットワークの状態を自動的に検証するテストケースを作成できます。

これらの取り組みを通じて、ネットワークエンジニアリングの生産性を飛躍的に向上させることができると信じています。 また、この分野での知見を積極的に共有し、業界全体の発展に貢献していきたいと考えています。

, hostname): return jsonify({'status': 'error', 'message': 'Invalid hostname'}), 400 username = 'your_username' # デフォルトユーザー config = get_config_from_device(hostname, username) if config: return jsonify({'hostname': hostname, 'config': config}), 200 else: return jsonify({'status': 'error', 'message': 'Configuration not found'}), 404 # デバイスから設定を取得する関数 def get_config_from_device(hostname, username): try: # show running-config コマンドを実行して設定を取得 ssh_command = [ 'ssh', '-o', 'StrictHostKeyChecking=no', '-i', PRIVATE_KEY_PATH, f'{username}@{hostname}', 'show running-config' ] process = subprocess.run( ssh_command, capture_output=True, text=True, check=True ) return process.stdout except subprocess.CalledProcessError as e: print(f"Error getting configuration from {hostname}: {e.stderr}") return None # SSH鍵認証の設定 (例) # 1. MCPサーバーでSSH鍵を生成: # ssh-keygen -t rsa -b 2048 -f /path/to/your/private_key -N "" # 2. 生成された公開鍵 (/path/to/your/private_key.pub) をネットワーク機器に登録 if __name__ == '__main__': app.run(debug=True) 

セキュリティに関する注意点

  • APIエンドポイントの認証・認可: 上記の例ではAPIエンドポイントの認証・認可が実装されていません。 実際の運用では、APIキー認証やOAuth 2.0などを導入し、不正なアクセスを防ぐ必要があります。
  • 入力値の検証: 上記の例では、hostnameに対して簡易的な入力値検証のみを行っています。 configパラメータについても、より厳密な検証を行い、不正なコマンドの実行を防ぐ必要があります。
  • SSH鍵の保護: SSH鍵は非常に重要な情報です。 適切なアクセス制御を行い、不正なアクセスを防ぐ必要があります。

よくある失敗とアンチパターン

  1. プロンプトが曖昧すぎる: 「Ciscoルータを設定して」のような曖昧な指示では、Claude Codeは期待通りの設定スクリプトを生成できません。 具体的なインターフェース名やIPアドレス、ルーティングプロトコルなどを指定する必要があります。
  2. エラーハンドリングを考慮しない: 生成された設定スクリプトをそのままネットワーク機器に適用すると、エラーが発生した場合にネットワークがダウンしてしまう可能性があります。 設定スクリプトにエラーハンドリングを追加し、エラーが発生した場合にロールバックできるようにする必要があります。
  3. セキュリティを考慮しない: MCPサーバーの認証を実装せずに公開すると、悪意のある第三者にネットワーク機器を制御される可能性があります。 強固な認証メカニズムを実装する必要があります。

アンチパターンの例 (Python)


改善されたコード (Python)


なぜ改善されたのか?

  • subprocess.runcheck=Trueを追加することで、コマンドが失敗した場合に例外を発生させ、エラーハンドリングを可能にしています。
  • capture_output=True, text=Trueを追加することで、標準出力と標準エラー出力をキャプチャし、エラーメッセージを表示できるようにしています。
  • StrictHostKeyChecking=noは本来セキュリティリスクですが、今回は簡略化のため使用。実運用ではSSH鍵交換を適切に行うべきです。
  • ロールバック処理を追加しました。設定変更前に設定ファイルをバックアップし、エラー発生時にバックアップファイルから設定をリストアします。

現場で使われる実践的コード・テクニック

以下に、私が実際にNETCONで使用した、より実践的なコード例を紹介します。 これは、CiscoルータのBGP設定を自動生成し、適用するためのPythonスクリプトです。


テクニックのポイント

  • 設定をテンプレート化し、パラメータを埋め込むことで、柔軟な設定生成を可能にしています。
  • 設定情報をJSON形式で外部ファイルから読み込むことで、設定の変更を容易にしています。
  • subprocess.runを使ってSSH鍵認証経由で設定を適用しています。
  • エラー発生時のロールバック処理を実装しています。

bgp_config.jsonの例


類似技術との比較

技術 メリット デメリット 最適な利用環境/要件
Ansible 冪等性、豊富なモジュール 学習コストが高い、設定ファイルが複雑 大規模なネットワークで、複雑な設定を自動化する場合。設定の冪等性が重要な環境。
Terraform インフラの状態管理、宣言的な設定 ネットワーク機器のサポートが限定的 クラウド環境とオンプレミス環境を統合的に管理する場合。インフラの状態管理が重要な環境。
Python + Netmiko 柔軟性、スクリプトによる制御 エラーハンドリングが必要、冪等性の確保が難しい 小規模なネットワークで、特定のタスクを自動化する場合。柔軟なスクリプト制御が必要な環境。
Claude Code + MCP 設定スクリプトの自動生成、迅速なプロトタイピング LLMの性能に依存、セキュリティ対策が必要、APIの利用制限 迅速なプロトタイピングが必要な場合。設定スクリプトの自動生成を試したい環境。

Claude Code + MCP のデメリット詳細

  • LLMの性能に依存: Claude Codeの性能は、LLMのバージョンや学習データに依存します。 LLMがバージョンアップされた場合、以前と同じプロンプトでも異なる結果が生成される可能性があります。 また、LLMが学習していない特定のネットワーク機器やプロトコルの設定は、うまく生成できない場合があります。
  • APIの利用制限: Claude CodeはAPIを通じて利用することが一般的ですが、APIには利用制限(リクエスト数、トークン数など)が設けられている場合があります。 大量の設定スクリプトを生成する場合や、頻繁にAPIを呼び出す必要がある場合は、利用制限に注意する必要があります。
  • コスト: Claude CodeのAPI利用にはコストがかかる場合があります。 特に、大規模なネットワークで多数の設定スクリプトを生成する場合は、コストを考慮する必要があります。
  • バージョン管理: LLMのバージョンアップにより動作が変わる可能性があるため、生成された設定のバージョン管理が重要になります。

まとめと今後の展望

JANOG57 NETCONでの経験を通じて、Claude Codeはネットワーク設定の自動化に非常に有効なツールであることがわかりました。 しかし、LLMの性能に依存する部分や、セキュリティ上のリスクもあるため、適切な対策を講じる必要があります。CLAUDE.mdのようなプロンプト集を作成し、MCPサーバーを構築することで、より安全かつ効率的な自動化を実現することができます。

今後の展望

今後は、Claude Codeをさらに活用するために、以下の点に取り組んでいきたいと考えています。

  • プロンプトの自動最適化: Claude Codeにプロンプトを自動的に最適化させることで、より高度な設定スクリプトを生成できるようにする。
    • 技術的課題: どのようにプロンプトの有効性を評価し、改善方向を決定するか。強化学習などの手法の適用。
    • 実現方法: プロンプトの変更履歴を記録し、A/Bテストを実施。パフォーマンスの高いプロンプトを自動的に選択。 具体的なアルゴリズムとしては、Multi-armed bandit問題に対するUCB1(Upper Confidence Bound 1)アルゴリズムや、Thompson Samplingなどが考えられます。
  • ネットワーク構成の自動検出: Claude Codeにネットワーク構成を自動的に検出させ、それに基づいて設定スクリプトを生成できるようにする。
    • 技術的課題: ネットワーク機器から構成情報を収集し、LLMが理解できる形式に変換する方法。
    • 実現方法: NetmikoやScrapliなどのライブラリを使用して、ネットワーク機器から構成情報を収集し、JSON形式でLLMに提供。 具体的には、Netmikoのsend_commandメソッドや、Scrapliのsend_configメソッドなどを利用し、show running-configコマンドやshow ip interface briefコマンドなどを実行することで、構成情報を収集できます。
  • 継続的インテグレーション/継続的デリバリー (CI/CD) パイプラインへの統合: 生成された設定スクリプトを自動的にテストし、本番環境にデプロイできるようにする。
    • 技術的課題: 生成された設定スクリプトのテストを自動化する方法。テスト環境の構築と管理。
    • 実現方法: 設定スクリプトをテスト環境に適用し、ネットワークの疎通確認や設定の整合性チェックを自動的に実施。 例えば、PyTestやRobot Frameworkなどのテストフレームワークを利用し、設定適用後のネットワークの状態を自動的に検証するテストケースを作成できます。

これらの取り組みを通じて、ネットワークエンジニアリングの生産性を飛躍的に向上させることができると信じています。 また、この分野での知見を積極的に共有し、業界全体の発展に貢献していきたいと考えています。

コメント

タイトルとURLをコピーしました