0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Amazon ECS入門 - Nginxをデプロイして学ぶコンテナ運用の基本

0
Posted at

はじめに

Docker Composeを使うと、ローカル環境で簡単にコンテナを起動・管理できます。

一方、本番環境では、以下のような要件が出てきます。

  • コンテナ障害時に自動復旧したい
  • 複数のコンテナへ負荷分散したい
  • コンテナ数を簡単に増やしたい
  • CloudWatch Logsでログを確認したい
  • AWS IAMで権限制御したい

このような用途で利用されるのが、Amazon ECSです。

本記事では、Amazon ECS Managed Instancesを使ってNginxを構築します。

また、HTMLファイルはDockerイメージに含めず、Amazon S3に保存した index.htmlS3 Files でコンテナへマウントします。

これにより、S3上のHTMLを書き換えるだけで、数秒後にNginxの表示内容へ反映される構成を作ります。

ECSとは

Amazon ECSは、AWSが提供するコンテナオーケストレーションサービスです。

Docker Composeが主に1台のサーバー上でコンテナを起動する仕組みであるのに対し、ECSはAWS上で複数のコンテナを管理できます。

Docker Compose

Server
└── nginx
Amazon ECS

ECS Cluster
└── ECS Service
    └── ECS Task
        └── nginx

ECSでは、コンテナを直接起動するのではなく、以下のような構成で管理します。

ECSの要素 説明
Cluster コンテナを実行する基盤
Task Definition コンテナの設計図
Task 実行中のコンテナ
Service Task数を維持する仕組み
Capacity Provider コンテナ実行基盤の管理

今回作成する構成

今回は以下の構成を作成します。

既存VPC

├── Private Subnet-A
│   ├── 踏み台サーバー
│   ├── Internal ALB
│   └── ECS Managed Instance
│       └── nginx Task
│
├── Private Subnet-C
│   ├── Internal ALB
│   └── ECS Managed Instance
│       └── nginx Task
│
└── Amazon S3
    └── index.html
        ↑
        S3 Filesでマウント

ポイントは以下です。

項目 内容
ECS実行基盤 Managed Instances
OS Amazon Linux
VPC 既存VPC
Subnet Private Subnet
ALB Internal ALB
Target Group IPターゲット
Webサーバー nginx:latest
HTML配置先 Amazon S3
HTMLマウント先 /usr/share/nginx/html
動作確認 踏み台サーバーからInternal ALBへアクセス
スケール確認 Desired Countを1から2へ変更

S3バケット名について

S3バケット名はグローバルで一意である必要があります。

そのため、AWS推奨のアカウントIDを含めた名前にします。

ecs-nginx-demo-<AWSアカウントID>-ap-northeast-1-an

例です。

ecs-nginx-demo-123456789012-ap-northeast-1-an

このようにすることで、他のAWSアカウントとバケット名が重複しにくくなります。

S3バケットを作成する

AWSマネジメントコンソールで以下を開きます。

S3 > 汎用バケット > バケットを作成

設定値は以下です。

項目 設定値
バケットタイプ 汎用
バケット名 ecs-nginx-demo-<AWSアカウントID>-ap-northeast-1-an
AWSリージョン アジアパシフィック(東京)ap-northeast-1
オブジェクト所有者 ACL無効
パブリックアクセスをすべてブロック 有効
バケットのバージョニング 無効
デフォルト暗号化 Amazon S3 マネージドキー
バケットキー 有効

image.png

作成後、バケットを開きます。

index.htmlをアップロードする

ローカルPCで以下のファイルを作成します。

ファイル名は index.html です。

<!DOCTYPE html>
<html>
<head>
  <title>ECS S3 Files Demo</title>
</head>
<body>
  <h1>Hello ECS</h1>
</body>
</html>

S3バケットを開き、以下の順に操作します。

S3 > 対象バケット > オブジェクト > アップロード

設定値は以下です。

項目 設定値
アップロードファイル index.html
保存先 バケット直下
アクセス許可 変更なし
ストレージクラス 標準

アップロード後、以下のようになっていれば問題ありません。

s3://ecs-nginx-demo-<AWSアカウントID>-ap-northeast-1-an/index.html

IAMポリシーを作成する

S3 FilesがS3バケットを読み取れるように、IAMポリシーを作成します。

AWSマネジメントコンソールで以下を開きます。

IAM > ポリシー > ポリシーの作成

「JSON」を選択し、以下を入力します。

<AWSアカウントID> は自分のAWSアカウントIDに置き換えます。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowListBucket",
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket"
      ],
      "Resource": "arn:aws:s3:::ecs-nginx-demo-<AWSアカウントID>-ap-northeast-1-an"
    },
    {
      "Sid": "AllowReadObjects",
      "Effect": "Allow",
      "Action": [
        "s3:GetObject"
      ],
      "Resource": "arn:aws:s3:::ecs-nginx-demo-<AWSアカウントID>-ap-northeast-1-an/*"
    }
  ]
}

ポリシー名は以下にします。

S3FilesReadOnlyForEcsNginx

設定値です。

項目 設定値
ポリシー名 S3FilesReadOnlyForEcsNginx
説明 Allow ECS task to read nginx html files from S3

IAMロールを作成する

次に、ECS TaskからS3を読むためのIAMロールを作成します。

AWSマネジメントコンソールで以下を開きます。

IAM > ロール > ロールを作成

設定値は以下です。

項目 設定値
信頼されたエンティティタイプ AWSサービス
ユースケース Elastic Container Service
ユースケース詳細 Elastic Container Service Task

許可ポリシーで、先ほど作成した以下のポリシーを選択します。

S3FilesReadOnlyForEcsNginx

ロール名は以下にします。

ecs-task-role-nginx-s3files
項目 設定値
ロール名 ecs-task-role-nginx-s3files
説明 Task role for nginx to mount S3 Files

このロールは、後ほどTask Definitionの Task role に指定します。

Security Groupを作成する

今回必要なSecurity Groupは2つです。

Security Group名 用途
sg-ecs-nginx-alb Internal ALB用
sg-ecs-nginx-task ECS Task用

通信経路は以下です。

踏み台サーバー
    ↓ HTTP:80
Internal ALB
    ↓ HTTP:80
ECS Task nginx

ALB用Security Groupを作成する

AWSマネジメントコンソールで以下を開きます。

EC2 > セキュリティグループ > セキュリティグループを作成

基本情報です。

項目 設定値
セキュリティグループ名 sg-ecs-nginx-alb
説明 Security group for internal ALB of ECS nginx
VPC 既存VPC

インバウンドルールです。

タイプ プロトコル ポート ソース
HTTP TCP 80 踏み台サーバーのSecurity Group

踏み台サーバーのSecurity Groupをソースに指定します。

例です。

sg-bastion

アウトバウンドルールです。

タイプ プロトコル ポート 宛先
すべてのトラフィック すべて すべて 0.0.0.0/0

ALBからECS Taskへ通信するため、アウトバウンドはデフォルトのままで問題ありません。

ECS Task用Security Groupを作成する

同じく以下を開きます。

EC2 > セキュリティグループ > セキュリティグループを作成

基本情報です。

項目 設定値
セキュリティグループ名 sg-ecs-nginx-task
説明 Security group for ECS nginx tasks
VPC 既存VPC

インバウンドルールです。

タイプ プロトコル ポート ソース
HTTP TCP 80 sg-ecs-nginx-alb

ここでは、踏み台サーバーからの直接アクセスは許可しません。

ECS TaskにはALBからのみアクセスさせます。

アウトバウンドルールです。

タイプ プロトコル ポート 宛先
すべてのトラフィック すべて すべて 0.0.0.0/0

S3 FilesでS3へアクセスするため、ECS Task側から外向き通信が必要です。

Private Subnetの場合、S3へ到達するために以下のいずれかが必要です。

  • NAT Gateway
  • NAT Instance
  • S3 Gateway Endpoint

閉域構成にしたい場合は、S3 Gateway Endpointを利用します。

Target Groupを作成する

ALBからECS Taskへ転送するため、Target Groupを作成します。

AWSマネジメントコンソールで以下を開きます。

EC2 > ターゲットグループ > ターゲットグループの作成

基本設定

項目 設定値
ターゲットタイプ IPアドレス
ターゲットグループ名 tg-ecs-nginx
プロトコル HTTP
ポート 80
IPアドレスタイプ IPv4
VPC 既存VPC
プロトコルバージョン HTTP1

今回はECS Serviceと連携するため、ターゲットタイプは IPアドレス にします。

ECS Taskは awsvpc ネットワークモードでENIを持つため、ALBはTaskのIPアドレスへ直接転送します。

ヘルスチェック設定

項目 設定値
ヘルスチェックプロトコル HTTP
ヘルスチェックパス /
正常しきい値 5
非正常しきい値 2
タイムアウト 5秒
間隔 30秒
成功コード 200

Nginxは / にアクセスすると index.html を返します。

そのため、ヘルスチェックパスは / で問題ありません。

ターゲット登録

作成時点ではターゲットを手動登録しません。

ECS Serviceを作成すると、ECSが自動でTaskのIPアドレスをTarget Groupへ登録します。

そのため、ターゲット登録画面では何も選択せずに作成します。

Internal ALBを作成する

AWSマネジメントコンソールで以下を開きます。

EC2 > ロードバランサー > ロードバランサーの作成

「Application Load Balancer」を選択します。

基本設定

項目 設定値
ロードバランサー名 alb-ecs-nginx-internal
スキーム 内部
IPアドレスタイプ IPv4

スキームは 内部 を選択します。

これにより、ALBはPrivate Subnet内でのみ利用されます。

ネットワークマッピング

項目 設定値
VPC 既存VPC
サブネット Private Subnet-A、Private Subnet-C

ALBは高可用性のため、2つ以上のAZに配置します。

今回はPrivate Subnetを2つ選択します。

Security Group

項目 設定値
Security Group sg-ecs-nginx-alb

Listener

項目 設定値
プロトコル HTTP
ポート 80
デフォルトアクション tg-ecs-nginx へ転送

作成後、ALBのDNS名を控えます。

例です。

internal-alb-ecs-nginx-internal-xxxxxxxx.ap-northeast-1.elb.amazonaws.com

ECSクラスターを作成する

AWSマネジメントコンソールで以下を開きます。

ECS > Clusters > Create Cluster

設定値は以下です。

項目 設定値
Cluster name ecs-cluster-nginx
Infrastructure Managed Instances
OS Amazon Linux
VPC 既存VPC
Subnets Private Subnet-A、Private Subnet-C

Managed Instancesを選ぶと、ECSがManaged Instances用のCapacity Providerを自動作成します。

今回の記事では、Capacity Providerを個別に事前作成せず、クラスター作成時にECSへ自動作成させます。

Task Definitionを作成する

AWSマネジメントコンソールで以下を開きます。

ECS > task difinitions > Create

Task Definition基本設定

項目 設定値
Task definition family nginx-task
Launch type Managed Instances
Network mode awsvpc
Task role ecs-task-role-nginx-s3files
Task execution role ecsTaskExecutionRole

Task roleには、S3 FilesでS3を読むためのロールを指定します。

Task execution roleは、ECSがコンテナイメージ取得やCloudWatch Logs出力に使うロールです。

通常は ecsTaskExecutionRole を利用します。

Task size

項目 設定値
CPU 0.25 vCPU
Memory 0.5 GB

Nginxの簡単な検証なので、小さいサイズで十分です。

コンテナを追加する

Task Definition作成画面で、コンテナを追加します。

コンテナ基本設定

項目 設定値
Container name nginx
Image URI nginx:latest
Essential container Yes
Private registry authentication Off

Image URIについて

今回はDocker Hubで公開されている公式Nginxイメージを利用します。

nginx:latest

これは、Docker Hub上のNginx公式イメージの最新版タグを意味します。

ECRを使う場合は以下のようなURIになります。

123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/nginx:latest

今回はECRは使わず、Docker Hubの nginx:latest を直接指定します。

Port mappings

項目 設定値
Container port 80
Protocol TCP
Port name nginx-80-tcp
App protocol HTTP

Nginxはコンテナ内で80番ポートをListenします。

ALBからもHTTP:80でアクセスするため、Container portは80にします。

S3 Files Volumeを設定する

Task DefinitionのVolume設定で、S3 Filesを追加します。

Volume設定

項目 設定値
Volume name s3-html-volume
Volume type S3 Files
File System fs-XXXXXXXXXXXXXXXX
S3 prefix /
Read only 有効

File Systemには、先ほど作成したファイルシステムを指定します。

S3 prefixはバケット直下を利用するため / にします。

つまり、以下のファイルがコンテナ内に見えるようになります。

s3://ecs-nginx-demo-<AWSアカウントID>-apne1/index.html

↓

/usr/share/nginx/html/index.html

Mount points

コンテナ nginx に対して、以下のマウント設定を追加します。

項目 設定値
Container nginx
Source volume s3-html-volume
Container path /usr/share/nginx/html
Read only 有効

Nginx公式イメージでは、HTMLの公開ディレクトリは以下です。

/usr/share/nginx/html

ここへS3 Filesをマウントすることで、S3上の index.html がNginxのトップページになります。

CloudWatch Logsを設定する

コンテナのログ設定を行います。

項目 設定値
Log collection 有効
Log driver awslogs
Log group /ecs/nginx-task
Region ap-northeast-1
Stream prefix ecs

NginxのアクセスログやエラーログをCloudWatch Logsで確認できるようになります。

ECS Serviceを作成する

AWSマネジメントコンソールで以下を開きます。

ECS > Clusters > ecs-cluster-nginx > Services > Create

Service基本設定

項目 設定値
Compute options Capacity provider strategy
Capacity provider Managed Instances作成時に自動作成されたもの
Task definition Family nginx-task
Service name nginx-service
Desired tasks 1

Networking

項目 設定値
VPC 既存VPC
Subnets Private Subnet-A、Private Subnet-C
Security group sg-ecs-nginx-task
Public IP Disabled

今回はPrivate Subnet構成のため、Public IPは無効にします。

Load balancing

すべて先ほど作成したロードバランサ・ターゲットグループを選択します。

項目 設定値
Load balancer type Application Load Balancer
Load balancer alb-ecs-nginx-internal
Listener HTTP:80
Target group tg-ecs-nginx
Container nginx
Container port 80

ECS Serviceを作成すると、Taskが起動し、TaskのIPアドレスがTarget Groupへ自動登録されます。

動作確認する

ECS Service作成後、以下を確認します。

ECS > Clusters > ecs-cluster-nginx > Services > nginx-service

Tasksタブで、Taskの状態が以下になっていることを確認します。

RUNNING

次にTarget Groupを確認します。

EC2 > ターゲットグループ > tg-ecs-nginx > Targets

TaskのIPアドレスが登録され、状態が以下になっていれば正常です。

healthy

踏み台サーバーからALBへアクセスします。

curl http://<Internal ALBのDNS名>

以下のように表示されれば成功です。

<h1>Hello ECS</h1>

S3のHTMLを書き換えて反映確認する

S3の index.html を更新します。

<!DOCTYPE html>
<html>
<head>
  <title>ECS S3 Files Demo</title>
</head>
<body>
  <h1>Hello ECS Version2</h1>
</body>
</html>

アップロード後、数秒待ってから踏み台サーバーで再度確認します。

curl http://<Internal ALBのDNS名>

以下のように変われば成功です。

<h1>Hello ECS Version2</h1>

Dockerイメージの再作成も、ECS Serviceの更新も不要です。

タスク数を増やす

ECS Serviceを更新し、Task数を増やします。

ECS > Clusters > ecs-cluster-nginx > Services > nginx-service > Update

Desired tasksを変更します。

項目 変更前 変更後
Desired tasks 1 2

更新後、TasksタブでTaskが2つ起動していることを確認します。

RUNNING Task: 2

Target Groupでも、登録済みターゲットが2つになります。

EC2 > ターゲットグループ > tg-ecs-nginx > Targets

構成は以下のようになります。

Internal ALB
    │
    ├── nginx Task 1
    └── nginx Task 2

ALBが2つのTaskへ負荷分散します。

CloudWatch Logsを確認する

CloudWatch Logsを開きます。

CloudWatch > Logs > Log groups > /ecs/nginx-task

ログストリームを開くと、Nginxのログを確認できます。

踏み台サーバーから何度かアクセスします。

curl http://<Internal ALBのDNS名>

ログが出力されれば、CloudWatch Logs連携も正常です。

Docker Composeとの違い

Docker Composeでは、基本的に1台のサーバー上でコンテナを起動します。

Docker Compose

Server
└── nginx

ECSでは、ServiceがTask数を維持します。

Amazon ECS

Cluster
└── Service
    ├── Task 1
    └── Task 2

Taskが停止しても、Serviceが指定された数に戻そうとします。

今回であれば、Desired tasksを2にしている場合、1つのTaskが停止しても、ECSが新しいTaskを起動しようとします。

ECSを利用するメリット

ECSを利用すると、以下のようなメリットがあります。

  • コンテナ障害時の自動復旧
  • Desired tasksによる簡単なスケールアウト
  • ALBとの連携
  • CloudWatch Logsとの統合
  • IAMによる権限制御
  • S3 FilesによるHTML更新の簡素化
  • Managed Instancesによるインスタンス管理負荷の軽減

まとめ

本記事では、Amazon ECS Managed Instancesを利用して、Nginxを構築しました。

また、HTMLファイルをDockerイメージに含めず、Amazon S3に保存し、S3 FilesでNginxコンテナへマウントしました。

Amazon ECSは、簡単にコンテナ環境を構築・運用でき、スケールもできるため、従来のDocker環境に比べ本番運用に適していることがわかります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?