使用Apache Airflow DAG中的AWS SES发送故障电子邮件

时间:2018-06-01 14:22:45

标签: amazon-web-services airflow amazon-ses

每当我的DAG中的任务无法运行或重试运行时,我都会尝试让Airflow通过AWS SES向我发送电子邮件。我使用的是AWS SES凭证,而不是我的一般AWS凭证。

我目前 airflow.cfg

[email]
email_backend = airflow.utils.email.send_email_smtp


[smtp]
# If you want airflow to send emails on retries, failure, and you want to use
# the airflow.utils.email.send_email_smtp function, you have to configure an
# smtp server here
smtp_host = emailsmtpserver.region.amazonaws.com 
smtp_starttls = True
smtp_ssl = False
# Uncomment and set the user/pass settings if you want to use SMTP AUTH
smtp_user = REMOVEDAWSACCESSKEY
smtp_password = REMOVEDAWSSECRETACCESSKEY
smtp_port = 25
smtp_mail_from = myemail@myjob.com

我的DAG中的当前任务旨在故意失败并重试:

testfaildag_library_install_jar_jdbc = PythonOperator(
    task_id='library_install_jar',
    retries=3,
    retry_delay=timedelta(seconds=15),
    python_callable=add_library_to_cluster,
    params={'_task_id': 'cluster_create', '_cluster_name': CLUSTER_NAME, '_library_path':s3000://fakepath.jar},
    dag=dag,
    email_on_failure=True,
    email_on_retry=True,
    email=’myname@myjob.com’,
    provide_context=True
)

除了没有发送电子邮件外,一切都按设计工作,重试设定的次数并最终失败。我也检查了上面提到的任务中的日志,并且从未提及过smtp。

我看过类似的问题here,但唯一的解决办法对我不起作用。此外,Airflow的文档(例如示例here)似乎也不适用于我。

SES是否可以使用Airflow的email_on_failure和email_on_retry功能?

我目前正在考虑的是使用on_failure_callback函数调用AWS here提供的python脚本来发送失败的电子邮件,但这不是此时的首选路径。

谢谢你,感谢任何帮助。

2 个答案:

答案 0 :(得分:5)

- 通过工作SES更新6/8

这是我写的关于我们如何完成所有工作的文章。这个答案的底部有一个小摘要。

几点重点:

  1. 我们决定不使用Amazon SES,而是使用sendmail 我们现在已经开始使用SES了。
  2. 气流工作者为email_on_failureemail_on_retry功能提供服务。在Dag运行期间,您可以journalctl –u airflow-worker –f进行监控。在生产服务器上,在使用新的smtp设置更改airflow.cfg后,您无需重新启动气流工作人员 - 应自动选择它。无需担心搞乱当前正在运行的Dags。
  3. 以下是有关如何使用sendmail的技术说明:

    由于我们在localhost上从ses更改为sendmail,因此我们必须更改airflow.cfg中的smtp设置。

    新配置为:

    [email]
    email_backend = airflow.utils.email.send_email_smtp
    
    
    [smtp]
    # If you want airflow to send emails on retries, failure, and you want to use
    # the airflow.utils.email.send_email_smtp function, you have to configure an
    # smtp server here
    smtp_host = localhost
    smtp_starttls = False
    smtp_ssl = False
    # Uncomment and set the user/pass settings if you want to use SMTP AUTH
    #smtp_user = not used
    #smtp_password = not used
    smtp_port = 25
    smtp_mail_from =  myjob@mywork.com
    

    这适用于生产和本地气流实例。

    如果他们的配置与我的配置不同,可能会收到一些常见错误:

    • socket.error: [Errno 111] Connection refused - 您必须将smtp_host中的airflow.cfg行更改为localhost
    • smtplib.SMTPException: STARTTLS extension not supported by server. - 您必须将smtp_starttls中的airflow.cfg更改为False

    在我的本地测试中,我试图简单地强制气流显示尝试发送电子邮件时发生的事情的日志 - 我创建了一个虚假的dag,如下所示:

    # Airflow imports
    from airflow import DAG
    from airflow.operators.python_operator import PythonOperator
    from airflow.operators.bash_operator import BashOperator
    from airflow.operators.dummy_operator import DummyOperator
    
    # General imports
    from datetime import datetime,timedelta
    
    def throwerror():
        raise ValueError("Failure")
    
    SPARK_V_2_2_1 = '3.5.x-scala2.11'
    
    args = {
        'owner': ‘me’,
        'email': ['me@myjob'],
        'depends_on_past': False,
        'start_date': datetime(2018, 5,24),
        'end_date':datetime(2018,6,28)
    }
    
    dag = DAG(
        dag_id='testemaildag',
        default_args=args,
        catchup=False,
        schedule_interval="* 18 * * *"
        )
    
    t1 = DummyOperator(
        task_id='extract_data',
        dag=dag
    )
    
    t2 = PythonOperator(
        task_id='fail_task',
        dag=dag,
        python_callable=throwerror
    )
    
    t2.set_upstream(t1)
    

    如果您执行journalctl -u airflow-worker -f,您可以看到该工作人员说它已向您的DAG中的电子邮件发送了一封警告电子邮件,但我们仍然没有收到该电子邮件。然后,我们决定通过cat /var/log/maillog查看sendmail的邮件日志。我们看到了这样的日志:

    Jun  5 14:10:25 production-server-ip-range postfix/smtpd[port]: connect from localhost[127.0.0.1]
    Jun  5 14:10:25 production-server-ip-range postfix/smtpd[port]: ID: client=localhost[127.0.0.1]
    Jun  5 14:10:25 production-server-ip-range postfix/cleanup[port]: ID: message-id=<randomMessageID@production-server-ip-range-ec2-instance>
    Jun  5 14:10:25 production-server-ip-range postfix/smtpd[port]: disconnect from localhost[127.0.0.1]
    Jun  5 14:10:25 production-server-ip-range postfix/qmgr[port]: MESSAGEID: from=<myjob@mycompany.com>, size=1297, nrcpt=1 (queue active)
    Jun  5 14:10:55 production-server-ip-range postfix/smtp[port]: connect to aspmx.l.google.com[smtp-ip-range]:25: Connection timed out
    Jun  5 14:11:25 production-server-ip-range postfix/smtp[port]: connect to alt1.aspmx.l.google.com[smtp-ip-range]:25: Connection timed out
    

    所以这可能是最大的“哦对决”时刻。在这里,我们可以看到我们的smtp服务实际发生了什么。我们使用telnet确认我们无法连接到gmail的目标IP范围。

    我们确定该电子邮件正在尝试发送,但sendmail服务无法成功连接到ip范围。

    我们决定允许AWS中端口25上的所有出站流量(因为我们的气流生产环境是ec2实例),现在它可以成功运行。我们现在能够接收有关失败和重试的电子邮件(提示:email_on_failureemail_on_retry在您的DAG API Reference中默认为True - 您无需将其放入如果你不愿意,你的args,但在它中明确地陈述正确或错误仍然是好的做法。)

    SES现在有效。这是气流配置:

    [email]
    email_backend = airflow.utils.email.send_email_smtp
    
    
    [smtp]
    # If you want airflow to send emails on retries, failure, and you want to use
    # the airflow.utils.email.send_email_smtp function, you have to configure an
    # smtp server here
    smtp_host = emailsmtpserver.region.amazonaws.com 
    smtp_starttls = True
    smtp_ssl = False
    # Uncomment and set the user/pass settings if you want to use SMTP AUTH
    smtp_user = REMOVEDAWSACCESSKEY
    smtp_password = REMOVEDAWSSECRETACCESSKEY
    smtp_port = 587
    smtp_mail_from = myemail@myjob.com (Verified SES email)
    

    谢谢!

答案 1 :(得分:0)

这里有类似的情况,我尝试遵循相同的调试过程,但没有日志输出。另外,我的airflow ec2 实例的出站规则对所有端口和ips 都是开放的,所以应该是其他一些原因。

我注意到,当您从 SES 创建 SMTP 凭证时,它还会创建一个 IAM 用户。我不确定您的案例中的气流如何运行(ec2 实例上的裸机或包装在容器中),以及如何设置用户访问权限。