GN⁺: Flink SQL 도입기
(hyperconnect.github.io)Flink SQL 도입 배경
- Azar Matching Dev Team에서 관리하던 Flink 기반 앱 중 CPU 96개를 사용하는 무거운 레거시 앱이 있었음
- 이 앱은 여러 기능을 모놀리식 구조로 구현하여 유지보수가 어려웠음
- 인프라 작업으로 실행 노드를 변경하자 앱이 정상적으로 동작하지 않는 문제가 발생함
- 높은 운영 피로도를 감수하며 유지보수할지, 다른 방법으로 대체할지를 결정해야 했음
고를 수 있었던 선택지들
- 기존 앱의 중요한 기능은 이미 새로운 Flink 앱으로 구현되어 있었음
- 조건부 이벤트 발행 및 로직 수행 부분을 대체할 방법을 고민함
- 하나의 Flink App으로 구현
- 장점: 운영이 간편함
- 단점: 앱이 커질 가능성이 크고, 한 부분이 실패하면 다른 기능도 영향받기 쉬움
- 여러 Flink App으로 구현
- 장점: 독립적으로 관리 가능
- 단점: 앱 개수가 늘어나면 부담 증가
- Flink SQL 사용
- 장점: 쿼리로 로직 정의 가능, 하나의 클러스터만 관리
- 단점: 복잡한 로직 표현 어려움, 클러스터 관리에 익숙하지 않으면 어려움
- 하나의 Flink App으로 구현
Flink SQL을 선택한 이유 및 대안 기술과의 비교
- Flink SQL 도입 전 ksqlDB와 Spark Structured Streaming을 검토함
- Flink SQL 선택 이유:
- High Availability
- Checkpoint와 Savepoint를 통해 앱 상태를 안정적으로 저장 및 복구 가능
- JobManager는 HA 모드로 구성 가능
- 고급 스트리밍 기능 지원
- SQL 문법으로 다양한 스트리밍 처리 기능 지원
- 윈도우, 조인, 이벤트 타임 처리, 워터마크 등 지원
- UDF 및 Custom Connector를 통한 확장성
- 사용자 정의 함수 및 다양한 데이터 소스와 sink 연결 가능
- High Availability
vs ksqlDB
- Confluent 플랫폼에 포함되어 있지만, stateful 스트리밍 처리에서 HA 동작이 비효율적임
vs Spark Structured Streaming
- Spark SQL 엔진 기반으로 구현, UDF 및 Custom Sink 작성 가능
- 마이크로 배치 단위로 동작하여 실시간 처리에 불리할 수 있음
클러스터 환경 구축 및 쿼리 배포 방식
로컬에서 간단하게 테스트하기
- Flink Cluster를 로컬에서 띄우고 SQL 쿼리를 제출하는 방법 소개
운영 환경에서의 클러스터 아키텍쳐
- Kubernetes 위에서 Flink SQL Cluster 구성
- Application mode와 Session mode 비교
GitOps 방식을 이용한 쿼리 배포
- GitHub Actions를 사용하여 쿼리 배포 및 Job 중단 구현
주요 operation 사례 및 트러블슈팅 경험
JobManager 또는 TaskManager가 Fail 하는 경우
- JobManager는 HA 설정을 통해 Fail 시에도 작업 계속 가능
- TaskManager는 Fail 시 작업이 재분배되어 계속됨
쿼리가 Fail 하는 경우
- 비정상 데이터 인입 시나 컴퓨팅 자원 부족 시 발생
- JSON 포맷 에러 무시 설정 및 기본값 설정 가능
클러스터 재시작 시 일부 Job이 Fail 하는 경우
- timeout 및 retry 설정 수정 필요
쿼리의 조건을 하나 수정해서 다시 배포하고 싶은 경우
- 간단한 수정일 때만 savepoint를 이용한 state 복원 가능
주요 모니터링 포인트
-
numRunningJobs
,taskmanager.cpu.load
,taskmanager.memory.used
등 지표 확인
마치며
- Flink SQL 도입으로 생산성 및 운영 효율성 향상
- 안정성 뛰어나며, GitOps Controller 패턴 구현 계획
flink와 같은 분산 시스템은 rack을 2~3개 유지함으로써 HA를 유지해야하는데 kubernetes를 연동함으로써 HA를 보장한 것 같네요. 근데 결국 kube slave node에 대한 리소스도 고민해야할텐데 flink만 띄우는 node를 구성한건지 생각이 되네요 (flink 부하시에 slave node 다운 이슈가 있을 듯)
그런 관점에서 kubernetes를 쓰는 장점이 있을까요?
또한 flink에서 윈도우 함수를 쓰게 되면 그 사이 데이터는 메모리에 유지됨으로써 sql join문이 동작하는 건데 trade - off 관점에서 보았을때 flink는 좋은 선택지일까 생각이 듭니다. 시간이 지날수록 거대해지는 sql + job이 죽게되면 발생하는 엄청난 일..
저도 최상단 data source에서 join이 필요한 상황일때 flink를 안쓰고 어떤 방식으로 application level로 내려서 처리 할 수 있을지 고민이 되네요.