web-dev-qa-db-fra.com

Méthode recommandée pour la mise à jour des tâches du service AWS ECS

J'essaie actuellement de configurer un élément de configuration simple qui reconstruira mon projet, créera une nouvelle image de menu fixe, transmettra la nouvelle image à un référentiel Amazon ecr, créera une nouvelle révision d'une définition de tâche existante avec la dernière image de menu fixe, mettra à jour un service en cours d’exécution avec la nouvelle révision de la définition de tâche et enfin, arrêtez la tâche existante qui exécute l’ancienne révision et démarrez-en une avec la nouvelle révision.

Tout fonctionne bien sauf pour commencer la nouvelle révision de la tâche.

À partir d'un script bash, la dernière commande que j'appelle est la suivante:

aws ecs update-service --cluster "$CLUSTER" --service "$SERVICE" --task-definition "$TASK_DEFINITION":"$REVISION"

Cela entraîne une erreur d'événement de:

(service rj-api-service) was unable to place a task because no container instance met all of its requirements. The closest matching (container-instance bbbc23d5-1a09-45e7-b344-e68cc408e683) is already using a port required by your task.

Et cela a du sens car le conteneur que je remplace est exactement le même que le nouveau et s’exécutera sur le même port, il ne contient que la dernière version de mon application.

J'avais l'impression que la commande update-service arrêterait la tâche existante et lancerait la nouvelle, mais il semblerait qu'elle lance la nouvelle en premier et, si elle réussit, arrête l'ancienne.

Quelle est la meilleure pratique pour gérer cela? Devrais-je arrêter l'ancienne tâche en premier? Dois-je d'abord supprimer le service dans mon script et recréer le service complet à chaque mise à jour?

Actuellement, je n'ai besoin que d'une instance de la tâche en cours d'exécution, mais je ne souhaite pas me mettre au travail si j'en ai besoin pour pouvoir mettre à l'échelle automatiquement plusieurs instances. Des suggestions sur la meilleure façon de résoudre ce problème?

19
on3al

Le message que vous recevez est qu'ECS tente d'effectuer un déploiement bleu-vert. Cela signifie qu'il essaie d'allouer votre nouvelle révision de tâche sans arrêter la tâche en cours pour éviter les temps d'arrêt de votre service. Une fois que la dernière tâche est prête (état stable), l'ancienne sera finalement supprimée. 

Le problème avec ce type de déploiement est que vous devez disposer de suffisamment de ressources libres dans votre cluster pour conserver et exécuter les 2 tâches (ancienne et nouvelle) pendant une période donnée. Par exemple, si vous déployez une tâche avec 2 Go de mémoire et 2 processeurs, votre cluster doit disposer de cette quantité de ressources libres pour pouvoir mettre à jour le service avec une nouvelle révision de tâche. 

Vous avez 2 options:

  1. Faites évoluer votre cluster en ajoutant une nouvelle instance EC2 afin de disposer de suffisamment de ressources libres et d'effectuer le déploiement.
  2. Changez la configuration de votre service afin de ne pas effectuer de déploiement bleu-vert (n'autorisez qu'une tâche à la fois dans votre cluster).

Pour exécuter l'option numéro 2, il vous suffit de définir les valeurs suivantes:

  • Minimun pourcentage sain: 0
  • Maximun pourcentage: 100

Exemple

 Example

Ce qui signifie que vous ne souhaitez exécuter que 100% des tâches souhaitées (et pas plus!) Et que vous êtes prêt à avoir un temps d'indisponibilité pendant le déploiement d'une nouvelle version (0% de service en bon état).

Dans l'exemple, je suppose que vous ne voulez qu'une tâche, mais les valeurs Minimun pour cent sain et Maximun pour cent fonctionneront pour n'importe quelle quantité de tâches désirées.

J'espère que ça aide! Faites-moi savoir si vous avez un autre doute.

21
Fabian Rivera

Vous pouvez démarrer la nouvelle révision de tâches en procédant comme suit à l'aide d'un script Shell dans votre environnement de construction.

  1. Stockez le modèle json de définition tasks dans votre environnement de construction dans un fichier (par exemple, le fichier modèle est web-server.json et la famille de définition de tâche est web-server).

  2. Utiliser le répertoire de fichiers comme répertoire en cours et exécuter la définition de la tâche de registre (se produit pour la première exécution s'il n'existe pas)

    aws ecs register-task-definition --cli-input-json file://web-server.json

  3. Obtenez l'identifiant de la tâche en cours d'exécution (TASK_ID) dans une variable du script Shell.

    TASK_ID=`aws ecs list-tasks --cluster default --desired-status RUNNING --family web-server | egrep "task" | tr "/" " " | tr "[" " " | awk '{print $2}' | sed 's/"$//'`

  4. Obtenez la révision de tâche (TASK_REVISION) en variables dans le script Shell.

    TASK_REVISION=`aws ecs describe-task-definition --task-definition web-server | egrep "revision" | tr "/" " " | awk '{print $2}' | sed 's/"$//'`

  5. Arrête la tâche en cours en cours d'exécution

    aws ecs stop-task --cluster default --task ${TASK_ID}

  6. Commencer immédiatement une nouvelle tâche

    aws ecs update-service --cluster default --service web-server --task-definition web-server:${TASK_REVISION} --desired-count 1

Comme meilleure pratique, vous pouvez maintenir le nombre souhaité de comptes minimum pour 2 tâches (deux tâches exécutées dans le service) et effectuer des mises à jour progressives (Mettre à jour une tâche à la fois) à l'aide du script suivant (Extension des étapes ci-dessus pour plusieurs conteneurs) temps d'arrêt (veillez à conserver suffisamment de temps après les premières mises à jour du conteneur, par exemple, veillez à ce qu'il soit prêt à accepter de nouvelles demandes).

cd /<directory-containing-web-server.json>
aws ecs register-task-definition --cli-input-json file://web-server.json
OLD_TASK_ID=`aws ecs list-tasks --cluster default --desired-status RUNNING --family web-server | egrep "task" | tr "/" " " | tr "[" " " |  awk '{print $2}' | sed 's/"$//'`

TASK_REVISION=`aws ecs describe-task-definition --task-definition web-server | egrep "revision" | tr "/" " " | awk '{print $2}' | sed 's/"$//'`
aws ecs stop-task --cluster default --task ${OLD_TASK_ID}

OLD_TASK_ID=`aws ecs list-tasks --cluster default --desired-status RUNNING --family web-server | egrep "task" | tr "/" " " | tr "[" " " |  awk '{print $2}' | sed 's/"$//'`
aws ecs update-service --cluster default --service web-server --task-definition web-server:${TASK_REVISION} --desired-count 1

sleep 30
aws ecs stop-task --task ${OLD_TASK_ID}
aws ecs update-service --cluster default --service web-server --task-definition web-server:${TASK_REVISION} --desired-count 2

Remarque: Vous devez configurer la famille de définition de tâche, le nombre d'instances souhaité et le modèle de définition de tâche en conséquence.

2
Ashan

Pour mettre à jour une définition de tâche dans les "tâches" en cours d'exécution dans le service, vous devez supprimer les tâches et démarrer une nouvelle tâche.

De cette façon, je résous le problème de la mise à jour de la définition de tâche dans les tâches

J'ai écrit le code suivant:

    # Register a new Task definition 
    aws ecs register-task-definition --family testing-cluster --cli-input-json file://scripts/taskdefinition/testingtaskdef.json --region $AWS_REGION

    # Update Service in the Cluster
    aws ecs update-service --cluster $CLUSTER_NAME --service $SERVICE --task-definition testing-cluster --desired-count 1 --region $AWS_REGION 



    DECRIBED_SERVICE=$(aws ecs describe-services --region $AWS_REGION --cluster $CLUSTER_NAME --services $SERVICE);
    CURRENT_DESIRED_COUNT=$(echo $DECRIBED_SERVICE | jq --raw-output ".services[0].desiredCount")
    #    - echo $CURRENT_DESIRED_COUNT

    CURRENT_TASK_REVISION=$(echo $DECRIBED_SERVICE | jq -r ".services[0].taskDefinition")
    echo "Current Task definition in Service" + $CURRENT_TASK_REVISION

    CURRENT_RUNNING_TASK=$(echo $DECRIBED_SERVICE | jq -r ".services[0].runningCount")
    echo $CURRENT_RUNNING_TASK

    CURRENT_STALE_TASK=$(echo $DECRIBED_SERVICE | jq -r ".services[0].deployments | .[] | select(.taskDefinition != \"$CURRENT_TASK_REVISION\") | .taskDefinition")
    echo "Task defn apart from current service Taskdefn" +  $CURRENT_STALE_TASK
    #   - echo $CURRENT_STALE_TASK

    tasks=$(aws ecs --region $AWS_REGION list-tasks --cluster $CLUSTER_NAME | jq -r '.taskArns | map(.[40:]) | reduce .[] as $item (""; . + $item + " ")')
    echo "Tasks are as follows" 
    echo $tasks
    TASKS=$(aws ecs --region $AWS_REGION describe-tasks --cluster $CLUSTER_NAME --task $tasks);
    #    - echo $TASKS
    OLDER_TASK=$(echo $TASKS | jq -r ".tasks[] | select(.taskDefinitionArn!= \"$CURRENT_TASK_REVISION\") | .taskArn | split(\"/\") | .[1] ")
    echo "Older Task running  " + $OLDER_TASK
    for old_task in $OLDER_TASK; do
        aws ecs --region us-east-1 stop-task --cluster $CLUSTER_NAME --task $old_task
    done    

    # Run new tasks with the updated new Task-definition
    aws ecs --region $AWS_REGION run-task --cluster $CLUSTER_NAME --task-definition $CURRENT_TASK_REVISION
1
Roopa

Utilisez -> AWS CLI

Obtenir OLD_TASK_ID

aws ecs list-tasks --cluster ${ecsClusterName} --desired-status RUNNING --family ${nameTaskDefinition} | egrep "task/" | sed -E "s/.*task\/(.*)\"/\1/"

Arrêter la tâche

aws ecs stop-task --cluster ${ecsClusterName} --task ${OLD_TASK_ID}

Mettre à jour le service ECS

aws ecs update-service --cluster ${ecsClusterName} --service ${nameService} --task-definition ${nameTaskDefinition}:${version} --desired-count 1 --force-new-deployment
0
user3740244

Donc, je travaille maintenant.

Après avoir appelé aws ecs update service avec la nouvelle définition de tâche, j’ai appelé aws ecs list-tasks, puis j’ai exécuté «aws stop task» pour chaque tâche en cours d’exécution pour le service. Le nombre souhaité pour le service étant égal à 1, il tente immédiatement de démarrer la sauvegarde des tâches et utilise la nouvelle définition de service.

Ce n'est pas très joli mais ça semble fonctionner assez bien pour l'instant.

0
on3al