Atualize o contêiner de um serviço no Amazon ECS

30

Que tipo de abordagem é recomendada para atualizar o contêiner de um serviço em execução no Amazon ECS?

A documentação da AWS diz: "Se você atualizou a imagem do Docker do seu aplicativo, você pode criar uma nova definição de tarefa com essa imagem e implantá-la em seu serviço, uma tarefa por vez. " Isso é praticamente tudo que está atualmente disponível na documentação atualmente (13 de abril de 2015).

Eu entendi corretamente que a única maneira de atualizar meu contêiner de aplicativos no Amazon ECS é criar uma nova tarefa, interromper a tarefa antiga e iniciar a nova tarefa?

Eu tenho usado com sucesso uma tag "latest" com o Core OS & Fleetctl. Isso tem a vantagem de não precisar alterar a tag da imagem do Docker para novas atualizações, pois o recarregamento do serviço verá novas alterações e atualizará o contêiner (usando a mesma tag "latest").

Que tipo de abordagens você usou para atualizar seu serviço com a imagem do docker atualizada no Amazon ECS?

    
por Petrus Repo 13.04.2015 / 15:33

6 respostas

17

Não tenho certeza se isso é considerado uma questão abandonada - deparei com isso enquanto resolvia meu problema e agora adicionava minha solução agora que ela foi resolvida.

Para atualizar o serviço com um novo contêiner, você precisa:

  1. carregar novo contêiner no repositório;
  2. atualização da definição de tarefa do acionador;
  3. atualização do contêiner de acionamento;
  4. importante: verifique se as regras de serviço permitem o lançamento de uma nova versão da tarefa.

Se a tarefa de serviço não for atualizada para a versão mais recente, verifique a guia "events" para erros. Por exemplo, talvez o ECS não tenha conseguido iniciar uma nova versão de seu serviço: você tem apenas uma instância ec2 no cluster e a porta do aplicativo já está sendo usada no host. Neste caso, defina os limites "min health / max health" para "0%, 100%" - dessa forma, o ECS escolherá matar o contêiner antigo antes de implantar um novo. Isso também está acontecendo ao longo de alguns minutos - não se apresse se você não vir um feedback imediato.

Abaixo, há um exemplo de script de implantação para atualizar o contêiner em um cluster e serviço pré-configurados. Note que não há necessidade de especificar versões se você quer dizer apenas "use as últimas da família".

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
    
por 03.05.2016 / 17:22
8

Para atualizar seu aplicativo, atualize a definição da tarefa e atualize o serviço. Consulte o link

    
por 27.08.2015 / 16:47
1

Eu uso parte do script ecs-deploy com meus aprimoramentos (ele tira imagens de todas as descrições de contêiner e substitui sua parte de etiqueta com $ TAG_PURE): link

# 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"
    
por 06.10.2016 / 13:08
1

Depois de fazer o upload de uma nova imagem do Docker, mesmo que tenha a mesma tag usada por uma tarefa, é necessário copiar a tarefa mais recente e, em seguida, configurar o serviço para usar essa nova tarefa. Opcionalmente, pode-se simplesmente ter duas tarefas duplicadas e configurar o Serviço para alternar entre elas cada vez que a imagem do Docker for atualizada.

Basicamente, para fazer com que um novo contêiner do Docker seja feito pelo ECS, uma atualização para o Serviço precisa ativá-lo, e a única maneira de fazer o acionador do Serviço é atualizá-lo de alguma forma - por exemplo, para usar um número de tarefa diferente.

Observe que os Contêineres em execução existentes podem não parar automaticamente apenas porque o Serviço foi atualizado - talvez seja necessário consultar sua lista de tarefas e interrompê-las manualmente.

    
por 23.11.2016 / 17:51
1

A abordagem que funciona para mim é semelhante ao acima. Depois de criar seu serviço e tarefa e começar tudo, edite o Grupo de Auto-Escalonamento e garanta min , max e desejado estão definidos para 1 .

O grupo pode ser o padrão; Se você não tiver certeza, poderá acessá-lo selecionando a guia Instâncias do ECS no cluster e, em seguida, na lista suspensa Ações , escolha Recursos do cluster e clique no link próximo à parte inferior da caixa de diálogo que é aberta.

Quando tudo estiver em vigor, sempre que você quiser implantar uma imagem de contêiner atualizada, vá para a área Tarefa do cluster e Pare a tarefa . Você receberá um aviso, mas, desde que o escalonamento automático esteja configurado, o serviço o iniciará novamente com o último push.

Não é necessário criar novas versões do serviço ou da tarefa.

Observe que o serviço / tarefa é atualizado em qualquer lugar, de instantaneamente para dentro de um minuto ou mais. Se você ficar desesperado esperando, você pode simplesmente executar nova tarefa manualmente. O serviço não será o proprietário, por isso não é o ideal, mas ainda assim irá gerar um novo caso ele morra.

    
por 01.05.2017 / 23:14
0

Eu sei que este é um tópico antigo, mas a solução é muito mais fácil do que a maioria das respostas aqui é.

Como atualizar o contêiner em execução em duas etapas:

O abaixo assume que você tem um serviço executando uma tarefa que está referenciando um contêiner com tags latest (ou qualquer outra tag estática que não seja alterada nas atualizações de contêiner).

  1. Envie seu novo contêiner para o repositório
  2. Manualmente mate suas tarefas

Se o objetivo é que consigamos uma nova construção na natureza, não precisamos depender do nosso serviço para isso (e eu diria, nós não deveríamos confiar nisso). Se você matar sua tarefa, o serviço reconhecerá que ela não tem o Desired Count de tarefas em execução e simplesmente criará uma nova. Isso acionará um novo pull do seu contêiner, com base na mesma tag.

Os serviços do ECS são uma rede de segurança HA, não um substituto para o seu pipeline de CD / CI.

Bônus: Se o objetivo é que um serviço reconheça que um novo contêiner foi enviado (independentemente das tags), precisamos considerar as implicações disso. Queremos realmente que um serviço básico controle nosso canal de implantação para nós? Provavelmente não. Idealmente, você empurrará seus contêineres com tags diferentes (com base nas versões de lançamento ou algo assim). Nesse caso, a barreira à implantação é que o serviço precisa ser notificado de algo novo - novamente, é uma rede de segurança para o serviço e nada mais.

Como implantar novas tags em três etapas:

  1. Envie seu novo container:tag para o repositório
  2. Crie uma nova definição de tarefa referenciando o novo tag
  3. Atualize seu serviço para fazer referência à nova definição de tarefa
    • Cuidado aqui! Se você tiver minimum healthy definido como 0% , como algumas outras respostas sugerem, você está dando autoridade total à AWS para eliminar todo o seu serviço para implantar a nova definição de tarefa. Se você preferir uma implantação gradual / gradual, defina seu mínimo como algo >0% .
    • Como alternativa, defina seu minimum healthy para 100% e seu maximum healthy para algo >100% para permitir que seu serviço implante as novas tarefas antes de eliminar as antigas (minimizando o impacto para seus usuários).

A partir desse ponto, seu serviço reconhecerá automaticamente que você especificou uma nova tarefa e trabalhará para implantá-la com base nos limites minimum / maximum healthy que você configurou.

    
por 23.03.2018 / 17:13