ОБНОВЛЕНИЕ: теперь это выглядит как фиксированный , поэтому нет необходимости применять обходной путь, описанный ниже
Я видел то же самоеповедение при использовании контейнеров ECS Fargate для запуска сценариев Python - и это вызвало то же разочарование!
Я думаю, это связано с тем, что агент журналов CloudWatch публикует события журнала в пакетном режиме:
Как пакетируются события журнала?
Пакет заполняется и публикуется при выполнении любого из следующих условий:
Время buffer_duration
прошло с момента добавления первого события журнала.
Меньше чем batch_size
событий журнала накоплено, но добавление нового события журнала превышает batch_size
.
Количество событий журнала достигло batch_count
.
События журнала из пакета не занимают более 24 часов, но при добавлении нового события журналапревышает ограничение в 24 часа.
(Ссылка:https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AgentReference.html)
Таким образом, возможное объяснение состоит в том, что события журнала буферизуются агентом, но еще не опубликованы, когда задача ECS остановлена.(И если так, то это похоже на проблему ECS - любые инженеры AWS ECS, желающие высказать свое мнение по этому вопросу ...?)
Кажется, нет прямого способа обеспечить публикацию журналов., но он предполагает, что можно подождать не менее buffer_duration
секунд (по умолчанию 5 секунд), и любые предыдущие журналы должны быть опубликованы.
После небольшого тестирования, которое я опишу ниже, вотОбходной путь, на котором я приземлился.Сценарий оболочки run_then_wait.sh
переносит команду для запуска сценария Python, чтобы добавить спящий режим после завершения сценария.
Dockerfile
FROM python:3.7-alpine
ADD run_then_wait.sh .
ADD main.py .
# The original command
# ENTRYPOINT ["python", "main.py"]
# To run the original command and then wait
ENTRYPOINT ["sh", "run_then_wait.sh", "python", "main.py"]
run_then_wait.sh
#!/bin/sh
set -e
# Wait 10 seconds on exit: twice the `buffer_duration` default of 5 seconds
trap 'echo "Waiting for logs to flush to CloudWatch Logs..."; sleep 10' EXIT
# Run the given command
"$@"
main.py
import logging
import time
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger()
if __name__ == "__main__":
# After testing some random values, had most luck to induce the
# issue by sleeping 9 seconds here; would occur ~30% of the time
time.sleep(9)
logger.info("Hello world")
Надеемся, что подход может быть адаптирован к вашей ситуации.Вы также можете реализовать спящий режим внутри своего скрипта, но может быть сложнее убедиться, что он происходит независимо от того, как он завершается.
Трудно доказать, что предложенное объяснение является точным, поэтому я использовал приведенный выше код для проверкибыл ли обходной путь эффективным.Тест был исходной командой против run_then_wait.sh
, по 30 прогонов каждый.В результате проблема наблюдалась в 30% случаев по сравнению с 0% времени соответственно.Надеюсь, что это так же эффективно для вас!