Amazon ECSのサービスのコンテナーを更新する


32

Amazon ECSで実行されているサービスのコンテナーを更新するには、どのようなアプローチが推奨されますか?

AWSのドキュメントは言う:「あなたはあなたのアプリケーションのドッカーイメージを更新した場合、あなたはそのイメージに新しいタスクの定義を作成し、あなたのサービス、一度に一つのタスクにそれを展開することができます。」これは、現在ドキュメント(2015年4月13日)で現在利用可能なほとんどすべてです。

Amazon ECSでアプリケーションコンテナを更新する唯一の方法は、新しいタスクを作成してから、古いタスクを停止して新しいタスクを開始することだと正しく理解しましたか?

Core OSおよびFleetctlで「latest」タグを使用しています。これには、サービスをリロードすると新しい変更が表示され、同じタグ「最新」を使用してコンテナが更新されるため、Dockerイメージのタグを新しい更新のために変更する必要がないという利点があります。

Amazon ECSの更新されたdockerイメージでサービスを更新するためにどのようなアプローチを使用しましたか?


また、実稼働環境で継続的に実行する必要のあるさまざまなデーモンを展開するためにECSを使用したいと考えているため、これも理解しようとしています。
parent5446

1
確認のために、ecsサービスを再起動すると最新バージョンのイメージがプルダウンされるとおっしゃいましたか?私はこれに関するドキュメントを探していましたが、どこにも見つかりません。
mmilleruva

1
これに関する確認はありますか?
リアーオハナ

@LiorOhana悲しいことにそれは本当です。詳細については私の答えをご覧ください。
hamx0r

以下に新しい詳細な回答を掲載しましたが、ここで明確にするために、サービスは常に、設定したタグに基づいて、リポジトリからコンテナの新しいコピーを取得しようとします。タスクが殺されている場合は、サービスが再びそれを展開するとき、それは何のない思い出がありませんでしたレポでは、唯一の何があるレポで。
-MrDuk

回答:


18

これが放棄された質問と見なされるかどうかわからない-問題のトラブルシューティング中につまずき、解決された今すぐソリューションを追加します。

新しいコンテナでサービスを更新するには、次のことが必要です。

  1. 新しいコンテナをリポジトリにアップロードします。
  2. トリガータスク定義の更新。
  3. コンテナの更新をトリガーします。
  4. 重要:サービスルールがタスクの新しいバージョンの起動を許可していることを確認してください。

サービスタスクが最新バージョンに更新されていない場合は、[イベント]タブでエラーを確認してください。たとえば、ECSがサービスの新しいバージョンを開始できなかった可能性があります。クラスターには1つのec2インスタンスしかなく、アプリケーションポートはホストで既に使用されています。この場合、「最小ヘルス/最大ヘルス」制限を「0%、100%」に設定します-このように、ECSは新しいコンテナーを展開する前に古いコンテナーを強制終了します。これも数分で発生します。すぐにフィードバックが表示されない場合は急いでください。

以下は、事前に構成されたクラスターおよびサービス内のコンテナーを更新するデプロイメントスクリプトの例です。「ファミリの最新バージョンを使用する」という意味であれば、バージョンを指定する必要はありません。

awsRegion=us-east-1
containerName=..
containerRepository=..
taskDefinitionFile=...
taskDefinitionName=...
serviceName=...


echo 'build docker image...'
docker build -t $containerName .

echo 'upload docker image...'
docker tag $containerName:latest $containerRepository:$containerName
docker push $containerRepository:$containerName

echo 'update task definition...'
aws ecs register-task-definition --cli-input-json file://$taskDefinitionFile --region $awsRegion > /dev/null

echo 'update our service with that last task..'
aws ecs update-service --service $serviceName --task-definition $taskDefinitionName --region $awsRegion  > /dev/null

2
これにより、タスク定義をファイルとしてローカルに配置する必要があります。正しく理解できれば、それが環境変数を定義できる唯一の場所です。環境変数をローカルに持たずにこれを行う方法はありますか?理想的には、タスク/サービス/コンテナ/その他に関する他の情報を送信せずに、新しいドッカーイメージタグを指すコマンドを発行したいと思います。
rmac

1
コメントset "min health/max health" limits to "0%, 100%"は黄金色です。どうもありがとうございます!
-sivabudh

1
ここで注意することは、をに設定するmin0%、サービスがデプロイするタスク定義を変更するときに、そのデプロイメントのすべてのタスクを同時に停止する完全な権限を本質的に付与することになります。
MrDuk


1

ecs-deployスクリプトの一部を改善して使用しています(すべてのコンテナーの説明から画像を取得し、そのタグ部分を$ TAG_PUREに置き換えます):https ://gist.github.com/Forever-Young/e939d9cc41bc7a105cdcf8cd7ab9d714

# based on ecs-deploy script
TASK_DEFINITION_NAME=$(aws ecs describe-services --services $SERVICE --cluster $CLUSTER | jq -r .services[0].taskDefinition)
TASK_DEFINITION=$(aws ecs describe-task-definition --task-def "$TASK_DEFINITION_NAME" | jq '.taskDefinition')
NEW_CONTAINER_DEFINITIONS=$(echo "$TASK_DEFINITION" | jq --arg NEW_TAG $TAG_PURE 'def replace_tag: if . | test("[a-zA-Z0-9.]+/[a-zA-Z0-9]+:[a-zA-Z0-9]+") then sub("(?<s>[a-zA-Z0-9.]+/[a-zA-Z0-9]+:)[a-zA-Z0-9]+"; "\(.s)" + $NEW_TAG) else . end ; .containerDefinitions | [.[] | .+{image: .image | replace_tag}]')
TASK_DEFINITION=$(echo "$TASK_DEFINITION" | jq ".+{containerDefinitions: $NEW_CONTAINER_DEFINITIONS}")
# Default JQ filter for new task definition
NEW_DEF_JQ_FILTER="family: .family, volumes: .volumes, containerDefinitions: .containerDefinitions"
# Some options in task definition should only be included in new definition if present in
# current definition. If found in current definition, append to JQ filter.
CONDITIONAL_OPTIONS=(networkMode taskRoleArn)
for i in "${CONDITIONAL_OPTIONS[@]}"; do
  re=".*${i}.*"
  if [[ "$TASK_DEFINITION" =~ $re ]]; then
    NEW_DEF_JQ_FILTER="${NEW_DEF_JQ_FILTER}, ${i}: .${i}"
  fi
done

# Build new DEF with jq filter
NEW_DEF=$(echo $TASK_DEFINITION | jq "{${NEW_DEF_JQ_FILTER}}")
NEW_TASKDEF=`aws ecs register-task-definition --cli-input-json "$NEW_DEF" | jq -r .taskDefinition.taskDefinitionArn`

echo "New task definition registered, $NEW_TASKDEF"

aws ecs update-service --cluster $CLUSTER --service $SERVICE --task-definition "$NEW_TASKDEF" > /dev/null

echo "Service updated"

答えのリンクから有用な情報を提供し、リンク腐敗を提供することをお勧めします。お願いできますか?
-BE77Y

1
回答を更新しました
-ForeverYoung

1

新しいDockerイメージをアップロードした後、タスクで使用されるタグと同じタグが付いていても、最新のタスクをコピーし、その新しいタスクを使用するようにサービスを構成する必要があります。必要に応じて、2つの重複タスクを単純に作成し、Dockerイメージが更新されるたびにそれらの間でスワップするようにサービスを構成できます。

基本的に、新しいDockerコンテナーをECSで作成するには、サービスの更新でトリガーする必要があります。サービストリガーを作成する唯一の方法は、何らかの方法で更新することです。異なるタスク番号。

サービスが更新されたからといって、実行中の既存のコンテナが自動停止しない場合があります。タスクリストを見て、手動で停止する必要がある場合があります。


これは実際には正しくありません。サービスに依存する代わりに、いつでも手動でタスクを強制終了できます。サービスは、それが殺されたことを検出すると、それを再び立ち上げようとし、同じものの再プルを強制しますtag
MrDuk

1

私にとって有効なアプローチは、上記と同様です。サービスとタスクを作成し、すべてを開始した後、Auto-Scaling Groupを編集して、minmax、およびdesired1に設定されていることを確認します。

グループはデフォルトのグループである場合があります。不明な場合は、クラスターの[ ECSインスタンス ]タブを選択してアクセスできます。次に、[ アクション]ドロップダウンから[ クラスターリソース ]を選択し、表示されるダイアログボックスの下部近くにあるリンクをクリックします。

それがすべて整ったら、更新されたコンテナイメージをデプロイしたいときいつでも、クラスターのタスクエリアに行き、タスク停止します。警告が表示されますが、自動スケーリングが設定されていれば、サービスは最新のプッシュで再開します。

サービスまたはタスクの新しいバージョンを作成する必要はありません。

サービス/タスクは、瞬時から数分程度でどこでも更新されることに注意してください。必死に待っている場合は、新しいタスクを手動で実行するだけで済みます。サービスはそれを所有しないので、理想的ではありませんが、死んだ場合でも新しいものを起動します。


1

私はこれが古いスレッドであることを知っていますが、解決策はここでの答えのほとんどがそうであるよりもはるかに簡単です。

2つのステップで実行中のコンテナーを更新する方法:

以下は、タグ付けされたコンテナlatest(またはコンテナの更新後も変更されないその他の静的タグ)を参照しているタスクを実行するサービスがあることを前提としています。

  1. 新しいコンテナをリポジトリにアップロードします
  2. タスクを手動で強制終了する

目標が新しいビルドを世に出すことである場合、そのためにサービスに実際に依存する必要はありません(そして、私はそれに依存するべきではないと主張します)。タスクを強制終了すると、サービスはDesired Count実行中のタスクがないことを認識し、単に新しいタスクを起動します。これにより、同じタグに基づいて、コンテナの再プルがトリガーされます。

ECSサービスはHAセキュリティネットであり、CD / CIパイプラインに代わるものではありません


ボーナス:目標が(タグに関係なく)新しいコンテナーがプッシュされたことをサービスに認識させることである場合、その意味を考慮する必要があります。展開パイプラインを制御する基本的なサービスが本当に必要ですか?そうではない。理想的には、(リリースバージョンなどに基づいて)異なるタグでコンテナをプッシュします。この場合、展開の障壁は、サービスに何か新しいことを通知する必要があることです。これも、サービスのセーフティネットであり、それ以上のことはありません。


3つの手順で新しいタグを展開する方法:

  1. container:tagリポジトリに新しいものをアップロードします
  2. 新しいを参照する新しいタスク定義を作成する tag
  3. サービスを更新して、新しいタスク定義を参照します
    • ここで注意してください!他のいくつかの回答が示唆するようにminimum healthy設定し0%ている場合、新しいタスク定義をデプロイするために、AWSにサービス全体を強制終了する完全な権限を付与しています。ローリング/段階的展開を希望する場合は、最小値を何かに設定します>0%
    • または、minimum healthyto 100%とyour maximum healthyを設定して、古いタスクを終了する前に>100%サービスが新しいタスクを展開できるようにします(ユーザーへの影響を最小限に抑えます)。

この時点から、サービスは新しいタスクを指定したことを自動的に認識し、構成したminimum/ maximum正常なしきい値に基づいてそのタスクの展開に取り組みます。


素敵な、ありがとう、他の回答よりも良い
Olegzandr Denman
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.