mcpField
A
aws-ec2

aws-ec2

github.com/bagelholeクラウド・DevOps1.2k331 回インストール23 週間前に更新
リポジトリ

aws-ec2 について

本番、ステージング、開発ワークロードを管理するチーム向けに、Amazon EC2 のデプロイと運用を支援するスキルです。定型起動、スケーリング、Spot インスタンス、AMI 管理、一般的な障害調査を扱います。

主な機能

  1. 01EC2 インスタンスの起動と管理
  2. 02起動テンプレートとユーザーデータの設定
  3. 03Auto Scaling グループの構成
  4. 04Spot インスタンスのリクエストと設定
  5. 05AMI の作成と管理
  6. 06起動・接続障害の調査

活用シーン

  1. 01アプリケーション環境用のコンピュートを起動
  2. 02再利用可能なゴールデン AMI の作成
  3. 03ロードバランサー配下でのインスタンス拡張
  4. 04SSH やインスタンス起動の障害調査

インストール

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

$npx skills add https://github.com/bagelhole/devops-security-agent-skills --skill aws-ec2

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

同梱ファイルreferences/ec2-operations.md

詳細

AWS EC2

本番環境、ステージング環境、開発環境のワークロード向けに、Amazon EC2 コンピューティングインスタンスをデプロイおよび管理します。

このスキルを使用する場面

  • アプリケーションのホスティング用に新しいコンピューティングインスタンスを起動する
  • 一貫性のあるデプロイ用にゴールデン AMI を構築する
  • ロードバランサーの背後にオートスケーリンググループを設定する
  • コスト削減のためにワークロードを Spot インスタンスに移行する
  • インスタンスの接続性、パフォーマンス、起動失敗のトラブルシューティングを行う
  • 再利用可能なインフラストラクチャ用に起動テンプレートを作成する

前提条件

  • AWS CLI v2 がインストールされ、設定済みであること(aws configure)
  • IAM 権限:ec2:*、autoscaling:*、elasticloadbalancing:*、iam:PassRole
  • サブネットを含む既存の VPC(aws-vpc を参照)
  • SSH キーペアが作成済みであること(aws ec2 create-key-pair --key-name my-key --query 'KeyMaterial' --output text > my-key.pem)

インスタンスタイプ選択ガイド

カテゴリタイプユースケース
汎用t3, t3a, m6i, m7gウェブサーバー、小規模データベース、開発/テスト
コンピューティング最適化c6i, c7gバッチ処理、メディアエンコード、ML 推論
メモリ最適化r6i, r7g, x2idnインメモリーキャッシュ、大規模データベース
ストレージ最適化i3, i4i, d3データウェアハウジング、分散ファイルシステム
高速コンピューティングp4d, g5, inf2ML トレーニング、GPU レンダリング、推論
バースト可能t3.micro-t3.2xlarge定常負荷は低く、時折バーストが発生するワークロード

インスタンスを起動する

# Launch a production web server
aws ec2 run-instances \
  --image-id ami-0abcdef1234567890 \
  --instance-type t3.medium \
  --key-name my-key \
  --security-group-ids sg-12345678 \
  --subnet-id subnet-12345678 \
  --iam-instance-profile Name=EC2AppProfile \
  --metadata-options "HttpTokens=required,HttpEndpoint=enabled" \
  --block-device-mappings '[{
    "DeviceName": "/dev/xvda",
    "Ebs": {
      "VolumeSize": 30,
      "VolumeType": "gp3",
      "Iops": 3000,
      "Throughput": 125,
      "Encrypted": true
    }
  }]' \
  --tag-specifications 'ResourceType=instance,Tags=[
    {Key=Name,Value=web-server-01},
    {Key=Environment,Value=production},
    {Key=Team,Value=platform}
  ]' \
  --user-data file://userdata.sh

# Launch with IMDSv2 required (security best practice)
aws ec2 run-instances \
  --image-id ami-0abcdef1234567890 \
  --instance-type t3.micro \
  --metadata-options "HttpTokens=required,HttpPutResponseHopLimit=1,HttpEndpoint=enabled" \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=secure-instance}]'

ユーザーデータスクリプト

#!/bin/bash
# userdata.sh - Bootstrap a web server on Amazon Linux 2023
set -euxo pipefail

# System updates
dnf update -y

# Install and start web server
dnf install -y nginx
systemctl enable nginx
systemctl start nginx

# Install CloudWatch agent
dnf install -y amazon-cloudwatch-agent
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
  -a fetch-config -m ec2 \
  -s -c ssm:AmazonCloudWatch-linux

# Install CodeDeploy agent
dnf install -y ruby wget
cd /home/ec2-user
wget https://aws-codedeploy-us-east-1.s3.us-east-1.amazonaws.com/latest/install
chmod +x ./install
./install auto

# Signal CloudFormation (if launched via CFN)
# /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ASG --region ${AWS::Region}

起動テンプレート

# Create a launch template with full configuration
aws ec2 create-launch-template \
  --launch-template-name web-server-template \
  --version-description "v1 - AL2023 with nginx" \
  --launch-template-data '{
    "ImageId": "ami-0abcdef1234567890",
    "InstanceType": "t3.medium",
    "KeyName": "my-key",
    "SecurityGroupIds": ["sg-12345678"],
    "IamInstanceProfile": {"Name": "EC2AppProfile"},
    "MetadataOptions": {
      "HttpTokens": "required",
      "HttpEndpoint": "enabled"
    },
    "BlockDeviceMappings": [{
      "DeviceName": "/dev/xvda",
      "Ebs": {
        "VolumeSize": 30,
        "VolumeType": "gp3",
        "Encrypted": true
      }
    }],
    "TagSpecifications": [{
      "ResourceType": "instance",
      "Tags": [
        {"Key": "Environment", "Value": "production"},
        {"Key": "ManagedBy", "Value": "launch-template"}
      ]
    }],
    "Monitoring": {"Enabled": true},
    "UserData": "'"$(base64 -w0 userdata.sh)"'"
  }'

# Create a new version of the launch template
aws ec2 create-launch-template-version \
  --launch-template-name web-server-template \
  --source-version 1 \
  --version-description "v2 - updated AMI" \
  --launch-template-data '{"ImageId": "ami-0newami1234567890"}'

# Set the default version
aws ec2 modify-launch-template \
  --launch-template-name web-server-template \
  --default-version 2

オートスケーリンググループ

# Create ASG with mixed instances (on-demand + spot)
aws autoscaling create-auto-scaling-group \
  --auto-scaling-group-name web-asg \
  --mixed-instances-policy '{
    "LaunchTemplate": {
      "LaunchTemplateSpecification": {
        "LaunchTemplateName": "web-server-template",
        "Version": "$Default"
      },
      "Overrides": [
        {"InstanceType": "t3.medium"},
        {"InstanceType": "t3a.medium"},
        {"InstanceType": "m5.large"}
      ]
    },
    "InstancesDistribution": {
      "OnDemandBaseCapacity": 2,
      "OnDemandPercentageAboveBaseCapacity": 25,
      "SpotAllocationStrategy": "capacity-optimized"
    }
  }' \
  --min-size 2 --max-size 10 --desired-capacity 4 \
  --vpc-zone-identifier "subnet-aaa,subnet-bbb" \
  --target-group-arns "arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/web-tg/abc123" \
  --health-check-type ELB \
  --health-check-grace-period 300 \
  --tags '[
    {"Key":"Name","Value":"web-asg","PropagateAtLaunch":true},
    {"Key":"Environment","Value":"production","PropagateAtLaunch":true}
  ]'

# Create target tracking scaling policy (target 60% CPU)
aws autoscaling put-scaling-policy \
  --auto-scaling-group-name web-asg \
  --policy-name cpu-target-tracking \
  --policy-type TargetTrackingScaling \
  --target-tracking-configuration '{
    "PredefinedMetricSpecification": {
      "PredefinedMetricType": "ASGAverageCPUUtilization"
    },
    "TargetValue": 60.0,
    "ScaleInCooldown": 300,
    "ScaleOutCooldown": 60
  }'

# Create scheduled scaling for known traffic patterns
aws autoscaling put-scheduled-update-group-action \
  --auto-scaling-group-name web-asg \
  --scheduled-action-name scale-up-morning \
  --recurrence "0 8 * * MON-FRI" \
  --min-size 4 --max-size 20 --desired-capacity 8

aws autoscaling put-scheduled-update-group-action \
  --auto-scaling-group-name web-asg \
  --scheduled-action-name scale-down-evening \
  --recurrence "0 20 * * MON-FRI" \
  --min-size 2 --max-size 10 --desired-capacity 2

Spot インスタンス

# Request Spot instances
aws ec2 request-spot-instances \
  --spot-price "0.05" \
  --instance-count 3 \
  --type "one-time" \
  --launch-specification '{
    "ImageId": "ami-0abcdef1234567890",
    "InstanceType": "c5.xlarge",
    "KeyName": "my-key",
    "SecurityGroupIds": ["sg-12345678"],
    "SubnetId": "subnet-12345678"
  }'

# Check current Spot prices
aws ec2 describe-spot-price-history \
  --instance-types t3.medium t3a.medium m5.large \
  --availability-zone us-east-1a \
  --product-descriptions "Linux/UNIX" \
  --start-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
  --query "SpotPriceHistory[].{Type:InstanceType,Price:SpotPrice,AZ:AvailabilityZone}" \
  --output table

# Create a Spot Fleet request
aws ec2 request-spot-fleet \
  --spot-fleet-request-config '{
    "IamFleetRole": "arn:aws:iam::123456789012:role/aws-ec2-spot-fleet-role",
    "TargetCapacity": 10,
    "SpotPrice": "0.10",
    "AllocationStrategy": "capacityOptimized",
    "LaunchSpecifications": [
      {"ImageId": "ami-xxx", "InstanceType": "c5.xlarge", "SubnetId": "subnet-aaa"},
      {"ImageId": "ami-xxx", "InstanceType": "c5a.xlarge", "SubnetId": "subnet-bbb"}
    ]
  }'

AMI 管理

# Create an AMI from a running instance
aws ec2 create-image \
  --instance-id i-0abc123def456 \
  --name "web-server-$(date +%Y%m%d)" \
  --description "Web server golden AMI" \
  --no-reboot \
  --tag-specifications 'ResourceType=image,Tags=[
    {Key=Name,Value=web-server-golden},
    {Key=Version,Value=2026.03.24}
  ]'

# Copy AMI to another region for disaster recovery
aws ec2 copy-image \
  --source-image-id ami-0abcdef1234567890 \
  --source-region us-east-1 \
  --region us-west-2 \
  --name "web-server-dr-copy"

# Deregister old AMIs and delete associated snapshots
aws ec2 deregister-image --image-id ami-old123
aws ec2 delete-snapshot --snapshot-id snap-old123

# Share AMI with another AWS account
aws ec2 modify-image-attribute \
  --image-id ami-0abcdef1234567890 \
  --launch-permission "Add=[{UserId=987654321098}]"

インスタンス管理

# List running instances with key details
aws ec2 describe-instances \
  --filters "Name=instance-state-name,Values=running" \
  --query "Reservations[].Instances[].{ID:InstanceId,Type:InstanceType,IP:PrivateIpAddress,Name:Tags[?Key=='Name']|[0].Value,State:State.Name}" \
  --output table

# Stop and start instances
aws ec2 stop-instances --instance-ids i-0abc123def456
aws ec2 start-instances --instance-ids i-0abc123def456

# Resize an instance (stop first)
aws ec2 stop-instances --instance-ids i-0abc123def456
aws ec2 wait instance-stopped --instance-ids i-0abc123def456
aws ec2 modify-instance-attribute \
  --instance-id i-0abc123def456 \
  --instance-type '{"Value": "t3.large"}'
aws ec2 start-instances --instance-ids i-0abc123def456

# Get console output for debugging boot issues
aws ec2 get-console-output --instance-id i-0abc123def456

# Get instance screenshot (helps debug GUI issues)
aws ec2 get-console-screenshot --instance-id i-0abc123def456

Auto Scaling を使用した Terraform EC2

resource "aws_launch_template" "web" {
  name_prefix   = "web-"
  image_id      = data.aws_ami.amazon_linux.id
  instance_type = "t3.medium"

  iam_instance_profile {
    name = aws_iam_instance_profile.web.name
  }

  metadata_options {
    http_tokens   = "required"
    http_endpoint = "enabled"
  }

  block_device_mappings {
    device_name = "/dev/xvda"
    ebs {
      volume_size = 30
      volume_type = "gp3"
      encrypted   = true
    }
  }

  user_data = base64encode(file("userdata.sh"))

  tag_specifications {
    resource_type = "instance"
    tags = {
      Name        = "web-server"
      Environment = "production"
    }
  }
}

resource "aws_autoscaling_group" "web" {
  name                = "web-asg"
  min_size            = 2
  max_size            = 10
  desired_capacity    = 4
  vpc_zone_identifier = [aws_subnet.private_a.id, aws_subnet.private_b.id]
  target_group_arns   = [aws_lb_target_group.web.arn]
  health_check_type   = "ELB"

  launch_template {
    id      = aws_launch_template.web.id
    version = "$Latest"
  }

  tag {
    key                 = "Name"
    value               = "web-asg"
    propagate_at_launch = true
  }
}

resource "aws_autoscaling_policy" "cpu" {
  name                   = "cpu-target-tracking"
  autoscaling_group_name = aws_autoscaling_group.web.name
  policy_type            = "TargetTrackingScaling"

  target_tracking_configuration {
    predefined_metric_specification {
      predefined_metric_type = "ASGAverageCPUUtilization"
    }
    target_value = 60.0
  }
}

トラブルシューティング

問題原因対処法
インスタンスが pending のままになる容量不足別の AZ またはインスタンスタイプを試してください
インスタンスに SSH 接続できないセキュリティグループまたは NACL がポート 22 をブロックしているSG のインバウンドルールとルートテーブルを確認してください
インスタンスが直ちに終了するEBS ボリュームの上限または AMI の問題describe-instances で StateReason を確認してください
IMDSv1 の非推奨警告が表示されるメタデータオプションが設定されていない起動テンプレートで HttpTokens=required を設定してください
ユーザーデータが実行されないスクリプトにシバンがない、または Base64 エンコードされていない#!/bin/bash ヘッダーを確認し、/var/log/cloud-init-output.log を確認してください
Spot インスタンスが終了したAWS によって容量が回収された容量最適化割り当てを使用し、タイプを分散してください
ASG が異常なインスタンスを置き換えないヘルスチェックの猶予期間が短すぎるアプリケーションの起動時間を考慮して猶予期間を延長してください
EBS のスループットがボトルネックになるgp2 ボリュームが IOPS に対して小さすぎるgp3 に移行し、IOPS/スループットを明示的に設定してください

関連スキル

  • aws-vpc - VPC ネットワーキング、サブネット、セキュリティグループ
  • aws-iam - インスタンスプロファイルとロール
  • aws-cost-optimization - 適正なインスタンスサイズと Spot 戦略
  • terraform-aws - Infrastructure as Code によるデプロイ
  • cloudformation - AWS ネイティブの IaC テンプレート

コメント