はじめに
AWSでコンテナワークロードを本格的に運用する場合、ECS(Elastic Container Service)の理解は避けて通れません。ECSはAWSネイティブのコンテナオーケストレーションサービスであり、Kubernetesほど複雑ではなく、AWSサービスとの親和性が高いという特徴があります。
しかし、ECSには「クラスター」「タスク定義」「タスク」「サービス」といった固有の概念があり、これらの関係性を正しく理解しないと、適切な設計や運用ができません。本記事では、ECSのアーキテクチャを体系的に解説し、タスク定義の作成からサービスの構築・管理までを実践的に紹介します。
この記事を読むことで、以下のことが理解できるようになります。
- ECSのコンポーネント(クラスター、タスク定義、タスク、サービス)の役割と関係性
- タスク定義の各パラメータの意味と設定方法
- ECSサービスの作成と運用に必要な設定項目
- 本番環境を見据えたベストプラクティス
ECSアーキテクチャの全体像
ECSの構成要素
ECSを理解するには、4つの主要コンポーネントとその関係を把握することが重要です。
flowchart TB
subgraph ECS["Amazon ECS"]
Cluster["クラスター<br/>論理的なコンテナ実行環境"]
subgraph Services["サービス"]
ServiceA["サービスA<br/>Desired Count: 2"]
ServiceB["サービスB<br/>Desired Count: 3"]
end
subgraph Tasks["実行中のタスク"]
Task1["タスク1"]
Task2["タスク2"]
Task3["タスク3"]
Task4["タスク4"]
Task5["タスク5"]
end
TaskDefA["タスク定義A<br/>(設計図)"]
TaskDefB["タスク定義B<br/>(設計図)"]
end
Cluster --> Services
ServiceA --> Task1
ServiceA --> Task2
ServiceB --> Task3
ServiceB --> Task4
ServiceB --> Task5
TaskDefA -.->|参照| Task1
TaskDefA -.->|参照| Task2
TaskDefB -.->|参照| Task3
TaskDefB -.->|参照| Task4
TaskDefB -.->|参照| Task5各コンポーネントの役割
| コンポーネント | 役割 | 例え |
|---|---|---|
| クラスター | コンテナを実行する論理的な環境 | 工場の建物 |
| タスク定義 | コンテナの設計図(JSON形式) | 製品の設計書 |
| タスク | タスク定義から起動されたコンテナ群 | 製造された製品 |
| サービス | タスクの数と配置を管理する仕組み | 生産ラインの管理者 |
クラスター
クラスターは、ECSにおける最上位の論理的なリソースグループです。タスクとサービスを束ねる役割を持ちます。
クラスターを分離する一般的なパターンは以下のとおりです。
- 環境別(開発、ステージング、本番)
- アプリケーション別(フロントエンド、バックエンド)
- チーム別(チームA、チームB)
クラスター自体には追加料金は発生しません。課金は、クラスター内で実行されるタスクのコンピューティングリソース(FargateまたはEC2)に対して行われます。
タスク定義
タスク定義は、コンテナをどのように実行するかを定義するJSON形式の設計図です。以下の要素を指定します。
- 使用するコンテナイメージ
- CPU・メモリの割り当て
- 環境変数やシークレット
- ネットワーク設定
- ログ出力設定
- IAMロール
タスク定義はバージョン管理され、リビジョン番号が自動的に付与されます。一度作成したタスク定義は変更できず、修正する場合は新しいリビジョンとして登録します。
タスク
タスクは、タスク定義に基づいて起動されたコンテナのインスタンスです。1つのタスクには1つ以上のコンテナを含めることができます。
タスクの起動方法は2種類あります。
| 起動方法 | 用途 | 特徴 |
|---|---|---|
| スタンドアロンタスク | バッチ処理、一時的な処理 | 処理完了後に自動終了 |
| サービス経由 | 常時稼働のWebアプリ | 指定した数を維持 |
サービス
サービスは、指定した数のタスクを常に維持し、ヘルスチェックや自動復旧を管理するコンポーネントです。以下の機能を提供します。
- 指定したタスク数(Desired Count)の維持
- 異常終了したタスクの自動再起動
- ローリングデプロイによる無停止更新
- ロードバランサーとの統合
- Auto Scalingによる自動スケーリング
起動タイプの選択
ECSでは、タスクを実行するインフラストラクチャとして「EC2起動タイプ」と「Fargate起動タイプ」を選択できます。
flowchart TB
subgraph LaunchTypes["起動タイプの選択"]
ECS["Amazon ECS"]
subgraph EC2Type["EC2起動タイプ"]
EC2Instance1["EC2インスタンス"]
EC2Instance2["EC2インスタンス"]
Container1["コンテナ"]
Container2["コンテナ"]
Container3["コンテナ"]
EC2Instance1 --> Container1
EC2Instance1 --> Container2
EC2Instance2 --> Container3
end
subgraph FargateType["Fargate起動タイプ"]
FargateTask1["Fargateタスク"]
FargateTask2["Fargateタスク"]
FargateContainer1["コンテナ"]
FargateContainer2["コンテナ"]
FargateTask1 --> FargateContainer1
FargateTask2 --> FargateContainer2
end
end
ECS --> EC2Type
ECS --> FargateTypeEC2起動タイプ
EC2起動タイプでは、ユーザーがプロビジョニングしたEC2インスタンス上でコンテナが実行されます。
メリット
- インスタンスタイプを自由に選択可能
- GPUインスタンスが利用可能
- リザーブドインスタンスやSavings Plansでコスト最適化
- ホストレベルのカスタマイズが可能
デメリット
- EC2インスタンスの管理(パッチ適用、スケーリング)が必要
- キャパシティプランニングの負担
- 初期設定の複雑さ
Fargate起動タイプ
Fargate起動タイプでは、AWSがインフラストラクチャを完全に管理し、タスクごとに独立した実行環境が提供されます。
メリット
- サーバー管理が一切不要
- タスクレベルでのセキュリティ分離
- 使用した分だけの従量課金
- 素早いプロビジョニング
デメリット
- GPUサポートなし
- 一部のインスタンス機能(特権コンテナなど)の制限
- EC2と比較してコスト単価が高い場合がある
選択の判断基準
| 判断ポイント | Fargate推奨 | EC2推奨 |
|---|---|---|
| 運用負荷 | 最小化したい | 許容できる |
| ワークロード | 変動が大きい | 安定している |
| 特殊要件 | なし | GPU、特権コンテナなど |
| コスト | 変動課金を許容 | 固定費で最適化したい |
本記事では、運用負荷が低く導入しやすいFargate起動タイプを中心に解説します。
タスク定義の作成
タスク定義の構造
タスク定義はJSON形式で記述され、大きく「タスクレベルの設定」と「コンテナ定義」に分かれます。
flowchart TB
subgraph TaskDef["タスク定義"]
subgraph TaskLevel["タスクレベル設定"]
Family["family: タスク定義名"]
Network["networkMode: ネットワークモード"]
CPU["cpu: タスク全体のCPU"]
Memory["memory: タスク全体のメモリ"]
ExecutionRole["executionRoleArn: 実行ロール"]
TaskRole["taskRoleArn: タスクロール"]
end
subgraph ContainerDefs["containerDefinitions"]
Container1["コンテナ1の定義"]
Container2["コンテナ2の定義"]
end
end
TaskLevel --> ContainerDefs基本的なタスク定義の例
以下は、Nginx Webサーバーを実行するシンプルなタスク定義の例です。
|
|
タスクレベルのパラメータ
タスク定義の主要なパラメータを解説します。
family
タスク定義の名前です。同じfamilyで複数のリビジョンを管理できます。命名規則として、アプリケーション名やサービス名を使用することを推奨します。
|
|
networkMode
タスクのネットワークモードを指定します。Fargateではawsvpcのみサポートされます。
| モード | 説明 | Fargate対応 |
|---|---|---|
| awsvpc | タスクごとにENIを割り当て | 対応 |
| bridge | Docker標準のブリッジネットワーク | 非対応 |
| host | ホストのネットワークを共有 | 非対応 |
| none | ネットワーク無効 | 非対応 |
cpu / memory
タスク全体で使用するCPUとメモリを指定します。Fargateでは以下の組み合わせから選択します。
| cpu(単位) | memory(MB) |
|---|---|
| 256 | 512, 1024, 2048 |
| 512 | 1024〜4096(1024単位) |
| 1024 | 2048〜8192(1024単位) |
| 2048 | 4096〜16384(1024単位) |
| 4096 | 8192〜30720(1024単位) |
| 8192 | 16384〜61440(4096単位) |
| 16384 | 32768〜122880(8192単位) |
|
|
executionRoleArn
ECSエージェントがタスクを実行するために使用するIAMロールです。以下の操作権限が必要です。
- ECRからのイメージプル
- CloudWatch Logsへのログ送信
- Secrets Managerからのシークレット取得(使用する場合)
AWSマネージドポリシーAmazonECSTaskExecutionRolePolicyを使用するのが一般的です。
taskRoleArn
タスク内のコンテナがAWSサービスにアクセスするために使用するIAMロールです。例えば、S3バケットへのアクセスやDynamoDBへのクエリを行う場合に必要です。
flowchart LR
subgraph ECSTask["ECSタスク"]
Container["コンテナ"]
end
ExecutionRole["実行ロール<br/>executionRoleArn"]
TaskRole["タスクロール<br/>taskRoleArn"]
ECR["Amazon ECR"]
CloudWatch["CloudWatch Logs"]
S3["Amazon S3"]
DynamoDB["DynamoDB"]
ExecutionRole -->|イメージ取得| ECR
ExecutionRole -->|ログ送信| CloudWatch
Container -->|タスクロール経由| TaskRole
TaskRole -->|アクセス| S3
TaskRole -->|アクセス| DynamoDBコンテナ定義のパラメータ
containerDefinitions配列内で各コンテナの設定を定義します。
基本設定
| パラメータ | 説明 | 必須 |
|---|---|---|
| name | コンテナの名前 | はい |
| image | コンテナイメージのURI | はい |
| essential | このコンテナが停止するとタスクが停止するか | いいえ(デフォルト: true) |
|
|
portMappings
コンテナが公開するポートを定義します。Fargateのawsvpcモードでは、hostPortはcontainerPortと同じ値になります。
|
|
environment / secrets
環境変数の設定方法は2種類あります。
environment(プレーンテキスト)
|
|
secrets(Secrets Manager / Parameter Store連携)
機密情報はSecrets ManagerまたはSystems Manager Parameter Storeから取得します。
|
|
logConfiguration
コンテナのログ出力先を設定します。CloudWatch Logsを使用する場合の例を示します。
|
|
ログドライバーはawslogs以外にもsplunk、fluentd、awsfirelensなどを選択できます。
healthCheck
コンテナのヘルスチェックを設定します。ECSはこの設定に基づいてコンテナの状態を監視します。
|
|
| パラメータ | 説明 | デフォルト |
|---|---|---|
| command | ヘルスチェックコマンド | - |
| interval | チェック間隔(秒) | 30 |
| timeout | タイムアウト(秒) | 5 |
| retries | 失敗許容回数 | 3 |
| startPeriod | 起動猶予期間(秒) | 0 |
完全なタスク定義の例
実際の本番環境を想定した、より完全なタスク定義の例を示します。
|
|
AWS CLIでのタスク定義の登録
タスク定義をAWS CLIで登録する場合は、以下のコマンドを使用します。
|
|
ECSサービスの作成と管理
サービスの役割
ECSサービスは、タスクのライフサイクルを管理し、以下の機能を提供します。
flowchart TB
subgraph Service["ECSサービス"]
DesiredCount["Desired Count: 3"]
Scheduler["スケジューラー"]
subgraph Tasks["実行中のタスク"]
Task1["タスク1<br/>RUNNING"]
Task2["タスク2<br/>RUNNING"]
Task3["タスク3<br/>RUNNING"]
end
end
ALB["Application<br/>Load Balancer"]
AutoScaling["Auto Scaling"]
Scheduler -->|維持| Tasks
ALB -->|トラフィック分散| Tasks
AutoScaling -->|スケール制御| DesiredCountサービス作成の前提条件
ECSサービスを作成する前に、以下のリソースを準備します。
- ECSクラスター - サービスを配置するクラスター
- タスク定義 - サービスが使用するタスク定義
- VPCとサブネット - タスクを実行するネットワーク環境
- セキュリティグループ - タスクへのトラフィック制御
- ロードバランサー(任意) - トラフィックの分散
サービス定義のパラメータ
主要なサービス設定パラメータを解説します。
基本設定
| パラメータ | 説明 |
|---|---|
| serviceName | サービスの名前 |
| cluster | 配置先のクラスター |
| taskDefinition | 使用するタスク定義(family:revision) |
| desiredCount | 維持するタスク数 |
| launchType | 起動タイプ(FARGATE or EC2) |
ネットワーク設定
FargateではnetworkConfigurationが必須です。
|
|
assignPublicIpの設定は、タスクがインターネットにアクセスする方法によって決まります。
| 設定 | 用途 |
|---|---|
| ENABLED | パブリックサブネットで直接インターネットアクセス |
| DISABLED | プライベートサブネット + NAT Gateway経由 |
ロードバランサー設定
ALBまたはNLBと統合する場合の設定です。
|
|
デプロイメント設定
ローリングデプロイの動作を制御します。
|
|
| パラメータ | 説明 | 推奨値 |
|---|---|---|
| maximumPercent | デプロイ時の最大タスク数(%) | 200 |
| minimumHealthyPercent | 最低限維持するタスク数(%) | 100 |
| deploymentCircuitBreaker | デプロイ失敗時の自動ロールバック | 有効推奨 |
maximumPercent: 200、minimumHealthyPercent: 100の場合、3タスクのサービスでは以下のように動作します。
- 新しいタスクを3つ起動(最大6タスク)
- 新タスクがヘルシーになったら古いタスクを停止
- 常に最低3タスクが稼働
AWS CLIでのサービス作成
サービス定義をJSONファイルで準備し、AWS CLIで作成します。
|
|
サービスの更新
タスク定義を更新してデプロイする場合は、update-serviceコマンドを使用します。
|
|
サービスのAuto Scaling
ECSサービスは、Application Auto Scalingと統合してタスク数を自動調整できます。
flowchart LR
CloudWatch["CloudWatch<br/>メトリクス"] --> AutoScaling["Application<br/>Auto Scaling"]
AutoScaling --> ECSService["ECSサービス<br/>Desired Count"]
subgraph Metrics["監視メトリクス"]
CPU["CPU使用率"]
Memory["メモリ使用率"]
Request["リクエスト数"]
end
Metrics --> CloudWatchスケーラブルターゲットの登録
|
|
ターゲット追跡スケーリングポリシー
CPU使用率に基づくスケーリングポリシーの例です。
|
|
サイドカーパターンの実装
ECSでは、1つのタスクに複数のコンテナを含めるサイドカーパターンを実装できます。代表的なユースケースを紹介します。
ログ収集サイドカー
アプリケーションログをFluentBitで収集し、外部に転送するパターンです。
flowchart LR
subgraph Task["ECSタスク"]
App["アプリコンテナ"]
FluentBit["FluentBit<br/>サイドカー"]
end
App -->|ログ出力| FluentBit
FluentBit -->|転送| CloudWatch["CloudWatch Logs"]
FluentBit -->|転送| S3["Amazon S3"]
|
|
プロキシサイドカー
Envoyなどのプロキシをサイドカーとして配置し、サービスメッシュを構築するパターンです。AWS App Meshと組み合わせて使用します。
ベストプラクティス
タスク定義のベストプラクティス
-
イメージタグの固定
latestタグは避け、具体的なバージョンタグを使用する- ECRのイメージタグイミュータビリティを有効化する
-
リソース設定の最適化
- 本番環境の負荷を計測してから適切なCPU・メモリを設定する
- 過剰なリソース割り当てはコスト増加につながる
-
シークレット管理
- 環境変数に機密情報を直接記載しない
- Secrets ManagerまたはParameter Storeを使用する
-
ログ設定
- 必ずログ出力を設定し、トラブルシューティングに備える
- ログの保持期間とコストを考慮してロググループを設計する
サービス運用のベストプラクティス
-
デプロイメントサーキットブレーカーの有効化
- デプロイ失敗時の自動ロールバックで可用性を確保する
-
ヘルスチェックの適切な設定
- アプリケーションの起動時間を考慮して
startPeriodを設定する - ヘルスチェックエンドポイントは軽量な処理にする
- アプリケーションの起動時間を考慮して
-
マルチAZ配置
- 複数のアベイラビリティゾーンにタスクを分散する
- サブネットは少なくとも2つのAZに配置する
-
Auto Scalingの設定
- 最小タスク数は可用性要件に基づいて設定する
- スケールイン・アウトのクールダウン期間を適切に設定する
まとめ
本記事では、Amazon ECSのアーキテクチャからタスク定義の作成、サービスの管理までを解説しました。主要なポイントは以下のとおりです。
- ECSの4つのコンポーネント(クラスター、タスク定義、タスク、サービス)の関係性を理解することが重要
- タスク定義はコンテナの設計図であり、イメージ、リソース、環境変数、ログ設定などを定義する
- ECSサービスはタスクのライフサイクルを管理し、ロードバランサー統合やAuto Scalingを提供する
- Fargate起動タイプを選択することで、インフラ管理の負担を大幅に軽減できる
ECSは学習コストが比較的低く、AWSサービスとの統合も容易なため、コンテナワークロードの第一歩として適しています。まずはシンプルなタスク定義から始め、徐々にサイドカーパターンやAuto Scalingなどの高度な機能を取り入れていくことを推奨します。