В настоящее время я пытаюсь настроить простой CI, который перестроит мой проект, создаст новый образ докера, переместит новый образ в хранилище amazon ecr, создаст новую ревизию существующего определения задачи с последним образом докера, обновит запустить службу с новой ревизией определения задачи и, наконец, остановить существующую задачу, на которой выполняется старая ревизия, и запустить одну, на которой выполняется новая ревизия.

Все работает нормально, кроме запуска новой ревизии задачи.

Из скрипта bash последняя команда, которую я вызываю:

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

Это приводит к ошибке события:

(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.

И это имеет смысл, потому что контейнер, который я заменяю, точно такой же, как и новый, и будет работать на том же порту, он просто содержит последнюю версию моего приложения.

У меня сложилось впечатление, что команда update-service остановит существующую задачу и запустит новую, но похоже, что сначала она запускает новую, а в случае успеха останавливает старую.

Какова лучшая практика для обработки этого? Должен ли я сначала остановить старую задачу? Должен ли я сначала удалить службу в моем сценарии и заново создавать всю службу при каждом обновлении?

В настоящее время мне нужен только 1 экземпляр выполняемой задачи, но я не хочу включать себя, если мне нужно это, чтобы иметь возможность автоматического масштабирования до нескольких экземпляров. Любые предложения о том, как решить эту проблему?

35
on3al 3 Сен 2017 в 01:49

3 ответа

Вы можете начать новую редакцию задач с помощью следующих шагов, используя скрипт оболочки в вашей среде сборки.

  1. Сохраните шаблон json определения задач в своем создать среду в файле (например, файл шаблона - web-server.json, а семейство определений задач - web-server).

  2. Использовать каталог файлов в качестве текущего каталога и выполнить определение задачи реестра (происходит при первом запуске, если не существует)

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

  3. Получить идентификатор запущенной задачи (TASK_ID) для переменной в сценарии оболочки.

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

  4. Получить ревизию задачи (TASK_REVISION) для переменных в сценарии оболочки.

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

  5. Остановить текущую задачу

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

  6. Немедленно начать новое задание

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

Рекомендуется сохранять минимум желаемого количества для 2 задач (две задачи, выполняющиеся внутри службы) и выполнять непрерывные обновления (обновлять по одной задаче за раз), используя следующий скрипт (расширение вышеуказанных шагов для нескольких контейнеров) с нулем. время простоя (убедитесь, что у вас достаточно времени после первых обновлений контейнера, например, сна 30, чтобы он был готов принимать новые запросы).

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

Примечание. Необходимо соответствующим образом настроить семейство определений задач, число экземпляров и шаблон определения задач.

3
Ashan 4 Сен 2017 в 01:18

Так что теперь у меня это работает.

После того как я вызвал aws ecs update service с новым определением задачи, я вызываю aws ecs list-tasks и затем запускаю 'aws stop task' для каждой запущенной задачи службы. Поскольку желаемое количество для службы равно 1, оно немедленно пытается запустить резервное копирование задач и использует новое определение службы.

Это не очень красиво, но, похоже, пока работает достаточно хорошо.

0
on3al 3 Сен 2017 в 19:43

Чтобы обновить определение задачи в «задачах», запущенных в сервисе, необходимо удалить задачи и запустить новую задачу.

Таким образом, я решаю проблему обновления определения задач в задачах.

Я написал следующий код:

    # 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 7 Май 2018 в 05:49