MENU
category

[AWS]ECS 設計、構築、運用のポイント集

ECSをSIで扱う際に知る必要のある設計、構築、運用までの知識を体系化。
SIでECSを扱う際に必要な情報一式を集約。

目次

PJ 役割分担と本記事の前提

前提:複数の役割を兼任する場合もあるが、以下で人物定義する。

  • アプリケーション開発者
    AWS上で稼動するシステムのアプリケーションを開発する人を指す。ざっくりなくくりとしては、ソースコードを扱う人。
  • システムの管理者
    システムを監視、運用する人を指す。一般的には、AWSを所有する顧客自身になるケースが多い。
  • インフラ(AWSサービス)担当者
    AWSのサービスを構築し、アプリケーションが動作するための基盤(サーバやコンテナなど)を構築するする人を指す。本記事は、この担当者目線での記事となる。

以下の役割分担を想定し、本記事はインフラ担当者向けに整理している。

あわせて読みたい
[AWS]ECSの役割分担はどるあるべき?アプリ担当とインフラ担当の境界線 コンテナを扱う場合、アプリとインフラの担当者が兼任していれば、それほど問題にならないが、分業している場合には、それぞれの役割分担としての境界線が引きずらいと...

ECS とは?

  • コンテナを統合管理するオーケストレーター。
    • オーケストレーター:
      • 複数コンテナを統合管理することができる。(実際には、各コンテナホスト上のAgentに対して、オーケストレーターから指示を出す。)
      • コンテナの配置や、稼動タスク数の維持、コンテナ間通信の管理などを行う。

コンテナ実行環境(データプレーン)

  • コンテナ実行環境としてDockerが稼動するEC2または、サーバレスのfargateを選択することができる。(実行環境もECSの一部のようでもあるが、下図のように実行環境は、ECSとは別サービスとして説明されている文献が多い)

以下、[AWS Black Belt Online Seminar] CON201 ECS入門より。

ECSの用語について

以下、[AWS Black Belt Online Seminar] Amazon Elastic Container Service より。  

  • クラスター(cluster)
    • サービスの集合を指す。
    • サービスを稼動する実行環境を定義する。(fargate、EC2など)
  • サービス (service)
    • ELBとタスク(コンテナ)のセット。アプリケーションの機能(プロセス)を提供するために可用性や拡張性を備えたインフラ一式を指す。(ELBは必須ではない。)
    • 稼動するタスクの元になるタスク定義、タスク数、オートスケーリング有無を指定する。
  • タスク(task)
    • タスク定義に基づいて起動するコンテナ群を指す。※タスク内のコンテナは同一ホストで実行される。
  • タスク定義(task definitions)
    • コンテナのイメージURI、コンテナに割り当てるリソース、環境変数などを指定する。

補足事項

  • サービスにおけるELBの必要性について
    • 必須ではない。タスク数の維持はロードバランサの役割ではなく、ECS サービススケジューラが行う。

ECSの設計

タスク定義に含めるコンテナ数について

1つのタスクの中には、複数のコンテナを稼動することも可能だが、コンテナのスケールアウト、スケールインはタスクの単位で行われるため、複数コンテナを含めた場合にはすべてのコンテナが同時に増減する動作となり、柔軟なスケールができない。

また、タスク内のコンテナ障害時には、デフォルトで同一タスク内の残りのコンテナを停止して、新たにタスクが作成される(タスク数が維持される)動作となるため、同一タスク内に複数コンテナを格納すると、システムによっては可用性が下がる場合がある。

上記を踏まえると、タスク内には基本コンテナを1つ。または、1つのコンテナのサイドカー構成が良いと考える。ただし、同一コンテナ内であれば、コンテナ間通信が可能なため、簡易な評価目的などであれば、同一タスク定義に複数コンテナを含める方がシンプルな構成となるメリットがある。

注意事項)CodeDeployによるBlue/Greenデプロイを使用する場合の制約事項

  • Blue/Greenデプロイを使用する場合は、サービスに紐づくターゲットグループが1つである必要がある。そのため、1つのサービスに複数のポートで受信する構成は不可能。つまり、1つのタスク定義の中に複数コンテナを含めて、そのコンテナがそれぞれ異なるポートで通信を受ける必要がある場合には、Blue/Greenデプロイが不可能。(ローリングアップデートであれば、可能)
  • 以下のような構成をとり、且つBlue/Greenデプロイを使用する場合には、バックエンドからフロントエンドへの通信はインターネットを経由する方法しかない。仮にバックエンドからフロントエンドへ内部通信を行うには、フロントコンテナのサービスに対して複数のターゲットグループを割り当てる必要があるが、Blue/Greenデプロイでは、サービスに割り当てるターゲットグループが1つのみという制約があるため。

    構成例:
    「外部ALB」 -「フロントエンドコンテナのサービス」-「内部 ALB」-「バックエンドコンテナのサービス」

パラメータ前提

ECSのパラメータは多岐にわたるため、以下の前提でパラメータサンプルを記載する。

  • Fargateを使用
  • Blue/Greenデプロイ
  • サービス1つ。
  • サイドカー構成(fluentbitを利用、ビルドによるカスタマイズ含む)

クラスター設計

項目設定例決め方備考
クラスター名[$system]-[$env]-cluster任意
インフラストラクチャFargateアプリ要件
Container Insights有効サービスの監視要件

パフォーマンス監視用として取得を推奨。

タスク定義

実際のPJでは、環境変数が100個以上必要な場合もある。タスク定義全体にアプリ要件で確定する部分が多いため、アプリケーション担当が分かれている場合には、アプリケーション担当にてタスク定義を設計する仕切りを推奨。

また、タスク定義はJSONでも作成、編集が可能でありJSONの方が保守性がよい。
参考:ECSタスク定義をコンソールから作って後悔した後、コード管理するため最速でJSON登録可能にする超愚直な方法

項目設定例決め方備考
起動タイプの互換性AWS Fargateサービスの保守性要件
タスクロール[$system]-[{$env}-frontapp-task-role名称は任意。
ロールに割り当てる権限は、コンテナから他のAWSサービスにアクセスする場合に、該当のポリシーを設定する。
ネットワークモードawsvpcFARGATEの場合はawsvpc固定
オペレーティングシステム/アーキテクチャLinuxアプリ要件
タスク実行ロール[$system]-[{$env}-ecs-task-ex-roleアプリ要件(コンテナ間の通信要件)コンテナ実行に必須(ECS共通ロール想定)
タスクメモリ16GBアプリ要件
タスクCPU2vCPUアプリ要件
コンテナ[$system]-[{$env}-frontapp-cont,
log_router
コンテナ名称は任意
log_routerは、FireLensによるfluentbitのデフォルトコンテナ名。
App Mesh 統合の有効化無効アプリ要件(サービス間の通信要件)
プロキシ設定無効アプリ要件
FireLens の統合を有効にする有効ログ保管要件(アプリ要件)

ログを整形せず、全てCloudWatch Logsや、splunkに転送する。以外のケースでは有効にする。
タイプfluentbitFirelensを使用する場合に、fluentbitかfluentdを選択可能。
軽量なfluentbitを推奨。
イメージ[$system]-[{$env}-frontapp-fluentbit-repo:latest
のURI
fluentbitのカスタマイズを行う場合には、該当のURI(fluentbitのイメージを格納したECRのリポジトリ)を指定。
カスタマイズしない場合は、デフォルトでイメージのURIが入力される。
fluentbitのカスタマイズが必要なケースはこちらを参照。

コンテナ (frontapp)

項目設定例決め方備考
コンテナ名frontapp任意の名称
イメージURI[$system]-[$env]-frontapp-repo:[$タグ]
のURI
稼動するコンテナのイメージのURI 
メモリ制限(MB)アプリ要件
ポートマッピングホストポート : 8080
プロトコル : TCP
コンテナポート : 8080
アプリ要件
ヘルスチェック
コマンド
アプリごとに異なる。アプリ要件動作はこちらを参照。
環境変数アプリごとに異なる。
アプリ要件

コンテナのDockerfileで定義された環境変数に応じて設定。
コンテナタイムアウト1つのタスクに複数コンテナを使用しており、依存関係がある場合に使用を検討。
それ以外のケースでは不要。
参考:ECS で依存関係を設定したタスクのヘルスステータスがUNHEALTHYのまま終了しないときの対処方法
ネットワーク設定アプリ要件

ネットワークを無効化する場合などに設定。
ログドライバーawsfirelensログ保管要件(アプリ要件)

ログを整形せず、全てCloudWatch Logsや、splunkに転送する。以外のケースではawsfirelensを使用。
ストレージ(ソースボリューム)アプリ要件

コンテナにEFSマウントが必要な場合に指定する。
ストレージ(コンテナパス)アプリ要件

コンテナにEFSマウントが必要な場合に指定する。コンテナのマウント先。
リソースの制限(NOFILE)ソフト制限:10240,
ハード制限:10240
アプリ要件

コンテナ (log_router)

項目設定例決め方備考
コンテナ名log_router任意の名称
イメージURI[$system]-[$env]-frontapp-fluentbit-repo:[$タグ]のURI稼動するコンテナのイメージのURI

カスタマイズしない場合は、デフォルトで設定される。
メモリ制限(MB)アプリ要件
ポートマッピングログルータはポートを使用しない。
ヘルスチェックコマンドアプリごとに異なる。アプリ要件
環境変数アプリごとに異なる。アプリ要件
コンテナタイムアウト1つのタスクに複数コンテナを使用しており、依存関係がある場合に使用を検討。
それ以外のケースでは不要。
参考:ECS で依存関係を設定したタスクのヘルスステータスがUNHEALTHYのまま終了しないときの対処方法
ネットワーク設定アプリ要件

ネットワークを無効化する場合などに設定。
ログドライバーawslogsサービスの保守性要件

fluentbit自体のログの転送先。障害調査のため、取得を推奨。
ログドライバーキー
awslogs-group
/ecs/[$system-[$env]/frontapp/fluent-bit任意のロググループの名称
ログドライバーキー
awslogs-region
ap-northeast-1任意のリージョン
ログドライバーキー
awslogs-stream-prefix
firelens任意の名称
firelensConfiguration/config-file-typefileアプリ要件

fluentbitをカスタマイズする場合に、extra.confの場所を指定する場合に指定。
firelensConfiguration/config-file-value/fluent-bit/etc/extra.confアプリ要件、サービスの保守性要件

fluentbitをカスタマイズする場合に、extra.confの場所を指定する場合に指定。

サービス設計
[$system]-[$env]-frontapp-service

項目設定例決め方備考
オペレーティングシステムファミリーLinuxアプリ要件
タスク定義[$system]-[$env]-frontapp-family起動するタスク定義を指定
プラットフォームのバージョン1.4.0アプリ要件
クラスター[$system]-[$env]-clusterサービスを稼動するクラスタ
サービス名[$system]-[$env]-frontapp-service任意
サービスタイプREPLICAFARGATEの場合はREPLICA固定
タスクの数2サービスの性能要件
デプロイメントタイプBlue/Green デプロイメント(CodeDeploy を使用)サービスの可用性要件(保守性要件)
デプロイメント設定CodeDeployDefault:ECSAllAtOneceサービスの可用性要件
VPC[$system]-[$env]-vpcサービスの通信要件
サブネット[$system]-[$env]-private-subnet01a,
[$system]-[$env]-private-subnet01c
サービスの通信要件
セキュリティグループ[$system]-[$env]-frontapp_sgサービスの通信要件
パブリックIP無効アプリ要件
ヘルスチェックの猶予期間300秒アプリ要件
ロードバランサー[$system]-[$env]-frontapp-alb該当サービスにトラフィックを転送するALBを指定。
プロダクションリスナーポート443:HTTPSALBの受信ポートを指定。ALBのテスト用受信ポートであり、ECSサービス(コンテナ)の受信ポートではない。
サービスの受信ポートは、コンテナの「ポートマッピング」設定を参照。
テストリスナーポート1443:HTTPSBlue/Greenデプロイ時のALBが受けるテストポートを指定。

ALBのテスト用受信ポートであり、アプリを意識せずに指定が可能。
ターゲットグループ1[$system]-[$env]-frontapp-alb-tg01アプリ要件

コンテナで受信可能なポートに対してトラフィックを転送する。
Blue/Greenデプロイ実行の度に、サービスに紐づくターゲットグループが1と2で交互に代わる。
※1
ターゲットグループ2[$system]-[$env]-frontapp-alb-tg02アプリ要件

コンテナで受信可能なポートに対してトラフィックを転送する。
サービス検出の統合の有効化無効アプリ要件

サービス間(コンテナ間)通信の要件として必要な場合は有効化。
AutoScalingService Auto Scallingの設定を変更することで、サービスの必要数を調整するサービスの性能要件
タスクの最小数2サービスの性能要件
タスクの必要数2サービスの性能要件
タスクの最大数4サービスの性能要件
Service Auto Scalingターゲットの追跡サービスの性能要件
ポリシー名Scalling-Policy-for-CPUUtilizationサービスの性能要件
ECSサービスメトリクスECSServiceAverageCPUUtilizationサービスの性能要件
ターゲット値60サービスの性能要件
スケールインの無効化OFFサービスの性能要件

※1. Blue/Greenデプロイを行う場合のターゲットグループ入れ替わり動作

以下のような動作となり、デプロイの度に2つのターゲットグループは入れ替わる動作となる。そのため、ターゲットグループにBlue環境用や、Green環境用というような名称は使用しない方が良い。

  1. 初期状態:
    • ターゲットグループ1を使用して、サービスに対してトラフィック転送される。
    • ターゲットグループ2は使用されない。
  1. Blue/Greenデプロイ実施 1回目
    • ALBのテスト用のリスナーポートのトラフィックをGreen環境へ転送する際にターゲットグループ
    • ALBのテスト用のリスナーポートのトラフィックをGreen環境へ転送する際にターゲットグループ2が使用される。
    • トラフィックの切り替えを行うことで、本番用のリスナーポートのトラフィックがターゲットグループ2に転送されるようになる。
    • が使用される。
    • トラフィックの切り替えを行うことで、本番用のリスナーポートのトラフィックがターゲットグループ2に転送されるようになる。
  1. Blue/Grenデプロイ実施 2回目
    • ALBのテスト用のリスナーポートのトラフィックをGreen環境へ転送する際にターゲットグループ1が使用される。
    • トラフィックの切り替えを行うことで、本番用のリスナーポートのトラフィックがターゲットグループ1に転送されるようになる。

ECSの構築

※カスタマイズしたfluentbitの作成や、ECRなど関連リソースの作成が必要なため、包括的に別途公開予定。

運用

イメージのビルド運用

  • Cloud9などDockerが使用できるEC2上で都度手動によるビルド
    • ECRの機能によりイメージを(基本 or 拡張)スキャンして、スキャン結果を踏まえて、イメージの再構築、or デプロイを判断するようなケースで使用。
  • パイプライン内で自動的にビルド
    • Dockerfileを更新して、CodeCommitへのpushをトリガとして自動的にビルド、&デプロイをするようなケースで使用。


イメージのタグ運用

  • タグの変更可否(イミュータブル設定)
    • 禁止した方が、誤ったバージョンのデプロイなどの事故が防げるため推奨。禁止するとイメージが新しくなる度に、最新イメージのタグをタスク定義に反映する必要があるが、パイプラインを使用している場合には、自動的にタスク定義を作成してくれるため、あまり意識する必要もなくなる。
  • 割り当てるタグの例
    • 上記イメージのビルド運用において、手動ビルドを行う場合には、「1.0」 「1.1」のようにアプリケーションの一般的なパッケージなどで使用されるバージョンを付与するケースが多い。
    • パイプラインによるビルド自動化を行う場合、CodeCommit上のソースのハッシュ値の一部をタグに使用する場合もある。この方式のメリットは、ソースとイメージが対応付けできる点。

ECS Auto Scalingの動作について

  • ECSのタスク障害が起きた場合は、「タスクの最小数」ではなく、「タスクの必要数」まで、タスクを稼働(復旧)する。
  • スケールイン/スケールアウト時の動作
    いずれかが実行されたタイミングで、タスクの稼働数が、増減するとともに「タスクの必要数」が同数に増減する。そのため、タスクの障害が発生した場合には、直前の状態(直前のタスクの必要数)に戻る動作となる。
  • 仮にタスクの最小数を0とした場合、自動的にスケールインして、タスクが0になることはない。
  • タスクの手動停止方法
    通常タスクの必要数を0にすれば、タスクは0になるが、オートスケールが有効化されている場合には タスクの必要数を0にする直前のメトリクスによって、オートスケールする可能性がある。
    そのため、以下2ついずれかを実施すると確実に停止できる。    

    –  タスクの最大数も合わせて 0 に変更する  
    –  AWS CLI の register-scalable-target コマンドにてスケールアウトの一時停止を実行する
     <コマンド例>  “`  
    $ aws application-autoscaling register-scalable-target \  
    –service-namespace ecs \  
    –scalable-dimension “ecs:service:DesiredCount” \  
    –resource-id “service/sample-cluster/sample-service” \  
    –suspended-state DynamicScalingOutSuspended=true
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

目次