web-dev-qa-db-fra.com

Journaux de flux d'air BrokenPipeException

J'utilise un environnement Airflow en cluster dans lequel j'ai quatre instances AWS ec2 pour les serveurs.

ec2-instances

  • Serveur 1: serveur Web, planificateur, file d'attente Redis, base de données PostgreSQL
  • Serveur 2: Serveur Web
  • Serveur 3: Travailleur
  • Serveur 4: travailleur

Ma configuration fonctionne parfaitement depuis trois mois maintenant, mais sporadiquement environ une fois par semaine, une exception de tuyau cassé se produit lorsque Airflow tente de consigner quelque chose.

*** Log file isn't local.
*** Fetching here: http://ip-1-2-3-4:8793/log/foobar/task_1/2018-07-13T00:00:00/1.log

[2018-07-16 00:00:15,521] {cli.py:374} INFO - Running on Host ip-1-2-3-4
[2018-07-16 00:00:15,698] {models.py:1197} INFO - Dependencies all met for <TaskInstance: foobar.task_1 2018-07-13 00:00:00 [queued]>
[2018-07-16 00:00:15,710] {models.py:1197} INFO - Dependencies all met for <TaskInstance: foobar.task_1 2018-07-13 00:00:00 [queued]>
[2018-07-16 00:00:15,710] {models.py:1407} INFO - 
--------------------------------------------------------------------------------
Starting attempt 1 of 1
--------------------------------------------------------------------------------

[2018-07-16 00:00:15,719] {models.py:1428} INFO - Executing <Task(OmegaFileSensor): task_1> on 2018-07-13 00:00:00
[2018-07-16 00:00:15,720] {base_task_runner.py:115} INFO - Running: ['bash', '-c', 'airflow run foobar task_1 2018-07-13T00:00:00 --job_id 1320 --raw -sd DAGS_FOLDER/datalake_digitalplatform_arl_workflow_schedule_test_2.py']
[2018-07-16 00:00:16,532] {base_task_runner.py:98} INFO - Subtask: [2018-07-16 00:00:16,532] {configuration.py:206} WARNING - section/key [celery/celery_ssl_active] not found in config
[2018-07-16 00:00:16,532] {base_task_runner.py:98} INFO - Subtask: [2018-07-16 00:00:16,532] {default_celery.py:41} WARNING - Celery Executor will run without SSL
[2018-07-16 00:00:16,534] {base_task_runner.py:98} INFO - Subtask: [2018-07-16 00:00:16,533] {__init__.py:45} INFO - Using executor CeleryExecutor
[2018-07-16 00:00:16,597] {base_task_runner.py:98} INFO - Subtask: [2018-07-16 00:00:16,597] {models.py:189} INFO - Filling up the DagBag from /home/ec2-user/airflow/dags/datalake_digitalplatform_arl_workflow_schedule_test_2.py
[2018-07-16 00:00:16,768] {cli.py:374} INFO - Running on Host ip-1-2-3-4
[2018-07-16 00:16:24,931] {logging_mixin.py:84} WARNING - --- Logging error ---

[2018-07-16 00:16:24,931] {logging_mixin.py:84} WARNING - Traceback (most recent call last):

[2018-07-16 00:16:24,931] {logging_mixin.py:84} WARNING -   File "/usr/lib64/python3.6/logging/__init__.py", line 996, in emit
    self.flush()

[2018-07-16 00:16:24,932] {logging_mixin.py:84} WARNING -   File "/usr/lib64/python3.6/logging/__init__.py", line 976, in flush
    self.stream.flush()

[2018-07-16 00:16:24,932] {logging_mixin.py:84} WARNING - BrokenPipeError: [Errno 32] Broken pipe

[2018-07-16 00:16:24,932] {logging_mixin.py:84} WARNING - Call stack:

[2018-07-16 00:16:24,933] {logging_mixin.py:84} WARNING -   File "/usr/bin/airflow", line 27, in <module>
    args.func(args)

[2018-07-16 00:16:24,934] {logging_mixin.py:84} WARNING -   File "/usr/local/lib/python3.6/site-packages/airflow/bin/cli.py", line 392, in run
    pool=args.pool,

[2018-07-16 00:16:24,934] {logging_mixin.py:84} WARNING -   File "/usr/local/lib/python3.6/site-packages/airflow/utils/db.py", line 50, in wrapper
    result = func(*args, **kwargs)

[2018-07-16 00:16:24,934] {logging_mixin.py:84} WARNING -   File "/usr/local/lib/python3.6/site-packages/airflow/models.py", line 1488, in _run_raw_task
    result = task_copy.execute(context=context)

[2018-07-16 00:16:24,934] {logging_mixin.py:84} WARNING -   File "/usr/local/lib/python3.6/site-packages/airflow/operators/sensors.py", line 78, in execute
    while not self.poke(context):

[2018-07-16 00:16:24,934] {logging_mixin.py:84} WARNING -   File "/home/ec2-user/airflow/plugins/custom_plugins.py", line 35, in poke
    directory = os.listdir(full_path)

[2018-07-16 00:16:24,934] {logging_mixin.py:84} WARNING -   File "/usr/local/lib/python3.6/site-packages/airflow/utils/timeout.py", line 36, in handle_timeout
    self.log.error("Process timed out")

[2018-07-16 00:16:24,934] {logging_mixin.py:84} WARNING - Message: 'Process timed out'
Arguments: ()

[2018-07-16 00:16:24,942] {models.py:1595} ERROR - Timeout
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/airflow/models.py", line 1488, in _run_raw_task
    result = task_copy.execute(context=context)
  File "/usr/local/lib/python3.6/site-packages/airflow/operators/sensors.py", line 78, in execute
    while not self.poke(context):
  File "/home/ec2-user/airflow/plugins/custom_plugins.py", line 35, in poke
    directory = os.listdir(full_path)
  File "/usr/local/lib/python3.6/site-packages/airflow/utils/timeout.py", line 37, in handle_timeout
    raise AirflowTaskTimeout(self.error_message)
airflow.exceptions.AirflowTaskTimeout: Timeout
[2018-07-16 00:16:24,942] {models.py:1624} INFO - Marking task as FAILED.
[2018-07-16 00:16:24,956] {models.py:1644} ERROR - Timeout

Parfois, l'erreur dira aussi

*** Log file isn't local.
*** Fetching here: http://ip-1-2-3-4:8793/log/foobar/task_1/2018-07-12T00:00:00/1.log
*** Failed to fetch log file from worker. 404 Client Error: NOT FOUND for url: http://ip-1-2-3-4:8793/log/foobar/task_1/2018-07-12T00:00:00/1.log

Je ne sais pas pourquoi les journaux fonctionnent environ 95% du temps, mais échouent de manière aléatoire à d'autres moments. Voici mes paramètres de journal dans mon fichier Airflow.cfg,

# The folder where airflow should store its log files
# This path must be absolute
base_log_folder = /home/ec2-user/airflow/logs

# Airflow can store logs remotely in AWS S3 or Google Cloud Storage. Users
# must supply an Airflow connection id that provides access to the storage
# location.
remote_log_conn_id =
encrypt_s3_logs = False

# Logging level
logging_level = INFO

# Logging class
# Specify the class that will specify the logging configuration
# This class has to be on the python classpath
# logging_config_class = my.path.default_local_settings.LOGGING_CONFIG
logging_config_class =

# Log format
log_format = [%%(asctime)s] {%%(filename)s:%%(lineno)d} %%(levelname)s - %%(message)s
simple_log_format = %%(asctime)s %%(levelname)s - %%(message)s

# Name of handler to read task instance logs.
# Default to use file task handler.
task_log_reader = file.task

# Log files for the gunicorn webserver. '-' means log to stderr.
access_logfile = -
error_logfile = 

# The amount of time (in secs) webserver will wait for initial handshake
# while fetching logs from other worker machine
log_fetch_timeout_sec = 5

# When you start an airflow worker, airflow starts a tiny web server
# subprocess to serve the workers local log files to the airflow main
# web server, who then builds pages and sends them to users. This defines
# the port on which the logs are served. It needs to be unused, and open
# visible from the main web server to connect into the workers.
worker_log_server_port = 8793

# How often should stats be printed to the logs
print_stats_interval = 30

child_process_log_directory = /home/ec2-user/airflow/logs/scheduler

Je me demande si je devrais peut-être essayer une technique différente pour ma journalisation, telle que l'écriture sur un godet S3 ou s'il y a autre chose que je peux faire pour résoudre ce problème.

Mise à jour:

L'écriture des journaux sur S3 n'a pas résolu ce problème. En outre, l'erreur est plus cohérente maintenant (toujours sporadique). Cela se produit plus comme 50% du temps maintenant. Une chose que j'ai remarquée est que la tâche sur laquelle elle se produit est ma tâche de création AWS EMR. Le démarrage d'un cluster AWS EMR prend environ 20 minutes, puis la tâche doit attendre que les commandes Spark soient exécutées sur le cluster EMR. Ainsi, la tâche unique dure environ 30 minutes. Je me demande si la durée d'exécution d'une tâche Airflow est trop longue et si c'est la raison pour laquelle l'écriture dans les journaux commence à échouer. Si tel est le cas, je pourrais alors diviser la tâche EMR pour créer une tâche pour la création de DME, puis une autre tâche pour les commandes Spark sur le cluster de DME.

Note:

J'ai également créé un nouveau ticket de bug sur Jira d'Airflow ici https://issues.Apache.org/jira/browse/AIRFLOW-2844

9
Kyle Bridenstine

Ce problème est le symptôme d'un autre problème que je viens de résoudre ici AirflowException: échec de la commande Celery - Le nom d'hôte enregistré ne correspond pas au nom d'hôte de cette instance .

Je n'ai pas vu la AirflowException: la commande Celery a échoué pendant un certain temps car elle est apparue dans les journaux airflow worker. Ce n’est que lorsque j’ai regardé les journaux d’opération d’airflow en temps réel que j’ai vu que l’erreur était renvoyée, j’ai également eu l’exception BrokenPipeException dans ma tâche.

Cela devient toutefois un peu plus étrange. Je ne verrais que l'exception BrokenPipeException levée si je faisais print("something to log")etl'erreur AirflowException: Celery command failed... se produisait sur le noeud Worker. Lorsque j'ai modifié toutes mes instructions d'impression pour qu'elles utilisent import logging ... logging.info("something to log"), je ne pouvais pas voir BrokenPipeException maisla tâche échouerait toujours à cause de l'erreur AirflowException: Celery command failed.... Mais si je n'avais pas vu l'exception BrokenPipeException être levée dans mes journaux de tâches Airflow, je n'aurais pas su pourquoi la tâche échouait, car une fois que j'ai éliminé les instructions d'impression, je n'ai jamais vu d'erreur dans la tâche Airflow. logs (uniquement sur les logs $ airflow worker)

Si longue histoire courte il y a quelques emporter.

  1. Ne faites pas print("something to log") utilisez la journalisation intégrée d'Airflow en important la journalisation, puis utilisez la classe de journalisation telle que import logging puis logging.info("something to log").

  2. Si vous utilisez une instance AWS EC2 en tant que serveur pour Airflow, il est possible que vous rencontriez ce problème: https://github.com/Apache/incubator-airflow/pull/2484 un correctif pour ce problème a déjà été intégré à Airflow version 1.10 (j'utilise actuellement Airflow version 1.9). Mettez à niveau votre version Airflow vers la version 1.10 . Vous pouvez également utiliser la commande icipip install git+git://github.com/Apache/incubator-airflow.git@v1-10-stable. En outre, si vous ne souhaitez pas mettre à niveau votre version d'Airflow, vous pouvez suivre les étapes de le problème github pour mettre à jour manuellement le fichier avec le correctif ou fork Airflow et sélectionner le commit qui le corrige.

2
Kyle Bridenstine