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

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

AWSのドキュメントには、「アプリケーションのDockerイメージを使用して、そのイメージを使用して新しいタスク定義を作成し、それをサービスに一度に1つのタスクでデプロイできます。」これは、現在(2015年4月13日)現在ドキュメントで利用可能なほとんどすべてです。

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

I have been successfully using a tag "latest" with Core OS & Fleetctl. This has the benefit of not needing to change the Docker image's tag for new updates, since reloading the service will see new changes and update the container (using the same tag "latest").

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

30
@LiorOhana残念ながらそれは本当です。詳細は私の答えを見てください。
追加された 著者 hamx0r,
本番環境で継続的に実行する必要があるさまざまなデーモンをデプロイするためにECSを使用することを望んでいるので、これも理解しようとしています。
追加された 著者 AsianHornet,
下記の@ foreveryoungの回答から、解決策は github.com/silinternational/ecs-deploy にあります。そのレポを見て、あなたはこれまでにここに投稿されたものよりも堅牢なソリューションを見るでしょう。 latest を使用すると問題が発生します。ただし、 latest を使用する必要がある場合は、リポジトリから強制的に取得するために aws ecs update-service --force-new-deployment を実行するだけで済みます。 docs.aws.amazon.com/cli/latest/reference/ecs /…
追加された 著者 Mike D,
確認のため、ecsサービスを再起動すると最新バージョンのイメージがプルダウンされるとおっしゃいましたかこれに関するドキュメントを探していましたが、どこにも見つかりません。
追加された 著者 Kazi Abdullah Al Mamun,
これについて何か確認?
追加された 著者 komedit1,
私は以下に新しい詳細な回答を投稿しましたが、ここではっきりさせるために:あなたのサービスはあなたが設定したタグに基づいて、常にあなたのコンテナの新しいコピーをリポジトリから引き出そうとします。タスクが強制終了された場合、サービスがそのタスクを再度デプロイすると、リポジトリ内の の内容は記憶されず、リポジトリ内ののみとなります。
追加された 著者 MrDuk,

6 答え

これが放棄された質問と見なされるかどうかわからない - 私の問題をトラブルシューティングし、解決したので今私の解決策を追加している間にこれにつまずいた。

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

  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
15
追加された
これにより、タスク定義をファイルとしてローカルに持つことが強制されます。正しく理解していれば、それが環境変数を定義できる唯一の場所です。環境変数をローカルに持たずにこれを行う方法はありますか?理想的には、task/service/container/etcに関する他の情報を送信せずに、新しいdocker imageタグを指すコマンドを発行したいです。
追加された 著者 Prateesh,
set "min health/max health"を "0%、100%"に制限することに対するコメントは金色です。どうもありがとうございます!
追加された 著者 tor,
ここで注意してください。 min0%に設定した場合、サービスが展開するタスク定義を変更すると、基本的には min を停止する完全な権限が与えられます。その展開のためのすべてのタスク。
追加された 著者 MrDuk,

To update your application, update the task definition and then update the service. See http://docs.aws.amazon.com/AmazonECS/latest/developerguide/update-service.html

8
追加された

新しいDockerイメージをアップロードした後、タスクで使用されているものと同じタグがある場合でも、最新のタスクをコピーしてから、その新しいタスクを使用するようにサービスを構成する必要があります。必要に応じて、Docker Imageが更新されるたびに、2つの重複したタスクを持ち、それらの間で交換するようにサービスを設定することもできます。

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

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

1
追加された
これは実際には真実ではありません - あなたがそれをするのをあなたのサービスに頼る代わりにいつでも手動でタスクを殺すことができます。それが殺されたことをサービスが検出すると、それは再びそれを起こすことを試み、同じ tag の再プルを強制します
追加された 著者 MrDuk,

I use some part from ecs-deploy script with my improvements (it takes images from every container description, and replaces its tag part with $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("(?[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"
1
追加された
link-rotを提供するために、あなたの答えの中のリンクから有用な情報を提供することをお勧めします。できますか?
追加された 著者 m6tt,
私の答えを更新しました
追加された 著者 OlivierR,

私のために働くアプローチは上記と似ています。サービスとタスクを作成し、すべての作業を開始したら、 Auto-Scalingグループを編集し、 minmaxが必要/em>が 1 に設定されている。

このグループがデフォルトのグループになることがあります。よくわからない場合は、クラスタの[ ECSインスタンス]タブを選択し、[アクション]ドロップダウンから[クラスタリソース]を選択してアクセスできます。ダイアログボックスの一番下近くにあるリンクをクリックして開きます。

すべて完了したら、更新したコンテナイメージをいつでもデプロイしたい場合は、タスクエリアに移動し、停止タスクします。警告が出ますが、オートスケーリングが設定されていれば、サービスは最新のプッシュでそれを再開します。

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

サービス/タスクは、瞬時から1分程度の間でどこでも更新されます。あなたが必死に待っているなら、あなたはただ手動で新しいタスクを実行することができます。サービスはそれを所有しないでしょう、それでそれは理想的ではありません、しかしそれが死んだらそれはまだ新しいものをスピンアップするでしょう。

1
追加された

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

実行中のコンテナを2段階で更新する方法

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

  1. Upload your new container to the repository
  2. Manually kill your tasks

私たちが目的を達成して新たな構築を実現するのであれば、そのために私たちのサービスに頼る必要はありません(そして私は主張します、 )あなたがあなたのタスクを殺した場合、サービスはそれが実行中のタスクの Desired Count を持っていないことを認識し、単に新しいものをスピンアップします。これは、同じタグに基づいてコンテナの再プルを引き起こすでしょう。

ECSサービスはHAセキュリティネットで、 not CD/CIパイプラインの代替品です。


Bonus: If the goal is to have a service recognize a new container has been pushed (regardless of tags), we need to consider the implications of that. Do we really want a basic service controlling our deployment pipeline for us? Likely not. Ideally, you'll push your containers with different tags (based on release versions or something). In this case, the barrier to deployment is that the service has to be notified of something new -- again, it's a safety net for the service, and nothing more.


3つのステップで新しいタグを配置する方法:

  1. Upload your new container:tag to the repository
  2. Create a new task definition referencing the new tag
  3. Update your service to reference the new task definition
    • Careful here! If you have minimum healthy set to 0% as some other answers suggest, you're giving AWS full authority to kill your entire service in order to deploy the new task definition. If you prefer a rolling/gradual deployment, set your minimum to something >0%.
    • Alternatively, set your minimum healthy to 100% and your maximum healthy to something >100% to allow your service to deploy the new tasks before killing off the old ones (minimizing the impact to your users).

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

0
追加された