Amazon ECSで実行されているサービスのコンテナーを更新するには、どのようなアプローチが推奨されますか?
AWSドキュメント は次のように述べています。「アプリケーションのDockerイメージを更新した場合、そのイメージを使用して新しいタスク定義を作成し、一度に1つのタスクでサービスにデプロイできます。」これは、現在(2015年4月13日)のドキュメントで現在利用できるもののほとんどすべてです。
Amazon ECSでアプリケーションコンテナーを更新する唯一の方法は、新しいタスクを作成してから、古いタスクを停止して新しいタスクを開始することであることを正しく理解しましたか?
Core OSとFleetctlで「最新」のタグを正常に使用しています。サービスをリロードすると新しい変更が表示され、コンテナーが更新されるため(同じタグ「最新」を使用)、新しい更新のためにDockerイメージのタグを変更する必要がないという利点があります。
Amazon ECSで更新されたDockerイメージを使用してサービスを更新するために使用したアプローチの種類は何ですか?
これが放棄された質問と見なされるかどうかわからない-私の問題をトラブルシューティングし、解決した今私の解決策を追加しているときにこれに偶然遭遇しました。
新しいコンテナでサービスを更新するには、以下を行う必要があります。
サービスタスクが最新バージョンに更新されていない場合は、[イベント]タブでエラーを確認してください。たとえば、ECSが新しいバージョンのサービスを開始できなかった可能性があります。クラスターにはec2インスタンスが1つしかなく、アプリケーションポートはホストですでに使用されています。この場合、「最小ヘルス/最大ヘルス」の制限を「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
アプリケーションを更新するには、タスク定義を更新してから、サービスを更新します。 http://docs.aws.Amazon.com/AmazonECS/latest/developerguide/update-service.html を参照してください
私はこれが古いスレッドであることを知っていますが、解決策は、ここでのほとんどの答えがそうであるようにするよりもはるかに簡単です。
以下では、latest
というタグの付いたコンテナー(またはコンテナーの更新全体で変化しない他の静的タグ)を参照するタスクを実行しているサービスがあることを前提としています。
目標が私たちが新しいビルドを公開することである場合、そのためにサービスに依存する必要は本当にありません(そして、私はすべきではありませんそれに依存します)。タスクを強制終了すると、サービスはタスクのDesired Count
が実行されていないことを認識し、新しいタスクを起動します。これにより、同じタグに基づいて、コンテナーの再プルがトリガーされます。
ECSサービスはHAセキュリティネットですnot CD/CIパイプラインの代わりです。
ボーナス:新しいコンテナがプッシュされたことをサービスに認識させることを目的とする場合(タグに関係なく)、その影響を考慮する必要があります。展開パイプラインを制御する基本的なサービスが本当に必要ですか?おそらくそうではない。理想的には、(リリースバージョンなどに基づいて)異なるタグでコンテナーをプッシュします。この場合、展開の障壁は、サービスに新しい何かを通知する必要があることです。これも、サービスのセーフティネットであり、それ以上のものではありません。
container:tag
をリポジトリにアップロードしますtag
を参照する新しいタスク定義を作成しますminimum healthy
を0%
に設定している場合、新しいタスク定義をデプロイするためにAWSにサービス全体を強制終了する完全な権限を与えています。段階的/段階的な展開を希望する場合は、最小値を>0%
に設定します。minimum healthy
を100%
に設定し、maximum healthy
を何か>100%
に設定して、サービスがnew古いタスクを削除する前のタスク(ユーザーへの影響を最小限に抑える)。この時点から、サービスは新しいタスクを指定したことを自動的に認識し、設定したminimum
/maximum
健全なしきい値に基づいてそれを展開します。
私は ecs-deploy script の一部を使用して改善を加えています(すべてのコンテナーの説明からイメージを取得し、そのタグ部分を$ 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"
新しいDockerイメージをアップロードした後、タスクで使用されているものと同じタグが付いていても、最新のタスクをコピーし、その新しいタスクを使用するようにサービスを構成する必要があります。必要に応じて、2つの重複するタスクを実行し、Dockerイメージが更新されるたびにサービスを切り替えるようにサービスを構成することもできます。
基本的に、新しいDockerコンテナーをECSで作成するには、サービスの更新でトリガーする必要があり、サービストリガーを作成する唯一の方法は、なんらかの方法で更新することです。たとえば、別のタスク番号。
サービスが更新されたからといって、実行中の既存のコンテナが自動停止しない場合があることに注意してください。タスクリストを確認して手動で停止する必要がある場合があります。
私のために働くアプローチは上記に似ています。サービスとタスクを作成し、すべてを開始したら、Auto-Scaling Groupを編集して、min、maxおよびdesiredは1に設定されます。
グループはデフォルトのグループである可能性があります。わからない場合は、クラスターのECS Instancesタブを選択して、ActionsドロップダウンでCluster Resourcesを選択し、開いたダイアログボックスの下部近くにあるリンクをクリックします。
それがすべて整ったら、更新されたコンテナーイメージをデプロイしたいときはいつでも、クラスターのTaskエリアに移動し、Stoptask。警告が表示されますが、自動スケーリングが設定されている場合、サービスは最新のプッシュで再開を開始します。
サービスまたはタスクのいずれかの新しいバージョンを作成する必要はありません。
サービス/タスクは、瞬時から数分以内のどこかに自分自身を更新することに注意してください。あなたが必死に待っている場合は、手動で新しいタスクを実行することができます。サービスはそれを所有しないため、理想的ではありませんが、サービスが停止した場合でも新しいサービスを起動します。
--force-new-deployment
api呼び出しでecs update-service
オプションを使用できます。サービス自体を更新する必要はありません。 docs から:
サービスの新規デプロイメントを強制するかどうか。デフォルトではデプロイメントは強制されません。このオプションを使用して、サービス定義を変更せずに新しいデプロイメントをトリガーできます。たとえば、サービスのタスクを更新して、同じイメージ/タグの組み合わせ(my_image:latest)で新しいDockerイメージを使用するか、Fargateタスクを新しいプラットフォームバージョンにロールすることができます。
これは、aws-cliの場合と同じくらい簡単です。
aws ecs update-service --cluster my-cluster --service my-service --force-new-deployment