AWS移行計画 — Synology → ECS on Fargate¶
概要
AEGISが実収益を生み始めた段階で、BCP(事業継続計画)・可用性・運用負荷の観点から Synology NAS → AWS ECS (Fargate) への移行を計画する。 本ドキュメントは移行の技術設計・コスト分析・段階的移行手順を網羅する。
ステータス: 計画段階(AWSアカウント・コスト監視は構築済み)
本移行は収益が安定した段階で実施する。現時点では設計ドキュメントとしてのみ存在する。 実施時期は未定。ただし、AWSアカウント・IAM Identity Center・Budget Alert・ ダッシュボードCostパネルは2026-03-25に構築済み。
移行の動機¶
なぜSynologyから移行するのか¶
| 観点 | Synology (現行) | AWS (移行後) |
|---|---|---|
| 物理障害 | NAS故障・停電でシステム全停止 | AZ冗長で単一障害点なし |
| ネットワーク | 家庭ISP依存(障害時は全停止) | AWS Direct Connect不要(API outbound のみ) |
| OS管理 | DSM手動アップデート | Fargate: OS管理不要 |
| スケーリング | 物理ハードウェア制約 | タスク定義変更のみ |
| DR(災害復旧) | バックアップなし(単一NAS) | EFS自動バックアップ + Cross-Region複製 |
| セキュリティ | SSH + Tailscale(攻撃面あり) | SSHポート自体が存在しない |
| 監視 | 自前 aegis-monitor | CloudWatch統合(メトリクス・ログ・アラーム) |
BCP上の最大リスク¶
flowchart TB
RISK["Synology単一障害点"]
RISK --> R1["NAS本体故障<br/>全サービス停止"]
RISK --> R2["ISP障害<br/>Saxo API到達不能"]
RISK --> R3["停電<br/>UPS容量超過で全停止"]
RISK --> R4["DSMアップデート失敗<br/>Docker環境破損"]
R1 & R2 & R3 & R4 --> IMPACT["影響: PT停止<br/>→ ポジション管理不能<br/>→ 損失拡大リスク"]
style RISK fill:#e74c3c,stroke:#c0392b,color:#fff
style IMPACT fill:#e67e22,stroke:#d35400,color:#fff
リージョン選定: us-east-1¶
通信先はほぼ全て米国東海岸¶
AEGISが通信する外部APIのサーバー所在地とレイテンシ比較:
| API | サーバー所在地 | ap-northeast-1(東京)→ API | us-east-1 → API |
|---|---|---|---|
| Polygon.io | US East | ~170ms | ~1-3ms |
| Unusual Whales | US | ~150ms | ~5-10ms |
| FRED (St. Louis Fed) | US | ~180ms | ~10-20ms |
| Finnhub | US | ~150ms | ~5-10ms |
| Yahoo Finance | US | ~150ms | ~1-5ms |
| Saxo Bank | EU (Copenhagen) | ~250ms | ~80-100ms |
Polygon/UWはintraday収集で15分〜60秒間隔のポーリングを行うため、レイテンシが低い方がスループットに直結する。 Saxo APIはEU所在だが、トークン更新は5分に1回、注文送信は1日数回なので80msと250msの差は無意味。
コスト差: 東京は25-38%割高¶
| サービス | us-east-1 | ap-northeast-1 | 差 |
|---|---|---|---|
| Fargate vCPU/h | $0.04048 | $0.05056 | +25% |
| Fargate Memory/GB/h | $0.004445 | $0.005553 | +25% |
| NAT Gateway/h | $0.045 | $0.062 | +38% |
| EFS GB/月 | $0.30 | $0.36 | +20% |
Fargateだけで月$150 → \(188程度、総額で**月\)40-50の差**が出る。
開発母艦(Mac)からの通信¶
CI/CDはGitHub Actions経由なので、Macから直接AWSに通信する場面は通常運用ではない。 デバッグ時のECS Exec(SSHもどき)も数百msのレイテンシがあっても操作に支障はないレベル。
結論
通信先・コストの両面でus-east-1が合理的。東京リージョンを選ぶ積極的理由がない。
ECS on EC2 vs ECS on Fargate¶
前提: ECSはオーケストレーション層¶
ECS(Elastic Container Service)はコンテナの配置・管理を行うオーケストレーションであり、 その上で「EC2インスタンスを自前管理する」か「Fargateにインフラを委ねる」かを選択する。
比較マトリクス¶
| 観点 | ECS on EC2 | ECS on Fargate | AEGIS判定 |
|---|---|---|---|
| OS管理 | パッチ適用・Docker更新が必要 | 完全マネージド | Fargate優位 |
| 障害復旧 | 手動でインスタンス復旧 or ASG設定要 | 自動タスク再配置(AZ跨ぎ含む) | Fargate優位 |
| 共有ボリューム | ホストパスマウント(現行同様) | EFSのみ(実装変更要) | EC2が楽だがEFSで解決可能 |
| docker.sock | マウント可能(monitor用) | 不可 | EC2が楽だがECS API で解決可能 |
| SSHデバッグ | 直接SSH可 | ECS Exec経由 | EC2が便利だがECS Execで十分 |
| コスト(月額) | ~$89-134 | ~$200 | EC2が安い |
| セキュリティ | SSHポート管理・SG管理必要 | 攻撃面が極めて小さい | Fargate優位 |
| スケーリング | ASG設定+容量計画が必要 | タスク数変更のみ | Fargate優位 |
| 起動速度 | インスタンス常時起動 | タスク起動30-60秒 | 常時稼働なので差なし |
| 運用負荷(総合) | 中〜高 | 低 | Fargate優位 |
結論: Fargate を採用¶
判断理由
月$60-100のコスト増は、実資金を運用するシステムの安定性・BCP保険として十分に合理的。 Fargateの技術的障壁(共有ボリューム、docker.sock、supervisord)はすべて実装で解決可能であり、 解決後はEC2より運用負荷が大幅に低くなる。
技術的障壁と解決策¶
Fargateには3つの技術的障壁があるが、いずれも実装で解決可能。
1. 共有ボリューム — EFS(Elastic File System)で解決¶
現状の共有ボリューム分析¶
| ボリューム | サイズ | I/Oパターン | EFS適性 |
|---|---|---|---|
tokens/ |
<1MB | 5分に1回書込み、読取り数回/分 | 完全に問題なし |
wft_state/ |
<100MB | 数秒に1回JSON書込み | 問題なし |
pt_state/ |
<100MB | 同上 | 問題なし |
quote_samples/ |
<100MB | append-only JSONL | 問題なし |
live_data_archive/ |
~7GB | EOD時にparquet書込み、読取り頻繁 | 問題なし |
logs/ |
<1GB | append-only | 下記「ログ戦略」参照 |
polygon_v2/ |
~50GB+ | バッチ読み書き | S3 + DataSync |
EFSレイテンシは問題にならない
EFSのレイテンシは ~1-5ms。AEGISのボトルネックはSaxo API応答(数十ms)・Polygon API応答(数十ms)であり、
ファイルI/Oの数msは誤差。tokens/やstate/は特に小ファイル・低頻度なので全く問題なし。
EFS設計¶
graph TB
subgraph EFS["Amazon EFS (リージョナル)"]
AP1["Access Point<br/>/tokens<br/>UID:1000 GID:1000"]
AP2["Access Point<br/>/state<br/>UID:1000 GID:1000"]
AP3["Access Point<br/>/live_data_archive<br/>UID:1000 GID:1000"]
AP4["Access Point<br/>/quote_samples<br/>UID:1000 GID:1000"]
end
subgraph Tasks["ECS Fargate Tasks"]
TK["aegis-token-keeper<br/>RW: /tokens"]
WFT["aegis-wft<br/>RW: /tokens, /state<br/>RO: /live_data_archive"]
QC["aegis-quote-collector<br/>RO: /tokens<br/>RW: /quote_samples"]
LDAS["aegis-ldas-*<br/>RW: /live_data_archive"]
DASH["aegis-dashboard<br/>RO: /tokens, /state,<br/>/live_data_archive"]
end
TK --> AP1
WFT --> AP1 & AP2 & AP3
QC --> AP1 & AP4
LDAS --> AP3
DASH --> AP1 & AP2 & AP3
classDef efs fill:#f39c12,stroke:#e67e22,color:#fff
class AP1,AP2,AP3,AP4 efs
EFSコスト見積¶
| 項目 | 容量 | 単価 | 月額 |
|---|---|---|---|
| EFS Standard(頻繁アクセス) | ~8GB | $0.30/GB | $2.40 |
| EFS IA(低頻度アクセス) | — | $0.025/GB | — |
| EFS スループット(バースト) | 含む | — | $0 |
| 合計 | ~$3-5 |
polygon_v2/(~50GB)はEFSではなくS3に配置し、必要時にFargate タスクからS3 APIでアクセスする。
バックテストはMac上で実行するため、S3→Mac同期で対応。
ログ戦略¶
現行のAEGISコンテナはloguru等でファイルにログ出力している(/var/log/pt/, /var/log/ldas/ 等)。
Fargateではログの扱いに2つの選択肢がある。
| 方式 | 仕組み | メリット | デメリット |
|---|---|---|---|
| A: CloudWatch Logs | Fargateのawslogsドライバがstdout/stderrを自動収集 |
集約・検索・保持期間設定が容易、追加実装なし | アプリ側のログ出力先をファイル→stdout/stderrに変更する改修が必要 |
| B: EFS + ファイル | 現行同様にファイルに書込み | アプリ改修ゼロ | ログの検索・集約は自前、ローテーション管理も自前 |
| C: 併用 | stdout/stderrに出力しつつ、EFS上にもファイル出力 | CloudWatchで集約しつつ、ファイルでの調査も可能 | loguru設定の変更が必要(sinksの追加) |
推奨: 方式C(併用)
- loguruの
add()でsinkを2つ設定:sys.stderr(→ CloudWatch Logs自動収集)+ EFS上のファイル(現行互換) - CloudWatch Logsは保持期間を設定可能(例: 30日)で、古いログは自動削除
- EFS上のファイルログは即座にgrepできるため、ECS Execでの調査時に便利
- 改修量は各コンテナのloguru初期化部分にsink追加するだけ(数行)
# 改修例: loguru設定(各コンテナの起動スクリプト)
from loguru import logger
import sys
# CloudWatch Logs用(Fargateが自動収集)
logger.add(sys.stderr, level="INFO", format="{time} | {level} | {message}")
# EFS ファイル用(現行互換、ローテーション付き)
logger.add(
"/var/log/pt/pt_{time:YYYY-MM-DD}.log",
level="DEBUG",
rotation="1 day",
retention="14 days", # EFS上は14日保持
)
ログ出力先の変更はアプリ改修が必要
Fargateにすれば自動的にCloudWatch Logsに送られるわけではない。
Fargateのawslogsログドライバはコンテナのstdout/stderrを収集する仕組みであるため、
現行のようにファイルにのみ出力している場合はCloudWatch Logsには何も記録されない。
stdout/stderrへの出力を追加する改修が必要。
2. docker.sock依存 — ECS API + CloudWatch に置換¶
現行の監視方式(aegis-monitor)¶
# 現在: docker.sockをマウントしてコンテナ監視
import docker
client = docker.from_env()
for container in client.containers.list():
status = container.status # "running" / "exited"
stats = container.stats(stream=False) # CPU/メモリ
Fargate移行後の監視方式¶
# Fargate版: boto3 ECS API でタスク監視
import boto3
ecs = boto3.client('ecs')
cw = boto3.client('cloudwatch')
# タスク死活監視(docker.sock不要)
tasks = ecs.list_tasks(cluster='aegis', desiredStatus='RUNNING')
for task_arn in tasks['taskArns']:
details = ecs.describe_tasks(cluster='aegis', tasks=[task_arn])
for task in details['tasks']:
status = task['lastStatus'] # RUNNING / STOPPED
health = task['healthStatus'] # HEALTHY / UNHEALTHY
reason = task.get('stoppedReason') # 停止理由(自動記録)
started = task['startedAt'] # 起動時刻
# リソース監視(CloudWatch Container Insights 自動収集)
metrics = cw.get_metric_data(
MetricDataQueries=[{
'Id': 'cpu',
'MetricStat': {
'Metric': {
'Namespace': 'ECS/ContainerInsights',
'MetricName': 'CpuUtilized',
'Dimensions': [
{'Name': 'ClusterName', 'Value': 'aegis'},
{'Name': 'ServiceName', 'Value': 'aegis-wft'}
]
},
'Period': 60,
'Stat': 'Average'
}
}],
StartTime=datetime.utcnow() - timedelta(minutes=5),
EndTime=datetime.utcnow()
)
Fargate版で追加で得られるもの¶
| 機能 | docker.sock版(現行) | ECS API + CloudWatch版 |
|---|---|---|
| コンテナ死活 | container.status |
task.lastStatus + healthStatus |
| CPU/メモリ | container.stats() |
CloudWatch Container Insights(自動) |
| ログ | ファイルベース | CloudWatch Logs(集約・検索・保持) |
| 停止理由 | なし(手動調査) | stoppedReason 自動記録 |
| 再起動回数 | なし | ECS Service Events 自動記録 |
| アラーム | 自前(Slack/Twilio) | CloudWatch Alarms → SNS → Slack/SMS |
| ダッシュボード | aegis-dashboard 自前 | CloudWatch Dashboards(追加可) |
監視の質が向上する
docker.sock版は「コンテナが生きているか」しか見えないが、 CloudWatch統合によりCPU/メモリ推移・ログ集約・停止理由の自動記録・アラーム自動化が得られる。 aegis-monitorの改修は必要だが、結果としてより高品質な監視になる。
3. supervisord(LDAS) — Fargate タスク分割¶
現行のLDAS構成¶
graph TB
subgraph LDAS_Current["aegis-ldas (現行: supervisord管理)"]
SUP["supervisord"]
SUP --> CRON["cron<br/>EOD収集 17:15 ET"]
SUP --> INTRA["intraday<br/>15分間隔スナップショット"]
SUP --> UWF["uw_flow<br/>60秒ポーリング"]
end
style LDAS_Current fill:#3498db,stroke:#2980b9,color:#fff
問題点: 1コンテナに3プロセスを同居させているため、1プロセスの障害が他に波及するリスクがある。
Fargate移行後: 3タスクに分割¶
graph TB
subgraph LDAS_New["LDAS (Fargate: 独立タスク)"]
EOD["aegis-ldas-eod<br/>EventBridge Scheduled Task<br/>17:15 ET 平日のみ"]
INTRA["aegis-ldas-intraday<br/>ECS Service (常時稼働)<br/>15分間隔スナップショット"]
UWF["aegis-ldas-uwflow<br/>ECS Service (常時稼働)<br/>60秒ポーリング"]
end
EFS[("EFS<br/>/live_data_archive")]
EOD -->|RW| EFS
INTRA -->|RW| EFS
UWF -->|RW| EFS
style EOD fill:#27ae60,stroke:#1e8449,color:#fff
style INTRA fill:#2980b9,stroke:#2471a3,color:#fff
style UWF fill:#8e44ad,stroke:#7d3c98,color:#fff
| 現行(supervisord内) | Fargate移行後 | 種別 | スケジュール |
|---|---|---|---|
| cron (EOD collect) | aegis-ldas-eod | Scheduled Task | EventBridge: cron(15 17 ? * MON-FRI *) |
| intraday loop | aegis-ldas-intraday | ECS Service | 常時稼働(市場時間に自律的にアクティブ化) |
| uw_flow polling | aegis-ldas-uwflow | ECS Service | 常時稼働(60秒ポーリング) |
メリット:
- EOD収集が落ちてもintraday収集に影響しない(障害分離)
- 個別にリソース割当・ログ分離・ヘルスチェック可能
- EODはScheduled Task(実行時のみ課金 → 月$0.30程度)
4. Cloudflare Tunnel — サイドカーで維持¶
aegis.llmtradelab.com は Cloudflare で管理されているため、 cloudflared を Fargate サイドカーコンテナとしてそのまま維持する。
graph LR
USER["ユーザー"] -->|HTTPS| CF["Cloudflare Edge"]
CF -->|Tunnel| CFD["cloudflared<br/>(サイドカー)"]
CFD -->|localhost:8080| DASH["aegis-dashboard"]
subgraph FargateTask["ECS Fargate Task"]
CFD
DASH
end
将来的にALB + ACMに置き換える選択肢もあるが、 既存のCloudflare構成をそのまま使うのが移行コスト最小。
AWS アーキテクチャ設計¶
全体構成図¶
graph TB
subgraph VPC["VPC (10.0.0.0/16) — us-east-1"]
subgraph PubSub["Public Subnets"]
NAT1["NAT Gateway<br/>AZ-a"]
NAT2["NAT Gateway<br/>AZ-b (DR)"]
end
subgraph PrivSub["Private Subnets (Fargate タスク配置)"]
subgraph AZa["AZ-a"]
WFT_A["aegis-wft"]
TK_A["aegis-token-keeper"]
QC_A["aegis-quote-collector"]
LDAS_I_A["aegis-ldas-intraday"]
LDAS_U_A["aegis-ldas-uwflow"]
end
subgraph AZb["AZ-b (フェイルオーバー先)"]
DASH_B["aegis-dashboard<br/>+ cloudflared"]
MON_B["aegis-monitor"]
end
end
EFS[("Amazon EFS<br/>(Multi-AZ)")]
end
subgraph External["外部サービス"]
SAXO["Saxo Bank API"]
POLY["Polygon.io"]
UW["Unusual Whales"]
FRED["FRED"]
end
subgraph AWS_Services["AWSマネージドサービス"]
ECR["ECR<br/>コンテナレジストリ"]
SM["Secrets Manager<br/>API Keys / OAuth2"]
CW["CloudWatch<br/>Logs + Metrics + Alarms"]
EB["EventBridge<br/>EODスケジュール"]
SNS["SNS<br/>→ Slack / SMS"]
S3["S3<br/>polygon_v2 / バックアップ"]
end
WFT_A & TK_A & QC_A --> SAXO
LDAS_I_A & LDAS_U_A --> POLY & UW & FRED
WFT_A & TK_A & QC_A & LDAS_I_A & LDAS_U_A & DASH_B --> EFS
EB -->|"17:15 ET"| LDAS_EOD["aegis-ldas-eod<br/>(Scheduled Task)"]
LDAS_EOD --> EFS
MON_B --> CW
CW --> SNS
classDef efs fill:#f39c12,stroke:#e67e22,color:#fff
classDef ext fill:#95a5a6,stroke:#7f8c8d,color:#fff
class EFS efs
class SAXO,POLY,UW,FRED ext
ネットワーク設計¶
| コンポーネント | CIDR / 設定 | 備考 |
|---|---|---|
| VPC | 10.0.0.0/16 |
us-east-1 |
| Public Subnet AZ-a | 10.0.1.0/24 |
NAT Gateway配置 |
| Public Subnet AZ-b | 10.0.2.0/24 |
NAT Gateway配置(冗長) |
| Private Subnet AZ-a | 10.0.10.0/24 |
Fargateタスク配置(主) |
| Private Subnet AZ-b | 10.0.20.0/24 |
Fargateタスク配置(副) |
| Security Group (egress) | All outbound allowed | Saxo/Polygon等へのAPI通信 |
| Security Group (intra-task) | SG self-reference | タスク間通信(EFS経由が主) |
NAT Gateway コスト
NAT Gatewayは $32/月/個 + データ転送 \(0.045/GB。 AEGISの外部API通信量は月数GB程度なので、**1 NAT Gatewayで十分**(冗長は将来的に追加)。 月額: ~\)35
ECS クラスタ・サービス設計¶
タスク定義一覧¶
| タスク名 | vCPU | メモリ | 種別 | 稼働パターン |
|---|---|---|---|---|
| aegis-wft | 1.0 | 2GB | ECS Service | 常時稼働 |
| aegis-token-keeper | 0.25 | 0.5GB | ECS Service | 常時稼働 |
| aegis-quote-collector | 0.25 | 0.5GB | ECS Service | 常時稼働 |
| aegis-ldas-intraday | 0.5 | 1GB | ECS Service | 常時稼働 |
| aegis-ldas-uwflow | 0.25 | 0.5GB | ECS Service | 常時稼働 |
| aegis-ldas-eod | 0.5 | 1GB | Scheduled Task | 平日17:15 ET(~15分/回) |
| aegis-polygon-quotes | 1.0 | 1GB | ECS Service | 常時稼働 |
| aegis-dashboard + cloudflared | 0.5 + 0.25 | 1GB + 0.5GB | ECS Service | 常時稼働 |
| aegis-monitor | 0.25 | 0.5GB | ECS Service | 常時稼働 |
サービス設定¶
{
"serviceName": "aegis-wft",
"launchType": "FARGATE",
"desiredCount": 1,
"deploymentConfiguration": {
"maximumPercent": 200,
"minimumHealthyPercent": 100
},
"networkConfiguration": {
"awsvpcConfiguration": {
"subnets": ["subnet-private-a", "subnet-private-b"],
"securityGroups": ["sg-aegis-tasks"],
"assignPublicIp": "DISABLED"
}
},
"enableExecuteCommand": true
}
enableExecuteCommand
ECS Execを有効にすることで、SSHなしでFargateタスク内にシェルセッションを開ける。
デバッグ時: aws ecs execute-command --cluster aegis --task <task-id> --container aegis-wft --interactive --command "/bin/sh"
シークレット管理¶
現行(Synology)¶
/volume1/aegis/.env — POLYGON_API_KEY, UW_TOKEN, etc.
/volume1/aegis/tokens/ — saxobank_tokens_live.json (OAuth2)
AWS移行後¶
| シークレット | 保管先 | アクセス方法 |
|---|---|---|
| POLYGON_API_KEY | Secrets Manager | タスク定義の secrets で注入 |
| UNUSUAL_WHALES_API_TOKEN | Secrets Manager | 同上 |
| FRED_API_KEY | Secrets Manager | 同上 |
| TWILIO_ACCOUNT_SID / AUTH_TOKEN | Secrets Manager | 同上 |
| Saxo OAuth2 tokens | EFS /tokens/ |
token-keeperがファイル書込み(現行同様) |
| Cloudflare Tunnel Token | Secrets Manager | cloudflared タスク定義で注入 |
# ECS Task Definition (抜粋)
containerDefinitions:
- name: aegis-wft
secrets:
- name: POLYGON_API_KEY
valueFrom: "arn:aws:secretsmanager:us-east-1:ACCOUNT:secret:aegis/polygon-key"
- name: UNUSUAL_WHALES_API_TOKEN
valueFrom: "arn:aws:secretsmanager:us-east-1:ACCOUNT:secret:aegis/uw-token"
mountPoints:
- sourceVolume: efs-tokens
containerPath: /data/tokens
readOnly: false
Saxo OAuth2 トークンはファイルベース維持
Saxo APIのOAuth2トークンはtoken-keeperが5分ごとにファイルに書き込み、他のタスクが読む という現行の方式をEFS上で維持する。Secrets Managerでは更新頻度(5分毎)に適さない。
CI/CD パイプライン変更¶
現行(SSH → Synology)¶
sequenceDiagram
participant Dev as Mac mini
participant GH as GitHub
participant GA as GitHub Actions
participant SYN as Synology
Dev->>GH: git push
GH->>GA: Trigger workflow
GA->>SYN: SSH via Tailscale
SYN->>SYN: git pull + docker compose rebuild
GA-->>GH: Deploy status
AWS移行後(ECR + ECS)¶
sequenceDiagram
participant Dev as Mac mini
participant GH as GitHub
participant GA as GitHub Actions
participant ECR as Amazon ECR
participant ECS as Amazon ECS
Dev->>GH: git push
GH->>GA: Trigger workflow
GA->>GA: docker build
GA->>ECR: docker push (tagged image)
GA->>ECS: aws ecs update-service --force-new-deployment
ECS->>ECS: Rolling update (new task → health check → old task drain)
GA->>ECS: aws ecs wait services-stable
GA-->>GH: Deploy status ✅/❌
変更点:
| 項目 | 現行(Synology) | AWS移行後 |
|---|---|---|
| イメージビルド | Synology上でdocker compose build | GitHub Actions上でbuild → ECR push |
| デプロイ | SSH → git pull → compose up | ECS update-service(ローリングアップデート) |
| ロールバック | 手動 git revert + compose up | aws ecs update-service --task-definition <前のリビジョン> |
| VPN | Tailscale必須 | 不要(AWS API経由) |
| ヘルスチェック | deploy.sh内のスクリプト | ECS ヘルスチェック(自動) |
GitHub Actions ワークフロー(AWS版)¶
# .github/workflows/deploy-aws.yml
name: Deploy to AWS ECS
on:
push:
branches: [main, 'feat/pt-*']
paths:
- 'aegis_v3/**'
- 'AEGIS/**'
env:
AWS_REGION: us-east-1
ECR_REPOSITORY: aegis
ECS_CLUSTER: aegis
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write # OIDC
contents: read
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials (OIDC)
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::role/github-actions-aegis
aws-region: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
id: ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build & push images
run: |
COMMIT_SHA=${{ github.sha }}
# 変更があったサービスのみビルド・プッシュ
for service in wft token-keeper quote-collector ldas dashboard monitor; do
docker build -t $ECR_REPO/aegis-${service}:${COMMIT_SHA} \
-f aegis_v3/${service}-docker/Dockerfile .
docker push $ECR_REPO/aegis-${service}:${COMMIT_SHA}
done
- name: Update ECS services
run: |
for service in aegis-wft aegis-token-keeper aegis-quote-collector \
aegis-ldas-intraday aegis-ldas-uwflow \
aegis-polygon-quotes aegis-dashboard aegis-monitor; do
aws ecs update-service \
--cluster $ECS_CLUSTER \
--service $service \
--force-new-deployment
done
- name: Wait for stable
run: |
aws ecs wait services-stable \
--cluster $ECS_CLUSTER \
--services aegis-wft aegis-token-keeper aegis-dashboard
OIDC認証
AWS認証にはGitHub Actions OIDC(OpenID Connect)を使用し、 長期のアクセスキーをGitHub Secretsに保存しない。セキュリティのベストプラクティス。
監視・アラート設計¶
CloudWatch統合¶
flowchart TB
subgraph Sources["メトリクスソース"]
CI["Container Insights<br/>CPU / Memory / Network"]
CL["CloudWatch Logs<br/>全タスクのログ集約"]
HC["ECS Health Checks<br/>タスク死活"]
MON["aegis-monitor<br/>カスタムメトリクス"]
end
subgraph Alarms["CloudWatch Alarms"]
A1["CPU > 80% (5分持続)"]
A2["Memory > 80% (5分持続)"]
A3["Task count < desired (1分)"]
A4["Token age > 1800秒"]
A5["LDAS data stale > 2時間"]
A6["WFT heartbeat stale > 10分<br/>(市場時間のみ)"]
end
subgraph Actions["アクション"]
SNS["SNS Topic"]
SLACK["Slack #aegis_管理"]
SMS["Twilio SMS<br/>(Critical のみ)"]
end
CI --> A1 & A2
HC --> A3
MON --> A4 & A5 & A6
A1 & A2 -->|Warning| SNS --> SLACK
A3 & A4 -->|Critical| SNS --> SLACK & SMS
A5 & A6 -->|Critical<br/>市場時間のみ| SNS --> SLACK & SMS
aegis-monitor の改修内容¶
| チェック項目 | 現行方式 | AWS移行後 |
|---|---|---|
| コンテナ死活 | docker.sock → client.containers.list() |
boto3 ecs.describe_tasks() |
| CPU/Memory | docker.sock → container.stats() |
CloudWatch Container Insights(自動) |
| Saxoトークン有効期限 | ファイルmtime確認 | EFS上のファイルmtime確認(同じ) |
| LDASデータ鮮度 | parquetファイルmtime | EFS上のparquetファイルmtime(同じ) |
| ホストリソース | /proc マウント |
不要(CloudWatch Insights が代替) |
| ログ | ファイル読取り | CloudWatch Logs Insights クエリ |
| アラート送信 | 自前Slack/Twilio | CloudWatch Alarms → SNS → Lambda → Slack/Twilio |
コスト詳細分析¶
月額コスト内訳¶
| 項目 | 月額 (USD) | 備考 |
|---|---|---|
| Fargate (常時稼働 8サービス) | $170 | 下記タスク別内訳参照 |
| Fargate (Scheduled: EOD) | $0.30 | 平日22回 × 15分 × 0.5vCPU |
| EFS | $3-5 | ~8GB Standard ストレージ |
| NAT Gateway | $35 | \(32固定 + データ転送 ~\)3 |
| CloudWatch Logs | $5-10 | ~10GB/月の取込み・保存 |
| CloudWatch Container Insights | $0 | ECS基本メトリクスは無料 |
| ECR | $1-2 | ~5GBのイメージストレージ |
| Secrets Manager | $3 | 6-8シークレット × $0.40 |
| S3 (polygon_v2 + バックアップ) | $2-5 | ~60GB S3 Standard |
| データ転送 | $3-5 | API通信(月数GB) |
| 合計 | ~$225-235 |
Fargate タスク別コスト内訳¶
Fargate料金: vCPU = $0.04048/h、メモリ = $0.004445/GB/h(us-east-1)
| タスク | vCPU | メモリ | 月稼働 | vCPU費 | メモリ費 | 小計 |
|---|---|---|---|---|---|---|
| aegis-wft | 1.0 | 2GB | 730h | $29.55 | $6.49 | $36.04 |
| aegis-token-keeper | 0.25 | 0.5GB | 730h | $7.39 | $1.62 | $9.01 |
| aegis-quote-collector | 0.25 | 0.5GB | 730h | $7.39 | $1.62 | $9.01 |
| aegis-ldas-intraday | 0.5 | 1GB | 730h | $14.78 | $3.24 | $18.02 |
| aegis-ldas-uwflow | 0.25 | 0.5GB | 730h | $7.39 | $1.62 | $9.01 |
| aegis-polygon-quotes | 1.0 | 1GB | 730h | $29.55 | $3.24 | $32.79 |
| aegis-dashboard | 0.5 | 1GB | 730h | $14.78 | $3.24 | $18.02 |
| cloudflared (サイドカー) | 0.25 | 0.5GB | 730h | $7.39 | $1.62 | $9.01 |
| aegis-monitor | 0.25 | 0.5GB | 730h | $7.39 | $1.62 | $9.01 |
| aegis-ldas-eod | 0.5 | 1GB | ~5.5h | $0.22 | $0.02 | $0.24 |
| Fargate合計 | $150.16 |
比較: Synology vs AWS¶
| 項目 | Synology (現行) | AWS Fargate |
|---|---|---|
| ハードウェア | DS1823+ ¥180,000(償却中) | — |
| 電気代 | ~¥3,000/月 (~$20) | — |
| ISP | ~¥5,000/月 (~$33) の一部 | — |
| AWS費用 | — | ~$230/月 |
| 実質月額 | ~$30-50 + 故障リスク | ~$230 |
| 年額 | ~$360-600 + 故障リスク | ~$2,760 |
| OS管理 | 手動 | 不要 |
| 障害復旧 | 手動(数時間〜) | 自動(数分) |
| BCP | なし(単一障害点) | AZ冗長 |
コスト差の解釈
年間約$2,000の差額(~30万円/年)は、月に数十万〜数百万円の収益を生むシステムのBCP保険として合理的。 Synologyの物理故障(RAID劣化、PSU障害、NICチップ不良)1回の損失で十分回収できる。
Fargate Savings Plans¶
1年 or 3年のCompute Savings Plansを適用すると:
| プラン | 割引率 | Fargate月額 | 総月額 |
|---|---|---|---|
| On-Demand | — | $150 | ~$230 |
| 1yr Savings Plan | ~20% | ~$120 | ~$200 |
| 3yr Savings Plan | ~35% | ~$98 | ~$178 |
段階的移行計画¶
Phase 0: 準備(AWS基盤構築)¶
所要期間: 1-2日
作業内容:
-
AWS基盤をIaC(Terraform or CDK)で構築
- VPC + Subnets + NAT Gateway
- ECS Cluster (Fargate)
- EFS + Access Points
- ECR リポジトリ
- Secrets Manager
- CloudWatch Log Groups
- IAM Roles (タスク実行ロール、タスクロール)
- EventBridge Rules (EODスケジュール)
- SNS Topics + Slack/SMS連携
-
GitHub Actions OIDCプロバイダ設定
-
ECRにイメージをpush(全コンテナ)
gantt
title AWS移行タイムライン
dateFormat YYYY-MM-DD
axisFormat %m/%d
section Phase 0 準備
AWS基盤構築 (IaC) :p0a, 2026-06-01, 2d
ECRイメージpush :p0b, after p0a, 1d
section Phase 1 非クリティカル
aegis-monitor移行 :p1a, after p0b, 2d
aegis-dashboard移行 :p1b, after p1a, 1d
aegis-polygon-quotes移行 :p1c, after p1b, 1d
並行稼働検証 (1週間) :p1d, after p1c, 7d
section Phase 2 データ収集
aegis-ldas分割+移行 :p2a, after p1d, 3d
EFSデータ同期確認 :p2b, after p2a, 2d
並行稼働検証 (1週間) :p2c, after p2b, 7d
section Phase 3 トレーディング
aegis-token-keeper移行 :p3a, after p2c, 1d
aegis-wft移行 :p3b, after p3a, 1d
aegis-quote-collector移行 :p3c, after p3b, 1d
並行稼働検証 (2週間) :p3d, after p3c, 14d
Synology停止 :p3e, after p3d, 1d
Phase 1: 非クリティカルサービス移行¶
対象: monitor, dashboard, polygon-quotes
移行順序と理由:
- aegis-monitor — docker.sock → ECS API 改修が必要。最も改修量が多いため最初に着手
- aegis-dashboard + cloudflared — Cloudflare Tunnel設定の動作確認
- aegis-polygon-quotes — データバックフィル。失敗しても実運用に影響なし
検証項目:
- EFS マウント正常動作
- CloudWatch Logs にログ出力
- Cloudflare Tunnel 経由でダッシュボードアクセス可能
- aegis-monitor が ECS API でタスク状態を取得可能
- polygon-quotes が EFS 上の parquet を読み書き可能
Phase 2: データ収集系移行¶
対象: LDAS(3タスクに分割)
重要: データ収集はPTの前提条件。ここでの障害はトレーディングに直結する。
- LDAS supervisord → 3 Fargate タスクに分割
- Synology LDAS と AWS LDAS を並行稼働(1週間)
- EFS上のデータをMac BTで読み取り可能か検証(S3経由の同期パス確認)
- 並行稼働で問題なしを確認後、Synology LDAS停止
検証項目:
- EOD Scheduled Task が 17:15 ET に正常起動・完了
- Intraday が 15分間隔でスナップショット取得
- UW Flow が 60秒ポーリングで正常取得
- 全parquetファイルが EFS 上に正しく書込まれている
- SynologyとAWSのデータが一致(diff検証)
Phase 3: トレーディング系移行(最重要)¶
CRITICAL: 実資金に直結するため最も慎重に
移行順序:
- aegis-token-keeper — Saxo OAuth2トークン更新がEFS上で正常動作するか確認
- aegis-wft — WFT/PTの全9シナリオが正常動作するか確認
- aegis-quote-collector — LQSサンプリングが正常動作するか確認
並行稼働(2週間):
- SynologyとAWSの両方で同時にPTを実行(同じシナリオ)
- 注文はAWS側のみ有効(Synology側はdry-run or WFTモード)
- 2週間でトレード判定が一致することを確認
検証項目:
- token-keeperがEFS上にトークンを正常書込み(5分間隔)
- 全タスクがEFS上のトークンを正常読取り
- WFTシナリオが全て正常にスキャン・判定を実行
- LQSが30 req/min でSaxo APIを正常サンプリング
- 市場時間外にヘルスチェックがhealthyを返す
- Saxo API注文が正常に送信・約定される
- CloudWatch Alarmsが正常に発火・通知される
- タスク異常停止時に自動再起動されることを確認
- ECS Execでタスク内にシェル接続可能
Phase 4: Synology停止・DR構築¶
Synology停止後:
- Synologyはバックアップ・開発用途のみに転用
- EFS 自動バックアップ有効化(日次 → 35日保持)
- (将来的に)Cross-Region レプリケーション(us-west-2)
ロールバック計画¶
各Phaseでのロールバック手順:
| Phase | ロールバック方法 | 所要時間 |
|---|---|---|
| Phase 1 | Synology側のmonitor/dashboard/quotesを再起動 | 数分 |
| Phase 2 | Synology LDASを再起動、AWS LDASを停止 | 数分 |
| Phase 3 | Synology PT/token-keeperを再起動、AWS側を停止 | 数分 |
| 全体 | 全AWSサービスを停止、Synology全コンテナを再起動 | 10分以内 |
Synology は移行完了後も一定期間維持
Phase 3完了後も1ヶ月程度はSynologyを「コールドスタンバイ」として維持する。 AWS側で想定外の問題が発生した場合に即座にロールバック可能。
将来的な拡張¶
Fargate Spot(コスト最適化)¶
polygon-quotes や monitor など、中断耐性のあるタスクにFargate Spotを適用可能:
| タスク | Spot適用 | 理由 |
|---|---|---|
| aegis-wft | 不可 | PT中断は損失リスク |
| aegis-token-keeper | 不可 | トークン切れはPT停止 |
| aegis-quote-collector | 不可 | 市場時間中のサンプリング欠損 |
| aegis-ldas-intraday | 不可 | スナップショット欠損 |
| aegis-ldas-uwflow | 可 | 中断しても次の60秒で復帰 |
| aegis-ldas-eod | 可 | 失敗してもリトライ可能 |
| aegis-polygon-quotes | 可 | バックフィルなので中断耐性あり |
| aegis-dashboard | 可 | 一時的なダウンは許容 |
| aegis-monitor | 可 | 60秒間隔なので中断影響小 |
Spot適用で月$20-30の削減が見込める。
BT on Fargate(オンデマンド計算)¶
バックテストをFargateで実行する将来構想。sweepで数十〜数百パターンを同時実行できるのが最大の価値。
単発BT実行¶
# Mac からBTをAWS上で実行
aws ecs run-task \
--cluster aegis \
--task-definition aegis-bt \
--launch-type FARGATE \
--overrides '{
"containerOverrides": [{
"name": "aegis-bt",
"command": ["python", "scripts/run_backtest_multiple_scenarios.py",
"--scenario", "XW_BEST_20260310",
"--start", "2019-01-02", "--end", "2026-01-30",
"--deterministic", "--seed", "0"]
}]
}'
Sweep並列実行(Fargateの真価)¶
MBP 1台ではCPUコア数・メモリの物理制約で同時実行数が限られる(2並列が上限ルール)。
Fargateならタスク数に物理的な上限がないため、run-taskをN回叩けばN並列で走る。
# 例: TP × CR × DTE の組み合わせ100パターンを一括実行
for config in configs/sweep/*.yaml; do
aws ecs run-task \
--cluster aegis \
--task-definition aegis-bt \
--launch-type FARGATE \
--overrides "{
\"containerOverrides\": [{
\"name\": \"aegis-bt\",
\"command\": [\"python\", \"scripts/run_backtest_multiple_scenarios.py\",
\"--config\", \"$config\",
\"--start\", \"2024-01-02\", \"--end\", \"2026-01-30\",
\"--deterministic\", \"--seed\", \"0\",
\"--output-s3\", \"s3://aegis-bt-results/\"]
}]
}" &
done
wait
echo "全タスク投入完了。結果は S3 に出力される。"
Sweep コスト試算¶
Fargateは使った分だけ課金。タスクが完了すれば即停止・課金停止。
| シナリオ | タスク数 | vCPU | メモリ | 実行時間 | コスト |
|---|---|---|---|---|---|
| 単発BT(25ヶ月) | 1 | 2 | 4GB | ~1h | $0.10 |
| Sweep 10パターン | 10 | 2 | 4GB | ~1h | $1.00 |
| Sweep 50パターン | 50 | 2 | 4GB | ~1h | $5.00 |
| Sweep 100パターン | 100 | 2 | 4GB | ~1h | $10.00 |
| 大規模Sweep 100パターン (7年BT) | 100 | 4 | 8GB | ~3h | $50.00 |
MBPでの待ち時間 vs Fargateコスト
100パターンのsweepをMBP(2並列制限)で実行すると、50ラウンド × 1h = 約50時間(2日以上)。 Fargateなら100並列で約1時間、コストは**\(10**。 月に数回のsweepなら月\)20-50程度の追加コストで、開発速度が劇的に向上する。
BT on Fargateの前提条件¶
- BTデータをS3に配置: QuantData CSVs + polygon_v2 parquets を S3バケットにアップロード
- 結果出力もS3: BTの出力(trades CSV, monthly CSV等)をS3に書き出す改修
- aegis-bt タスク定義: 2-4 vCPU、4-8GB メモリ(BTの複雑さに応じて)
- S3 → Mac同期: 結果をMacにダウンロードして分析(
aws s3 sync)
sequenceDiagram
participant Mac as MBP
participant S3 as S3 (BT Data)
participant ECS as ECS Fargate
participant S3R as S3 (Results)
Mac->>ECS: run-task × N (sweep)
ECS->>S3: Read BT data (parquets)
ECS->>ECS: Execute backtest
ECS->>S3R: Write results (CSV)
ECS->>ECS: Task exits (課金停止)
Mac->>S3R: aws s3 sync (結果取得)
Mac->>Mac: 分析・比較
開発母艦の方針: MBP 1台体制¶
AWS移行後のMacの役割を整理すると、常時起動の必要がなくなる:
| 用途 | 現在の担当 | AWS移行後 | 常時起動必要? |
|---|---|---|---|
| PT/WFT実行 | Synology | AWS Fargate | — |
| LDAS収集 | Synology | AWS Fargate | — |
| Dashboard | Synology | AWS Fargate | — |
| 監視・通知 | Synology | AWS Fargate | — |
| 開発(コード編集) | Mac | Mac | 作業時のみ |
| バックテスト | Mac | Mac → Fargate | 実行時のみ → 不要 |
| git push(デプロイ起点) | Mac | Mac | 作業時のみ |
据え置き Mac Mini/Studio vs MBP 持ち歩き¶
| 観点 | Mac Mini/Studio 据え置き(東京) | MBP 持ち歩き |
|---|---|---|
| BT実行 | 高性能(M4 Pro/Max据え置き可) | M4 Proなら十分、電源・発熱の制約あり |
| 開発 | リモート接続が必要(SSH/VNC) | ローカルで直接作業 |
| 可用性 | 東京拠点の電源・ネットワーク障害で接続不能 | 手元にあるので確実 |
| 旅行時 | 別途MBPが必要(結局2台持ち) | 1台で完結 |
| BT on Fargate実装後 | Macでの重い計算が不要に | 同左 |
結論: MBP 1台で完結させる
- AWS移行後、Macに常時起動の役割はない
- BT on Fargateを実装すれば、ローカルで重い計算を走らせる必要もなくなる
- パーマネントトラベラー生活で東京拠点のMac Miniへのリモート接続に依存するのは単一障害点を増やすだけ
- 据え置きMacが必要なのは「重いBTをMacで回し続ける必要がある間」だけ
graph LR
subgraph Current["現在の構成"]
MM["Mac Mini (東京)<br/>開発 + BT"]
SYN["Synology (東京)<br/>PT + LDAS + Dashboard"]
end
subgraph Future["AWS移行後の構成"]
MBP["MBP (持ち歩き)<br/>開発 + git push のみ"]
AWS["AWS us-east-1<br/>全サービス + BT"]
end
Current -->|移行| Future
style SYN fill:#e74c3c,stroke:#c0392b,color:#fff
style MM fill:#f39c12,stroke:#e67e22,color:#fff
style MBP fill:#27ae60,stroke:#1e8449,color:#fff
style AWS fill:#3498db,stroke:#2980b9,color:#fff
段階的な移行
- AWS移行完了 → Synology停止、Mac Miniは開発+BT用に残す
- BT on Fargate実装 → Mac Miniの役割がなくなる
- MBP 1台体制に移行、Mac Miniは売却 or 予備機として保管
AWSアカウント・認証構成(2026-03-25 構築済み)¶
アカウント情報¶
| 項目 | 値 |
|---|---|
| アカウントID | 677414637283 |
| ルートメール | fukutani.ryo@denovo-inc.jp |
| リージョン | us-east-1 (バージニア北部) |
| 組織ID | o-ersk9r7lzm |
| SSO Start URL | https://d-9066077395.awsapps.com/start |
| 無料クレジット | $100 USD(2026-09-25まで) |
IAM Identity Center(SSO)¶
長期アクセスキーを使わないモダンな認証構成:
| コンポーネント | 認証方式 | 備考 |
|---|---|---|
| 人間(Console + CLI) | IAM Identity Center SSO | aws sso login --profile aegis |
| GitHub Actions CI/CD | OIDC(OpenID Connect) | アクセスキー不要 |
| Fargateタスク | IAM Task Role | タスクに紐づくRoleで自動認証 |
| Dashboard (Synology) | IAM User(最小権限) | CE読み取り専用 aegis-dashboard-cost-reader |
SSO設定ファイル (~/.aws/config):
[default]
sso_session = aegis-sso
sso_account_id = 677414637283
sso_role_name = AdministratorAccess
region = us-east-1
output = json
[sso-session aegis-sso]
sso_start_url = https://d-9066077395.awsapps.com/start
sso_region = us-east-1
sso_registration_scopes = sso:account:access
コスト監視体制(構築済み)¶
AWS Budgets アラート¶
月間予算 $500 に対して、以下のしきい値でアラート通知:
| 金額 | 予算比 | メール通知 | SMS通知 |
|---|---|---|---|
| $30 | 6% | o | |
| $50 | 10% | o | |
| $100 | 20% | o | |
| $150 | 30% | o | |
| $200 | 40% | o | o |
| $250 | 50% | o | |
| $300 | 60% | o | o |
| $350 | 70% | o | |
| $400 | 80% | o | o |
| $500 | 100% | o | o |
- メール送信先:
fukutani.ryo@a-t.link - SMS送信先: SNS Topic
aegis-budget-sms→+818017435786 - Budget名:
AEGIS-Monthly-Cost
ダッシュボード Cost パネル(実装済み)¶
Block Bダッシュボードに AWS Cost Explorer 連携パネルを実装済み:
- Flask API:
/api/block-b/aws-cost— 当月コスト・月末予測・Budget消化率・サービス別内訳・過去6ヶ月推移 - React:
AWSCostPanelコンポーネント — 1時間キャッシュ、サービス名自動簡略化 - 認証: IAM User
aegis-dashboard-cost-reader(CE + Budgets 読み取り専用) - 環境変数:
AWS_COST_ACCESS_KEY_ID,AWS_COST_SECRET_ACCESS_KEY,AWS_ACCOUNT_ID
Cost Explorerの制約
新規AWSアカウントではCost Explorerのデータが利用可能になるまで24-48時間かかる。 データがない期間はパネルにエラーメッセージが表示される。
実装チェックリスト¶
移行実施時の作業一覧:
事前準備(構築済み)¶
- AWSアカウント作成 (677414637283, us-east-1)
- IAM Identity Center 有効化 + 管理者ユーザー
ryo作成 - AWS CLI SSO設定 (
~/.aws/config) - AWS Budgets アラート設定 (\(30〜\)500、メール + SMS)
- SNS Topic
aegis-budget-sms+ SMS サブスクリプション - IAM User
aegis-dashboard-cost-reader(CE読み取り専用) - ダッシュボード Cost パネル実装 (Flask API + React)
インフラ(IaC)¶
- Terraform/CDK プロジェクト作成
- VPC + Subnets + NAT Gateway
- ECS Cluster
- EFS + Access Points (tokens, state, live_data_archive, quote_samples)
- ECR リポジトリ (aegis-wft, aegis-token-keeper, 等)
- IAM Roles (ecsTaskExecutionRole, ecsTaskRole)
- Secrets Manager (API keys)
- CloudWatch Log Groups
- EventBridge Rule (EOD schedule)
- SNS Topics + Subscriptions (監視用)
- Security Groups
- GitHub Actions OIDC プロバイダ設定
アプリケーション改修¶
- aegis-monitor: docker.sock → boto3 ECS API
- aegis-monitor:
/proc→ CloudWatch Metrics API - aegis-monitor: ログ読取り → CloudWatch Logs Insights
- aegis-ldas: supervisord → 3独立エントリーポイント分割
- 全コンテナ: loguru sinkにstderr出力を追加(CloudWatch Logs収集用、ファイル出力も併用維持)
- 全コンテナ: 環境変数からSecrets Manager値を読取り
BT on Fargate¶
- S3バケット作成 (aegis-bt-data, aegis-bt-results)
- BTデータ(QuantData CSVs + polygon_v2)をS3にアップロード
- aegis-bt タスク定義作成 (2-4 vCPU, 4-8GB)
- BT出力のS3書出し改修
- sweep並列投入スクリプト作成
- 結果集約・比較ツール作成
CI/CD¶
- deploy-aws.yml ワークフロー作成
- ECR push ステップ
- ECS update-service ステップ
- Synology用ワークフローは残す(ロールバック用)
検証¶
- 全タスクの EFS マウント動作確認
- CloudWatch Logs 出力確認
- CloudWatch Alarms 発火テスト
- ECS Exec 接続テスト
- タスク異常停止 → 自動再起動テスト
- ローリングデプロイテスト
- ロールバック手順テスト
作成日: 2026-03-25 | 最終更新: 2026-03-25 | 担当: Claude Code