amazon web services - signin - Mejores prácticas para actualizar las tareas de servicio de AWS ECS
servicios de amazon (5)
Así que tengo esto trabajando ahora.
Después de llamar aws ecs update service
con la nueva definición de tarea, llamo aws ecs list-tasks
y luego ejecuto ''aws stop task'' en cada tarea en ejecución para el servicio. Debido a que el recuento deseado para el servicio es 1, inmediatamente intenta iniciar la copia de seguridad de las tareas y utiliza la nueva definición del servicio.
Esto no es muy bonito, pero parece funcionar lo suficientemente bien por ahora.
Actualmente estoy intentando configurar un CI simple que reconstruirá mi proyecto, creará una nueva imagen de docker, empujará la nueva imagen a un repositorio de ecr de amazon, creará una nueva revisión de una definición de tarea existente con la última imagen de docker, actualizará ejecutando el servicio con la nueva revisión de la definición de tarea, y finalmente, detenga la tarea existente ejecutando la revisión anterior e inicie una ejecutando la nueva revisión.
Todo funciona bien, excepto para iniciar la nueva revisión de la tarea.
Desde un script de bash, el comando final que llamo es:
aws ecs update-service --cluster "$CLUSTER" --service "$SERVICE" --task-definition "$TASK_DEFINITION":"$REVISION"
Esto resulta en un error de evento 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.
Y esto tiene sentido porque el contenedor que estoy reemplazando es exactamente igual al nuevo y se ejecutará en el mismo puerto, solo contiene la última versión de mi aplicación.
Tenía la impresión de que el comando update-service
detendría la tarea existente e iniciaría la nueva, pero parece que primero inicia la nueva, y si tiene éxito, detiene la anterior.
¿Cuál es la mejor práctica para manejar esto? ¿Debo detener la vieja tarea primero? ¿Debo eliminar primero el servicio en mi script y volver a crear todo el servicio en cada actualización?
Actualmente solo necesito 1 instancia de la tarea en ejecución, pero no quiero encajarme si necesito esto para poder escalar automáticamente a varias instancias. ¿Alguna sugerencia sobre la mejor manera de abordar esto?
El mensaje que está recibiendo es porque ECS está intentando realizar una implementación azul-verde. Significa que está intentando asignar la revisión de su nueva tarea sin detener la tarea actual para evitar el tiempo de inactividad en su servicio. Una vez que la tarea más nueva esté lista (estado estable), la anterior se eliminará finalmente.
El problema con este tipo de implementación es que necesita tener suficientes recursos libres en su clúster para mantener y ejecutar las 2 tareas (la anterior y la nueva) durante un período de tiempo. Por ejemplo, si está implementando una tarea con 2 GB de memoria y 2 CPU, su clúster necesitará tener esa cantidad de recursos gratuitos para actualizar el servicio con una nueva revisión de tareas.
Tienes 2 opciones:
- Amplíe su clúster agregando una nueva instancia de EC2 para que pueda tener suficientes recursos libres y realizar la implementación.
- Cambie la configuración de su servicio para no realizar una implementación azul-verde (permita solo 1 tarea al mismo tiempo en su clúster).
Para realizar la opción número 2 solo necesita establecer los siguientes valores:
- Porcentaje mínimo saludable : 0
- Porcentaje máximo : 100
Ejemplo
Lo que significa que solo desea tener el 100% de las tareas deseadas en ejecución (¡y nada más!) Y está dispuesto a tener un tiempo de inactividad mientras implementa una nueva versión (0% de servicio saludable).
En el ejemplo, asumo que solo desea una tarea deseada, pero los valores de porcentaje saludable mínimo y porcentaje máximo funcionarán para cualquier cantidad de tareas que desee.
¡Espero eso ayude! Déjame saber si tienes alguna otra duda.
Para actualizar una definición de tarea en las "tareas" que se ejecutan en el servicio, debe eliminar las tareas e iniciar una nueva tarea.
De esta manera, resuelvo el problema de actualizar la definición de tareas en tareas.
He escrito el siguiente código:
# 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
Puede iniciar la nueva revisión de tareas con los siguientes pasos utilizando un script de shell en su entorno de compilación.
Almacene la plantilla json de definición de tareas en su entorno de compilación en un archivo (por ejemplo, el archivo de plantilla es
web-server.json
y la familia de definición de tareas esweb-server
).Utilice el directorio de archivos como directorio actual y ejecute la definición de la tarea de registro (sucede si se ejecuta por primera vez, si no existe)
aws ecs register-task-definition --cli-input-json file://web-server.json
Obtenga el ID de la tarea en ejecución (TASK_ID) en una variable en el script de shell.
TASK_ID=`aws ecs list-tasks --cluster default --desired-status RUNNING --family web-server | egrep "task" | tr "/" " " | tr "[" " " | awk ''{print $2}'' | sed ''s/"$//''`
Obtenga la revisión de la tarea (TASK_REVISION) para las variables en el script de shell.
TASK_REVISION=`aws ecs describe-task-definition --task-definition web-server | egrep "revision" | tr "/" " " | awk ''{print $2}'' | sed ''s/"$//''`
Detener la tarea actual en ejecución
aws ecs stop-task --cluster default --task ${TASK_ID}
Inmediatamente comienza una nueva tarea
aws ecs update-service --cluster default --service web-server --task-definition web-server:${TASK_REVISION} --desired-count 1
Como práctica recomendada, puede mantener el recuento deseado mínimo para 2 tareas (dos tareas que se ejecutan dentro del servicio) y realizar actualizaciones continuas (Actualizar una tarea a la vez) usando la siguiente secuencia de comandos (Extensión de los pasos anteriores para varios contenedores) con cero tiempo de inactividad (asegúrese de mantener suficiente tiempo después de las primeras actualizaciones del contenedor, por ejemplo, dormir 30 para que esté listo para aceptar nuevas solicitudes).
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
Nota: Debe configurar la familia de definición de tareas, el recuento deseado de instancias y la plantilla de definición de tareas en consecuencia.
Uso -> AWS CLI
Obtener OLD_TASK_ID
aws ecs list-tasks --cluster ${ecsClusterName} --desired-status RUNNING --family ${nameTaskDefinition} | egrep "task/" | sed -E "s/.*task//(.*)/"//1/"
Detener la tarea
aws ecs stop-task --cluster ${ecsClusterName} --task ${OLD_TASK_ID}
Actualizar el servicio de ECS
aws ecs update-service --cluster ${ecsClusterName} --service ${nameService} --task-definition ${nameTaskDefinition}:${version} --desired-count 1 --force-new-deployment