はじめに
クラウド環境におけるアプリケーションの運用において、高可用性と柔軟なスケーラビリティは重要な要素です。本記事では、AWS Auto ScalingとDockerコンテナを組み合わせることで、アプリケーションの可用性を向上させる方法について解説します。
AWS Auto Scalingとは
AWS Auto Scalingは、需要の変化に応じてリソースを自動的に増減させることができるAWSのサービスです。主な機能として以下が挙げられます:
- 需要予測: トラフィックパターンに基づいた自動スケーリング
- コスト最適化: 必要なリソースのみを利用することによるコスト削減
- 高可用性: 障害発生時の自動復旧によるダウンタイムの最小化
Dockerとの相性
Dockerコンテナは軽量で起動が速く、環境に依存しない一貫性のあるデプロイが可能です。これらの特性は、Auto Scalingと組み合わせることで以下のメリットをもたらします:
- 迅速なスケールアウト: コンテナの起動が速いため、需要の急増に素早く対応
- 一貫性のある環境: 全てのインスタンスで同一の環境を保証
- リソース効率: 複数のコンテナを1つのホスト上で実行可能
AWS Auto ScalingとDockerの連携アーキテクチャ
基本アーキテクチャ
AWS上でDockerコンテナを活用したAuto Scalingを実現するための基本的なアーキテクチャは以下の通りです:
- Amazon ECR: Dockerイメージのリポジトリ
- Amazon ECS/EKS: コンテナオーケストレーションサービス
- Auto Scaling Group: EC2インスタンスのスケーリングを管理
- Application Load Balancer: トラフィックの分散
![AWS Auto ScalingとDockerの連携アーキテクチャ図]
ECSを使用したアーキテクチャ例
インターネット → ALB → ECS Service (Auto Scaling) → ECSタスク (Docker)
↑
CloudWatch (メトリクスに基づいたスケーリング)
実装ステップ
1. Dockerイメージの準備
まずはアプリケーションのDockerfileを作成し、イメージをビルドします。
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
2. Amazon ECRへのプッシュ
ビルドしたDockerイメージをAmazon ECRにプッシュします。
# ECRにログイン
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin <AWS_ACCOUNT_ID>.dkr.ecr.ap-northeast-1.amazonaws.com
# イメージのタグ付け
docker tag my-app:latest <AWS_ACCOUNT_ID>.dkr.ecr.ap-northeast-1.amazonaws.com/my-app:latest
# ECRへのプッシュ
docker push <AWS_ACCOUNT_ID>.dkr.ecr.ap-northeast-1.amazonaws.com/my-app:latest
3. ECSクラスターの作成
AWSコンソールまたはCLIからECSクラスターを作成します。
aws ecs create-cluster --cluster-name my-cluster
4. タスク定義の作成
コンテナの実行に必要な設定をタスク定義として記述します。
{
"family": "my-app-task",
"networkMode": "awsvpc",
"executionRoleArn": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/ecsTaskExecutionRole",
"containerDefinitions": [
{
"name": "my-app",
"image": "<AWS_ACCOUNT_ID>.dkr.ecr.ap-northeast-1.amazonaws.com/my-app:latest",
"essential": true,
"portMappings": [
{
"containerPort": 3000,
"hostPort": 3000
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/my-app-task",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "ecs"
}
}
}
],
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512"
}
5. ECSサービスの作成と自動スケーリングの設定
タスク定義を元にECSサービスを作成し、Auto Scalingを設定します。
# サービスの作成
aws ecs create-service \
--cluster my-cluster \
--service-name my-app-service \
--task-definition my-app-task \
--desired-count 2 \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[subnet-xxxxx,subnet-yyyyy],securityGroups=[sg-zzzzz],assignPublicIp=ENABLED}" \
--load-balancers "targetGroupArn=arn:aws:elasticloadbalancing:ap-northeast-1:<AWS_ACCOUNT_ID>:targetgroup/my-app-tg/aaaaaa,containerName=my-app,containerPort=3000"
# Auto Scaling設定
aws application-autoscaling register-scalable-target \
--service-namespace ecs \
--scalable-dimension ecs:service:DesiredCount \
--resource-id service/my-cluster/my-app-service \
--min-capacity 2 \
--max-capacity 10
# スケーリングポリシーの設定(CPUベース)
aws application-autoscaling put-scaling-policy \
--service-namespace ecs \
--scalable-dimension ecs:service:DesiredCount \
--resource-id service/my-cluster/my-app-service \
--policy-name cpu-tracking-scaling-policy \
--policy-type TargetTrackingScaling \
--target-tracking-scaling-policy-configuration '{
"TargetValue": 70.0,
"PredefinedMetricSpecification": {
"PredefinedMetricType": "ECSServiceAverageCPUUtilization"
},
"ScaleOutCooldown": 60,
"ScaleInCooldown": 300
}'
スケーリングポリシーの詳細設定
Auto Scalingを効果的に活用するためには、適切なスケーリングポリシーの設定が重要です。
ターゲット追跡スケーリング
特定のメトリクス(CPU使用率など)を一定の値に保つように自動でスケーリングを行います。
{
"TargetValue": 70.0,
"PredefinedMetricSpecification": {
"PredefinedMetricType": "ECSServiceAverageCPUUtilization"
},
"ScaleOutCooldown": 60,
"ScaleInCooldown": 300
}
ステップスケーリング
メトリクスの変化の大きさに応じて、追加するインスタンス数を調整します。
{
"AdjustmentType": "ChangeInCapacity",
"MetricAggregationType": "Average",
"StepAdjustments": [
{
"MetricIntervalLowerBound": 0,
"MetricIntervalUpperBound": 20,
"ScalingAdjustment": 1
},
{
"MetricIntervalLowerBound": 20,
"ScalingAdjustment": 2
}
]
}
スケジュールベーススケーリング
トラフィックパターンが予測可能な場合、時間帯に応じてスケーリングを行います。
aws application-autoscaling put-scheduled-action \
--service-namespace ecs \
--scalable-dimension ecs:service:DesiredCount \
--resource-id service/my-cluster/my-app-service \
--scheduled-action-name scale-up-morning \
--schedule "cron(0 8 * * ? *)" \
--scalable-target-action MinCapacity=5,MaxCapacity=20
高可用性を実現するためのベストプラクティス
1. マルチAZ配置
複数のアベイラビリティゾーンにリソースを分散させることで、AZ障害に対する耐性を高めます。
# サブネット設定(複数AZ)
aws ecs create-service \
--network-configuration "awsvpcConfiguration={subnets=[subnet-az1,subnet-az2,subnet-az3],securityGroups=[sg-zzzzz],assignPublicIp=ENABLED}"
2. ヘルスチェックの最適化
コンテナのヘルスチェックを適切に設定することで、問題のあるコンテナを早期に検出し、置き換えることができます。
{
"healthCheck": {
"command": ["CMD-SHELL", "curl -f http://localhost:3000/health || exit 1"],
"interval": 30,
"timeout": 5,
"retries": 3,
"startPeriod": 60
}
}
3. グレースフルシャットダウン
コンテナ終了時に進行中のリクエストを処理できるよう、グレースフルシャットダウンを実装します。
// Node.jsの例
process.on('SIGTERM', () => {
console.log('SIGTERM signal received');
// 新しい接続を受け付けない
server.close(() => {
console.log('Server closed');
process.exit(0);
});
// 30秒後に強制終了
setTimeout(() => {
console.log('Forcing shutdown');
process.exit(1);
}, 30000);
});
4. ロードバランサーの設定最適化
ALBの設定を最適化して、トラフィック分散の効率を高めます。
# ターゲットグループのデレジストレーション遅延を設定
aws elbv2 modify-target-group-attributes \
--target-group-arn arn:aws:elasticloadbalancing:ap-northeast-1:<AWS_ACCOUNT_ID>:targetgroup/my-app-tg/aaaaaa \
--attributes Key=deregistration_delay.timeout_seconds,Value=60
パフォーマンスモニタリングとアラート設定
CloudWatchメトリクスの活用
重要なメトリクスを監視し、異常を検知するためのアラームを設定します。
# CPU使用率アラームの作成
aws cloudwatch put-metric-alarm \
--alarm-name HighCPUUtilization \
--alarm-description "Alarm when CPU exceeds 85%" \
--metric-name CPUUtilization \
--namespace AWS/ECS \
--statistic Average \
--period 60 \
--threshold 85 \
--comparison-operator GreaterThanThreshold \
--dimensions Name=ClusterName,Value=my-cluster Name=ServiceName,Value=my-app-service \
--evaluation-periods 3 \
--alarm-actions arn:aws:sns:ap-northeast-1:<AWS_ACCOUNT_ID>:my-alert-topic
X-Ray統合によるトレーシング
AWS X-Rayを統合することで、アプリケーションのパフォーマンスをより詳細に分析できます。
# X-Ray対応Dockerfile
FROM node:18-alpine
# X-Rayデーモンのインストール
RUN wget https://s3.us-east-2.amazonaws.com/aws-xray-assets.us-east-2/xray-daemon/aws-xray-daemon-linux-3.x.zip \
&& unzip aws-xray-daemon-linux-3.x.zip \
&& cp xray /usr/bin/xray \
&& rm -rf aws-xray-daemon-linux-3.x.zip
WORKDIR /app
COPY package*.json ./
RUN npm install
# X-Ray SDKのインストール
RUN npm install aws-xray-sdk
COPY . .
EXPOSE 3000
# X-Rayデーモンとアプリケーションを起動
CMD ["/bin/sh", "-c", "xray -o &; npm start"]
コスト最適化戦略
リザーブドキャパシティの活用
ベースロードに対してはリザーブドキャパシティを使用し、変動部分をAuto Scalingで対応することでコストを削減できます。
Spotインスタンスの活用
非本番環境や耐障害性のあるワークロードには、Spotインスタンスを活用することでコストを大幅に削減できます。
# Capacityプロバイダーを作成(Spotインスタンス用)
aws ecs create-capacity-provider \
--name Spot \
--auto-scaling-group-provider "autoScalingGroupArn=arn:aws:autoscaling:ap-northeast-1:<AWS_ACCOUNT_ID>:autoScalingGroup:xxxx,managedScaling={status=ENABLED,targetCapacity=100},managedTerminationProtection=DISABLED"
# クラスターにCapacityプロバイダーを関連付け
aws ecs put-cluster-capacity-providers \
--cluster my-cluster \
--capacity-providers Spot FARGATE \
--default-capacity-provider-strategy "capacityProvider=Spot,weight=1,base=0" "capacityProvider=FARGATE,weight=1,base=0"
まとめ
AWS Auto ScalingとDockerを組み合わせることで、アプリケーションの可用性を大幅に向上させることができます。本記事で紹介した手法を実装することで、以下のメリットが得られます:
- 高可用性: 障害発生時の自動復旧によるダウンタイムの最小化
- コスト最適化: 需要に応じたリソース割り当てによる無駄の削減
- 運用効率: 自動化による運用負荷の軽減
- スケーラビリティ: トラフィック増加に対する柔軟な対応
効果的なAuto Scaling戦略を実装するためには、アプリケーションの特性を理解し、適切なメトリクスとスケーリングポリシーを選択することが重要です。定期的なモニタリングと調整を行い、最適なパフォーマンスとコストバランスを実現しましょう。
コメント