在 Docker 上运行时,气流给出日志文件不存在错误

ish*_*ht3 9 python airflow airflow-scheduler

调度程序和网络服务器正在不同的容器上运行,当我运行 DAG 并检查网络服务器上的日志时,它向我显示了这个特定错误。

*** Log file does not exist: /usr/local/airflow/logs/indexing/index_articles/2019-12-31T00:00:00+00:00/1.log
*** Fetching from: http://465e0f4a4332:8793/log/indexing/index_articles/2019-12-31T00:00:00+00:00/1.log
*** Failed to fetch log file from worker. HTTPConnectionPool(host='465e0f4a4332', port=8793): Max retries exceeded with url: /log/indexing/index_articles/2019-12-31T00:00:00+00:00/1.log (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f0a143700d0>: Failed to establish a new connection: [Errno 111] Connection refused'))
Run Code Online (Sandbox Code Playgroud)

我设置了另一个类似问题中提到的气流变量,我在 cfg 文件上更改的唯一变量是这些。

AIRFLOW__CORE__SQL_ALCHEMY_CONN=postgresql+psycopg2://airflow:airflow@postgres:5432/airflow
AIRFLOW__CORE__LOAD_EXAMPLES=False
AIRFLOW__CORE__BASE_URL = http://{hostname}:8080
Run Code Online (Sandbox Code Playgroud)

我手动检查并正确生成了日志文件,我假设唯一的问题是无法通过网络服务器容器公开访问 url。我不确定我在哪里搞砸了,我正在本地运行和测试它。

Jam*_*mes 9

问题是因为 docker 容器不共享文件系统。响应的第一行表明了这一点。

然后,Airflow 会回退到尝试通过 HTTP 获取日志文件,如响应的第二行所示。其他答案尝试通过覆盖 HOSTNAME_CALLABLE 函数来解决此问题,但是除非主机通过 HTTP 公开日志文件,否则这将不起作用。

解决方案是通过安装共享卷来解决第一个问题。

在 docker-compose.yml 文件中,添加一个名为 的新卷logs-volume

volumes:
  logs-volume:
Run Code Online (Sandbox Code Playgroud)

然后,同样在 docker-compose.yml 文件中,将此卷添加到所需的日志目录(根据您的情况)/usr/local/airflow/logs/,对于每个服务:

services: 
  worker:
    volumes:
      - logs-volume:/usr/local/airflow/logs
  webserver:
    volumes:
      - logs-volume:/usr/local/airflow/logs
Run Code Online (Sandbox Code Playgroud)


dva*_*rub 1

工作人员的主机名未正确解析。添加文件hostname_resolver.py

import os
import socket
import requests
def resolve():
    """
    Resolves Airflow external hostname for accessing logs on a worker
    """
    if 'AWS_REGION' in os.environ:
        # Return EC2 instance hostname:
        return requests.get(
            'http://169.254.169.254/latest/meta-data/local-ipv4').text
    # Use DNS request for finding out what's our external IP:
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.connect(('1.1.1.1', 53))
    external_ip = s.getsockname()[0]
    s.close()
    return external_ip
Run Code Online (Sandbox Code Playgroud)

并导出:AIRFLOW__CORE__HOSTNAME_CALLABLE=airflow.hostname_resolver:resolve