web-dev-qa-db-ja.com

AWS ECSの再起動サービスで、同じタスク定義とダウンタイムなしのイメージ

タスク定義に変更を加えずに、AWSサービスを再起動(基本的にはサービス内のすべてのタスクを停止および開始)しようとしています。

この理由は、イメージにはすべてのビルドでlatestタグが添付されているためです。

すべてのタスクを停止してサービスで再作成してみましたが、これはtemporarily unavailableサービスがインスタンスで再起動しているときのエラー(2)。

これを処理する最良の方法は何ですか?言う、ダウンタイムがないように青緑の展開戦略?

これは私が現在持っているものです。欠点は、サービスのタスクが削除された後に再構築されているため、私のアプリが数秒間ダウンすることです。

configure_aws_cli(){
    aws --version
    aws configure set default.region us-east-1
    aws configure set default.output json
}

start_tasks() {
    start_task=$(aws ecs start-task --cluster $CLUSTER --task-definition $DEFINITION --container-instances $EC2_INSTANCE --group $SERVICE_GROUP --started-by $SERVICE_ID)
    echo "$start_task"
}

stop_running_tasks() {
    tasks=$(aws ecs list-tasks --cluster $CLUSTER --service $SERVICE | $JQ ".taskArns | . []");
    tasks=( $tasks )
    for task in "${tasks[@]}"
    do
        [[ ! -z "$task" ]] && stop_task=$(aws ecs stop-task --cluster $CLUSTER --task "$task")
    done
}

Push_ecr_image(){
    echo "Push built image to ECR"
    eval $(aws ecr get-login --region us-east-1)
    docker Push $AWS_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/repository:$TAG
}

configure_aws_cli
Push_ecr_image
stop_running_tasks
start_tasks
11
John Kariuki

使用する update-service そしてその --force-new-deployment 国旗:

aws ecs update-service --force-new-deployment --service my-service
9
Ben Whaley

少し待って。ユースケースを正しく理解していれば、これは公式の docs で対処されています。

更新されたDockerイメージが、サービスの既存のタスク定義にあるものと同じタグ(my_image:latestなど)を使用している場合、タスク定義の新しいリビジョンを作成する必要はありません。以下の手順を使用してサービスを更新し、サービスの現在の設定を保持して、[新しいデプロイメントを強制する...]を選択できます。

ダウンタイムを回避するには、2つのパラメーターを操作する必要があります:最小正常パーセントおよび最大パーセント

たとえば、サービスに4つのタスクが必要な数であり、最大パーセント値が200%である場合、スケジューラは4つの新しいタスクを開始してから4つの古いタスクを停止する場合があります(これを行うために必要なクラスターリソースが利用可能である場合)。最大パーセントのデフォルト値は200%です。

これは基本的に、タスク定義が変更されたかどうか、およびどの程度変更されたかに関係なく、古いものと新しいものの間に「重複」が存在する可能性があることを意味し、これが回復力と信頼性を実現する方法です。

UPDATE:Amazonには 導入済み ECS(EC2とFargateの両方)の外部展開コントローラーがあります。 TaskSetと呼ばれる新しいレベルの抽象化が含まれています。私はまだ試していませんが、サービスとタスク管理(両方のAPIがサポートされています)をこのように細かく制御することで、この問題と同様に問題を解決できる可能性があります。

7
yuranos87

新しいイメージをDockerリポジトリーにプッシュした後、 タスク定義の新しいリビジョンを作成 (既存のタスク定義と同じにすることができます)および サービスを更新 できます。新しいタスク定義リビジョンを使用します。これによりサービスのデプロイがトリガーされ、サービスはリポジトリから新しいイメージをプルします。

このようにして、タスク定義は同じままです(ただし、イメージのプルをトリガーするには、サービスを新しいタスク定義リビジョンに更新する必要があります)、イメージの「最新」タグを使用しますが、ECSサービスの展開を利用できます。ダウンタイムを回避する機能。

4
Eric N

タスク定義自体に変更がない場合でも、毎回タスク定義の新しいリビジョンを作成する必要があるという事実は正しくありません。

これには大まかなbashの実装が多数あります。つまり、AWSはECSサービススケジューラに、イメージの変更/更新、特に自動ビルドプロセスをリッスンさせる必要があります。

これに対する私のcrude回避策は、2つの同一のタスク定義を持ち、ビルドごとにそれらを切り替えることでした。そうすれば、冗長なリビジョンはありません。

これを行う特定のスクリプトスニペットを次に示します。

update_service() {
    echo "change task definition and update service"
    taskDefinition=$(aws ecs describe-services --cluster $CLUSTER --services $SERVICE | $JQ ".services | . [].taskDefinition")
    if [ "$taskDefinition" = "$TASK_DEF_1" ]; then
        newDefinition="$TASK_DEF_2"
    else
        newDefinition="$TASK_DEF_1"
    fi
    rollUpdate=$(aws ecs update-service --cluster $CLUSTER --service $SERVICE --task-definition $newDefinition)
}
1
John Kariuki

私のセットアップにもこの問題があります。ロードバランサーなしでECSを使用しています。私のコンテナーはポート80で実行されます。私のタスク定義には、ホストポート0とコンテナーポート80が定義されています。ポート80と443でnginxを使用し、:latestというタグの付いた新しいイメージをアップロードすると、次のエラーが表示され、サービスを次のように更新します:aws ecs update-service --force-new-deployment --service my-service

これは私が得るエラーです:

service my-service was unable to place a task because no container instance met all of its requirements. The closest matching container-instance 3d58315f-1062-416c-8997-412161ab18b5 is already using a port required by your task. For more information, see the Troubleshooting section.

ここで何が欠けているのかわかりませんか?

1
marcus

この質問は解決しましたか?多分これはあなたのために働くでしょう。

バージョンタグ、つまりv1.05latestタグを使用してECRにプッシュされた新しいリリースイメージでは、タスク定義のimageロケーターを明示的に更新して、 :v1.05のようにバージョンタグが後置されます。

:latestでは、この新しいイメージはaws ecs update-service --force-new-deployment --service my-serviceの後に新しいコンテナによってプルされませんでした。

私はこのようにタグ付けしてプッシュしていました:

docker tag ${imageId} ${ecrRepoUri}:v1.05
docker tag ${imageId} ${ecrRepoUri}:latest
docker Push ${ecrRepoUri}

...これは複数のタグをプッシュする適切な方法であるため:

docker tag ${imageId} ${ecrRepoUri}
docker Push ${ecrRepoUri}:v1.05
docker Push ${ecrRepoUri}:latest

これは、適切な例なしに 公式ドキュメント で簡単に言及されました。

0
ux.engineer

迅速かつ汚い方法:

  • タスクを実行しているEC2インスタンスにログイン
  • docker container listでコンテナを見つける
  • docker restart [container]を使用
0
yurez