← 학습 카테고리

Learn

Airflow

151개 모듈 · 현재 124번째

Airflow 모듈 124/151 airflow-learn-124

Airflow 업그레이드하기: 절차와 마이그레이션 트러블슈팅

Apache Airflow Official Documentation (in-repo snapshot) — Apache Software Foundation installation/upgrading.rst (전체, L1-287)

이 모듈을 다 읽으면

  • 업그레이드 전 DB 백업이 왜 '핫 백업'이 아니라면 서비스 중지 후 이루어져야 하는지 설명할 수 있다
  • 오프라인 SQL 마이그레이션 스크립트를 얻는 --show-sql-only 옵션의 사용법을 설명할 수 있다
  • MySQL utf8mb4 인코딩 문제로 마이그레이션이 실패하는 상황을 진단하고 복구하는 절차를 설명할 수 있다
  • 마이그레이션 후 뜨는 'incompatible data ... moved' 경고의 의미와 대처법을 설명할 수 있다

새 Airflow 버전은 DB 스키마 마이그레이션을 동반할 수 있어 `airflow db migrate` 실행이 필요하다. 이 모듈은 업그레이드 준비(백업), 실제 업그레이드 절차, 오프라인 SQL 마이그레이션, 오래된 MySQL 인코딩 문제 복구, 마이그레이션 후 데이터 이동 경고 대처법, 그리고 대규모 DB 마이그레이션 시간 산정에 대한 권고를 다룬다.

업그레이드 전 백업의 중요성

새 Airflow 버전은 DB 마이그레이션을 포함할 수 있으므로 업그레이드 시 `airflow db migrate`로 스키마를 갱신해야 한다. 마이그레이션할 것이 없어도 이 명령은 안전하게 실행할 수 있다.

마이그레이션 전에는 메타데이터 DB의 백업을 만드는 것이 강력히 권장된다. '핫 백업(hot backup)' 능력이 없다면 Airflow 인스턴스를 셧다운한 뒤에 백업해야 일관된 상태의 백업을 얻을 수 있다. 백업이 없는 상태에서 마이그레이션이 실패하면 절반만 마이그레이션된 상태에 빠질 수 있고, 이 경우 DB를 백업에서 복구한 뒤 마이그레이션을 재시도하는 것이 가장 쉬운 해결책일 수 있다. CLI와 DB 사이 네트워크 연결이 끊기는 것 같은 상황이 이런 실패의 한 원인이 될 수 있다.

핵심 포인트

  • 핫 백업 능력이 없다면 Airflow를 셧다운한 뒤 백업해야 일관성이 보장된다
  • 백업 없이 마이그레이션이 실패하면 절반만 마이그레이션된 상태에 빠질 수 있어 백업에서 복구 후 재시도가 최선일 수 있다

업그레이드 절차와 오프라인 SQL 스크립트

업그레이드는 원하는 새 버전을 지정해 apache-airflow를 재설치하는 것으로 시작한다. PyPI 패키지라면 원하는 버전을 constraint로 지정해 `pip install` 명령을 다시 실행한다. 이후 가상 환경이든 CLI 접근이 가능한 컨테이너든 어디서나 `airflow db migrate`를 실행해 DB를 수동으로 마이그레이션할 수 있다.

일부 배포(예: post-upgrade hook이 활성화된 Helm 차트, 또는 Airflow-as-a-Service의 UI 업그레이드)에서는 이 마이그레이션이 새 소프트웨어 설치 직후 자동으로 실행된다.

마이그레이션을 오프라인으로 미리 실행해보고 싶다면 `-s`/`--show-sql-only` 플래그로 실제 실행될 SQL 문만 확인할 수 있다. `--from-version`으로 시작 Airflow 버전을, `-n`/`--to-version`으로 목표 버전을 지정할 수 있다. 이 기능은 Airflow 2.0.0부터 Postgres/MySQL에서 지원된다. 예시:

airflow db migrate -s --from-version "2.4.3" -n "2.7.3"
airflow db migrate --show-sql-only --from-version "2.4.3" --to-version "2.7.3"

핵심 포인트

  • Helm 차트의 post-upgrade hook이나 관리형 서비스 UI 업그레이드에서는 DB 마이그레이션이 자동 실행될 수 있다
  • airflow db migrate -s(--show-sql-only)와 --from-version/--to-version(-n)으로 실제 실행될 SQL만 오프라인으로 미리 확인할 수 있다 (Postgres/MySQL, Airflow 2.0.0+)

MySQL utf8mb4 인코딩 문제 복구 절차

Airflow 1.10처럼 오래된 버전에서 수동으로, 또는 이전 MySQL 버전으로 생성된 DB는 원래 문자셋에 따라 새 버전으로 마이그레이션할 때 'key size too big', 'missing indexes' 같은 낯선 오류로 실패할 수 있다. 원인은 MySQL 8의 권장 문자셋/콜레이션인 `utf8mb4`/`utf8mb4_bin`가 버전에 따라 계속 바뀌어 왔고, 오래된 DB가 다른 문자셋으로 생성되었을 수 있기 때문이다. MySQL은 인덱스 키 크기에 제한이 있어 `utf8mb4`로는 Airflow의 ID 키 인덱스가 너무 커질 수 있다 — 그래서 Airflow는 모든 'ID' 키에 `utf8`(MySQL 8 기준 `utf8mb3`과 동일) 문자셋을 강제한다.

복구 절차의 개요는 다음과 같다: (1) DB를 백업한다. (2) `task_reschedule`, `xcom`, `task_fail`, `rendered_task_instance_fields`, `task_instance` 등 관련 테이블의 `SHOW CREATE TABLE` 출력을 확인해 `dag_id`, `run_id`, `task_id`, `key` 컬럼이 `utf8`/`utf8mb3`로 명시되어 있는지 점검한다 (문자셋이 없거나 `utf8mb4`로 되어 있으면 문제). (3) 수정할 테이블의 외래키 인덱스를 먼저 삭제한다(나중에 재생성하기 위해 `SHOW CREATE TABLE` 출력을 보관해둔다). (4) 문제 있는 ID 필드를 `ALTER TABLE ... MODIFY ... CHARACTER SET utf8mb3 COLLATE utf8mb3_bin`으로 수정한다. (5) 3단계에서 삭제한 외래키를 다시 생성한다.

이 작업 전에 Airflow 내부 DB 구조(`/database-erd-ref`)와 마이그레이션 목록(`/migrations-ref`)을 먼저 파악해두는 것이 권장된다. Airflow 버전에 따라 인덱스 구성이 다를 수 있음에 유의한다(예: `map_index`는 2.3.0에서 추가됨).

핵심 포인트

  • MySQL utf8mb4는 인덱스 키 크기 제한 문제로 Airflow ID 키에는 사용할 수 없어, Airflow는 ID 키에 utf8(=utf8mb3) 문자셋을 강제한다
  • 복구는 백업 → SHOW CREATE TABLE로 문제 컬럼 확인 → 외래키 삭제 → ALTER TABLE MODIFY로 문자셋 수정 → 외래키 재생성 순서로 진행한다
  • map_index처럼 버전별로 인덱스 구성이 다를 수 있으므로 SHOW CREATE TABLE 출력을 근거로 CONSTRAINT_NAME을 확인해야 한다

마이그레이션 후 데이터 이동 경고 대처

`airflow db migrate`가 대체로 문제없이 끝나지만, 간혹 DB에서 오래되거나 잘못된 것으로 보이는 데이터를 발견해 별도 테이블로 옮겨두는 경우가 있다. 이때 웹서버 UI에 경고가 표시된다: 원본 테이블에서 호환되지 않는 데이터를 발견해 마이그레이션 중 새 테이블로 옮겼으니 검토 후 필요 없으면 새 테이블을 직접 드롭해 경고를 없애라는 내용이다.

이 데이터는 대개 과거 버그로 인해 남은 손상된 데이터이며 Airflow에서 어차피 보이거나 쓰이지 않으므로, 감사(audit)나 이력 보존 목적이 아니라면 삭제하는 것이 최선의 선택지인 경우가 대부분이다.

테이블에 직접 접근 가능한 GUI 도구가 있다면 그것으로 드롭/이름변경/이관할 수 있고, 없다면 `airflow db shell`로 DB 셸에 들어가 조회/삭제할 수 있다. Kubernetes 환경에서는 웹서버나 스케줄러 파드에 `kubectl exec -it <pod> python`으로 접속해 파이썬 셸에서 `from airflow.settings import Session; session = Session(); session.execute("DROP TABLE _airflow_moved__2_2__task_instance"); session.commit()`처럼 직접 SQLAlchemy 세션으로 테이블을 드롭할 수 있다.

핵심 포인트

  • 마이그레이션이 호환되지 않는 데이터를 발견하면 별도의 _airflow_moved__ 테이블로 옮기고 웹서버 UI에 경고를 표시한다
  • 이 데이터는 대개 과거 버그로 남은 손상 데이터이므로 특별한 감사/이력 목적이 없다면 삭제가 권장된다
  • airflow db shell 또는 K8s의 kubectl exec + Session().execute(DROP TABLE ...)로 이동된 테이블을 직접 조회·삭제할 수 있다

마이그레이션 소요 시간 산정

DB 크기와 실제 마이그레이션 내용에 따라 마이그레이션에 상당한 시간이 걸릴 수 있다. 이력이 길고 DB가 크다면, 먼저 DB 복사본을 만들어 테스트 마이그레이션을 수행해 소요 시간을 가늠해보는 것이 권장된다. 일반적으로 '메이저' 업그레이드는 새 기능 추가로 DB 재구성이 필요한 경우가 많아 더 오래 걸리는 경향이 있다.

핵심 포인트

  • 이력이 길고 DB가 큰 환경은 실제 마이그레이션 전에 복사본으로 테스트 마이그레이션을 수행해 소요 시간을 미리 가늠하는 것이 권장된다
  • 메이저 업그레이드는 DB 재구성을 동반하는 경우가 많아 일반적으로 더 오래 걸린다