ablog

不器用で落着きのない技術者のメモ

ECS で EC2 と Fargate の起動タイプのタスクを併用して同じアプリケーションを実行する

ECS で EC2 と Fargate の起動タイプのタスクを併用して同じアプリケーションを実行してみた。ワークロードがない場合は、EC2 の1タスクだけ実行され(Fargate のタスクは 0)、EC2 のCPU使用率が50%を超えると EC2 に1タスク追加され、EC2 のCPU使用率が80% を超えると Fargate のタスクが追加されていくというのを試してみた。


EC2インスタンスから ab で負荷をかけて、

ECS の EC2 インスタンスにログインして htop でワークロードを確認するとこんな感じ。

CloudWatch のダッシュボードを見るとこんな感じで、CPU使用率が上がり、

ECS の EC2 は +1、Fargate は +1 タスクがスケールアウトしている。

手順は以下の通り。

準備

キーペア作成
  • ECSを利用するリージョンでキーペアを作成していない場合は作成しておく。
セキュリティグループ作成
  • セキュリティグループ名: ECS-SG
  • VPC: デフォルトVPC
タイプ プロトコル ポート範囲 ソース
HTTP TCP 80 マイIP
SSH TCP 22 マイIP
すべてのTCP TCP すべて 自分自身のセキュリティグループID

ELB

ELB作成
  • 種類: Application Load Balancer
  • 名前: ec2-fg-mix-alb
  • プロトコル: HTTP
  • ポート: 80
  • アベイラビリティーゾーン
    • VPC: デフォルト
    • ap-northeast-1a, ap-northeast-1c, ap-northeast-1d
  • セキュリティグループ: ECS-SG
  • ターゲットグループ:新しいターゲットグループ
    • 名前: ec2-fg-mix-tg

ECS

ECSタスク定義(EC2タイプ)作成
  • 起動タイプ: EC2
  • タスク定義名: ec2-task
  • ネットワークモード: awsvpc
  • タスクメモリ (MiB): 4096
  • タスク CPU (単位): 2048
  • コンテナの定義
    • コンテナ名: ec2-container
    • イメージ: httpd
    • メモリ制限: ソフト制限 128MB
    • ポートマッピング: 80
    • CPUユニット数: 2048
ECSタスク定義(Fargateタイプ)作成
  • 起動タイプ: FARGATE
  • タスク定義名: fg-task
  • ネットワークモード: awsvpc
  • タスクメモリ (GB): 4GB
  • タスク CPU (vCPU): 2 VCPU
  • コンテナの定義
    • コンテナ名: fg-container
    • イメージ: httpd
    • メモリ制限: ソフト制限 128MB
    • ポートマッピング: 80
    • CPUユニット数: 2048
クラスター作成
サービス(EC2起動タイプ)作成
  • 起動タイプ: EC2
  • タスク定義: ec2-task
  • クラスター: ec2-fg-mix-cluster
  • サービス名: ec2-service
  • タスクの数: 1
  • ELBタイプ: Application Load Balancer
  • ELB名: ec2-fg-mix-alb
  • パスパターン: /
  • 評価順:1
  • ヘルスチェックパス: /
  • Service Auto Scaling: Service Auto Scaling の設定を変更することで、サービスの必要数を調整する
  • タスクの最小数: 1
  • タスクの最大数: 2
  • 自動タスクスケーリングポリシー
    • ポリシー名: EC2ScaleOutPolicy
      • 既存のアラームの使用: EC2ScaleOutAlarm
      • スケーリングアクション: 追加 1 tasks、次の条件の場合 50 <= CPUUtilization
      • クールダウン期間: 30
    • ポリシー名: EC2ScaleInPolicy
      • 既存のアラームの使用: EC2ScaleInAlarm
      • スケーリングアクション: 削除 1 tasks、次の条件の場合 40 <= CPUUtilization
      • クールダウン期間: 30
サービス(FARGATE起動タイプ)作成
  • 起動タイプ: FARGATE
  • タスク定義: fargate-task
  • クラスター: ec2-fg-mix-cluster
  • サービス名: fg-service
  • タスクの数: 1
  • クラスタVPC: デフォルトVPC
  • サブネット: ap-northeast-1a のサブネット
  • パブリック IP の自動割り当て: ENABLED
  • セキュリティグループ: ECS-SG
  • ELBタイプ: Application Load Balancer
  • ELB名: ec2-fg-mix-alb
  • パスパターン: /
  • 評価順:1
  • ヘルスチェックパス: /
  • Service Auto Scaling: Service Auto Scaling の設定を変更することで、サービスの必要数を調整する
  • タスクの最小数: 1
  • タスクの最大数: 10
  • 自動タスクスケーリングポリシー
    • ポリシー名: FgScaleOutPolicy
      • 既存のアラームの使用: FgScaleOutAlarm
      • スケーリングアクション: 追加 1 tasks、次の条件の場合 80 <= CPUUtilization
      • クールダウン期間: 30
    • ポリシー名: Fg2ScaleInPolicy
      • 既存のアラームの使用: FgScaleInAlarm
      • スケーリングアクション: 削除 1 tasks、次の条件の場合 70 <= CPUUtilization
      • クールダウン期間: 30

CloudWatch Alarm

EC2起動タイプのスケールアウト用
  • 名前: EC2ScaleOutAlarm
  • CPUUtilization: >= 50
  • 期間: 1 / 1 データポイント
  • アクション
    • アラームが次の時: 警告
    • リソースタイプから: EC2 Container Service
    • 次から: service/ec2-fg-mix-cluster/ec2-service
    • 次のアクションを実行: EC2ScaleOutPolicy
EC2起動タイプのスケールイン用
  • 名前: EC2ScaleInAlarm
  • CPUUtilization: <= 40
  • 期間: 1 / 1 データポイント
  • アクション
    • アラームが次の時: 警告
    • リソースタイプから: EC2 Container Service
    • 次から: service/ec2-fg-mix-cluster/ec2-service
    • 次のアクションを実行: EC2ScaleInPolicy
Fargate起動タイプのスケールアウト用
  • 名前: FgScaleOutAlarm
  • CPUUtilization: >= 80
  • 期間: 1 / 1 データポイント
  • アクション
    • アラームが次の時: 警告
    • リソースタイプから: EC2 Container Service
    • 次から: service/ec2-fg-mix-cluster/fg-service
    • 次のアクションを実行: FgScaleOutPolicy
Fargate起動タイプのスケールイン用
  • 名前: FgScaleInAlarm
  • CPUUtilization: <= 70
  • 期間: 1 / 1 データポイント
  • アクション
    • アラームが次の時: 警告
    • リソースタイプから: EC2 Container Service
    • 次から: service/ec2-fg-mix-cluster/fg-service
    • 次のアクションを実行: FgScaleInPolicy

負荷をかけてスケールアウト/インを試す

  • ECSのEC2ホストに
$ sudo yum -y install htop 
$ sudo yum -y install httpd
  • 負荷をかける
$ ab -k -n 900000000 -c 100 http://*****.ap-northeast-1.elb.amazonaws.com/ &
$ ab -k -n 900000000 -c 100 http://*****.ap-northeast-1.elb.amazonaws.com/ &
$ ab -k -n 900000000 -c 100 http://*****.ap-northeast-1.elb.amazonaws.com/ &
$ ab -k -n 900000000 -c 100 http://*****.ap-northeast-1.elb.amazonaws.com/ &
$ ab -k -n 900000000 -c 100 http://*****.ap-northeast-1.elb.amazonaws.com/ &
$ ab -k -n 900000000 -c 100 http://*****.ap-northeast-1.elb.amazonaws.com/ &

補足

  • ECSのサービスを作成時にスケールアウト/インポリシーを仮で作成後に、CloudWatch Alarm でスケールアウト/インのアラームを作成し、ECSのサービスを更新して作成した CloudWatch Alarm と紐付ける。
  • 同じサービス名で削除して作り直すとマネジメントコンソールでは消えていても、バックグラウンドで削除完了していないと "Unable to Start a service that is still Draining." というエラーになる模様。しばらくして作り直すと成功した。
  • 同一クラスターにEC2とFARGATEのタスクを共存させる場合に以下のネットワークモードの組合せは可能なことを確認済。
    • FARGATE:awsvpc、EC2:awsvpc
    • FARGATE:awsvpc、EC2:bridge
  • 起動タイプがEC2でネットワークモードを awsvpc にした場合、1タスクで1つのENIを使うので、EC2インスタンスの ENI の最大数を超えるタスクを起動することはできない。ENIの最大数を超えるタスクを起動しようとすると RESOURCE:ENI エラーが発生する。

RESOURCE:* (container instance ID)
タスクによってリクエストされたリソースは、指定したコンテナインスタンスで使用できません。リソースが CPU、メモリ、ポート、または Ellastic Network Interface の場合は、コンテナインスタンスクラスターへの追加が必要になる場合があります。RESOURCE:ENI エラーの場合、awsvpc ネットワークモードを使用するタスクで必要な Elastic Network Interface アタッチメントポイントが、クラスターで利用できないことを示しています。Amazon EC2 インスタンスにアタッチできるネットワークインターフェイスの数には制限があり、プライマリネットワークインターフェイスも 1 つ分としてカウントされます。各インスタンスタイプでサポートされる Network Interface の数の詳細については、Linux インスタンスAmazon EC2 ユーザーガイドの「各インスタンスタイプのネットワークインターフェイスごとの IP アドレス」を参照してください。

API failures エラーメッセージ - Amazon Elastic Container Service
  • ab コマンドは -k オプションをつけて keep alive にしたほうがTCP接続のオーバーヘッドが小さくサーバーサイド(ECS)の CPU 使用率を上げやすい。