개요
이 글은 업무 중 만난 Airflow 서버 OS 업그레이드 작업에 대해 기록하기 위한 글이다.
먼저 업무에서 사용하는 Airflow 환경은 다음과 같다.
1. 서버
- AWS EC2
- Master 2대 (Webserver, Scheduler, Celery Flower 동작)
- Worker 2대 (Celery Worker 동작)
- Ubuntu 18.04 LTS (amd)
- 각 서버에 AWS EFS mount (DAG_FOLDER 동기화 및 airflow log/config 등 공유)
2. Airflow 설정
- Airflow HOME : /opt/airflow
Airflow home 경로 자체는 root 영역인 /opt/airflow이고, 그 아래에 airflow.cfg, logs, dags 폴더 등을 EFS 쪽으로 심볼릭 링크를 걸어 사용하는 것으로 보인다.
- Executor : CeleryExecutor
CeleryExecutor를 사용하는 만큼 Worker를 scalable하게 사용한다.
보통 AWS 환경에서 서버 scaling을 뜻하면 AWS AutoScaling 기능을 생각하는데, 이 글에서 다루는 환경은 AWS AutoScaling 기능을 사용하지 않는다. Dag가 동작하면서 Worker를 Launch 하여 Task를 해당 Worker에서 처리한 후, Worker를 Terminate 한다. 이를 위해 Worker AMI를 사용하는 Launch Templete을 사용한다.
3. Airflow Meta DB
- AWS RDS
- MySQL Community Engine 8.0
4. Message Broker
- AWS ElastiCashe
- Redis Engine 5.0
대충 이런 인프라를 기반으로 사용해왔는데 2023년 4월에 Ubuntu 18.04 LTS가 EOL 되어(……) 서버 담당자님으로부터 OS 업그레이드 검토 요청이 왔다.
참고 : https://endoflife.software/operating-systems/linux/ubuntu
그래서 Ubuntu 20.04 LTS로 업그레이드 작업 진행을 시작하려고 했다. 하지만 문제가 있었다. 일을 벌인 것을 후회하기 시작했다.
이슈 사항
기존 서버에 airflow 서비스 계정의 UID:GID는 1002:1002이었다. 그런데 신규 버전의 OS에서는 AWS 서비스가 추가되어 시스템 사용자로 UID:GID 1001:1001까지 사용하고 있었다. 당장은 ID 충돌이 나지 않지만, 이후 릴리즈에서는 충돌이 발생할 수 있는 상황이다. 따라서 이번 작업 중에 UID:GID 변경 수행 여부부터, UID:GID를 변경한다면 서비스 테스트를 위한 검증 환경 구성, 테스트 방법, 서버 전환 방법 등에 대한 고민이 필요한 상황이 되었다.
기존에 OS 업그레이드 작업을 할 때도 동일하게 서비스 계정의 UID:GID 변경이 발생하긴 했다. 다만 이전에 작업했던 서버들은 전부 EBS만 사용하기 때문에 EBS가 마운트 된 경로에서 chown을 수행하는 방식으로 충분히 해결할 수 있었다. 하지만 Airflow 인프라에서는 DAG_FOLDER 동기화를 위해 EFS를 사용하고 있는 상태다. 만약 OS 업그레이드용 서버에서 서비스 검증을 한답시고 신규 서비스 계정 UID:GID에 맞춰 chown을 수행하면 기존 서비스 계정이 파일/디렉터리에 대한 접근 권한을 잃게 되어 서비스에 영향을 미치게 된다.
방안
UID:GID 관련 문제로 나왔던 방안은 대략 다음과 같다.
1. UID:GID 변경 없이 OS 업그레이드만 수행한다.
이번 TO_BE OS 버전에서 충돌이 발생하는 것이 아니므로 다음 업그레이드 작업으로 미룬다.
=> 이미 발견된 이슈기도 하고, 이후로 미룰 이유는 없다고 판단한 것인지 고려조차 되지 않았던 것 같다.
그러므로 아래 방안은 전부 UID:GID 변경하는 것을 전제로 한 의견이다.
2. OS 업그레이드용 서버 뿐만 아니라 아예 검증용 Airflow 한 세트를 만든다.
OS 업그레이드 관련 서비스 검증을 위해 EC2 뿐만 아니라 EFS, Redis, RDS의 복제본을 생성해 서비스를 검증한다.
=> 가장 정석적이고 안전한 방법이다. 하지만 비용과 공수 생각을 안 할 수 없다.
사실 다른 환경의 Airflow에서 Ubuntu 20.04 LTS를 사용하고 있기 때문에 Airflow 설정만 제대로 되어 있다면 서비스의 정상 동작은 자명하다. 작업해야 하는 환경이 하나라면 해볼만 하겠으나, 5개 이상이기도 하고 아예 다른 신규 인프라 구성도 해야 하는 상황이라 너무 일이 커지는 감이 없지 않아 있었다.
그리고…… 서비스 검증이라고 해봐야 대단한 작업을 하는 게 아니다. webserver, scheduler 올리고 dag 하나 두 개 정도 트리거해볼 뿐이다. 배보다 배꼽이 더 큰 느낌인 셈이다.
그리고 서비스 검증을 위해 테스트 airflow 환경으로 설정값을 변경해주어야 하는 점도 있었다.
3. EFS 복제본만 새로 _old 경로로 마운트한다.
기존과 동일한 파일 시스템 구성에 서비스 검증 및 테스트를 위한 EFS 복제본을 생성해 /efs_old 정도의 경로로 마운트 한다. 그리고 서비스 동작 확인 및 EFS chown 소요 시간 산정 완료를 전제로, 기존 EFS는 서버 전환 과정에서 chown을 수행하여 파일/디렉터리 권한을 변경한다.
=> 개인적으로는 이 방안으로 진행하길 원했었다. 다만 몇 가지 고민이 필요한 지점이 있었는데, 다음과 같다.
a. DAG_FOLDER가 달라지는데 서비스 검증 과정에서 DAG_FOLDER 동기화는 어떻게 처리해야 하는가?
-> 보통 CD(Code Deploy)를 생각하면 Jenkins를 많이 생각하게 되는데, 이 환경은 airflow dag를 이용해 DAG_FOLDER 내 로컬 git 저장소를 대상으로 git 원격 저장소를 rebase 하여 Dag 정의 파일이나 로직 등도 배포한다. 즉, worker가 배포 task를 동작하면 자연스럽게 EFS에 의해 다른 서버에서도 동일하게 배포된 로직을 사용한다.
따라서 기존 worker에서 배포 dag가 동작하면 EFS 복제본을 마운트 한 경로에는 동기화가 되지 않아 디렉터리 양방향 동기화 등등에 대해 고민을 했었다.
그러나 생각해 낸 해결 방법은 꽤 허무했는데, 좀 번거롭긴 하지만 반영이 있을 때마다 EFS 복제본 쪽에도 수동으로 반영을 해주는 것이다. 어차피 임시로 잠깐 사용하는 것이기도 하고…… git 저장소가 열 개 이상인 것도 아니라 할만했다.
b. chown 수행 시간에는 얼마나 걸리는가? 수행 도중에 문제가 생길 가능성은 없는가?
-> chown 수행 시간에는 파일 용량보다는 파일 수가 더 영향을 미친다. 그리고 확인해 본 운영 환경 EFS 내 파일/디렉터리 수는 96만 개였다. Airflow Task Log를 EFS에 저장하고 있는데, 실행 주기가 3분인 dag가 여럿 존재해 파일 수가 많았다.
log 파일이야 버린다 치더라도 chown 수행 도중에 꼬이는 경우가 발생할 수 있을까? 꼬이면 골치 아플 것 같은데 꼬이면 어떡하지? 등등의 문제로 인해 이 방법은 사용하지 못했다.
c. 서버 전환 작업은 어떻게 진행해야 하는가?
chown을 수행하는 동안 서비스 중지 시간을 가져가야 하는가 말아야 하는가부터 쟁점이 된 것 같다.
서비스 담당자 의견은 이렇다.
- 신규 서버에 기존 서버 airflow GID와 동일한 group을 임시로 생성한다. 이름은 airflow_old 정도로 한다.
groupadd airflow_old -g 1002
- 신규 서버 airflow 계정을 airflow_old 그룹에 포함시킨다.
usermod -aG airflow airflow_old
이 경우, GID를 통해 기존 airflow 관련 디렉터리/파일에 접근할 수 있기 때문에 서비스 중지 없이 서버 전환이 가능하다.
반면 서버 담당자 의견은 이렇다.
- GID를 통해 접근을 할 수 있더라도 EFS 내 모든 파일/디렉터리의 소유자, 그룹 권한이 같지 않으면(775 정도) 문제가 될 수 있다.
- EFS 내 모든 파일/디렉터리의 소유자, 그룹 권한의 동일 여부를 검증하기 어렵다.
- EFS 내 모든 파일/디렉터리의 소유자, 그룹 권한이 같더라도 on service 상태에서 chown을 수행하면 파일 정합성 등에 문제가 생길 수 있을 것 같다. 즉, 안전하지 않다. 따라서 권한 등과 관련된 부분은 사전에 정리하고 서비스를 실행하는 게 맞겠다.
- 정말 on service 상태에서 전환을 해야 한다면 chown 수행 시 user, group 각각 두 번에 걸쳐서 수행하는 것이 안전하다.
-> 이 부분은 서버 담당자 의견이 좀 더 맞는 것 같다. 쓰기 중인 파일의 소유자를 변경할 때 서비스가 정상적으로 유지될지 잘 모르겠다.
4. 사용 중인 EFS 내 신규 디렉터리에 신규로 Airflow를 세팅한다.
검증용 서버 외의 자원 생성 없이 EFS 내 디렉터리를 새로 따서 Airflow 설정 환경을 새로 구성한다. 서비스 테스트를 마무리하면 기존 서버의 서비스를 내리고 신규 서버의 서비스만 유지하는 방법이다.
=> UID:GID 고민을 하지 않아도 되는 동시에 기존 Airflow 설정 환경을 포기하는 방법이다.
또 글에는 EFS 내 디렉터리를 간단하게 /airflow라고 표현하긴 했지만 실제로는 EFS 루트(/) 경로도 사용하고 있었다. 따라서 Airflow 설정 관련 디렉터리의 depth를 전체적으로 하나씩 내려야 했다. 결과적으로 작업 이후 기존 환경의 경로를 정리하지 않으면 EFS 내 디렉터리가 좀 지저분해진다. (지저분한 소스는 또 이루 말할 수 없이 지저분한데 인프라라도 좀 깔끔해야 하지 않겠는가.……)
고려해야 할 부분이 있다면 Airflow 설정 환경을 기존과 동일하게 설정할 수 있느냐이다. 다행히 Airflow에 배포되는 로직뿐만 아니라 Airflow 설치 스크립트 전부 GitLab으로 관리하고 있는 상태라 이 부분에 대한 고민은 크게 하지 않아도 되었다. 또 기존 디렉터리도 신규 서버에 마운트 하기 때문에 필요한 설정 등은 신규 경로로 복사할 수 있기도 했다.
다만 Airflow 설치 스크립트 등은 보통 한 번 세팅하고 나면 잘 유지보수하지 않게 되기 때문에…… 막상 실행시키면 잘 동작하지 않을 수 있다. 진행하면서 최신화가 필요하다.
그리고 Airflow 설정 디렉터리와 서버를 제외한 모든 리소스를 기존 환경과 공유하기 때문에 서비스 테스트 방법과 순서에 대한 고민이 필요하다.
결론
Airflow를 새로 세팅하는 4번 방식으로 검증을 진행하기로 했다.
4번 방법으로 진행하기로 판단한 이유는 다음과 같다.
- 검증용 서버 외 다른 자원을 생성하지 않아도 된다는 점에서 경제적이다.
- 신규 디렉터리 세팅이므로 UID:GID 충돌을 고민하지 않을 수 있다. 즉, 서비스 전환 방법을 고민하지 않아도 된다.
- chown을 수행하지 않아도 되므로 서비스 중지 시간을 길게 산정하지 않을 수 있다.
- chown을 수행하지 않아도 되므로 서버 담당자와 서버 전환을 위한 일정을 조율하지 않을 수 있다.
- 신규 서버와 기존 서버의 Airflow DAG_FOLDER 동기화는 수동으로 Git pull 하는 방식으로 해결할 수 있다.
- 기존 서버의 경로를 삭제하지 않으면 작업 이후에도 기존 서버의 설정을 참고할 수 있다.
- 개인적인 이유지만 업무에서 사용하고 있는 Airflow 설정 방법을 알아낼 수 있다…….
여러 가지 등등의 이유로 Airflow 환경을 신규로 세팅하는데 들어가는 공수가 Airflow 환경을 신규로 세팅함으로써 얻을 수 있는 이점보다 작다고 생각했다.
진짜 결론
이런 고민을 하지 않을 수 있도록 컨테이너 환경을 쓰는 게 좋겠다…….