요구는 두 가지였다. Job 이 실패하면 메일을 받고, Spark Job 로그에서 특정 패턴이 잡히면 메일을 받는다. 개발은 최소화하고 제품 기능을 최대한 쓴다.
| 요구 | 방식 | 개발량 |
|---|---|---|
| Job Fail 메일 | Virtual Cluster 의 Configure Email Alerting + Job 의 Alerts 토글 | UI 설정만 |
| 로그 패턴 메일 | 내장 기능 없음. Airflow 후속 Task 에서 판정 후 발송 | DAG 1개 |
CDE 에는 로그 메시지 패턴을 보고 알리는 기능이 없다. 가장 가까운 내장 옵션은 Cloudera Observability Premium 의 Workload View 알림인데 SLA · 실패율 기반이지 로그 패턴 기반이 아니고 별도 라이선스가 필요하다. 그래서 두 번째 요구는 Airflow 쪽에서 처리하는 것이 표준 경로다.
공식 문서가 명시하는 것은 Job Failure · Job SLA Miss 시점에 지정 주소로 메일을 보낸다는 트리거 동작뿐이고 본문 필드 명세는 공개돼 있지 않다. 실 운영에서 확인되는 항목은 Job 이름 · Run ID · 상태 · Virtual Cluster 와 CDE Service 이름 · 시작과 종료 시각 · Job Run UI 링크 정도이고, 에러 메시지나 스택트레이스는 포함되지 않거나 매우 제한적이다. 메일을 받고 CDE UI 로 들어가 로그를 보는 동선이 전제다. 정확한 본문은 테스트 발송 한 번으로 확정할 수 있다.
Private Cloud 1.5.0 문서의 Creating virtual clusters 항목은 "Configure Email Alerting 은 virtual cluster 를 생성하는 동안 구성해야 하며, Virtual Cluster details 를 편집해 이 기능을 켜거나 끌 수 없다" 고 적는다. 즉 이미 배포된 VC 에는 사후 활성화가 불가하다.
다만 이 문장을 그대로 최신 버전에 적용할 때는 주의가 필요하다. 명시적인 금지 문장이 있는 것은 1.5.0 문서(현재 아카이브) 뿐이고, 최신 Cloud 문서는 이 기능을 Technical Preview 로 표시하며 해당 항목을 그냥 언급하지 않는다. 문서에 없는 것은 부재이지 금지가 아니므로, 운영 버전의 UI 에서 실제로 편집 가능한지 먼저 확인하는 편이 낫다.
사후 활성화가 불가한 환경에서 선택지는 둘이다. 하나는 SMTP 설정을 포함한 신규 VC 를 만들고 Jobs · Resources · DAG 를 cde job create · cde resource create 로 재배포한 뒤 스케줄을 옮기고 기존 VC 를 제거하는 정식 경로다. 다른 하나는 운영 VC 를 그대로 두고 Airflow 레벨에서 메일을 보내는 우회다. VC 내장 Airflow 는 airflow.cfg 의 smtp_* 로 자체 SMTP 를 갖기 때문에 CDE UI 의 Alerts 토글이 보이지 않아도 Task 레벨 발송은 동작한다. 마이그레이션 부담을 생각하면 후자가 현실적이다.
| 경로 | 내용 | 특징 |
|---|---|---|
| 1-A | CDE 내장 Alerts 토글 | 개발 0. 본문 커스터마이즈 불가. VC 생성 시점 제약 |
| 1-B | Airflow email_on_failure |
Task 단위. 표준 Airflow 기능이라 추가 구현 없음 |
| 1-C | Airflow on_failure_callback |
본문을 직접 만들 수 있어 진단 정보 포함 가능 |
| 1-D | 일 1회 요약 Alert Spark Job | 실패 건을 모아 한 통. 즉시성은 없음 |
SLA Miss 는 Airflow 표준 sla 파라미터로 처리한다. SLA 를 넘겨도 Task 가 실패하지는 않고 알림만 발생한다는 점을 기억해야 한다. retries 가 걸린 Task 는 재시도마다 메일이 나가므로 발송 횟수를 미리 계산해 둔다.
로그를 grep 하는 접근은 불안정하다. 이 환경은 이미 일 배치로 하루치 데이터를 모아 패턴 필터링 결과를 Impala 조회 가능한 형태로 적재하고 있었고, CDE 자체 로그도 monitoring.cde_job_run_spark · cde_job_run_spark_logs 같은 Hive · Impala 테이블로 올라와 있었다. 로그 파일을 파싱하는 대신 이 테이블을 질의해 결과를 메일 본문 표로 만드는 편이 훨씬 안정적이고 본문에 실제 값을 담을 수 있다.
다만 이 경로는 배치 시점에만 동작하므로 실패 시점 트리거가 아니다. 실패는 내장 알림 또는 Airflow 콜백으로 즉시 알리고, 패턴 결과는 배치 뒤에 요약으로 보내는 이원 구성이 맞다.
알림 로직은 세 계층으로 나누면 Job 마다 중복이 생기지 않는다.
Layer 1 alert_common.py CDE Resource 에 올려 두는 순수 메커니즘
send_alert(to, subject, html, smtp_conf)
build_html_table(rows)
복호화 헬퍼(Fernet)
Layer 2 alert_spark_job_template.py Spark Job 베이스. conf 로 질의와 수신자를 주입
Layer 3 각 업무 DAG Layer 2 를 파라미터로 호출
Layer 1 은 도메인 지식을 전혀 갖지 않는다. 수신자 · 질의 · 제목 같은 결정 변수는 Job conf 로 주입해 Layer 3 에만 존재하게 한다. SMTP 계정 비밀번호는 코드에 넣지 않고 CDE Secret 으로 두고 런타임에 복호화한다.
from airflow.utils.email import send_email
def notify_failure(context):
ti = context["task_instance"]
body = (
f"<b>DAG</b>: {ti.dag_id}<br>"
f"<b>Task</b>: {ti.task_id}<br>"
f"<b>Run</b>: {context['run_id']}<br>"
f"<b>Log</b>: <a href='{ti.log_url}'>{ti.log_url}</a>"
)
send_email(to=["${ALERT_TO}"], subject=f"[CDE FAILED] {ti.dag_id}.{ti.task_id}", html_content=body)
default_args = {
"email": ["${ALERT_TO}"],
"email_on_failure": True,
"on_failure_callback": notify_failure,
}
VC 에서 SMTP 를 켠 뒤에는 시나리오를 나눠 한 번씩 확인한다. 일부러 실패하는 Spark Job 으로 내장 Alerts 가 오는지, email_on_failure 가 별도 설정 없이 동작하는지, on_failure_callback 으로 본문을 바꿀 수 있는지, EmailOperator 의 템플릿 렌더링이 되는지, SLA Miss 가 Task 실패 없이 알림만 내는지, retries 가 있을 때 메일이 몇 통 오는지를 각각 확인한다. CDE Airflow 는 Apache Airflow 의 표준 이메일 기능을 그대로 지원하므로 VC SMTP 가 켜져 있으면 email_on_failure · EmailOperator · send_email 이 추가 설정 없이 동작한다.