kafka 시작 시 오류, 해결 방법
Kafka는 LinkedIn이 설계한 높은 처리량, 분산형, 게시-구독 모델 기반 메시징 시스템으로 Scala로 작성되었으며 수평적 확장성, 안정성, 비동기 통신 및 높은 처리량을 특징으로 합니다. 사용된. 현재 점점 더 많은 오픈 소스 분산 처리 시스템이 Kafka와의 통합을 지원하고 있습니다. 백엔드 스트리밍 엔진인 Spark Streaming과 프런트엔드 메시징 시스템인 Kafka는 현재 스트림 처리 시스템의 주류 아키텍처 중 하나가 되고 있습니다. 그러나 점점 더 많은 보안 취약점, 데이터 유출 및 기타 문제가 발생함에 따라 시스템을 선택할 때 보안을 고려해야 하는 문제가 되고 있습니다. Kafka의 보안 메커니즘 부족으로 인해 데이터에 민감한 산업에 배포하는 데에도 심각한 문제가 발생했습니다. 안전상의 위험. 이 기사에서는 Kafka에 중점을 두고 먼저 전체 아키텍처와 주요 개념을 소개한 다음 아키텍처에 존재하는 보안 문제에 대한 심층 분석을 수행하고 마지막으로 Kafka 보안에 대한 Transwarp의 작업과 사용 방법을 공유합니다. Kafka 아키텍처 및 보안 먼저 Kafka에 대한 몇 가지 기본 개념을 이해해 보겠습니다. 주제: Kafka는 수신된 메시지를 범주로 나눕니다. 각 범주는 주제라고 하며 고유한 주제 이름으로 식별됩니다. 생산자: 주제에 메시지를 게시하는 프로세스를 생산자라고 합니다. 소비자: 주제의 메시지를 구독하는 프로세스를 소비자라고 합니다. 브로커: Kafka 클러스터에는 브로커라고 하는 하나 이상의 서버가 포함되어 있습니다. Kafka의 전체 아키텍처는 아래 그림에 나와 있습니다. 일반적인 Kafka 클러스터에는 메시지를 게시하는 생산자 그룹, 주제를 관리하는 브로커 그룹 및 메시지를 구독하는 소비자 그룹이 포함됩니다. 주제는 여러 파티션을 가질 수 있으며 각 파티션은 하나의 브로커에만 저장됩니다. 생산자는 단순히 각 파티션을 폴링하거나 특정 필드의 해시 값을 기반으로 파티션을 지정하는 등 특정 전략에 따라 메시지를 지정된 파티션으로 나눌 수 있습니다. 브로커는 ZooKeeper를 통해 클러스터의 모든 브로커를 기록하고, 파티션의 리더를 선택하고, 소비자 소비 메시지의 오프셋을 기록하고, 소비자 그룹이 변경될 때 브로커가 수동적으로 메시지를 수신 및 전송합니다. 생산자는 적극적으로 수행합니다. 메시지를 보냅니다. 소비자가 적극적으로 메시지를 가져옵니다. 그러나 Kafka 프레임워크를 분석하면 다음과 같은 심각한 보안 문제를 발견할 수 있습니다. 1. 네트워크의 모든 호스트는 Broker 프로세스를 시작하여 Kafka 클러스터에 참여할 수 있고 생산자로부터 메시지를 받을 수 있으며 메시지를 변조하여 보낼 수 있습니다. 소비자에게. 2. 네트워크의 모든 호스트는 악의적인 생산자/소비자를 시작하여 브로커에 연결하거나 불법 메시지를 보내거나 개인 메시지 데이터를 가져올 수 있습니다. 3. 브로커는 Kerberos 인증이 활성화된 ZooKeeper 클러스터에 대한 연결을 지원하지 않으며 ZooKeeper에 저장된 데이터에 대한 권한을 설정하지 않습니다. 모든 사용자는 ZooKeeper 클러스터에 직접 액세스하여 이 데이터를 수정하거나 삭제할 수 있습니다. 4. Kafka의 주제는 액세스 제어 목록 설정을 지원하지 않습니다. Kafka 클러스터에 연결된 모든 소비자(또는 생산자)는 모든 주제에 대한 메시지를 읽거나 보낼 수 있습니다. Kafka의 애플리케이션 시나리오가 점점 더 널리 보급됨에 따라, 특히 데이터 프라이버시 수준이 높은 영역(예: 도로 교통 비디오 감시)에서 위의 보안 문제의 존재는 일단 인트라넷이 해킹되거나 내부에 악의적이라면 시한폭탄과 같습니다. , 사용자는 브로커가 위치한 서버에 침입하지 않고도 모든 개인 데이터(차량 여행 기록 등)를 쉽게 도난당할 수 있습니다.
Kafka 보안 설계 위의 분석을 바탕으로 Transwarp는 다음 두 가지 측면에서 Kafka의 보안을 강화합니다. 인증: Kerberos와 IP를 기반으로 하는 두 가지 신원 인증 메커니즘을 설계하고 구현합니다. 전자는 강력한 신원 인증이며 후자보다 보안이 우수합니다. 후자는 신뢰할 수 있는 IP 주소가 있는 네트워크 환경에 적합하며 전자보다 배포가 더 쉽습니다. 권한 부여: 주제 수준 권한 모델을 설계하고 구현했습니다. 주제 권한은 READ(주제에서 데이터 가져오기), WRITE(주제에 데이터 생성), CREATE(주제 생성) 및 DELETE(주제 삭제)로 구분됩니다. Kerberos 기반의 ID 메커니즘은 아래 그림에 나와 있습니다. 브로커는 시작 시 구성 파일의 ID 및 키 파일을 사용하여 KDC(Kerberos 서버)에 인증해야 합니다. 인증이 통과되면 참가하게 됩니다. 그렇지 않으면 오류와 함께 종료됩니다. 생산자(또는 소비자)가 시작된 후 브로커와의 보안 소켓 연결을 설정하려면 다음 단계를 거쳐야 합니다. 1. 생산자는 KDC에 자신의 신원을 인증하고 통과하면 TGT( 티켓 요청 티켓), 그렇지 않으면 오류 2로 종료됩니다. 생산자는 TGT를 사용하여 KDC에서 Kafka 서비스를 요청하고, KDC는 TGT를 확인하고 SessionKey(세션 키) 및 ServiceTicket(서비스 티켓)을 생산자에게 반환합니다. 3. 생산자 SessionKey와 ServiceTicket을 사용하여 Broker와 연결을 설정합니다. Broker는 자체 키를 사용하여 ServiceTicket을 해독하고 SessionKey를 얻어 Producer와 통신한 다음 SessionKey를 사용하여 Producer의 신원을 확인하고 통과하면 연결이 설정됩니다. 그렇지 않으면 연결이 거부됩니다. ZooKeeper는 브로커 또는 소비자의 연결이 안전한지 확인하기 위해 Kerberos 인증 모드를 활성화해야 합니다. 주제의 ACL(액세스 제어 목록)은 ZooKeeper에 저장됩니다. 스토리지 노드의 경로는 /acl/lt;topicgt;/lt;usergt;이고, 노드 데이터는 R(ead), W(rite), C(reate)입니다. ), D(elete) 권한의 모음입니다. 예를 들어 /acl/transaction/jack 노드의 데이터가 RW이면 사용자 jack이 트랜잭션 주제를 읽고 쓸 수 있다는 의미입니다. 또한, kafka는 권한이 있는 사용자이므로, kafka 사용자만이 권한을 부여/취소할 수 있습니다. 따라서 ACL 관련 ZooKeeper 노드 권한은 kafka에는 모든 권한이 있고 다른 사용자에게는 권한이 없다는 것입니다. 안전한 Kafka 서비스를 구축하기 위해 먼저 Broker에 대한 Kerberos 인증 모드를 활성화합니다. 구성 파일은 /etc/kafka/conf/server.properties입니다. 그 중 인증 매개변수는 인증을 나타냅니다. 모드이며 선택적 구성 항목은 simple, kerberos 및 ipaddress이며 기본값은 simple입니다. 인증 모드가 kerberos인 경우 계정 속성 주체와 해당 키 파일 경로 keytab을 추가로 구성해야 합니다. 인증 모드가 ipaddress인 경우 생산자 및 소비자를 생성할 때 변경할 필요가 없습니다.
인증 모드가 Kerberos인 경우 해당 Principal과 Keytab을 미리 생성하고 API를 사용하여 로그인해야 합니다. 샘플 코드는 다음과 같습니다. public class SecureProducer Extensions Thread {private final kafka.javaapi.producer.Producerlt; 정수, Stringgt; private final Properties props = new Properties(String topic) { AuthenticationManager.setAuthMethod(“kerberos”), “/etc/producer1 .keytab”) ;props.put("serializer.class", "kafka.serializer.StringEncoder"); props.put("metadata.broker.list", "172.16.1.190:9092, 172.16.1.192:9092, 172.16 .1.193:9092 ″); // 키 유형이 필요하지 않습니다. // 메시지는 String 유형입니다. ; (새 ProducerConfig(props)); this.topic = 주제;