Kafka - 데이터 파이프라인 구축 시 고려사항, 카프카 커넥트와 카프카 클라이언트
이 포스트에서는 아래의 내용에 대해 알아본다.
- 데이터 파이프라인을 구축할 때 공통적으로 고려해야 할 문제들
- 카프카가 왜 데이터 통합에 적합하고, 어떻게 많은 문제들을 해결하는지?
- 카프카 커넥트 API 가 일반적인 프로듀서와 클라이언트와 어떻게 다른지, 언제 어떤 타입을 사용해야 하는지?
아파치 카프카를 사용한 데이터 파이프라인 구축의 활용 사례의 예는 아래와 같다.
- 아파치 카프카가 2개의 엔드포인트 중 하나가 되는 데이터 파이프라인
- 카프카에서 가져온 데이터를 S3 에 넣거나 몽고 DB 의 데이터를 카프카로 가져오는 경우
- 2개의 서로 다른 시스템을 연결하는 파이프라인을 만들면서 그 중간에 카프카 사용
- 트위터에서 카프카로 데이터를 전달한 후 다시 카프카에서 엘라스틱서치로 전달함으로써 트위터에서 가져온 데이터를 엘라스틱서치로 보내는 경우
데이터 파이프라인에 있어서 카프카가 갖는 주요한 역할은 데이터 파이프라인의 다양한 단계 사이사이에 있어 매우 크고 안정적인 버퍼 역할을 한다느느 것이다.
이것은 데이터 파이프라인의 데이터를 쓰는 쪽과 읽는 쪽을 분리함으로써 하나의 원본에서 가져온 동일한 데이터를 서로 다른 적시성과 가용성 요구 조건을 가진 여러 대상 애플리케이션이나 시스템으로 보낼 수 있게 한다.
데이터 파이프라인의 양쪽을 분리할 수 있다는 점은 신뢰성, 보안성, 효율성과 함께 카프카가 대부분의 데이터 파이프라인에 적합한 이유이다.
목차
개발 환경
- mac os
- openjdk 17.0.12
- zookeeper 3.9.2
- apache kafka: 3.8.0 (스칼라 2.13.0 에서 실행되는 3.8.0 버전)
1. 데이터 파이프라인 구축 시 고려사항
다수의 시스템을 통합하고자 하는 목적으로 소프트웨어 아키텍처를 디자인할 때 고려해야 할 중요한 몇 가지에 대해 알아보자.
1.1. 적시성(timeliness)
하루에 한 번 대량의 데이터를 받아야 하는 시스템도 있고, 데이터가 생성되자마자 받아야 하는 시스템도 있다.
좋은 데이터 통합 시스템은 각각의 데이터 파이프라인에 대해 서로 다른 적시성 요구 조건을 지원하면서도 업무에 대한 요구 조건이 변경되었을 때 이전하기가 쉽다.
쓰는 쪽에서는 필요에 따라 자주 혹은 가끔 카프카에 쓸 수 있고, 읽는 쪽 역시 최신 이벤트가 도착하는 즉시 혹은 배치 형태로 데이터를 읽어올 수 있다.
매시간 실행되어서 카프카에 연결한 뒤 지난 시간동안 누적된 이벤트들을 읽어오는 식이다.
카프카를 쓰는 쪽과 읽는 쪽 사이의 시간적 민감도에 대한 요구 조건을 분리시키는 거대한 버퍼로 생각하면 이해하기 쉽다.
쓰는 쪽에서는 실시간으로 쓸 수 있지만, 읽는 쪽에서는 배치 단위로 읽을 수 있고 그 반대도 가능하다.
이것은 백프레셔(back pressure) 적용 역시 단순하게 해준다.
백프레셔(back pressure)
소비자가 데이터를 처리하는 속도보다 생산자가 데이터를 생성하는 속도가 빠를 때 생기는 문제를 해결하기 위한 메커니즘
생산자가 데이터를 소비자에게 전송하기 전에 소비자가 처리할 수 있는 양을 조절하는 방식
즉, 데이터의 소비 속도가 온전히 읽는 쪽에 의해 결정되기 때문에 카프카 자체에서 필요한 경우 쓰는 쪽에 대한 응답을 늦춤으로써 백프레셔를 적용하는 것이다.
1.2. 신뢰성
단일 장애점을 최대한 피하는 한편 모든 종류의 장애 발생에 대해 신속하고 자동화된 복구를 수행해야 한다.
데이터 파이프라인은 대부분의 경우 중요한 비즈니스 시스템에 데이터가 전달되는 통로이기도 하기 때문에 몇 초간의 장애가 발생하는 것만으로도 전체 시스템에 큰 지장을 줄 수 있다.
특히 실시간에 가까운 적시성을 요구하는 시스템에서는 더욱 그렇다.
신뢰성에 대해 생각할 때 중요한 또 다른 고려 사항은 전달 보장이다.
데이터 유실을 허용하는 시스템도 있지만, 대부분의 경우 ‘최소 한 번’ 보장을 요구하는 것이 보통이기 때문에 원본 시스템에서 발생한 이벤트는 모두 목적지에 도착해야 한다.
‘정확히 한 번’ 전달 보장을 요구하는 경우도 많다.
즉, 원본 시스템에서 발생한 모든 이벤트가 이벤트 유실도 없고, 중복도 없이 목적지에 도착해야 하는 것이다.
Kafka - 신뢰성 있는 데이터 전달, 복제 에 카프카의 가용성과 신뢰성에 대해 나와있다.
카프카는 자체적으로 ‘최소 한 번’ 전달을 보장하며, 트랜잭션 모델이나 고유 키를 지원하는 외부 데이터 저장소와 결합되었을 때 ‘정확히 한 번’ 까지도 보장이 가능하다.
카프카 커넥트 API 가 오프셋을 다룰 때 외부 시스템과의 통합을 지원하는 API 를 제공하기 때문에 ‘정확히 한 번’ 전달을 보장하는 파이프라인을 구축하기 위한 커넥터를 개발하는 것 역시 더 쉬워졌다.
1.3. 높으면서도 조정 가능한 처리율
구축하려는 데이터 파이프라인은 매우 높은 처리율을 가질 수 있도록 확장이 가능해야 한다.
또한, 처리율이 갑자기 증가하는 경우에도 적응할 수 있어야 한다.
카프카는 쓰는 쪽과 읽는 쪽 사이에서 버퍼 역할을 하기 때문에 더 이상 프로듀서의 처리율과 컨슈머의 처리율을 묶어서 생각하지 않아도 된다.
프로듀서 처리율이 컨슈머 처리율을 넘어설 경우, 데이터는 컨슈머가 따라잡을 때까지 카프카에 누적되므로 복잡한 백프레셔 메커니즘을 개발할 필요도 없다.
카프카는 독립적으로 프로듀서나 컨슈머를 추가함으로써 확장이 가능하므로 변화하는 요구 조건에 맞춰 파이프라인의 한 쪽을 동적이면서도 독립적으로 확장할 수 있다.
카프카는 높은 처리율을 받아낼 수 있는 분산 시스템이다.
또한, 카프카 커넥트 API 는 작업을 병렬화하는데 초점을 맞추기 때문에 시스템 요구 조건에 따라 하나의 노드에서든 scale-out 된 여러 개의 노드에서든 아무 상관없이 실행될 수 있다.
1.4. 데이터 형식
데이터 파이프라인에서 가장 중요하게 고려해야 할 것 중 하나는 서로 다른 데이터 형식과 자료형을 적절히 사용하는 것이다.
예) 에이브로 타입을 사용해서 관계형 데이터를 카프카에 적재한 뒤 엘라스틱 서치에 쓸 때는 JSON 형식으로, HDFS(Hadoop Distributed File System, 하둡 분산형 파일 시스템) 에 쓸 때는 파케이(Parquet) 형식으로, S3 에 쓸 때는 CSV 로 변환
카프카 자체와 커넥트 API 는 데이터 형식에 완전히 독립적이다.
프로듀서와 컨슈머는 필요한 데이터 형식을 지원할 수만 있다면 어떤 시리얼라이저도 쓸 수 있다.
카프카 커넥트는 자료형과 스키마를 포함하는 고유한 인메모리 객체들을 갖고 있는데, 이 레코드를 어떤 형식으로도 저장할 수 있도록 장착 가능한 컨버터를 지원한다. 따라서 카프카에 사용하는 데이터 형식이 무엇이든 간에 사용할 수 있는 커넥터는 영향을 받지 않는다.
많은 source 와 sink 는 스키마를 갖고 있다.
source 에서 데이터와 함께 스키마를 읽어서 저장한 후, 호환성을 검증하거나 sink 데이터베이스의 스키마를 업데이트하는 데 사용할 수 있다.
예) MySQL 로부터 스노우 플레이크로의 데이터 파이프라인이 있을 때 MySQL 에 새로운 열 추가 시 잘 만들어진 파이프라인은 파이프라인을 통해 새로운 데이터를 적재할 때 스노우 플레이크에도 새로운 열을 추가함
카프카의 데이터를 외부 시스템에 쓸 경우, 싱크 커넥터(sink connector) 가 외부 시스템에 쓰여지는 데이터의 형식을 책임지며, 어떤 커넥터에서는 이 형식을 선택할 수 있다.
예) S3 커넥터에서는 에이브로 형식과 파케이 형식 중 하나를 고름
서로 다른 데이터 형식을 지원하는 것에 더하여 범용적인 데이터 통합 프레임워크는 다양한 source 와 sink 사이의 서로 다른 작동 방식 역시 처리할 수 있어야 한다.
예) Syslog 는 source 로서 데이터를 쓰는 반면, RDBMS 는 데이터를 읽을 수 있어야 함.
HDFS(Hadoop Distributed File System, 하둡 분산형 파일 시스템) 은 추가 전용이므로 데이터를 쓰는 작업밖에 할 수 없지만, 대부분의 시스템은 데이터를 추가하는 것 외에 기존 데이터 변경 역시 가능함
1.5. 변환
일반적으로 데이터 파이프라인을 구축하는 방식은 ETL
방식과 ELT
방식이 있다.
1.5.1. ETL(Extract-Transform-Load)
ETL
방식은 추출-변환-적재 의 줄임말로, 데이터 파이프라인이 통과하는 데이터에 변경을 가하는 작업까지도 담당한다.
연산과 저장의 부담을 부담을 데이터 파이프라인이 하는 이 방식은 장점이 되기도 하고 단점이 되기도 한다.
ETL
방식의 단점은 파이프라인에서 데이터의 변환이 일어나기 때문에 파이프라인 하단에서 데이터를 처리하고자 할 경우 손 쓸 방법이 없다는 것이다.
1.5.2. ELT(Extract-Load-Transform)
ELT
방식은 추출-적재-변환 의 줄임말로, 데이터 파이프라인은 대상 시스템에 전달되는 데이터가 원본 데이터와 최대한 비슷하도록(자료형 변환 정도) 최소한의 변환만을 수행한다.
대상 시스템은 가공되지 않은 raw data 를 받아서 모든 필요한 처리를 다 한다.
ELT
방식의 장점은 대상 시스템의 사용자에게 최대한의 유연성을 제공해 줄 수 있다는 점이다.
단점으로는 변환 작업이 대상 시스템의 CPU 와 자원을 차지한다는 점이다.
카프카 커넥트는 원본 시스템의 데이터를 카프카로 옮길 때, 혹은 카프카의 데이터를 대상 시스템으로 옮길 때 단위 레코드를 변환할 수 있게 해주는 단일 메시지 변환(Single Message Transformation) 기능을 제공한다.
단일 메시지 변환 기능은 다른 토픽으로 메시지를 보내거나, 필터링 하거나, 자료형을 바꾸거나 하는 등의 기능을 포함한다.
조인이나 aggregation 과 같이 더 복잡한 변환 작업은 카프카 스트림을 사용해서 처리할 수 있다.
카프카 스트림에 대한 내용은 추후 다룰 예정입니다. (p. 232)
1.6. 보안
카프카 보안에 대한 좀 더 상세한 내용은 추후 다룰 예정입니다. (p. 233)
데이터 파이프라인 관점에서의 보안 고려 사항은 아래와 같다.
- 누가 카프카로 수집되는 데이터에 접근 가능한지?
- 파이프라인을 통과하는 데이터가 암호화되었는지?
- 누가 파이프라인을 변경할 수 있는지?
- 파이프라인이 접근이 제한된 곳의 데이터를 읽거나 써야할 경우 인증을 통과할 수 있는지?
- 개인 식별 정보를 포함할 때 법을 준수하는지?
카프카는 source 에서 카프카로 데이터를 보내거나, 카프카에서 sink 로 데이터를 보내는 전송 과정에서 데이터 암호화를 지원한다.
SASL(Simple Authentication and Security Layer)을 사용한 인증과 인가 역시 지원한다.
카프카는 허가를 받거나 받지않은 접근 내역을 추적할 수 있는 감사 로그도 지원한다.
예) 각 토픽에 데이터가 어디에서 왔고 누가 그것을 수정했는지 추적 가능
카프카 커넥트는 외부 데이터 시스템에 연결 및 인증할 수 있어야 하며, 커넥터 설정 역시 외부 데이터 시스템의 인증을 통과할 수 있도록 자격 증명(credential)을 포함해야 한다.
설정 파일을 관리하고 접근 제한에 손이 가기 때문에 자격 증명을 설정 파일에 포함하는 것은 권장하지 않는다.
일반적인 방법은 하시코프 볼트 와 같은 외부 비밀 관리 시스템을 사용하는 것이다.
카프카 커넥트는 외부 비밀 설정(KIP-297: Externalizing Secrets for Connect Configurations)을 지원한다.
카프카는 플러그 인이 가능한 외부 설정 제공자를 지원하는 프레임워크를 제공하므로 이 프레임워크를 사용하여 볼트, AWS, Azure 등과 통합하고 싶다면 오픈 소스 커뮤니티에서 개발된 외부 설정 제공자를 찾아서 사용하면 된다.
1.7. 장애 처리
모든 데이터가 항상 완벽한 것은 아니므로 사전에 장애 처리에 관한 계획을 세워야 한다.
- 잘못된 레코드가 파이프라인으로 유입되는 것을 방지할 수 있는지?
- 파싱할 수 없는 레코드가 유입되었을 때 복구가 가능한지?
- 실수로 발생한 결함이 있는 레코드를 수정하여 재처리할 수 있는지?
- 잘못된 이벤트인데 며칠이 지난 뒤에야 문제가 있다는 것을 알아차렸을 경우 어떻게 해야하는지?
카프카는 모든 이벤트를 장기간에 걸쳐 저장할 수 있도록 설정할 수 있기 때문에, 필요할 경우 이전 시점으로 돌아가서 에러를 복구할 수 있다.
대상 시스템에 데이터가 유실된 경우, 카프카에 저장된 이벤트들을 재생하는 것 역시 가능하다.
1.8. 결합(Coupling)과 민첩성(Agility)
데이터 파이프라인을 구현할 때는 데이터 원본과 대상을 분리할 수 있어야 한다.
여기서는 의도치않게 결합이 생길 수 있는 경우에 대해 알아보자.
1.8.1. Ad-hoc(임기응변) 파이프라인
어떤 조직들은 애플리케이션을 연결할 때마다 커스텀 파이프라인을 구축한다.
예) logstash 를 이용하여 로그를 엘라스틱 서치에 넣고, Flume 을 이용해서 로그를 HDFS 에 넣고, Oracle GoldenGate 를 이용해서 오라클의 데이터를 HDFS 에 넣고..
이 경우 데이터 파이프라인이 특정한 엔드포인트에 강하게 결합되며, 이는 조직이 새로운 시스템을 도입할 때마다 추가적인 데이터 파이프라인을 구축해야 한다는 의미이다.
이것은 새로운 기술을 도입하는데 들어가는 비용을 증대시키고, 혁신을 가로막는다.
1.8.2. 메타데이터 유실
데이터 파이프라인이 스키마 메타데이터를 보존하지 않고, 스키마의 진화도 지원하지 않는다면 source 쪽에서 데이터를 생성하는 소프트웨어와 sink 쪽에서 데이터를 사용하는 소프트웨어를 강하게 결합시킨다.
또한, 스키마 정보가 없기 때문에 두 소프트웨어는 모두 데이터를 파싱하고 해석하는 방법에 대해 알고 있어야 한다.
이 상태에서 source 쪽에 새 필드를 추가했다고 하면 sink 쪽의 애플리케이션이 깨지던지 아니면 동시에 애플리케이션을 모두 업그레이드해주어야 한다.
파이프라인에서 스키마 진화를 지원한다면 각 소프트웨어는 시스템 중단을 걱정할 필요없이 자신들의 애플리케이션을 변경할 수 있다.
1.8.3. 과도한 처리
데이터 파이프라인에서 어느 정도의 데이터 처리를 피할 수는 없지만 과도한 처리는 권장하지 않는다.
데이터 파이프라인은 서로 다른 데이터 형식을 사용하는, 서로 다른 활용 사례를 가진 시스템 사이에서 데이터를 이동시키는데 파이프라인에서 너무 많은 처리를 하게 되면 하단에 있는 시스템들이 데이터 파이프라인을 구축할 때 어떤 필드를 보존할지, 데이터를 어떻게 aggregation 할지 등의 선택지가 별로 없다.
또한 하단에 있는 애플리케이션의 요구 조건이 변경될 때마다 계속해서 파이프라인도 변경해주어야 하는데 이것은 유연하지 못한 방법이다.
가공되지 않은 raw data 를 가능한 한 건드리지 않은 채로 하단에 있는 애플리케이션으로 내려보내고, 데이터를 처리 및 aggregation 하는 방법은 애플리케이션이 하도록 하는 것이 좀 더 유연한 방법이다.
2. 카프카 커넥트 vs 프로듀서/컨슈머
카프카에 데이터를 쓰거나 읽을 때 2가지 방법으로 구현할 수 있다.
- 전통적인 프로듀서와 컨슈머를 사용하는 방법(카프카 클라이언트)
- 카프카 클라이언트는 애플리케이션에 포함되는 클라이언트를 가리킴
- 애플리케이션에서 카프카에 데이터를 쓰거나 읽어올 수 있게 해줌
- 즉, 카프카 클라이언트는 애플리케이션의 코드를 변경할 수 있으면서 카프카에 데이터를 쓰거나 읽어오고 싶을 때 사용함
- 커넥트 API 와 커넥터 사용
- 카프카를 직접 코드나 API 를 작성하지 않고 사용하며, 변경할 수 없는 데이터 저장소에 연결시켜야 할 때 사용함
- 카프카 커넥트를 이용해서 외부 데이터 저장소의 데이터를 카프카로 가져올 수도 있고, 카프카에 저장된 데이터를 외부 저장소로 내보낼 수도 있음
- 카프카 커넥트를 사용하려면 연결하고자 하는 저장소에 맞는 커넥터가 필요한데, 요즘은 많은 커넥터가 나와있음
- 즉, 카프카 커넥트를 사용하기 위해서 할 일은 설정 파일을 작성하는 것 뿐임
만약 카프카와 연결하고자 하는 데이터 저장소의 커넥커가 아직 없다면 카프카를 이용하기 위한 방법으로 아래 2가지 선택지가 있다.
- 카프카 클라이언트를 사용하여 애플리케이션 직접 작성
- 커넥트 API 를 사용하여 애플리케이션 직접 작성
커넥트 API 는 설정 관리, 오프셋 저장, 병렬 처리, 에러 처리, 서로 다른 데이터 형식 지원 및 REST API 를 통한 표준화된 관리 기능을 제공하므로 커넥트 API 를 사용하여 애플리케이션을 작성하는 것을 권장한다.
카프카를 데이터 저장소와 연결하는 간단한 애플리케이션을 개발하는 것은 세세하게 설정해 줄 부분이 많기 때문에 작업이 쉽지만은 않으며, 이 애플리케이션을 계속 유지보수해야 하고 다른 사람들이 사용법을 배워야 한다.
카프카 커넥트는 카프카 생태계의 표준화된 일부일 뿐 아니라 대부분의 작업을 대신해주므로 개발자는 외부 저장소와 데이터를 주고 받는 일에만 신경쓰면 된다.
참고 사이트 & 함께 보면 좋은 사이트
본 포스트는 김병부 저자의 O’REILLY 카프카 핵심 가이드 2판를 기반으로 스터디하며 정리한 내용들입니다.
- 카프카 핵심 가이드
- 예제 코드 & 오탈자
- Doc:: Kafka
- Git:: Kafka
- 하시코프 볼트
- KIP-297: Externalizing Secrets for Connect Configurations