mcpField
H
huawei-cloud-ecs-passwordless-login

huawei-cloud-ecs-passwordless-login

github.com/huaweicloudクラウド・DevOps59188 回インストール2 日前に更新
リポジトリ

huawei-cloud-ecs-passwordless-login について

hcloud CLI と COC を使い、Huawei Cloud ECS への一時的なパスワードなし SSH 接続を構成するスキルです。複数インスタンスへの Ed25519 鍵の配布、接続確認、永続接続の確立後に鍵を削除します。

主な機能

  1. 01COC の IAM 認可設定
  2. 02Ed25519 SSH 鍵の生成
  3. 03複数 ECS への鍵配布
  4. 04SSH 検証と ControlMaster 設定
  5. 05鍵とスクリプトの定時削除

活用シーン

  1. 01ECS への一時的なパスワードなし SSH 設定
  2. 02接続確認後も永続接続を維持
  3. 03SSH テストに失敗した ECS の特定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/huaweicloud/huaweicloud-skills --skill huawei-cloud-ecs-passwordless-login

インストール後、Claude Code で/huawei-cloud-ecs-passwordless-loginを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
acceptance-criteria.md
cli-installation-guide.md
iam-policies.md
verification-method.md

詳細

Huawei Cloud ECS のパスワードレスログイン

概要

COC(Cloud Operations Center)を使用して、7 ステップの自動ワークフローで Huawei Cloud ECS へのパスワードレス SSH ログインを設定します。

  1. IAM 認可 — COC サービス用の ServiceAgencyForCOC エージェンシーを作成し、必要な 4 つのロールを紐付けます。エージェンシーがすでに存在する場合(HTTP 409)は、全工程をスキップします
  2. 鍵の生成 — ローカルで Ed25519 SSH 鍵ペアを生成します
  3. スクリプトの作成 — 公開鍵をデプロイする、パラメーター化された COC スクリプトを作成または再利用します
  4. スクリプトの実行 — COC 経由で、1 台または複数の対象 ECS インスタンス上でスクリプトを実行します(バッチ処理。各対象のリージョンと resource_id は COC CLI の ListResources で解決されます)
  5. SSH テスト — すべての対象 ECS へのパスワードレス SSH 接続を確認します
  6. 接続の維持 — SSH ControlMaster を確立し、鍵のクリーンアップ後もエージェントが SSH アクセスを継続できるようにします
  7. セキュリティクリーンアップ — 60 秒後に、リモートの authorized_keys から鍵を自動的に削除し、ローカルの鍵ペアを削除して、COC スクリプトをクリーンアップします

ツールチェーン: hcloud CLI(KooCLI)+ ローカル SSH ツール。デプロイは COC スクリプトの実行のみで行います。

リージョンモデル:COC は、cn-north-4(中国サイト)と ap-southeast-3(国際サイト)のみをサポートするグローバルレベルのサービスです。対象 ECS インスタンスは異なるリージョンに存在する場合があります(バッチ処理)。すべての COC/IAM API 呼び出しと、COC ListResources による対象の解決には coc_region を使用してください。対象の解決にあたり、事前に ECS リージョンを指定する必要はありません。各対象の実際のリージョンは、ListResources のレスポンスで返されます。詳細は注意事項を参照してください。

前提条件

  • hcloud CLI(KooCLI)がインストールされ、AK/SK で認証済みであること — CLI インストールガイドを参照してください
  • エージェンシーの作成と COC の操作に十分な権限を持つ IAM ユーザーであること — IAM ポリシーを参照してください
  • SSH クライアントと ssh-keygen がローカルで利用できること
  • 対象 ECS のインスタンス ID またはエラスティック IP を、カンマ区切りのリストで指定すること(各 ECS は ACTIVE 状態である必要があります)
  • ECS に uniagent が事前インストールされていること — COC スクリプトの実行には、ECS に事前インストールされた uniagent エージェントが必要です。hcloud COC ListResources コマンドで uniagent の状態を確認し、agent_state フィールドを調べてエージェントが正常に動作していることを確認してください
セキュリティ
  • 秘密鍵の内容を会話や出力に決して表示しないでください
  • 60 秒の期間を超えて秘密鍵をログに記録したり、永続化したりしないでください
  • クリーンアップは必須です。SSH テストが成功した場合、cleanup_delay 秒以内に鍵を必ず削除してください
  • authorized_keys から公開鍵を削除しても、ブロックされるのは新しい SSH 接続のみです。既存のセッションは中断されません
  • SSH テストに失敗した場合は、デバッグのために鍵を保持し、クリーンアップを実行しないでください

ワークフロー

以下の番号付き手順を順番に実行します。各手順で使用する正確なコマンド構文については、基本コマンドのセクションを参照してください。

1. IAM 認可

アカウントごとに一度だけ設定します。 COC が ECS インスタンスを操作できるように認可します。

この手順のすべての IAM 呼び出しは、COC がサポートするリージョン(coc_region)、すなわち cn-north-4(中国)または ap-southeast-3(国際)に対して実行します。

  1. ドメイン ID の取得 — KeystoneListAuthDomains を呼び出し、id を抽出します。
  2. エージェンシーの作成 — 名前を ServiceAgencyForCOC、信頼ドメインを op_svc_coc として CreateAgency を呼び出します。
    • HTTP 200 — 新しいエージェンシーが作成されました。agency.id を記録し、手順 3 に進みます。
    • HTTP 409 — エージェンシーはすでに存在します。IAM フェーズ全体(手順 3~4)をスキップし、手順 2(鍵の生成)に進みます。
  3. ロール ID の検索 — 4 つのロール(IAM ReadOnlyAccess、RMS ReadOnlyAccess、DCS UserAccess、COCServiceAgencyPolicy)それぞれに対して KeystoneListPermissions を呼び出します。ロールが見つからない場合は中止してください。アカウントにアクセス権がない可能性があります。
  4. ロールの紐付け — 4 つのロール ID それぞれに対して AssociateAgencyWithAllProjectsPermission を呼び出します。
    • HTTP 200 — 正常に紐付けられました。
    • HTTP 409 — すでに紐付けられています。スキップして続行します。
2. ローカル SSH 鍵ペアを生成する

Ed25519 鍵ペアを生成します。コメント coc-temp-key はクリーンアップ用のマーカーです。サポートされているのは Ed25519 鍵のみです。RSA、ECDSA、DSA の鍵タイプはサポートされていません。このスキルとは互換性がないため、生成またはデプロイしないでください。

鍵のフィンガープリントを記録します。秘密鍵の内容は決して表示しないでください。

3. COC スクリプトを作成または再利用する
  1. 既存のものを確認する — --name_like="coc_ssh_key_setup" を指定して ListScripts --cli-region=<coc_region> を呼び出します。見つかった場合は script_uuid を記録し、手順 2 をスキップします。
  2. 新規作成する — スクリプトの内容を記載した JSON ファイルを作成し、CreateScript --cli-region=<coc_region> --cli-jsonInput=<file> を呼び出します。スクリプト本文に特殊文字が含まれる場合のシェルの引用符の問題を避けるため、インラインの --content ではなく --cli-jsonInput を使用してください。返された script_uuid を記録します。
4. 対象 ECS でスクリプトを実行する

対象 ECS インスタンスのバッチ全体でデプロイスクリプトを実行します。COC では、1 回の実行につき最大 200 ホスト、1 バッチにつき最大 10 ホスト(batch_index/rotation_strategy)がサポートされています。そのため、対象を 10 以下のバッチに分割してください。

  1. 対象を解決し、リージョンを確認する — ecs_instance_id/ecs_ip の各エントリについて、COC ListResources --cli-region=<coc_region> --provider=ecs --type=cloudservers を呼び出し、エントリを ECS リソースに解決します。ListResources に必要なのは coc_region のみです。事前に ECS のリージョンを指定する必要はありません。レスポンスには各リソースの region_id と resource_id(および properties.addresses 内の IP)が含まれます。対象が複数の ECS リージョンにまたがる場合もあります。対象ごとに (region_id, resource_id) のペアを記録します。

    • リソース ID で指定する場合 — ID のエントリには --resource_id_list.N="<instance_id>" を渡します。返された完全一致の resource_id を、COC の実行ペイロードで使用します。
    • IP で指定する場合 — IP のエントリには必ず --ip_list.N="<EIP>" を渡します。--ip_list は完全一致で照合します。返された各リソースについて、対象を記録する前に properties.addresses[].addr が照会した <EIP> と一致することを確認してください。
      • 完全一致する場合 — (region_id, resource_id) のペアを記録して続行します。
      • 一致しない/リソースが返されない場合 — 不一致を報告し、そのエントリの処理をスキップ/停止します。別の IP に暗黙的にフォールバックしないでください。スクリプトが誤ったインスタンスで実行される可能性があります。
  2. 実行する — 公開鍵を埋め込み、解決済みの対象ペアをすべてバッチごとにグループ化した JSON ファイルを作成し、ExecuteScript --cli-region=<coc_region> --cli-jsonInput=<file> を呼び出します。公開鍵の内容に関するシェルの引用符の問題を避けるため、手順 3 と同じ方法を使用します。execute_uuid を記録します。

  3. ポーリングする — 終端ステータスになるまで、5 秒ごとに GetScriptJobInfo --cli-region=<coc_region> を呼び出します。注:セキュリティ上、API はレスポンス内の param_value をマスキングします。デプロイは手順 5 の SSH テストで確認してください。

    ステータスアクション
    RUNNING5 秒待って再度ポーリングします
    SUCCESS手順 5 に進みます
    FAILED/TIMEOUT対象ごとのエラーを報告し、停止します

    最大 2 分(24 回ポーリング)です。

5. SSH 接続をテストする

生成した鍵を使用して、パスワードなしの SSH をテストします。対象 ECS のすべてで実行してください。

  • すべての対象が SSH_OK を返す場合 — 手順 6 に進みます。
  • いずれかの対象で失敗した場合 — 失敗した対象を報告します。ここで停止してください。 デバッグのために鍵を保持します。クリーンアップを実行しないでください。
6. SSH 接続を永続化する

ステップ 7 で鍵を削除した後も、エージェントがすべての対象 ECSにアクセスできるよう、SSH ControlMaster を設定します。

  1. SSH 設定を追記する — 各対象について、ControlMaster auto、ControlPath /tmp/coc_ssh_%r@%h:%p、ControlPersist <persist_timeout>、ServerAliveInterval <server_alive_interval>、ServerAliveCountMax <server_alive_count_max> を指定した Host <EIP> ブロックを ~/.ssh/config に追加します。
  2. マスターを起動する — 各対象について、ssh -N -f <ssh_user>@<EIP> -i <key> を実行し、永続的なマスター接続をバックグラウンドで起動します。
  3. 確認する — 各対象について、鍵ファイルを指定せずに ssh <ssh_user>@<EIP> "echo SSH_MUX_OK" を実行します。SSH_MUX_OK が返されれば、多重化が機能しています。

SSH 設定とソケットはクリーンアップ不要です。設定項目に問題はなく、ソケットは ControlPersist に従って自動的に期限切れになります。

7. セキュリティのクリーンアップ

必須です。 cleanup_delay 秒後(デフォルト:60 秒)に実行されるバックグラウンドタイマーを開始します。

  1. すべての対象で、リモートの ~<ssh_user>/.ssh/authorized_keys から coc-temp-key の行を削除します。
  2. DeleteScript --cli-region=<coc_region> を使用して COC スクリプトを削除します。
  3. <temp_dir>/ からローカルの鍵ファイルを削除します。

クリーンアップ後も、ControlMaster が鍵認証を回避するため、エージェントは任意の対象に ssh <EIP> で接続できます。

フォールバック:対象のリモート鍵を SSH 経由で削除できない場合は、ワンショットの COC スクリプトを作成して実行します(失敗したホストのみを対象とするバッチとして実行します)。

#!/bin/bash
set -e
HOME_DIR=$(eval echo ~$SSH_USER)
sed -i '/coc-temp-key/d' "$HOME_DIR/.ssh/authorized_keys"
echo "KEY_REMOVED"

SSH_USER パラメーターに <ssh_user> を設定し、解決済みの各ホストのリージョンを使用して、失敗したホストのみを対象とするバッチとしてこのスクリプトを作成して実行します。実行完了後、すぐに削除します。

コアコマンド

プレースホルダー値(OS ごとの解決方法については「パラメーター」を参照):

プレースホルダーLinux / macOSWindows
<temp_dir>/tmp$env:TEMP
# 1. Check/setup COC IAM authorization
# IAM is regional in hcloud; the agency must be created in the COC-supported region (coc_region)
hcloud IAM KeystoneListAuthDomains/v3 --cli-region=<coc_region>
hcloud IAM CreateAgency/v3 \
  --cli-region=<coc_region> \
  --agency.domain_id="<domain_id>" \
  --agency.name="ServiceAgencyForCOC" \
  --agency.trust_domain_name="op_svc_coc" \
  --agency.duration="FOREVER"
hcloud IAM KeystoneListPermissions/v3 \
  --cli-region=<coc_region> \
  --display_name="<role_name>"
hcloud IAM AssociateAgencyWithAllProjectsPermission/v3 \
  --cli-region=<coc_region> \
  --agency_id="<agency_id>" --domain_id="<domain_id>" --role_id="<role_id>"

# 2. Generate local SSH key pair (Ed25519 only)
ssh-keygen -t ed25519 -f <temp_dir>/coc_ssh_key -N "" -C "coc-temp-key"
ssh-keygen -lf <temp_dir>/coc_ssh_key  # record fingerprint

# 3. Check for existing COC script
# COC API calls always target the COC-supported region (coc_region)
hcloud COC ListScripts --cli-region=<coc_region> --limit=100 --name_like="coc_ssh_key_setup"
# If not found, create a JSON file and use --cli-jsonInput:
cat > <temp_dir>/coc_create.json << 'JSONEOF'
{
  "body": {
    "name": "coc_ssh_key_setup",
    "type": "SHELL",
    "description": "Deploy SSH public key for passwordless login",
    "content": "#!/bin/bash\nset -e\nHOME_DIR=$(eval echo ~$SSH_USER)\nmkdir -p \"$HOME_DIR/.ssh\" && chmod 700 \"$HOME_DIR/.ssh\"\necho $PUBLIC_KEY >> \"$HOME_DIR/.ssh/authorized_keys\"\nchmod 600 \"$HOME_DIR/.ssh/authorized_keys\"\necho KEY_DEPLOYED_SUCCESSFULLY",
    "properties": {
      "risk_level": "LOW",
      "version": "1.0.0"
    },
    "script_params": [
      {
        "param_name": "PUBLIC_KEY",
        "param_description": "SSH public key to deploy",
        "param_value": "",
        "sensitive": true
      },
      {
        "param_name": "SSH_USER",
        "param_description": "Target SSH username on the ECS",
        "param_value": "",
        "sensitive": false
      }
    ]
  }
}
JSONEOF
hcloud COC CreateScript --cli-region=<coc_region> --cli-jsonInput=<temp_dir>/coc_create.json

# 4. Resolve batch targets & confirm each region, then execute script
# ecs_instance_id / ecs_ip are comma-separated lists. Do NOT assume a single region;
# COC ListResources resolves each entry (IP or ID) WITHOUT needing the ECS region in advance,
# and returns each resource's region_id and resource_id. Always target the coc_region endpoint.
hcloud COC ListResources --cli-region=<coc_region> --provider=ecs --type=cloudservers --limit=100 \
  --resource_id_list.1="<instance_id>"                       # for an ID entry (exact match)
hcloud COC ListResources --cli-region=<coc_region> --provider=ecs --type=cloudservers --limit=100 \
  --ip_list.1="<EIP>"                                        # for an IP entry (exact list match)

# Always verify the returned resource's properties.addresses[].addr exactly equals <EIP>
# before recording the target; otherwise the script may run against the wrong instance.
# Extract per resource: region_id, resource_id, and properties.addresses[].addr
#   RESULT=$(hcloud COC ListResources ... --cli-json-filter="data[]")
# Record (region_id, resource_id) pair per target; group into batches of <=10 hosts each.
cat > <temp_dir>/coc_execute.json << 'JSONEOF'
{
  "path": {"script_uuid": "<script_uuid>"},
  "body": {
    "execute_batches": [
      {
        "batch_index": 1,
        "rotation_strategy": "CONTINUE",
        "target_instances": [
          {"region_id": "<target1_region>", "resource_id": "<target1_id>"},
          {"region_id": "<target2_region>", "resource_id": "<target2_id>"}
        ]
      },
      {
        "batch_index": 2,
        "rotation_strategy": "CONTINUE",
        "target_instances": [
          {"region_id": "<target3_region>", "resource_id": "<target3_id>"}
        ]
      }
    ],
    "execute_param": {
      "execute_user": "root",
      "success_rate": 100,
      "timeout": 120,
      "script_params": [{
        "param_name": "PUBLIC_KEY",
        "param_value": pubkey
      },
      {
        "param_name": "SSH_USER",
        "param_value": "<ssh_user>"
      }]
    }
  }
}
JSONEOF
hcloud COC ExecuteScript --cli-region=<coc_region> --cli-jsonInput=<temp_dir>/coc_execute.json

# Poll execution status (note: GetScriptJobInfo redacts param_value for security; check SSH directly to verify)
hcloud COC GetScriptJobInfo --cli-region=<coc_region> --execute_uuid=<execute_uuid>

# 5. Test SSH connection (repeat for every target EIP)
for eip in <EIP1> <EIP2> <EIP3>; do
  ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
    -o ConnectTimeout=10 -i <temp_dir>/coc_ssh_key <ssh_user>@$eip "echo SSH_OK"
done

# 6. Establish persistent SSH connection (ControlMaster multiplexing, one per target)
for eip in <EIP1> <EIP2> <EIP3>; do
  cat >> ~/.ssh/config << EOF

Host $eip
  User <ssh_user>
  ControlMaster auto
  ControlPath /tmp/coc_ssh_%r@%h:%p
  ControlPersist <persist_timeout>
  ServerAliveInterval <server_alive_interval>
  ServerAliveCountMax <server_alive_count_max>
  StrictHostKeyChecking no
  UserKnownHostsFile /dev/null
EOF
  ssh -N -f <ssh_user>@$eip -i <temp_dir>/coc_ssh_key && echo "MASTER_CONNECTED $eip"
  ssh <ssh_user>@$eip "echo SSH_MUX_OK"  # verify multiplexing works
done

# 7. Security cleanup (background, survives parent shell exit via nohup + disown)
nohup bash -c '
sleep <cleanup_delay>
# Remove public key from every remote target
for eip in <EIP1> <EIP2> <EIP3>; do
  ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
    -o ConnectTimeout=5 -i <temp_dir>/coc_ssh_key <ssh_user>@$eip \
    "sed -i \"/coc-temp-key/d\" \$(eval echo ~<ssh_user>)/.ssh/authorized_keys" 2>/dev/null || true
done
# Delete COC script
hcloud COC DeleteScript --cli-region=<coc_region> --script_uuid="<script_uuid>" 2>/dev/null || true
# Delete local keys
rm -f <temp_dir>/coc_ssh_key <temp_dir>/coc_ssh_key.pub
echo "COC SSH keys cleaned up. Existing SSH sessions remain unaffected."
' > <temp_dir>/coc_cleanup.log 2>&1 &
disown
echo "Cleanup scheduled in <cleanup_delay>s (PID: $!, log: <temp_dir>/coc_cleanup.log)"

パラメーター

パラメーター必須デフォルト制約
ecs_instance_id条件付きなしECS インスタンス UUID のカンマ区切りリストです。ecs_ip が指定されていない場合は必須です。ecs_ip のエントリと混在させることができます。すべてのエントリがバッチの対象となります
ecs_ip条件付きなしECS のエラスティック IPv4 アドレスのカンマ区切りリストです。ecs_instance_id が指定されていない場合は必須です。ecs_instance_id のエントリと混在させることができます
ecs_regionいいえなしターゲットの解決には使用されなくなりました。 ターゲットの ECS リージョンは COC ListResources によって検出されます(事前に指定しなくても各リソースの region_id が返されます)。このパラメーターは任意のヒントとしてのみ保持されており、必須ではありません
coc_regionいいえcn-north-4COC サービスのリージョンです。COC はグローバルレベルのサービスであり、cn-north-4(中国サイト)と ap-southeast-3(インターナショナルサイト)のみがサポートされています。すべての COC/IAM API 呼び出しはこのリージョンを対象にする必要があります。ECS リージョンとは独立しています
ssh_userいいえrootターゲット ECS 上の SSH ユーザー名です。root と非 root のどちらもサポートされています。キーはユーザーの ~/.ssh/authorized_keys に配置されます
cleanup_delayいいえ60キーが自動クリーンアップされるまでの待機秒数です(最小 10、最大 300)
persist_timeoutいいえ3600すべてのセッションが終了した後も ControlMaster を維持する秒数です(最小 60、最大 86400)
server_alive_intervalいいえ30アクティブな TCP 接続を維持するため、リモートホストにキープアライブパケットを送信する間隔(秒)です(最小 5、最大 300)
server_alive_count_maxいいえ3クライアントが切断するまでの、応答のないキープアライブプローブの最大回数です(最小 1、最大 10)

出力形式

各ステップで、以下の構造に従って進捗を報告します。

StepOutput
1. AuthorizationAgency status (created / already exists), roles bound count (4/4)
2. Key GenerationKey fingerprint, key file paths
3. ScriptScript name, action (created / reused), script_uuid
4. Executionexecute_uuid、ターゲット数とバッチごとのステータス、ターゲットごとの最終結果
5. SSH Testターゲットごとの接続結果、SSH コマンド文字列
6. Persistent ConnectionControlMaster のステータス、多重化の検証、SSH エイリアス(<EIP> ごとに 1 つ)
7. CleanupTimer PID、カウントダウン通知、クリーンアップの確認

検証

ワークフローの各ステップを順に検証します。

  1. Authorization — CreateAgency が 200 を返す → 4 つすべてのロールをバインド(各ロールについて 200 または 409)。409 を返す → IAM フェーズ全体をスキップ(以前の実行ですでにエージェンシーの認可が完了しています)
  2. Key Generation — キーペアファイルが <temp_dir>/ に存在し、パーミッションが正しい
  3. Script — PUBLIC_KEY パラメーターを持つ coc_ssh_key_setup が存在し、有効な script_uuid を持つ
  4. Execution — GetScriptJobInfo で、2 分以内にバッチのステータスが SUCCESS になることを確認
  5. SSH Test — 各ターゲットにパスワード入力なしで接続でき、すべてのテストコマンドが SSH_OK を返す
  6. Persistent Connection — SSH 設定を追記(ControlMaster、ControlPersist、ServerAliveInterval を含む)。ssh -N -f <ssh_user>@<EIP> でマスターを起動し、各ターゲットで ssh <ssh_user>@<EIP> "echo SSH_MUX_OK" が成功する
  7. Cleanup — すべてのターゲットでリモートキーを削除し、COC スクリプトを削除し、ローカルのキーファイルを削除する。ssh <ssh_user>@<EIP> が ControlMaster 経由で引き続き接続できることを確認

詳細なチェックリストについては、検証方法および受け入れ基準を参照してください。

ベストプラクティス

  • IAM 認可の設定はアカウントごとに 1 回のみです。CreateAgency が 409 を返した場合、IAM フェーズ全体(エージェンシーとロールのバインド)は完了済みのため、全体をスキップしてください
  • ListScripts で --name_like フィルターを使用し、スクリプトの重複作成を避けてください
  • クリーンアップタイマーを開始する前に、必ず SSH 接続をテストしてください
  • SSH 接続に失敗した場合は、デバッグのためにキーをディスク上に残してください。自動でクリーンアップしないでください
  • クリーンアップタイマーはバックグラウンドのサブシェルで実行されます。クリーンアップが完了する前にプロセスを終了すると、キーが残ります
  • キーのクリーンアップ後も、エージェントは ssh <EIP> で SSH 接続できます。ControlMaster はキー認証を回避します
  • ローカルの known_hosts ファイルが汚染されないよう、-o UserKnownHostsFile=/dev/null を使用してください
  • SSH キーのコメント coc-temp-key は、クリーンアップ時に sed が使用するマーカーです。変更しないでください
  • COC スクリプトの実行は、1 回の実行あたり最大 200 ホスト、1 バッチあたり最大 10 ホストに制限されています。ターゲットが 10 ホストを超える場合は、batch_index ごとに最大 10 ホストとなるようバッチを分割してください
  • バッチ内のターゲットは複数の ECS リージョンにまたがる場合があります。Step 4 では、事前に指定しなくても region_id が返される COC ListResources を使用して、各ターゲットのリージョンを必ず確認してください。すべてのターゲットが同じ ecs_region にあると想定しないでください
  • バッチ内のすべてのターゲットで SSH をテストし、クリーンアップを実行してください。ターゲットが 1 つでも失敗すると実行は中断され、デバッグ用のキーが残ります
  • SSH 設定のエントリーは、クリーンアップ後も無害な古いエントリーとして残ります。必要に応じて後で削除できます
  • アイドル状態の ControlMaster 接続が NAT ゲートウェイやステートフルファイアウォールによって切断されないよう、~/.ssh/config で ServerAliveInterval(既定値は 30 秒)と ServerAliveCountMax(既定値は 3)を設定してください

参考ドキュメント

ドキュメント説明
CLI インストールガイドhcloud CLI と SSH ツールをインストールして設定します
IAM ポリシー必要な IAM 権限、委任の設定、エラー処理
検証方法ワークフローの各ステップを順番に検証します
受け入れ基準エンドツーエンドの受け入れチェックリスト全体

注意事項

  • COC スクリプトは uniagent に依存します — COC スクリプトの実行には、ECS に事前インストールされている uniagent エージェントが必要です。uniagent がインストールされていない場合、または状態に異常がある場合、COC スクリプトの実行は失敗します。次のコマンドで uniagent の状態を確認してください。
    hcloud COC ListResources --cli-region=<coc_region> --provider=ecs --type=cloudservers --limit=100
    
    応答の agent_state フィールドを確認し、エージェントが実行中であることを確かめてください。エージェントの状態に異常がある場合は、COC スクリプトを実行する前に uniagent の問題を修正してください。
  • リージョンモデル — COC と ECS では使用するリージョンが異なります。
    • COC はグローバルレベルのサービスです:対応リージョンは cn-north-4(中国サイト)と ap-southeast-3(国際サイト)のみです。すべての COC/IAM API 呼び出しは coc_region を対象にする必要があります。
    • ECS はリージョン単位のサービスです:対象となる各 ECS はそれぞれのリージョンにあり、バッチ内でもリージョンが異なる場合があります。各対象のリージョンはステップ 4 で ECS CLI を使用して確認し、その後、COC 実行ペイロード内の各 target_instance に region_id として渡します。COC はグローバルエンドポイントから対象リージョンへルーティングします。
    • COC/IAM/ECS の呼び出しでは、CLI プロファイルのデフォルトリージョンによる誤ルーティングを防ぐため、--cli-region でリージョンを明示的に指定します。
      • COC と IAM の呼び出し → --cli-region=<coc_region>
      • ECS 対象の特定(COC ListResources) → --cli-region=<coc_region>(グローバル COC エンドポイントを使用します。事前に ECS のリージョンを指定する必要はありません。応答に各リソースの region_id が含まれます)
      • SSH コマンド → <EIP> と <ssh_user> を直接使用します(リージョンの概念はありません)
  • COC スクリプトは、インラインの --content="..." ではなく、JSON ファイルを指定した --cli-jsonInput を使用して作成します。インラインで引用符を使うと、スクリプト本文に含まれるシェルの特殊文字によって解析エラーが発生します。
  • COC スクリプトは PUBLIC_KEY をパラメーター化しており、呼び出し間で保持され、異なるキーをデプロイできます。
  • 前回の実行ですでに COC スクリプトが作成されている場合は、再作成せずに再利用します。
  • クリーンアップでは nohup bash -c '...' & と disown を使用して、親シェルの終了後も処理を継続します。確認用の出力は <temp_dir>/coc_cleanup.log に記録されます。従来の (sleep N && ...) & パターンでは、非対話モードで親シェルが終了すると標準出力が失われます。
  • 秘密鍵は <temp_dir> に保存し、VCS にコミットしないでください。
  • SSH キーの種類は Ed25519 に固定されています(ssh-keygen -t ed25519)。RSA、ECDSA、DSA キーはこのスキルではサポートされません。生成またはデプロイしないでください。既存の互換性のないキーが検出された場合は、Ed25519 で再生成してください。
  • sed のクリーンアップ対象 coc-temp-key は、ssh-keygen の実行時に設定されるキーコメントと一致します。
  • クリーンアップ後は、ssh <EIP> を使用してください(キーファイルは不要です)。ControlMaster ソケットが認証を処理します。

コメント