【问题标题】:EMR DAG terminates before all steps are completedEMR DAG 在所有步骤完成之前终止
【发布时间】:2018-10-29 14:53:54
【问题描述】:

我在我的 DAG 中使用 EMR CreateJobFlow、AddSteps、StepSensor 和 TerminateJobFlow 运算符来启动 EMR 集群、添加步骤(2 个 spark 应用程序和 dist-cp),并在所有步骤完成或 1 个失败时终止。当我有一个 2 步 DAG(第一个是 Spark 应用程序,第二个是 dist-cp)时,我能够做到这一点,但是,当我有 2 个 spark 应用程序时,集群成功运行了第一个步骤,并且终止而不继续第二步和第三步。

通过一些挖掘,我可以看到 Airflow “戳”步骤以查看它们是否仍在运行。在这种情况下,似乎只有当 1 步完成时才认为它是“成功的”。

我的 spark 应用程序相当简单。第一个创建数据帧并将其写入本地 HDFS。第二个从 HDFS 读取数据并加入另一个数据集并写回 HDFS。第三步是s3-dist-cp,将数据从HDFS拷贝到s3。所有 3 个步骤都可以在 Spark-Shell 中以交互方式或作为 Spark-Submit 作业成功运行。我自己也克隆了 EMR 集群(没有气流)并且看到所有步骤都成功且没有任何错误,因此 EMR 和 Spark 不是这里的问题。

DAG 在下方


    from datetime import timedelta

    import airflow
    from airflow import DAG
    from airflow.contrib.operators.emr_create_job_flow_operator \
        import EmrCreateJobFlowOperator
    from airflow.contrib.operators.emr_add_steps_operator \
        import EmrAddStepsOperator
    from airflow.contrib.sensors.emr_step_sensor import EmrStepSensor
    from airflow.contrib.operators.emr_terminate_job_flow_operator \
        import EmrTerminateJobFlowOperator

    DEFAULT_ARGS = {
        'owner': 'airflow',
        'depends_on_past': False,
        'start_date': airflow.utils.dates.days_ago(2)   
    }

    SPARK_TEST_STEPS = [
        {
            'Name': 'monthly_agg',
            'ActionOnFailure': 'CONTINUE',
            'HadoopJarStep': {
                'Jar': 'command-runner.jar',
                'Args': ['spark-submit',
                          '--deploy-mode',
                           'cluster',
                          '--class' ,
                          'AggApp',
                          's3://jar1.jar' ]
                            }
        },   
        {
            'Name': 'monthly_agg2',
            'ActionOnFailure': 'CONTINUE',
            'HadoopJarStep': {
                'Jar': 'command-runner.jar',
                'Args': ['spark-submit',
                          '--deploy-mode',
                           'cluster',
                          '--class' ,
                          'SimpleApp',
                          's3:/jar2.jar' ]
                            }
        },  

        {
            'Name': 'copy-data',
            'ActionOnFailure': 'CONTINUE',
            'HadoopJarStep': {
                'Jar': 'command-runner.jar',
                'Args': ['s3-dist-cp',
                          '--src',
                          '/tempo',
                          '--dest',
                           's3://mydata/'
                        ]
                            }
        }
    ]

    JOB_FLOW_OVERRIDES = {
    'Instances': {'Ec2SubnetId': 'subnet-mysubnetid', 
        'InstanceGroups': [
            {
                'Name': 'Master nodes',
                'Market': 'ON_DEMAND',
                'InstanceRole': 'MASTER',
                'InstanceType': 'r4.2xlarge',
                'InstanceCount': 1
            },
            {
                'Name': 'Slave nodes',
                'Market': 'ON_DEMAND',
                'InstanceRole': 'CORE',
                'InstanceType': 'r4.2xlarge',
                'InstanceCount': 8,
                'EbsConfiguration': {'EbsBlockDeviceConfigs':[{'VolumeSpecification':{'SizeInGB':128,'VolumeType':'gp2'},'VolumesPerInstance':1}],'EbsOptimized':True}
            }
        ]},
        'Name':'airflow-monthly_agg_custom',
        'Configurations': [
        {
        'Classification':'spark-defaults','Properties':
            {'spark.sql.crossJoin.enabled':'true',
            'spark.serializer':'org.apache.spark.serializer.KryoSerializer',
            'spark.hadoop.mapreduce.fileoutputcommitter.algorithm.version':'2',
            "maximizeResourceAllocation":"true"},
        'Configurations':[]
        },
        {
        'Classification':'spark-hive-site','Properties':
        {'hive.metastore.client.factory.class':'com.amazonaws.glue.catalog.metastore.AWSGlueDataCatalogHiveClientFactory'}, 
        'Configurations':[]
        }
        ]}

    dag = DAG(
        'monthly_agg_custom',
        default_args=DEFAULT_ARGS,
        dagrun_timeout=timedelta(hours=4),
        schedule_interval='@once'
    )

    cluster_creator = EmrCreateJobFlowOperator(
        task_id='create_job_flow',
        job_flow_overrides=JOB_FLOW_OVERRIDES,
        aws_conn_id='aws_default',
        emr_conn_id='emr_default',
        dag=dag
    )

    step_adder = EmrAddStepsOperator(
        task_id='add_steps',
        job_flow_id="{{ task_instance.xcom_pull('create_job_flow', key='return_value') }}",
        aws_conn_id='aws_default',
        steps=SPARK_TEST_STEPS,
        dag=dag
    )

    step_checker = EmrStepSensor(
        task_id='watch_step',
        job_flow_id="{{ task_instance.xcom_pull('create_job_flow', key='return_value') }}",
        step_id="{{ task_instance.xcom_pull('add_steps', key='return_value')[0] }}",
        aws_conn_id='aws_default',
        dag=dag
    )

    cluster_remover = EmrTerminateJobFlowOperator(
        task_id='remove_cluster',
        job_flow_id="{{ task_instance.xcom_pull('create_job_flow', key='return_value') }}",
        aws_conn_id='aws_default',
        dag=dag
    )

    cluster_creator.set_downstream(step_adder)
    step_adder.set_downstream(step_checker)
    step_checker.set_downstream(cluster_remover)

【问题讨论】:

标签: python airflow


【解决方案1】:

问题是您将EmrStepSensor 作为一个stepadder 提供所有步骤,因此一旦完成,它就会终止集群。

解决方法是将所有步骤分开,并将最后一步的'id 给EmrStepSensor。或者,您可以仅使用其单独的步骤加法器 (step_adder_actual_step) 将其提供给 EmrStepSensor

step_adder_pre_step = EmrAddStepsOperator(
    task_id='pre_step',
    job_flow_id="{{ task_instance.xcom_pull('create_job_flow2', key='return_value') }}",
    aws_conn_id='aws_default',
    steps=pre_step,
    dag=dag
)

step_adder_actual_step = EmrAddStepsOperator(
    task_id='actual_step',
    job_flow_id="{{ task_instance.xcom_pull('create_job_flow2', key='return_value') }}",
    aws_conn_id='aws_default',
    steps=actual_step,
    dag=dag
)

step_checker = EmrStepSensor(
    task_id='watch_step',
    job_flow_id="{{ task_instance.xcom_pull('create_job_flow2', key='return_value') }}",
    step_id="{{ task_instance.xcom_pull('actual_step', key='return_value')[0] }}",
    aws_conn_id='aws_default',
    dag=dag
)

cluster_remover = EmrTerminateJobFlowOperator(
    task_id='remove_cluster',
    job_flow_id="{{ task_instance.xcom_pull('create_job_flow2', key='return_value') }}",
    aws_conn_id='aws_default',
    dag=dag
)

cluster_creator >> step_adder_pre_step >> step_adder_actual_step >> step_checker >> cluster_remover 

【讨论】:

    猜你喜欢
    • 2019-10-17
    • 2020-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-18
    • 1970-01-01
    相关资源
    最近更新 更多