Apache Kafka 에서 GDPR 다루기: 로그 삭제는 어떻게 하나요?

Hyojin Kwon·2023년 2월 11일
0

들어가며

Apache Kafka 를 사용하다보면 메시지를 추적하고 보존하는데는 매우 뛰어나다는 것을 알 수 있습니다. 하지만 메시지를 삭제하는 것도 아주 중요한 이슈가 될 수 있는데요.

무었보다도 the right to be forgotten, 즉 잊혀질 권리가 포함된 GDPR 이 좋은 예시입니다.

그렇다면 Kafka 에서 임의의 데이터를 어떻게 삭제할 수 있을까요? 결국, Kafka 의 기본 저장 매커니즘은 변경 불가능한 로그인데 말이죠.

공교롭게도 Kafka 는 GDPR 에 매우 적합합니다. Kafka 의 규정에는 사용자에게 잊혀질 권리 뿐만 아니라 개인 데이터 사본을 요청할 권리도 있음을 명시하고 있습니다. 또한 기업은 데이터가 어떤 용도로 사용되는지 상세히 기록해야 하는데, 이를 위해서 어플리케이션 간 이동하는 메시지를 기록하고 추적하는 것에 Kafka 는 유용합니다.

카프카에서 데이터를 삭제(또는 수정)하려면 어떻게 하나요?

카프카에서 메시지를 삭제하는 가장 간단한 방법은 단순히 만료되도록 내버려두는 것입니다. 기본적으로 Kafka는 데이터를 2주 동안 보관하며, 이 기간을 임의로 길게 또는 짧게 조정할 수 있습니다.

또한 지정된 시간 또는 오프셋보다 오래된 메시지가 있는 경우 명시적으로 삭제할 수 있는 Admin API도 있습니다.

하지만 Event Sourcing 아키텍처나 데이터 소스로서 데이터를 장기간 보관할 수 있는 카프카의 기능을 활용하고자 하는 기업이 점점 더 많아지고 있습니다. 이러한 경우, Kafka의 장기 보관 데이터를 GDPR을 준수하도록 만드는 방법을 이해하는 것이 중요합니다. 이를 위해 압축된 토픽은 키를 통해 메시지를 명시적으로 삭제하거나 교체할 수 있기 때문에 가장 적합한 도구입니다.

압축된 토픽에서 데이터는 관계형 데이터베이스에서와 같은 방식으로 제거되지 않습니다. 대신, 카프카는 카산드라 및 HBase에서 사용하는 것과 유사한 메커니즘을 사용하여 레코드가 제거되도록 표시된 다음 나중에 압축 프로세스가 실행될 때 삭제됩니다. 압축된 토픽에서 메시지를 삭제하는 것은 삭제하려는 키와 null 값을 사용하여 해당 토픽에 새 메시지를 작성하는 것만큼 간단합니다. 압축이 실행되면 메시지는 영구 삭제됩니다.

토픽의 키가 CustomerId가 아닌 다른 키인 경우에는 이 둘을 매핑하는 프로세스가 필요합니다. 예를 들어, Orders 토픽이 있는 경우, 어딘가에 보관된 Customer를 OrderId로 매핑해야 합니다. 이것은 외부 시스템일 수도 있고, 또 다른 Kafka 토픽일 수도 있습니다. 고객을 '잊어버리려면' 해당 주문을 조회하여 Kafka에서 명시적으로 삭제하거나 주문에 포함된 모든 고객 정보를 삭제하면 됩니다. 사용자-> 키 매핑을 보관하기 위해 데이터베이스를 사용해 자체 프로세스로 롤링할 수도 있고, Kafka 토픽에 보관할 수도 있으며, Kafka Stream을 사용해 전체 프로세스를 수행할 수도 있습니다.

덜 일반적이지만 언급할 가치가 있는 경우가 하나 있는데, 바로 (Kafka 가 순서를 지정하는 데 사용하는) 키가 사용자가 삭제하려는 키와 완전히 다른 경우입니다. ProductId를 기준으로 주문을 키로 지정해야 한다고 가정해 보겠습니다. 이 키를 선택하면 개별 고객에 대한 주문을 삭제할 수 없으므로 위의 간단한 방법은 작동하지 않습니다. 이 두 가지를 합성한 키를 사용하여 [ProductId][CustomerId] 키를 만든 다음 프로듀서에서 사용자 지정 파티셔너를 사용하여(Producer Config: "partitioner.class" 참조) ProductId를 추출하고 해당 값에 대해서만 파티션을 생성합니다. 그런 다음 앞서 설명한 메커니즘을 사용하여 [ProductId][CustomerId] 쌍을 키로 사용하여 메시지를 삭제할 수 있습니다.

Daniel Lebrero 가 제안한 전혀 다른 접근 방식도 언급할 가치가 있습니다. 메시지가 도착할 때 사용자별로 암호화 키를 사용하여 암호화됩니다. 암호화 키는 압축된 토픽에 저장됩니다. 사용자를 '잊어버려야' 하는 경우 암호화 키만 삭제하면 되므로 사용자의 모든 데이터는 로그에서 이해할 수는 없지만 그대로 남게 됩니다. 이 접근 방식에는 몇 가지 장점이 있습니다. (a) 각 사용자와 관련된 메타데이터가 훨씬 작아 사용자당 하나의 k-v 쌍(사용자->암호화 키) (b) 데이터를 장기적으로 저장하는 로그의 불변성이 유지됩니다. 단점은 리댁션(즉, 암호화/복호화)을 처리하는 프로세스가 생산자/소비자에 내장되어 있거나 암호화되지 않은 데이터에 대해 수명이 짧은 진입/출입 토픽을 사용하는 등 중요한 경로에 위치한다는 것입니다. Daniel은 개념 증명과 함께 이 접근 방식에서 발견한 몇 가지 함정에 대해서도 언급합니다.

데이터를 읽거나 데이터를 푸시하는 데이터베이스는 어떻게 되나요?

Kafka 커넥터를 사용해 한 데이터베이스에서 다른 데이터베이스로 데이터를 이동하는 파이프라인에 있는 경우가 종종 있습니다. 이 경우, 원본 데이터베이스에서 레코드를 삭제하고 Kafka를 통해 다운스트림에 있는 모든 Connect Sink로 전파되도록 해야 합니다. CDC를 사용하는 경우, 삭제가 소스 커넥터에 의해 포착되어 Kafka를 통해 전파되고 싱크에서 삭제됩니다. CDC 지원 커넥터를 사용하지 않는 경우에는 삭제를 관리하기 위한 사용자 정의 메커니즘이 필요합니다.

Compaction 은 메시지를 삭제하는 데 얼마나 걸리나요?

기본적으로 압축은 주기적으로 실행되며 메시지가 언제 삭제될지 명확하게 알려주지 않습니다. 다행히도 설정을 조정하여 더 엄격하게 보장할 수 있습니다. 가장 좋은 방법은 압축 프로세스가 지속적으로 실행되도록 구성한 다음, 압축 프로세스가 나머지 시스템에 과도한 영향을 미치지 않도록 속도 제한을 추가하는 것입니다.

cleanable ratio 를 0으로 설정하면 compaction 이 지속적으로 실행됩니다. 여기서는 작은 양의 값이 사용되므로 정리할 것이 없으면 클리너가 실행되지 않지만 정리할 것이 있으면 바로 실행됩니다. 로그 클리너 최대 I/O의 합리적인 값은 [디스크 하위 시스템의 최대 I/O] x 0.1 / [압축된 파티션 수]입니다. 따라서 이 값이 1MB/s로 계산된다고 가정하면 100GB의 토픽은 28시간 이내에 제거된 항목을 정리합니다. 물론 이 값을 조정하여 원하는 보장 시간을 얻을 수 있습니다.

마지막으로 한 가지 고려해야 할 사항은 Kafka의 파티션은 세그먼트라고 하는 파일 집합으로 만들어지며, 가장 최근 세그먼트(기록 중인 세그먼트)는 압축에 고려되지 않는다는 것입니다. 즉, 처리량이 낮은 토픽의 경우 롤링이 시작되고 압축이 시작되기 전에 최신 세그먼트에 메시지가 꽤 오랫동안 누적될 수 있습니다. 이 문제를 해결하기 위해 세그먼트가 정의된 시간 후에 강제로 롤링되도록 할 수 있습니다. 예를 들어 log.roll.hours=24를 설정하면 세그먼트가 아직 크기 제한에 도달하지 않은 경우 매일 강제로 롤링됩니다.

튜닝과 모니터링

compactor 를 조정하기 위한 여러 가지 구성이 있으며 (문서에서 log.cleaner.* 속성 참조), 압축 프로세스는 진행 상황에 관한 JMX 메트릭을 게시합니다. 실제로 토픽을 압축하고 만료 기간을 설정하여 데이터가 만료 시간보다 오래 보관되지 않도록 할 수 있습니다.

Summary

Kafka 는 설정된 시간이 지나면 항목이 만료되는 불변 토픽, 특정 키가 있는 메시지에 삭제 플래그를 지정할 수 있는 압축 토픽, CDC 지원 커넥터를 통해 데이터베이스 간에 삭제 내용을 전파할 수 있는 기능을 제공합니다.

0개의 댓글