회사에 입사하고 나서 처음으로 프로덕션 환경에서 데이터 파이프 라인을 구축하고 배포한 경험을 정리해보고자 한다. 사실 프로젝트 끝난지는 한달정도가 되어가는데.. 내일 새로운 빅데이터 플랫폼 구축 프로젝트가 시작되기 전에 나의 첫 프로젝트를 먼저 회고해보기로 했다. 나는 6개월짜리 Databricks 기반의 빅데이터 플랫폼을 구축하는 프로젝트에서 데이터 엔지니어링을 담당했다.
실제로는 4개월 정도 참여했으나, 프로젝트가 특이하게도 1차 배포 - 2차 배포 + 운영 의 프로세스로 진행되어 운좋게도 인프라 구축부터 파이프라인 개발, 운영 모니터링 과정의 ETL 파이프라인 개발의 한 cycle을 경험할 수 있었다. 총 4개월 - 길면 길고 짧다면 짧지만 - 동안 택시도 타고 주말도 반납하면서 실전에서 부딪히며 느꼈던 점들을 정리했다.
데이터 플랫폼도 개발계와 운영계가 필요한가요 ?
당연하게도 있으면 좋다! 그렇지만 필수는 아니라고 생각이 들었다. 데이터 브릭스 환경에서는 Unity Catalog 라는 개념이 있어서, 한 account 에서 생성한 workspace 들이 있다면 각각 다른 workspace 들도 동일한 스키마에 권한이 있다면 접근할 수 있다. 따라서 개발계와 운영계를 분리하더라도 데이터 접근에 한계가 없다. 개발계와 운영계별로 권한을 다르게 관리할 수 있고, 데이터 파이프라인도 개발계에서 테스트하다가 운영계에서 배포를 할 수 있다. ETL 파이프라인 뿐만 아니라 MLOps 파이프라인 및 실험 또한 가능하다.
그렇지만 필수는 아니라고 생각한다. 하나의 workspace에서도 개발용 데이터와 운영용 데이터를 분리할 수 있을 것이다. 또한 개발계 데이터와 운영계 데이터가 달라, 분석을 하는 경우에는 운영계 데이터를 봐야 실질적으로 레포트를 만들 수 있을 것이라고 생각이 들었다.
개발계와 운영계를 나누는 경우, 백엔드 application 을 배포할 때와 마찬가지로 환경 변수들만 분리하여 코드의 수정없이 재사용 가능하도록 개발하는 것이 중요하다.
이번 프로젝트의 경우에는 AWS 계정을 3개를 사용했으며 Management 영역, Production 영역, Development 영역으로 나누었다. Databricks workspace의 경우, workspace를 통합 가버넌스로 관리하는 Unity Catalog 용 metastore 를 Management 영역에 S3로 배치했다. 그리고 Production 영역에 운영계 workspace, Development 영역에 개발계 workspace를 두었다. Databricks metastore는 Hive metastore 처럼 메타데이터를 관리한다. 이 메타데이터에는 테이블 스키마, 파티션 정보, 위치, 컬럼 정보에 대한 메타 정보들이 있다.
개발계 workspace와 운영계 workspace 각각에 있는 테이블 메타데이터를 물리적으로 어디에 위치시키는 것이 좋을까 고민하였고, Management account의 S3에 두는 것이 논리적으로 옳다고 생각하여, Management 영역에 두기로 결정했다.
검증로직은 반복을 최소화하자
데이터 마이그레이션 이후, 적재된 데이터의 퀄리티를 검증하기 위해 검증 로직이 필요하다. 검증 로직은 결국 각 column과 row들을 하나씩 봐야 하기 때문에 for 문의 반복이 될 수 밖에 없다. 따라서 불필요한 반복문을 줄여주는 것이 최적화의 핵심이었다. 또한 처음에는 검증로직을 한 ETL Job의 마지막 Task 로 추가했었으나, 실행시간이 길어진다는 판단하에 별도로 분리하기로 했다. 상황에 따라서는 초기에 ETL 파이프라인을 배포했을 때는 검증로직을 포함하고, 안정화된 이후 검증로직을 분리하는 경우도 있다고 한다.
Spark 튜닝의 늪
데이터 마이그레이션 작업 (테이블 초기 전체 적재 작업) 에서 data skew 와 OOM 을 겪었고, 이를 해결하기 위해 여러가지 삽질 실험적으로 트러블 슈팅을 해야 했다. 관련된 내용은 아래 포스팅에 자세히 적어두었다.
ETL도 로그가 필요하다
ETL 파이프라인도 로그 데이터는 필요하다!! ETL 파이프라인에 대한 로그는 주로 데이터가 테이블에 삽입된 row 수, 삭제된 row 수, update 가 일어난 row 수를 수집한다. 또한 ETL 프로그램이 실행된 시작 시간과 종료 시간을 수집하여, 실행 시간이 갑자기 너무 길어지게 되면 이상을 감지할 수 있게 된다.
한편, 데이터 수를 count 하여 로그 데이터를 수집할 때 df.count() 를 하면 메모리 낭비가 심하고 실행시간도 길다. 모든 파티션을 스캔하여 레코드 수를 세고, 합산하기 때문에 소모가 크다. 이는 배치 작업을 불필요하게 길어지게 하는 원인이 된다고 판단했다. 따라서 이를 원천 Database 에 직접 query 를 (select * from TARGET_TABLE) 날려서 count를 수집하는 것으로 바꾸어 30분이 걸리던 job 을 8분정도로 단축할 수 있었다.
초반에 레포트를 수작업으로 작성하여 보고하는 것을 보고 노가다는 역시 귀찮.. 불편함을 느껴, 적극적으로 대시보드를 만들자고 건의했다. 만들다보니 이 로그 데이터도 수집하면 좋겠고, 저것도 수집하면 좋을 것 같고 해서 욕심에 로그 테이블이 확장되었다. 로그 테이블을 설계하기 전에 대시보드 설계를 마치고 꼭 필요한 데이터만 수집하는 방향이 좋아보인다.
꺼진 방화벽도 다시보자 ! 보안그룹 !
주로 인프라관련에서 문제가 있다면 보안 그룹 설정 (AWS에서는 방화벽 개념의 보안그룹이 존재한다.) 에서 port 를 열어주지 않아 발생하는 문제들이었다. 혹은 Database 연결시에 잘못된 Host 주소를 전달 받은 경우도 있었다. 등잔 밑이 어둡다는 말 처럼, 가장 기본적인 요소부터 체크할 필요도 있다.
자동화의 자동화를 위한 기준 정보 테이블
배치 작업을 자동화하기 위한 ETL 파이프라인을 자동화하여 관리하기 위해 '기준 정보 테이블' 들을 구성하였다. 이 기준 정보 테이블에는 각각의 ETL job 에 대한 정보가 들어간다. 테이블의 데이터의 기준이 되는 날짜 구간을 start date, end date로 두었다. 그리고 start date와 end date 정보를 원천 테이블에서 가져올 때 query 에 정보로 활용한다.
SELECT col_a, col_b, col_c
FROM target_table
WHERE start_date <= date AND date < end_date
해당 job 이 성공적으로 실행되면 로그 테이블에 SUCCESS가 남게 된다. SUCCESS가 남게 되면 end_date는 start_date가 된다. SUCCESS와 날짜 정보를 기준으로 멱등성을 보장할 수 있게 되는 것이다.
이외에도 primary key 역할을 하는 key column 들, 각 task 의 정보들, source table의 정보, landing zone의 정보 등 자동화에 필요한 값들도 기준 정보 테이블에서 관리한다. 이렇게 되면 ETL 파이프라인에서 개발자의 하드코딩을 방지하고, 파라미터 값들을 테이블에서 관리할 수 있다는 장점이 있다. 기준 정보 테이블이 잘못되면 파이프라인 결과도 잘못될 것이며, 엔지니어들이 모두 이 기준 정보 테이블의 방식을 정확히 이해하고 있어야 한다는 관리 포인트가 있다.
(당연하지만) 커뮤니케이션은 어딜가나 중요해
개발자도 커뮤니케이션이 중요하다! 라는 말은 이제는 어디에서나 들을 수 있다. 어떤 날은 회사에서 한마디도 하지 않은 날도 있다. 그렇지만 데이터 엔지니어 직군 특성상 다른 부서나 현업과 커뮤니케이션이 많이 필요한 직군이라고 생각이 들었다. 데이터 엔지니어 커뮤니티에서는 우스갯소리로 데이터 잡부라고 농담반 진담반으로 일컫는다. 나는 잡부라는 워딩보다는 제너럴리스트라는 워딩을 사용하고 싶다. 인프라팀과 방화벽 문제로 소통해야 하고, DBA에게 데이터베이스 접근 시 모니터링을 받아야 하며, 분석가 및 데이터 사이언티스트들의 니즈에 맞게 데이터를 수집 - 가공 - 적재해야 한다. 뿐만 아니라 데이터 엔지니어들끼리도 분명 어떻게 workflow를 디자인할 것이며, 어느 순서로 배치작업을 실행시키고, 운영해나갈지 스타일이 다를 것이므로 커뮤니케이션이 기본이라지만 가장 중요하다는 것을 많이 느꼈다. 문제를 빠르게 이해하고, 비용 효율적이면서도 지속 가능하게 해결하는 엔지니어가 되자.. (는 나한테 하는 말)
Databricks 어때요 ?
냉정하게 장점과 단점을 말해보자! 우선 필자는 22년도 에듀테크 스타트업에서 인턴을 하며 Databricks 와 데이터 엔지니어링을 처음으로 접했다. 그 당시에는 spark 문법에도 익숙하지 않았지만, 그때부터 지금까지 Databricks 플랫폼에서 여러 경험을 하고 있다.
장점부터 이야기 해보자면 다음과 같다.
- all-in-one Data Platform 이다.
Databricks가 지향하는 바이기도 하다. 데이터 엔지니어링, 데이터 사이언스, 데이터 분석, 데이터 가버넌스를 통합한 데이터 플랫폼이다. 뜯어보면 다양한 데이터 관련 기능들이 내장되어 있다. Redash 기반 대시보드, Notebook 환경, Workflow, Delta Live Table, Catalog, SQL Editor, MLFlow, Feature Store 등이 있다.
- 트렌디한, 빠르게 개발 & 보완되는 PaaS 서비스
원래 Databricks는 Data Lakehouse 라는 컨셉으로 마케팅을 했었는데, 현재는 유행의 흐름에 발맞춰 Generative AI 을 붙여 Intelligence Platform 이라는 컨셉으로 미는 것 같다. LLM 을 붙여서 text to sql 이나, Google colab 처럼 notebook cell 에 AI 어시스턴트를 붙여 트러블 슈팅을 용이하게 해놓기도 했다. 뿐만 아니라 사용자들의 에로사항을 듣는것인지, Spark Cluster 를 띄울 때 10분씩이나 걸린다는 점이 답답했는데, SQL warehouse의 경우 serverless 서비스를 도입하기도 했다.
- Spark Cluster를 쉽게 생성할 수 있다.
Spark 를 사용해야하는 엔지니어들에게 좋은 선택지인 것 같다. Spark 완벽 가이드 책에서도 spark 문법을 학습하기 위한 목적으로 Databricks community (무료로 제공한다.) 버전을 추천하기도 한다. 별도의 클러스터 구축 없이 Spark 클러스터의 구성을 Web Console에서 선택하고 인스턴스를 띄울 수 있다. 또한 Spark를 Jupyter Notebook 환경에서 사용할 수 있다. java, python, scala, SQL 를 모두 지원하는 것도 편리하다. auto scaling 이나 spark UI, Ganglia 와 같은 모니터링 도구도 별도 서버를 띄우지 않아도 Web console에서 바로 사용할 수 있다.
- Open Source에 비해 자잘한 에러들이 핸들링 된다.
airflow의 경우 executor 구성도 직접 해주어야하고, (그만큼 자유도가 높겠지만) 트러블 슈팅도 자잘한 이슈들이 많았다. 이에 비해 Databricks workflow는 얌전한 (?) 편이라는 생각이 들었다.
반면, 데이터브릭스를 처음부터 쌓아올리면서 느꼈던 단점들을 솔직하게 적어보았다.
- AWS 위에서 구축하는 것은 상당히 손이 많이 간다.
Azure 환경에서는 Databricks Workspace를 배포할 때 클릭 한번이면 된다고 하던데, AWS에서는 customized VPC 위에서 Private Link 를 사용한 구성을 위해서는 IAM role, S3 Bucket, VPC 구성, STS 설정 과 같이 여러 AWS서비스를 건드려야 한다. AWS 경험이 없는 상태에서 공식 document 만 보고 workspace를 배포하는 것은 진입 장벽이 있어 보인다.
- Git과의 연동이 불편했다.
Git 과 연동을 하여 repository 에서 workflow를 배포할 수 있으나 Git Credential 이 자꾸 끊기는 현상이 종종 일어난다. 배치 파이프라인이 아예 실패하게 되는 원인이 되기 때문이 치명적이다. 또한 Git을 UI에서만 명령어를 실행시킬 수 있으며, CLI 명령어 사용이 불가하다. UI에서 작업하게 되면 사용할 수 있는 명령어가 제한적이다.
- 클러스터의 종류와 사용자 role 등 데이터 가버넌스를 지원하는 건 좋지만, 조잡하다!!
권한을 세세하게 줄 수 있는 것은 장점임에 분명하지만, 한눈에 볼수는 없어서 복잡하다. Pipeline에서도 run as 를 누구로 설정하느냐에 따라서, cluster 종류에 따라서 실행 권한이 달라진다. 또 cluster 의 종류에 따라서 unity catalog 를 사용할 수 있는 클러스터가 있고, 특정 프로토콜의 경우에는 single mode에서만 지원이 된다는 등의 제약조건이 있다. 이는 Databricks 가 그들의 데이터 가버넌스라는 철학에 맞게 나름 클러스터 정책도 설계 해둔 것이겠지만.. 엔지니어의 마음대로 커스터마이징하기에 오히려 불편하다는 점이 있다!
- DLT를 밀고 있지만, 한계점이 있다. 그래서 다시 Spark 로 돌아갔다.
SQL로도 Spark 를 사용할 수 있다는 컨셉의 DLT. 또한 streaming data 에는 효과적이지만 DLT 문법이 제한적이다. 또한 DLT 파이프라인을 배포하는 환경이 분리되어있으며 전용 클러스터만 사용가능하여 개발해보다면 오히려 제약조건이라고 느껴져 pure spark 로 ETL 을 개발하는 것으로 다시 돌아갔다.
- Workflow 를 UI 에서 엮어야 한다는 점은 장점일까 단점일까
airflow 는 dag 를 코드로 엮을 수 있으나 databricks에서는 workflow 를 UI상에서 엮어주어야 한다. 또한 parameter 설정도 UI에서 해주어야 한다. 코드로 관리하게 해줬으면 좋겠다.
- 엔지니어에게 득이될까, 독이될까
Databricks 를 사용하면서 장점은 쉽게 개발한다는 점이지만 단점도 쉽게 개발한다는 점. 이미 잘 만들어진 플랫폼 서비스 위에서 개발하기 때문이다. 실제로 Hadoop eco system 을 이해하려면 결국에는 온프레미스 환경에서 직접 부딪히며 알아가는 재미가 있어야 하지 않을까, 엔지니어로서 경험으로서는 아쉽기도 하다. 온프레미스에서 직접 커스터마이징한 데이터 플랫폼도 경험해보고 싶은 욕심이 든다.
'Data Engineering > Trouble Shooting' 카테고리의 다른 글
[GitHub] ! [remote rejected] main -> main (pre-receive hook declined) 해결하기 (0) | 2023.06.14 |
---|