web-dev-qa-db-ja.com

デプロイ中にAWS ECS 503サービスが一時的に利用不可になる

アプリ用のApplication Load BalancerでAmazon Web Services EC2 Container Serviceを使用しています。新しいバージョンを展開すると、約2分間、503 Service Temporarily Unavailableになります。それは私のアプリケーションの起動時間より少し長いです。これは、今はゼロダウンタイムの展開ができないことを意味します。

起動中に新しいタスクを使用しない設定はありますか?または、ここで何が欠けていますか?

更新:

ALBのターゲットグループのヘルスチェック番号は次のとおりです。

Healthy threshold:     5
Unhealthy threshold:   2
Timeout:               5 seconds
Interval:              30 seconds
Success codes:         200 OK

健全なしきい値は「健全でないターゲットを健全と見なす前に必要な連続した健全性チェックの成功数」です
異常なしきい値は、「異常なターゲットを検討する前に必要な連続したヘルスチェックエラーの数」
Timeoutは、「応答がないときにヘルスチェックに失敗したことを意味する時間(秒単位)」です。
Intervalは「個々のターゲットのヘルスチェック間のおおよその時間」

更新2:したがって、クラスターは2つのEC2インスタンスで構成されていますが、必要に応じてスケールアップできます。必要な最小数は2です。アプリには特定のポート番号が必要なため、インスタンスごとに1つのタスクを実行します。デプロイする前に(jenkinsはaws cliスクリプトを実行します)インスタンスの数を4に設定します。これがないと、AWSは新しいタスクをデプロイできません(これは解決すべきもう1つの問題です)。ネットワークモードはブリッジです。

12
vargen_

そのため、問題はタスク定義のコンテナ設定のポートマッピングにあるようです。 80をホストとして、8080をコンテナポートとして使用する前。これらを使用する必要があると思いましたが、実際にはホストポートは任意の値にできます。 0に設定すると、ECSは32768〜61000の範囲のポートを割り当てるため、1つのインスタンスに複数のタスクを追加できます。これが機能するには、セキュリティグループを変更して、トラフィックがALBからこれらのポートのインスタンスに到達するようにする必要もありました。
したがって、ECSが同じインスタンスで複数のタスクを実行できる場合、50/200 min/max健全な割合は理にかなっており、新しいインスタンスを追加せずに新しいタスクリビジョンの展開を行うことができます。これにより、ゼロダウンタイム展開も保証されます。

質問またはコメントしてくださった皆さん、ありがとうございました!

9
vargen_

AWS ECSを使用しているので、サービスの「最小ヘルスパーセント」と「最大ヘルスパーセント」を教えてください

展開中にすべてのサービスが停止しないように、「最大ヘルスパーセント」が200、「最小ヘルスパーセント」が50であることを確認してください。

これら2つの用語のドキュメント定義を参照してください。

最大パーセントは、デプロイメント中の実行タスク数の上限を提供し、デプロイメントバッチサイズを定義できるようにします。

最小正常パーセントは、展開中の実行タスク数の下限を提供し、追加のクラスター容量を使用せずに展開できるようにします。

「最小ヘルスパーセント」が50に制限されているため、新しいバージョンのコンテナをデプロイする前にサービスコンテナの半分のみが強制終了されます。つまり、サービスの目的のタスク値がデプロイ時よりも「2」の場合古いバージョンの「1」コンテナのみが最初に強制終了され、新しいバージョンがデプロイされると、2番目の古いコンテナが強制終了され、新しいバージョンのコンテナがデプロイされます。これにより、常にリクエストを処理するサービスが存在するようになります。

同様に、「最大ヘルスパーセント」の200の制限は、展開中の特定の時点で、サービスのコンテナが目的のタスクの最大2倍までシュートできることをecs-agentに伝えます。

さらに質問がある場合はお知らせください。

3
Manish Joshi

設定では、2回のヘルスチェックに失敗して異常とマークされるまでに、アプリケーションの起動に30秒以上かかります(アプリがダウンした直後の最初のチェックを想定)。そして、少なくとも2分から最大3分かかり、再び正常とマークされます(ベストケースのシナリオでアプリがオンラインに戻った直後の最初のチェック、または最悪のケースでアプリが復帰する直前の最初のチェック)。

そのため、更新中に不健全とマークされないように、不健全なしきい値を増やすことで、迅速かつ汚い修正が行われます。また、Healthyしきい値を下げて、再びより早く健全にマークされるようにすることもできます。

しかし、本当にダウンタイムをゼロにしたい場合は、アプリの複数のインスタンスを使用して、AWSにManish Joshiが提案するようにデプロイをステージングする必要があります(ELBの背後に常に十分な正常なインスタンスがあり、サイトを運用し続けます)。

2
Seva

これを解決する方法は、ALBが正常な状態を保つために監視するアプリケーションファイルにフラットファイルを作成することでした。展開前に、スクリプトはOutOfServiceを登録するまでノードを監視しながらこのファイルを削除します。

そうすれば、すべてのライブ接続が停止し、排出されます。この時点で、ノードまたはアプリケーションプロセスを停止することにより、展開が開始されます。展開後、このフラットファイルを追加してノードをLBに追加し、このノードのInserviceを登録するまで監視してから、2番目のノードに移動して上記の同じ手順を完了します。

私のスクリプトは次のように見えます

# Remove Health Check target
echo -e "\nDisabling the ELB Health Check target and waiting for OutOfService\n"
rm -f /home/$USER/$MYAPP/server/public/alive.html

# Loop until the Instance is Out Of Service
while true
do
        RESULT=$(aws elb describe-instance-health --load-balancer-name $ELB --region $REGION --instances $AMAZONID)
        if echo $RESULT | grep -qi OutOfService ; then
                echo "Instance is Deattached"
                break
        fi
        echo -n ". "
        sleep $INTERVAL
done
2
Innocent Anigbo

あなたはJenkinsについて話していたので、Jenkins masterサービスを念頭に置いて答えますが、私の答えは他の場合でも有効です(たとえ良い例でなくても) [〜#〜] ecs [〜#〜]Jenkins masterは正しくスケーリングされないため、 1つのインスタンスのみ)。

503不正なゲートウェイ

頻繁に503ゲートウェイエラーチェックに関連するロードバランサーエラーに遭遇しました(いいえ健全なインスタンス)。ロードバランサー監視タブを見て、正常なホストの数が常に0を超えていることを確認してください。

HTTP healthcheckを実行している場合、サーバーが実際に稼働している場合にのみcode 2(有効なコードのリストはロードバランサー設定で構成可能)を返す必要がありますと実行しています。そうしないと、ロードバランサは、まだ完全に実行されていないインスタンスを自由に配置できます。

問題が常に503悪いゲートウェイを受け取ることである場合、インスタンスが応答に時間がかかりすぎるため(サービスの初期化中)である可能性があります。 so[〜#〜] ecs [〜#〜]それらがダウンしていると見なし、初期化が完了する前に閉じます。 Jenkins first runの場合がよくあります。

その最後の問題を回避するために、ロードバランサーの適応を検討することができますpingターゲットhealthcheck target for クラシックロードバランサーlistenerアプリケーションの場合ロードバランサー):

  • アプリケーションロードバランサーを使用して、常に200を返すを試してください(Jenkinsの場合、たとえば/robots.txtのような公開ファイルの場合があります)。
  • クラシックロードバランサーでは、HTTPテストではなくTCPポートテストを使用します。ポートを正しく開いていれば、常に成功します。

インスタンスごとに1つのノード

インスタンスごとにノードが1つだけであることを確認する必要がある場合は、クラシックロードバランサーを使用できます([〜#〜] ecs [ 〜#〜])。 クラシックロードバランサー[〜#〜] ecs [〜#〜]を使用すると、サーバーごとに1つのインスタンスのみが実行されます。 非HTTPポートにアクセスできる唯一のソリューションでもあります(たとえば、Jenkinsには80が必要ですが、スレーブには50000も必要です)。

ただし、従来のロードバランサーではポートが動的ではないため、次のようなポートマッピングを行う必要があります。

myloadbalancer.mydomain.com:80(ロードバランサーのポート80)-> instance:8081(コンテナーの外部ポート)-> service:80(コンテナーの内部ポート)。

そしてもちろん、サービスごとに1つのロードバランサーが必要です。

ジェンキンスヘルスチェック

それが本当にJenkinsサービスである場合は、Jenkins Metricsプラグインを使用して良いものを取得する必要があります- ヘルスチェックURL

それをインストールし、グローバルオプションでトークンを生成してpingをアクティブにすると、次のようなURLに到達できるはずです。 http://myjenkins.domain.com/metrics/mytoken12b3ad1/ping

このURLは、サーバーが完全に実行されている場合にのみHTTP code 2に応答します。これは、ロードバランサーが完全に準備が整ったときにのみアクティブにするために重要です。

ログ

最後に、インスタンスに何が起こっているのか、なぜ失敗したのかを知りたい場合は、ログを追加して、コンテナが何を言っているのかを確認できますAWS Cloudwatch

これをタスク定義に追加するだけです(コンテナ設定):

ログ設定:awslogs
awslogs-group:mycompany (コンテナログを再グループ化するCloudwatchキー)
awslogs-region:us-east-1 (クラスター領域)
awslogs-stream-prefix:myservice (ログ名を作成するためのプレフィックス)

コンテナの初期化中に何が起こっているのか、時間がかかりすぎている場合、または失敗している場合は、より多くの洞察が得られます。

それが役に立てば幸い!!!

1
arvymetal