현상
3개월에 한 번, 한 달에 한 번 등 스케쥴 주기가 긴 Dag를 생성했다. 기본 Dag 매개변수는 아래와 같아서 스케쥴 시간이 되도 자동으로 실행되지 않아 처음에는 트리거하여 실행했었다.
DEFAULT_DAG_ARGS = {
'depends_on_past': False,
'retries': 0,
'retry_delay': timedelta(seconds=20),
'provide_context': True,
'start_date': (datetime.now() - timedelta(days=2)),
'on_failure_callback': webhook.airflow_failed_callback,
'queue': 'default'
}
이후에 스케쥴러에 의해 자동으로 실행될 거라고 기대했는데, 매번 실행 시점이 되도 실행되지 않고 있었다.
원인
db clean 관련해 확인하다가 알게되었는데, 스케쥴 설정된 dag 실행의 연속성을 유지하기 위해서는 하나 이상의 dag_run이 존재해야 한다.
작업한 환경은 teamclairvoyant / db cleanup Dag를 이용해 주기적으로 Airflow Meta DB의 오래된 데이터를 삭제하고 있는데, 해당 Dag는 스케쥴이 설정된 dag의 연속성을 확보하기 위해 다음과 같은 설정으로 마지막 실행 인스턴스를 유지하고 있다.
- keep_last : 마지막 실행 인스턴스 유지 여부 (True/False)
- keep_last_filters : cleanup의 데이터 삭제 대상에서 제외할 필터 목록
- keep_last_group_by : DB 엔트리를 그룹화하고 집계 함수를 수행할 열
DATABASE_OBJECTS = [
{
"airflow_db_model": DagRun,
"age_check_column": DagRun.execution_date,
"keep_last": True,
"keep_last_filters": [DagRun.external_trigger.is_(False)],
"keep_last_group_by": DagRun.dag_id
}
]
즉, teamclairvoyant / db cleanup은 기본적으로 직접 트리거하여 실행한 dag_run 데이터는 유지하지 않고 삭제한다. 그리고 작업한 dag의 dag_run을 확인해보면…… 매우 슬픈 상태를 확인할 수 있다😭…….
다만 teamclairvoyant / db cleanup은 소스를 직접 수정할 수 있으므로 각자 환경에서 동작하는 db cleanup 설정을 확인해보는 것이 좋겠다.
해결
스케쥴러에 의해 dag를 실행시키게 하면 된다. 즉, start_date보다 shedule 주기가 짧아야 한다.
이 글에서는 shedule 주기를 임시로 일일 스케쥴로 변경했다.
# 기존
"45 0 * 3,6,9,12 2#1"
# 임시
"45 0 * * *"
정상 실행및 스케쥴 원복 후 airflow meta db에서 dag_run 데이터를 확인하면 다음과 같다. external_trigger 값이 0인 것을 확인할 수 있다.
이제 동일한 스케쥴 설정이지만 스케쥴에 의해 실행된 dag와 실행되지 않은 dag의 next_dagrun 값을 비교하면 다음과 같이 차이가 발생하는 것을 확인할 수 있다. 다만 스케쥴 원복 시점에 따라 다음 스케쥴로 넘어갈 수도 있는 것 같다.
start_date를 실행 주기보다 이전 시점으로 지정하는 게 더 깔끔한 방법 같다.
참고 문서
https://github.com/apache/airflow/pull/20838
https://github.com/teamclairvoyant/airflow-maintenance-dags/tree/master/db-cleanup