メタディスクリプション: GitHub ActionsとAWS EC2 Spot Instanceを活用した自動制御開発環境の構築方法。stop/start/status機能の実装詳細と実用的な運用手順を解説。
はじめに
GitHub ActionsとAWS EC2 Spot Instanceを組み合わせた自動制御開発環境を構築し、月額3-4ドルでClaude Code実行環境を運用する方法を解説します。
- 読書時間:約6分
- 技術スタック:GitHub Actions、AWS EC2、Spot Instance
- コスト削減効果:従来の80%減(月額$15-20 → $3-4)
対象読者
- AWS EC2とGitHub Actionsの基本知識がある方
- クラウド開発環境のコスト最適化に取り組みたい方
技術背景と解決アプローチ
従来の開発環境では24時間EC2を稼働させるため、実使用時間に対して過剰なコストが発生します。AWS EC2 Spot Instanceは最大90%のコスト削減が可能ですが、予告なく終了される可能性があります。この特性を逆手に取り、GitHub Actionsによる完全自動化で一時的な開発環境として活用します。
運用課題
- 固定費問題: t3.microでも月額15-20ドル
- 手動運用: AWSコンソールでの煩雑な操作
- 環境復旧: Spot Instance中断後の再構築
システム構成と主要機能
.github/workflows/ec2-control.yml # メインワークフロー
user-data.sh # EC2初期化スクリプト
AWS Infrastructure
├── EC2 Spot Instance (t3.micro)
├── EBS Volume (暗号化済み)
└── Security Group
主要機能
- ワンクリック操作: GitHub Actions UIからEC2制御
- データ永続化: EBSボリュームでデータ保持
- 完全自動化: 環境構築からVPN設定まで自動
AWS EC2 Spot Instance自動制御の実装手順
実際のGitHub Actions ワークフローファイルと必要な設定について、順を追って説明します。
事前準備:AWSリソースとGitHub Actions設定
1. VPCとネットワークの準備
ワークフローではVPCとサブネットを自動検出するため、適切なタグを設定したリソースが必要です:
# VPCの作成(既存VPCがない場合)
VPC_ID=$(aws ec2 create-vpc \
--cidr-block 10.0.0.0/16 \
--query 'Vpc.VpcId' \
--output text)
# VPCに「main」タグを追加(重要!ワークフローがこのタグで検索)
aws ec2 create-tags \
--resources $VPC_ID \
--tags Key=Name,Value=main
# インターネットゲートウェイの作成
IGW_ID=$(aws ec2 create-internet-gateway \
--query 'InternetGateway.InternetGatewayId' \
--output text)
# VPCにインターネットゲートウェイをアタッチ
aws ec2 attach-internet-gateway \
--vpc-id $VPC_ID \
--internet-gateway-id $IGW_ID
# パブリックサブネットの作成
SUBNET_ID=$(aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block 10.0.1.0/24 \
--availability-zone ap-northeast-1a \
--query 'Subnet.SubnetId' \
--output text)
# サブネットに「Public」タグを追加(重要!ワークフローがこのタグで検索)
aws ec2 create-tags \
--resources $SUBNET_ID \
--tags Key=Name,Value=Public-Subnet-1a
# パブリックIPの自動割り当てを有効化
aws ec2 modify-subnet-attribute \
--subnet-id $SUBNET_ID \
--map-public-ip-on-launch
# ルートテーブルの設定(インターネットアクセス用)
ROUTE_TABLE_ID=$(aws ec2 describe-route-tables \
--filters "Name=vpc-id,Values=$VPC_ID" \
--query 'RouteTables[0].RouteTableId' \
--output text)
aws ec2 create-route \
--route-table-id $ROUTE_TABLE_ID \
--destination-cidr-block 0.0.0.0/0 \
--gateway-id $IGW_ID
2. セキュリティグループとIAMリソースの準備
# 1. セキュリティグループの作成
SECURITY_GROUP_ID=$(aws ec2 create-security-group \
--group-name claude-code-smartphone-sg \
--description "Security group for development environment" \
--vpc-id $VPC_ID \
--query 'GroupId' \
--output text)
# 2. セキュリティグループにタグを追加(重要!ワークフローがこのタグで検索)
aws ec2 create-tags \
--resources $SECURITY_GROUP_ID \
--tags Key=Name,Value=claude-code-smartphone-sg
# 3. セキュリティグループルールの設定
# SSHアクセス(必要に応じてIPを制限してください)
aws ec2 authorize-security-group-ingress \
--group-id $SECURITY_GROUP_ID \
--protocol tcp \
--port 22 \
--cidr 0.0.0.0/0
# HTTPSアクセス(Webサービスを実行する場合)
aws ec2 authorize-security-group-ingress \
--group-id $SECURITY_GROUP_ID \
--protocol tcp \
--port 443 \
--cidr 0.0.0.0/0
# HTTPアクセス(開発用)
aws ec2 authorize-security-group-ingress \
--group-id $SECURITY_GROUP_ID \
--protocol tcp \
--port 80 \
--cidr 0.0.0.0/0
# 4. OIDCプロバイダーの作成(初回のみ)
aws iam create-open-id-connect-provider \
--url https://token.actions.githubusercontent.com \
--client-id-list sts.amazonaws.com \
--thumbprint-list YOUR_THUMBPRINT
# 5. IAMロールの作成(GitHub Actions用)
# まず信頼ポリシーファイルを作成
# YOUR_ACCOUNT_ID, YOUR_GITHUB_USERNAME, YOUR_REPO_NAMEを実際の値に置き換えてください
cat > trust-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::YOUR_ACCOUNT_ID:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
"token.actions.githubusercontent.com:sub": "repo:YOUR_GITHUB_USERNAME/YOUR_REPO_NAME:ref:refs/heads/main"
}
}
}
]
}
EOF
# IAMロールの作成
aws iam create-role \
--role-name GitHubActionsEC2Role \
--assume-role-policy-document file://trust-policy.json
# 6. 必要なポリシーをアタッチ
aws iam attach-role-policy \
--role-name GitHubActionsEC2Role \
--policy-arn arn:aws:iam::aws:policy/AmazonEC2FullAccess
# 7. インスタンスプロファイルの作成(必要に応じて)
aws iam create-instance-profile \
--instance-profile-name GitHubActionsEC2InstanceProfile
aws iam add-role-to-instance-profile \
--instance-profile-name GitHubActionsEC2InstanceProfile \
--role-name GitHubActionsEC2Role
重要な設定ポイント
タグ設定の重要性:
- VPCには必ず
Name=main
タグを設定 - パブリックサブネットには
Name=Public*
パターンのタグを設定 - セキュリティグループには
Name={PROJECT_NAME}-sg
パターンのタグを設定
これらのタグがないと、ワークフローの自動検出機能が動作しません。
3. GitHub Actions Secrets設定
リポジトリの Settings > Secrets and variables > Actions で以下を設定:
# 必須のSecrets
AWS_ROLE_ARN: arn:aws:iam::YOUR_ACCOUNT_ID:role/GitHubActionsEC2Role
GIT_USERNAME: your-github-username
GIT_EMAIL: your-email@example.com
GIT_TOKEN: ghp_YOUR_GITHUB_TOKEN
TAILSCALE_AUTH_KEY: tskey-auth-YOUR_KEY
# オプション(Secretsで設定しない場合はVariablesで設定可能)
# Settings > Secrets and variables > Actions > Variables
GIT_USERNAME: your-github-username # Secretsで設定していない場合
GIT_EMAIL: your-email@example.com # Secretsで設定していない場合
1. EC2自動制御のGitHub Actionsワークフロー設定
name: EC2 Instance Control
on:
workflow_dispatch:
inputs:
action:
description: 'EC2 Action'
required: true
default: 'status'
type: choice
options:
- status
- start
- stop
permissions:
id-token: write
contents: read
env:
AWS_REGION: ap-northeast-1
INSTANCE_NAME: claude-code-smartphone-server
INSTANCE_TYPE: t3.micro
SPOT_PRICE_MAX: "0.005"
VOLUME_SIZE: "20"
PROJECT_NAME: claude-code-smartphone
jobs:
ec2-control:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ${{ env.AWS_REGION }}
- name: Set GitHub user variables
run: |
echo "GH_USER=${{ secrets.GIT_USERNAME || vars.GIT_USERNAME }}" >> $GITHUB_ENV
echo "GH_MAIL=${{ secrets.GIT_EMAIL || vars.GIT_EMAIL }}" >> $GITHUB_ENV
- name: Execute EC2 Control
run: |
# 関数定義を行い、メイン処理を実行
# ここで以下の関数を定義します
case "${{ github.event.inputs.action }}" in
"status")
echo "📊 EC2インスタンスの状態確認中..."
check_instance_status
;;
"start")
echo "🚀 EC2インスタンスを起動中..."
start_or_create_instance
;;
"stop")
echo "⏹️ EC2インスタンスを停止中..."
stop_instance
;;
esac
ワークフローの主要特徴:
- workflow_dispatch: GitHub Actions UIからの手動実行と実行時アクション選択機能
- permissions: GitHub OIDCを使用したAWSへのセキュア接続(長期的な認証情報が不要)
- 環境変数: インスタンス設定の一元管理
2. EC2制御機能の実装
基本的な制御ロジック:
# Status check
get_instance_status() {
aws ec2 describe-instances \
--filters "Name=tag:Name,Values=$INSTANCE_NAME" \
--query 'Reservations[0].Instances[0].State.Name' \
--output text
}
# Start/Create instance
start_or_create_instance() {
EXISTING_INSTANCE=$(get_instance_id)
if [ -n "$EXISTING_INSTANCE" ]; then
aws ec2 start-instances --instance-ids "$EXISTING_INSTANCE"
else
create_spot_instance
fi
}
# Stop instance
stop_instance() {
INSTANCE_ID=$(get_instance_id)
aws ec2 stop-instances --instance-ids "$INSTANCE_ID"
}
3. Spot Instance作成
create_spot_instance() {
# Auto-detect VPC/Subnet
VPC_ID=$(aws ec2 describe-vpcs --filters "Name=tag:Name,Values=main" --query 'Vpcs[0].VpcId' --output text)
SUBNET_ID=$(aws ec2 describe-subnets --filters "Name=tag:Name,Values=Public*" --query 'Subnets[0].SubnetId' --output text)
# Get latest Ubuntu AMI
AMI_ID=$(aws ec2 describe-images --owners 099720109477 \
--filters "Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*" \
--query 'Images | sort_by(@, &CreationDate) | [-1].ImageId' --output text)
# Request Spot Instance
aws ec2 request-spot-instances \
--spot-price "$SPOT_PRICE_MAX" \
--instance-count 1 \
--type "one-time" \
--launch-specification "{
\"ImageId\": \"$AMI_ID\",
\"InstanceType\": \"$INSTANCE_TYPE\",
\"UserData\": \"$(base64 -i user-data.sh)\"}"
}
4. データ永続化設定
EBSボリューム設定でデータ保持:
"BlockDeviceMappings": [{
"DeviceName": "/dev/sda1",
"Ebs": {
"VolumeSize": 20,
"VolumeType": "gp3",
"DeleteOnTermination": false, // 重要: インスタンス終了時も削除しない
"Encrypted": true
}
}]
5. 自動環境セットアップ (user-data.sh)
#!/bin/bash
set -euo pipefail
# System update
sudo apt-get update && sudo apt-get upgrade -y
# Git configuration
git config --global user.name "$git_username"
git config --global user.email "$git_email"
echo "https://$git_username:$github_token@github.com" > ~/.git-credentials
chmod 600 ~/.git-credentials
git config --global credential.helper store
# Tailscale VPN
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --authkey="$tailscale_auth_key" --ssh
# Development tools
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker ubuntu
curl -fsSL https://claude.ai/install.sh | sh
トラブルシューティングガイド
GitHub Actions + EC2 Spot Instanceによるコスト最適化まとめ
GitHub Actions CI/CDとAWS EC2 Spot Instanceを組み合わせることで、従来の1/5のコストで柔軟なクラウド開発環境を構築できました。
特に重要だったAWSコスト削減のポイント:
- CI/CD自動化の徹底: GitHub Actionsによる環境構築からVPN設定まで完全自動化することで、ミスを防ぎつつ利便性を向上
- Spot Instanceコスト最適化: EC2 Spot Instanceの「安いけど中断される」特性を、開発環境の「使う時だけ起動」という要件にマッチさせた
- EBSデータ永続化: EBSボリュームの
DeleteOnTermination: false
設定により、インスタンス終了後もデータは残る
今後のAWSコスト最適化改善案
- 複数開発者での共有環境対応(現在は個人利用想定)
- CloudWatchによる自動停止機能(一定時間アイドル状態で自動停止)
- Terraformでのインフラ管理への移行
- AWS Lambdaによるスケジュール自動制御
クラウド開発環境の自動化に取り組む場合、このGitHub Actions + EC2 Spot Instanceアプローチが有効です。初期設定に手間はかかりますが、一度構築すれば自動化された開発環境を実現できます。
EC2自動化やCI/CD実装に関する質問やフィードバックは、GitHubのIssueで受け付けています。
参考資料
AWS公式ドキュメント
- AWS EC2 Spot Instances – EC2 Spot Instanceの公式ドキュメント
- AWS CLI Command Reference – AWS EC2関連のCLIコマンド
- EC2 User Data – EC2起動時スクリプトの詳細
- AWS Cost Optimization – AWSコスト最適化のベストプラクティス
GitHub Actions関連
- GitHub Actions Documentation – GitHub Actions CI/CDの基本
- Configuring OpenID Connect in AWS – GitHub ActionsとAWSのOIDC連携設定
- GitHub Actions Secrets – GitHub Actions Secrets管理
開発環境・VPN設定
- Tailscale SSH Documentation – Tailscale SSH設定ガイド
- Claude Code CLI – Claude Code開発環境
関連記事
- スマホからClaude CodeでEC2開発環境を使う方法 – 本記事の前提となる低コスト開発環境構築記事
