web-dev-qa-db-fra.com

Service de redémarrage AWS ECS avec la même définition de tâche et la même image sans temps d'arrêt

J'essaie de redémarrer un service AWS (essentiellement arrêter et démarrer toutes les tâches au sein du service) sans apporter de modifications à la définition de tâche.

La raison en est que l'image a la balise latest attachée à chaque build.

J'ai essayé d'arrêter toutes les tâches et de les recréer, mais cela signifie qu'il y a temporarily unavailable erreur lors du redémarrage des services dans mes instances (2).

Quelle est la meilleure façon de gérer cela? Disons: une stratégie de déploiement bleu-vert pour éviter les temps d'arrêt?

C'est ce que j'ai actuellement. Son inconvénient est que mon application sera arrêtée pendant quelques secondes car les tâches du service sont en cours de reconstruction après les avoir supprimées.

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

Utilisation update-service et le --force-new-deployment drapeau:

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

Attends une seconde. Si j'ai bien compris que vous utilisiez correctement le cas, cela est traité dans les --- docs :

Si votre image Docker mise à jour utilise la même balise que celle qui se trouve dans la définition de tâche existante pour votre service (par exemple, my_image: latest), vous n'avez pas besoin de créer une nouvelle révision de votre définition de tâche. Vous pouvez mettre à jour le service en utilisant la procédure ci-dessous, conserver les paramètres actuels de votre service et sélectionner Forcer le nouveau déploiement ....

Pour éviter les temps d'arrêt, vous devez manipuler 2 paramètres: pourcentage sain minimum et pourcentage maximum:

Par exemple, si votre service a un nombre souhaité de quatre tâches et une valeur maximale de 200%, le planificateur peut démarrer quatre nouvelles tâches avant d'arrêter les quatre anciennes tâches (à condition que les ressources de cluster requises pour ce faire soient disponibles). La valeur par défaut pour le pourcentage maximum est 200%.

Cela signifie essentiellement que peu importe si la définition de votre tâche a changé et dans quelle mesure, il peut y avoir un "chevauchement" entre l'ancienne et la nouvelle, et c'est le moyen d'atteindre la résilience et la fiabilité.

MISE À JOUR: Amazon vient de introduit Contrôleurs de déploiement externes pour ECS (EC2 et Fargate). Il comprend un nouveau niveau d'abstraction appelé TaskSet. Je ne l'ai pas encore essayé moi-même, mais un contrôle aussi précis de la gestion des services et des tâches (les deux API sont prises en charge) peut potentiellement résoudre le problème comme celui-ci.

7
yuranos87

Après avoir poussé votre nouvelle image vers votre référentiel Docker, vous pouvez créer une nouvelle révision de votre définition de tâche (elle peut être identique à la définition de tâche existante) et mettre à jour votre service pour utiliser la nouvelle révision de définition de tâche. Cela déclenchera un déploiement de service et votre service extraira la nouvelle image de votre référentiel.

De cette façon, votre définition de tâche reste la même (bien que la mise à jour du service vers une nouvelle révision de définition de tâche soit nécessaire pour déclencher l'extraction de l'image), et utilise toujours la "dernière" balise de votre image, mais vous pouvez profiter du déploiement du service ECS fonctionnalité pour éviter les temps d'arrêt.

4
Eric N

Le fait que je doive créer une nouvelle révision de ma définition de tâche à chaque fois même lorsqu'il n'y a aucun changement dans la définition de tâche elle-même n'est pas correct.

Il y a un tas d'implémentations bash grossières à ce sujet, ce qui signifie qu'AWS devrait demander au planificateur de service ECS d'écouter les modifications/mises à jour de l'image, en particulier pour un processus de construction automatisé.

Mon crude solution de contournement était d'avoir deux définitions de tâches identiques et de basculer entre elles pour chaque build. De cette façon, je n'ai pas de révisions redondantes.

Voici l'extrait de script spécifique qui fait cela.

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

J'ai également ce problème avec ma configuration. J'utilise ECS sans aucun équilibreur de charge. Mes conteneurs s'exécutent sur le port 80. Ma définition de tâche a le port d'hôte 0 et le port de conteneur 80 définis. J'utilise nginx sur les ports 80 et 443 et j'obtiens l'erreur suivante lorsque je télécharge une nouvelle image balisée: le plus récent et je mets à jour mon service comme ceci: aws ecs update-service --force-new-deployment --service my-service

Voici l'erreur que j'obtiens:

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.

Je ne sais pas ce que je manque ici?

1
marcus

Avez-vous résolu cette question? Peut-être que cela fonctionnera pour vous.

Avec une nouvelle image de version poussée vers ECR avec une balise de version, c'est-à-dire v1.05, et la balise latest, le localisateur image dans ma définition de tâche devaient être explicitement mis à jour pour que cette balise de version soit postfixée comme :v1.05.

Avec :latest, cette nouvelle image n'a pas été tirée par le nouveau conteneur après aws ecs update-service --force-new-deployment --service my-service.

Je faisais du marquage et de la poussée comme ceci:

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

... où c'est la bonne façon de pousser plusieurs balises:

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

Cela a été brièvement mentionné dans les documents officiels sans un exemple approprié.

0
ux.engineer

La manière rapide et sale:

  • connexion à l'instance EC2 exécutant la tâche
  • trouvez votre conteneur avec docker container list
  • utilisation docker restart [container]
0
yurez