airflow工作流引擎的使用

Airflow是一个以编程方式创作、调度和监控工作流的平台。

使用 Airflow 将工作流创作为有向无环图(DAG)任务。 Airflow 调度程序按照你指定的依赖项在一组workers上执行您的任务。同时,Airflow拥有丰富的命令行实用程序使得在DAG上进行复杂的诊断变得轻而易举。并且提供了丰富的用户界面使可视化生产中运行的工作流、监控进度和需要排查问题时变得非常容易。

airflow是由好几个部分组成的系统,包括:

  • 一个调度器:它处理触发工作流调度,并将任务提交给执行器运行。
  • 一个执行器:它处理正在运行的任务。在默认的 Airflow 安装中,它运行调度器内的所有内容,但大多数适合生产的执行器实际上将任务执行推送给workers。
  • 一个WEB服务器:它提供了一个方便的用户界面来检查、触发和调试 DAG 和任务的运行情况。
  • 一个包含DAG文件的文件夹:由调度器和执行器(以及执行程序拥有的任何workers)读取
  • 一个元数据数据库:供调度器、执行器和WEB服务器用来存储状态。

这几个部分运行的容器如下图所示。

postgres是数据库,这个是可选的,也可以是mysql或sqlserver。

redis是用来进行任务分发的,每一个worker都来redis里面取任务然后执行。

webserver用来提供web页面,方便用户进行控制。

参考: 五分钟快速了解Airflow工作流 - 知乎

基本功能和使用

安装:

pip install apache-airflow

 初始化数据库

airflow db init

添加用户

airflow users create \
--username admin \
--firstname admin \
--lastname admin \
--role Admin \
--email admin@admin.com

 运行airflow,只需要这一个命令即可。

airflow standalone

如果分开运行 airflow schedule和webserver也可以,不过有点麻烦。

# 启动 web 服务器,默认端口是 8080
airflow webserver -p 8080 -D

# 启动定时器
airflow scheduler -D

airflow会在~/airflow目录下创建一系列的文件。

默认的配置文件是~/airflow/airflow.cfg

最常见的是以下几个配置:

# 关闭examples
load_examples = False
# 时区
default_timezone = utc+8
# dags文件目录
dags_folder = /home/user/airflow/dags

用浏览器打开 localhost:8080,登陆就可以看到下面的页面:

点击上图的右侧 小三角形 运行某个DAG后,点击此DAG出现DAG运行的历史。

下图左侧的几个柱子就是运行的历史。

右侧是每次运行的detail

点击下面的小方块(task) ,右侧显示task的logs

点击Graph可以显示此DAG中多个任务的关系图。

点击某个任务,可以对此任务进行一些处理。  clear task清除任务状态等等。

编写DAG

airflow的源码里面包含许多例子都可以作为学习的demo

https://github.com/apache/airflow/tree/main/airflow/example_dags

最常用的就是bashOperator和pythonOperator。

以这个example_bash_operator.py为例:

前面是DAG的属性定义,后面是定义几个task,

this_will_skip >> run_this_last 定义task的依赖关系。

from __future__ import annotations

import datetime

import pendulum

from airflow import DAG
from airflow.operators.bash import BashOperator
from airflow.operators.empty import EmptyOperator

with DAG(
    dag_id="example_bash_operator",
    schedule="0 0 * * *",
    start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
    catchup=False,
    dagrun_timeout=datetime.timedelta(minutes=60),
    tags=["example", "example2"],
    params={"example_key": "example_value"},
) as dag:
    run_this_last = EmptyOperator(
        task_id="run_this_last",
    )

    # [START howto_operator_bash]
    run_this = BashOperator(
        task_id="run_after_loop",
        bash_command="echo 1",
    )
    # [END howto_operator_bash]

    run_this >> run_this_last

    for i in range(3):
        task = BashOperator(
            task_id="runme_" + str(i),
            bash_command='echo "{{ task_instance_key_str }}" && sleep 1',
        )
        task >> run_this

    # [START howto_operator_bash_template]
    also_run_this = BashOperator(
        task_id="also_run_this",
        bash_command='echo "ti_key={{ task_instance_key_str }}"',
    )
    # [END howto_operator_bash_template]
    also_run_this >> run_this_last

# [START howto_operator_bash_skip]
this_will_skip = BashOperator(
    task_id="this_will_skip",
    bash_command='echo "hello world"; exit 99;',
    dag=dag,
)
# [END howto_operator_bash_skip]
this_will_skip >> run_this_last

if __name__ == "__main__":
    dag.test()

这里还有一个有一点特别的地方,就是this_will_skip这个任务,

可 以看到返回值是99,BashOperator对99的处理就是认为这个任务被skip了。其他的非0值都会当作是任务失败。

    :param skip_on_exit_code: If task exits with this exit code, leave the task
        in ``skipped`` state (default: 99). If set to ``None``, any non-zero
        exit code will be treated as a failure.

如果是pythonOperator,可以使用如下的@task 标记进行任务定义

如果在python任务中,比如下面的print_context()函数中,执行了一个操作,希望返回失败的结果,return 1 是不行的。

    # [START howto_operator_python]
    @task(task_id="print_the_context")
    def print_context(ds=None, **kwargs):
        """Print the Airflow context and ds variable from the context."""
        pprint(kwargs)
        print(ds)
        return "Whatever you return gets printed in the logs"

    run_this = print_context()

在pythonOperator中,显示任务失败可以使用异常。执行到这个airflow就知道这个任务失败了。

from airflow.exceptions import AirflowException
raise AirflowException("error msg")

k8s环境下airflow的使用

airflow这么牛逼,大家就希望可以在分布式环境下运行它啦。 

k8s下的安装需要采用helm,具体的命令如下:

# helm install
helm repo add apache-airflow https://airflow.apache.org

# list all releases.
helm list.
helm upgrade --install airflow apache-airflow/airflow --namespace airflow --create-namespace --debug

# uninstalling the airflow
helm delete airflow --namespace airflow

如果你没有现成的k8s,可以用kind在docker中运行一个k8s,kind就是k8s in docker。

下载kind,放到/usr/local/bin目录下就可以使用。后面helm安装airflow跟普通k8s操作是一样的。

curl -Lo kind https://github.com/kubernetes-sigs/kind/releases/download/v0.11.1/kind-linux-amd64 && chmod +x kind && sudo cp kind /usr/local/bin/kind
kind create cluster --name airflow

helm repo add apache-airflow https://airflow.apache.org
helm upgrade 
# helm upgrade --install airflow apache-airflow/airflow --namespace airflow --create-namespace --debug
kubectl create namespace airflow
helm install airflow apache-airflow/airflow --namespace airflow --debug

运行起来之后 ,用k8s的端口转发将airflow的webserver 8080端口暴露到外面。

# 端口转发的命令需要修改成这样
kubectl port-forward --address 0.0.0.0  svc/airflow-webserver 8080:8080 --namespace airflow

kubectl get pods -A可以看到全部的pods

这样有一个问题,就是airflow的dags是从airflow的docker image里面获取的,如果需要用,还要自行定制airflow的镜像。

airflow自定义镜像

这个airflow官方已经为我们考虑好了。叫做 image extending就是镜像扩展, 基于airflow现在的镜像加上一些dags,或装一些软件。

不过由于airflow官方提供的镜像是用于生产环境的,对安全极度的重视,导致镜像没有root权限,你进去以后,apt install 装不了软件,什么都做不了。 如果想撇开airflow官方自己只能custom一个镜像,不过这个会有一些难度。

Building the image — docker-stack Documentation

FROM apache/airflow是基于官方的镜像进行制作。原始镜像是基于debian的镜像。

容器中dags目录位于 /opt/airflow目录下,我们自己编写的dag需要放到这个目录中。

USER root 指示下面的命令用root进行执行。

后面的环境变量需要用USER airflow,因为是用airflow这个用户启动应用。

所以用pip install 一些库的时候,需要安装到airflow这个用户的目录下面。

FROM apache/airflow:2.7.1

COPY --chown=airflow:root test_dag.py /opt/airflow/dags


USER root
RUN apt-get update \
  && apt-get install -y --no-install-recommends \
         openjdk-11-jre-headless \
  && apt-get autoremove -yqq --purge \
  && apt-get clean \
  && rm -rf /var/lib/apt/lists/*

USER airflow
ENV JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
RUN pip install --no-cache-dir "apache-airflow==${AIRFLOW_VERSION}" apache-airflow-providers-apache-spark==2.1.3

编译镜像:

将镜像加载到kind集群中,然后通过helm修改airflow的镜像属性重新部署pods。

docker build --pull --tag my-dags:0.0.1 .
kind load docker-image my-dags:0.0.1 --name "airflow"

helm upgrade airflow apache-airflow/airflow --namespace airflow \
    --set images.airflow.repository=my-dags \
    --set images.airflow.tag=0.0.1

时区的表示

start_date=pendulum.datetime(2023, 9, 19, tz="Asia/Shanghai"),

默认是tz='UTC' , 不能使用tz='UTC+8',而要使用"Asia/Shanghai"这样的表示方式。

Docker compose部署airflow

参考:Running Airflow in Docker — Airflow Documentation

curl -LfO 'https://airflow.apache.org/docs/apache-airflow/2.7.2/docker-compose.yaml'

这个文件中有7个services。分别如下:

还有一个flower,它的作用是查看worker的状态。

新建几个文件夹:用于挂载到容器中。 

mkdir -p dags logs config plugins

dags存放项目, logs存放日志。config 和plugins 里面没什么东西。

docker compose up  # 拉起容器
docker compose down #销毁容器

docker compose start  # 启动
docker compose stop  # 停止

 运行的几个容器:

用浏览器打开 localhost:8080输入用户名 airflow , 密码 airflow登录就可以看到界面了。

如果要在另外一台机子上部署airflow worker,把上面的docker-compose.yaml复制过去,只需要保留services:里面 airflow-worker:这个服务即可。当然具体的配置,需要改成合适的。

https://airflow.apache.org/docs/apache-airflow/2.7.2/docker-compose.yaml

最主要的配置是这几个: 参考调度神器airflow-安装 - 简书

运行后,可以在flower页面查看有多个worker.

注意,各个不在同一台机器上的worker下面的dags目录下的内容一定要相同,否则在执行dags时,他们是各自执行自己的,可能会出现问题。

在本机运行airflow worker

airflow默认在本地是测试环境,用的是sqlite数据库。

如果是分布式环境下,运行celery worker,就必须采用postsql或mysql这些数据库。

本文建议大家采用docker compose 的方式运行airflow镜像。

但是如果因为某些原因必须在本地运行 airflow worker,也不是不可以。

启动airflow worker的命令是

AIRFLOW_HOME=$PWD airflow celery worker

AIRFLOW_HOME这个环境变量如果不提供的话,默认是~/airflow目录。

但是你可能会发现,你的airflow怎么没有 celery这个命令呢???

root@hwei:~# airflow -h
Usage: airflow [-h] GROUP_OR_COMMAND ...

Positional Arguments:
  GROUP_OR_COMMAND

    Groups:
      config         View configuration
      connections    Manage connections
      dags           Manage DAGs
      db             Database operations
      jobs           Manage jobs
      pools          Manage pools
      providers      Display providers
      roles          Manage roles
      tasks          Manage tasks
      users          Manage users
      variables      Manage variables

    Commands:
      cheat-sheet    Display cheat sheet
      dag-processor  Start a standalone Dag Processor instance
      info           Show information about current Airflow and environment
      kerberos       Start a kerberos ticket renewer
      plugins        Dump information about loaded plugins
      rotate-fernet-key
                     Rotate encrypted connection credentials and variables
      scheduler      Start a scheduler instance
      standalone     Run an all-in-one copy of Airflow
      sync-perm      Update permissions for existing roles and optionally DAGs
      triggerer      Start a triggerer instance
      version        Show the version
      webserver      Start a Airflow webserver instance

Optional Arguments:
  -h, --help         show this help message and exit

难道是你安装的airflow版本不对吗?

不是的,airflow默认是本地模式,如果想看到celery这个命令选项,你必须在airflow.cfg这个配置文件中修改这几个参数才可以:

也就是要将airflow的运行模式调成集群模式才可以。

airflow在运行时,会自动加载AIRFLOW_HOME下的airflow.cfg这个配置文件,根据不同的配置文件做出改变。

如果你希望用当前目录下的airflow.cfg配置airflow,就要添加AIRFLOW_HOME=$PWD , -D可以让airflow worker在后台运行。

AIRFLOW_HOME=$PWD airflow celery worker -D

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Python有很多工作流引擎,可以用于构建、管理和执行工作流,以下是一些常用的工作流引擎: 1. Apache Airflow:这是一个基于Python的工作流管理工具,可以用于调度、监控和维护复杂的工作流。它提供了丰富的任务调度和依赖关系管理功能,支持多种任务类型和多种执行模式。 2. Prefect:一个用于构建工作流的现代Python库,它提供了一个可编程的、声明性的API,可以用于定义、运行和监控工作流。它支持多种数据源和多种任务类型,可以与其他Python库和工具集成。 3. Luigi:一个轻量级的Python工作流框架,它提供了一个简单的API,可以用于定义和运行工作流。它支持多种任务类型和多种执行模式,可以与其他Python库和工具集成。 使用这些工作流引擎,可以通过Python编写自定义任务、流程和依赖关系,以及自动化处理和部署工作流。例如,使用Apache Airflow,可以通过以下代码定义一个简单的工作流: ``` from airflow import DAG from airflow.operators.bash_operator import BashOperator from datetime import datetime, timedelta default_args = { 'owner': 'airflow', 'depends_on_past': False, 'start_date': datetime(2021, 1, 1), 'email': ['airflow@example.com'], 'email_on_failure': False, 'email_on_retry': False, 'retries': 1, 'retry_delay': timedelta(minutes=5), } dag = DAG( 'my_dag', default_args=default_args, description='A simple tutorial DAG', schedule_interval=timedelta(days=1), ) t1 = BashOperator( task_id='print_date', bash_command='date', dag=dag, ) t2 = BashOperator( task_id='sleep', bash_command='sleep 5', retries=3, dag=dag, ) t1 >> t2 ``` 这个代码片段定义了一个名为“my_dag”的工作流,其中包含两个任务:一个打印日期,一个休眠5秒。这些任务由BashOperator运行,并且t2任务具有重试逻辑。任务之间的依赖关系由“>>”操作符定义。您可以使用类似的代码定义和运行自定义工作流。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路边闲人2

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值