Airflow 무중단 이전
최근 EKS 클러스터 버전 업그레이드를, 노드별로 in-place 업그레이드 하는것이 아닌, 새로운 버전의 EKS 를 준비해서 기존버전 -> 신규버전으로 일종의 rolling update를 하는 작업을 진행하게 되었다.
이 때 여러 Addon(Istio, Argocd 등등), 애플리케이션들을 이전했는데, 특히 Airflow 를 무중단으로 이전하는 방법에 대해서 고민하고, 실제로 무중단로 이전한 과정에 대해서 공유해보고자 한다.
Airflow 컴포넌트
Airflow 무중단 이전 작업을 설계하기 앞서서, 정확히 Airflow 의 각 컴포넌트가 어떤 역할을 하는지 파악해보았다.
Airflow 는 아래와 같은 컴포넌트들로 구성되는데
- Scheduler : 예약된 워크플로우를 트리거하고, 실행할 작업을 executor 로 제출하는 작업을 처리하는 컴포넌트
- Webserver : DAG 와 작업의 동작을 확인하고, 실행시키거나, 디버깅 할 수 있는 인터페이스
- Metadata database : Airflow 의 컴포넌트가 워크플로우 및 작업의 상태를 저장하는데 사용하는 데이터베이스
위 컴포넌트들은 필수적으로 필요한 컴포넌트들이고, 이 외에 triggerer 등이 추가적으로 필요 할 수 있다.
여기서 scheduler 는 예약된 작업들을 트리거하고, executor 가 실행 할 수 있도록 하는 중요한 역할을 하는데, 이것은 Metadata database 를 바라보며 작업을 예약하거나, queued 된 예약된 작업을 executor 에 제출하는 역할을 한다.
무중단 이전 설계
따라서, 기존 버전의 EKS 와, 신규 버전의 EKS 양쪽에 동일한 Airflow 구성 (Metadata database 포함)을 하고, 점진적으로 기존 버전 EKS의 Airflow 에는 executor 에 작업을 submit 하지 않도록 하면서, 신규 버전 EKS 의 Airflow 에는 executor 에 작업을 submit 하도록 하는 형태로 작업하면 될 것이라고 구상했다.

위와 같이 구성을 하기 전에, 몇가지 우려되는 점이 있었는데.
- 동일한 구성, 동일한 Metadata database 를 바라보는 두 Airflow 가 있을 때, 한쪽 클러스터에만 워크플로우가 실행되어야 하는데, 양쪽에 동시에 실행되지 않을까?
- 기존 버전 EKS 에 존재하는 Airflow 인스턴스들을 내릴경우, 해당 클러스터 안에 존재하는 워크플로우들이 실패하게 될까?
결론부터 이야기하면 1번, 2번 모두 그렇지 않았다.

1번의 경우, Metadata database 의 테이블중 public.task_instance 를 보면 scheduled 된 워크플로우나, 수동으로 트리거한 워크플로우는 모두 해당 테이블에 queued 상태로 들어가게 되는데, 이 때 양쪽에 존재하는 스케쥴러중 하나가 queued 된 작업을 executor 에 제출하게 된다. 이 때 두 스케쥴러가 동시에 같은 데이터를 수정하지 않기 때문에 (Lock) 두 스케쥴러중 하나만이 작업을 가져가게 된다.
2번의 경우 실제로 테스트해본결과, Airflow 인스턴스들을 내린다고해서 기존 작업들에 SIGTERM 신호가 전달되거나 하지 않았다.
실제 작업 중 겪은 장애
양쪽 클러스터에 동일한 Airflow 인스턴스 (정확히는 동일한 helmchart 와 values 를 사용했다)를 세팅하고 DAG 들이 스케쥴링되고, 실행되는데 문제 없음을 확인했지만. Airflow 에서 사용할 전역 변수를 한쪽 인스턴스(웹서버)에서 수정하면, 반대편 웹서버에서는 해당 변수를 찾지 못하고, 반대로 해도 한쪽은 찾고 한쪽은 못찾는 장애가 발생하였다.
이것은 Airflow 가 데이터를 metadata database 에 저장할때, 특정 데이터들 (전역 변수)을 암호화 해서 저장하는데, Airflow 에서는 fernet key 를 사용한다.
따라서 기존 Airflow 에서 자동으로 생성된 fernet key 를 양쪽 helm value 에 동일하게 적용하고 실행하니, 완전하게 두 벌의 Airflow 가 문제없이 동작하는걸 확인 할 수 있었다.

장애 인 줄 알았던 것
이렇게 두벌의 Airflow 를 구성하고, 어느 한 쪽의 Airflow webserver 를 접근해서 DAG 실행 로그를 확인 할 때, 간헐적으로 로그가 확인이 되지 않아서 설정에 문제가 있나? 장애가 발생한건가? 라는 생각을 하기도 했었다.
결론적으로(당연하게도) 접근한 Airflow 가 속해있는 쿠버네티스 클러스터에 executor 가 실행중인 DAG 의 경우는 로그가 보이지만, 그렇지 않은경우에는 로그가 보이지 않는것에 불과했다.
당연한 동작이기 때문에 Airflow 를 양쪽에 생성하고, 한쪽 Airflow 를 내리고 신규 버전의 EKS 내의 새로 생성한 Airflow 쪽에만 모든 워크플로우가 실행되도록 하고 나서 당연하게도 해당 문제는 해결되었다.
결론
Airflow 를 무중단으로 이전하는 방법에 대해서 검색해보고, 적절한 접근법이 있으면 반영해서 작업하려고 했지만 딱히 내가 원하는 정보가 나오지 않아서 결국 뇌피셜(?)로 설계하고, 실제로 프로덕션 작업 이전에 개발 환경에서 Airflow 를 이것저것 만져보고 문제가 없음을 확인하고 프로덕션 Airflow 까지 원활하게 이전 작업을 완료했다.
처음에는 두 벌의 Airflow 를 동시에 존재하게 하는것이 문제가 없는가? 라는 의문이 계속 들었지만, 테스트를 해보니 결국 그런 설정에도 동일한 Metadata database 를 쓰고있다면 스케쥴러가 작업을 가져갈 때 두 스케쥴러중 오직 하나만이 작업을 가져가게 되는 (DB Lock 으로 인하여)구조라는것을 확인할 수 있었다.
그럼에도 (이론적으로) 문제가 없음을 확인했지만 혹시나 중복실행되면 어떡하지? 라는 걱정에 데이터 엔지니어분들과 이야기를 나눠봤는데, DAG 라는것이 결국 멱등성이 보장되어야 하는것이고, 그렇게 구성을 했다고 해서 중복실행되는 것에 대해서도 크게 걱정을 하지 않고 작업을 했다. (물론 중복실행 되지도 않지만!)
검색해서 좋은 레퍼런스를 찾아서 해결하는것도 좋지만, 해당 시스템이 어떤 구성을 갖고있고, 추상적인 레벨에서 어떻게 동작하는지를 확인하고 실제로 테스트해보면서 작업하면 충분히 무리없이 할 수 있다는걸 느끼게 되었다.
