리스너 구성
리스너 구성
카프카 클러스터를 보호하려면 결국 서버와 통신하는 채널(리스너)을 보호해야 해요. 이 페이지에서는 각 서버가 어떤 방식으로 클라이언트의 연결을 받는지, 리스너를 어떻게 정의하고 어떤 보안 프로토콜을 붙이는지 기본기를 차근차근 설명해드릴게요.
출처: 문서
본문
카프카 클러스터를 보호하려면 서버와 통신하는 데 사용되는 채널을 보호해야 해요. 각 서버는 클라이언트 및 다른 서버로부터 요청을 받는 데 사용할 리스너(listener)의 집합을 정의해야 해요. 각 리스너는 다양한 메커니즘으로 클라이언트를 인증하도록 구성할 수 있고, 서버와 클라이언트 사이의 트래픽이 암호화되도록 보장할 수도 있어요. 이 섹션은 리스너 구성을 위한 입문용 설명이에요.
카프카 서버는 여러 포트에서 연결을 수신하는 것을 지원해요. 이것은 서버 구성의 listeners 속성으로 설정하며, 활성화할 리스너의 쉼표로 구분된 목록을 받아요. 각 서버에는 리스너가 최소 하나 이상 정의되어야 해요. listeners에 정의되는 각 리스너의 형식은 다음과 같아요:
{LISTENER_NAME}://{hostname}:{port}
LISTENER_NAME은 보통 리스너의 용도를 설명하는 이름이에요. 예를 들어, 많은 구성이 클라이언트 트래픽에 별도의 리스너를 사용하므로, 해당 리스너를 구성에서 CLIENT라고 부르기도 해요:
listeners=CLIENT://localhost:9092
각 리스너의 보안 프로토콜은 별도의 구성인 listener.security.protocol.map에서 정의해요. 값은 각 리스너를 보안 프로토콜에 매핑한 목록을 쉼표로 구분한 형태예요. 예를 들어, 다음 값 구성은 CLIENT 리스너가 SSL을 사용하고 BROKER 리스너가 plaintext를 사용한다고 지정해요:
listener.security.protocol.map=CLIENT:SSL,BROKER:PLAINTEXT
보안 프로토콜의 가능한 옵션(대소문자 구분 없음)은 다음과 같아요:
PLAINTEXTSSLSASL_PLAINTEXTSASL_SSL
plaintext 프로토콜은 보안을 제공하지 않으며 추가 구성도 필요 없어요. 다음 섹션들에서 나머지 프로토콜을 어떻게 구성하는지 다룰게요.
각 필수 리스너가 별도의 보안 프로토콜을 사용한다면, listeners에서 보안 프로토콜 이름을 리스너 이름으로 사용하는 것도 가능해요. 위 예시를 사용하면, 다음과 같은 정의로 CLIENT와 BROKER 리스너의 정의를 생략할 수 있어요:
listeners=SSL://localhost:9092,PLAINTEXT://localhost:9093
하지만 각 리스너에 명시적인 이름을 붙이는 것을 권장해요. 각 리스너의 의도된 용도가 더 명확해지기 때문이에요.
이 목록의 리스너들 중에서, inter.broker.listener.name 구성을 리스너 이름으로 설정하면 브로커 간 통신에 사용할 리스너를 선언할 수 있어요. 인터-브로커(inter-broker) 리스너의 주요 목적은 파티션 복제(partition replication)예요. 정의되지 않은 경우, 인터-브로커 리스너는 security.inter.broker.protocol로 정의된 보안 프로토콜에 의해 결정되며, 기본값은 PLAINTEXT예요.
KRaft 클러스터에서 브로커(broker)는 process.roles에 broker 역할이 활성화된 모든 서버이고, 컨트롤러(controller)는 controller 역할이 활성화된 모든 서버예요. 리스너 구성은 역할에 따라 달라져요. inter.broker.listener.name으로 정의된 리스너는 브로커 간 요청에만 사용돼요. 반면 컨트롤러는 controller.listener.names 구성으로 정의되는 별도의 리스너를 사용해야 해요. 이 값은 인터-브로커 리스너와 같은 값으로 설정할 수 없어요.
컨트롤러는 다른 컨트롤러와 브로커 양쪽에서 요청을 받아요. 이러한 이유로, 서버에 controller 역할이 활성화되어 있지 않더라도(즉 브로커일 뿐이어도), 컨트롤러 리스너와 이를 구성하는 데 필요한 모든 보안 속성을 정의해야 해요. 예를 들어, 단독 브로커(standalone broker)에서 다음과 같은 구성을 사용할 수 있어요:
process.roles=broker
listeners=BROKER://localhost:9092
inter.broker.listener.name=BROKER
controller.quorum.bootstrap.servers=localhost:9093
controller.listener.names=CONTROLLER
listener.security.protocol.map=BROKER:SASL_SSL,CONTROLLER:SASL_SSL
이 예시에서도 컨트롤러 리스너는 SASL_SSL 보안 프로토콜을 사용하도록 구성되어 있지만, 브로커가 컨트롤러 리스너를 직접 노출하지 않으므로 listeners에는 포함되지 않아요. 이 경우 사용될 포트는 전체 컨트롤러 목록을 정의하는 controller.quorum.voters 구성에서 나와요.
브로커와 컨트롤러 역할이 모두 활성화된 KRaft 서버의 경우 구성이 비슷해요. 유일한 차이는 컨트롤러 리스너가 listeners에 포함되어야 한다는 점이에요:
process.roles=broker,controller
listeners=BROKER://localhost:9092,CONTROLLER://localhost:9093
inter.broker.listener.name=BROKER
controller.quorum.bootstrap.servers=localhost:9093
controller.listener.names=CONTROLLER
listener.security.protocol.map=BROKER:SASL_SSL,CONTROLLER:SASL_SSL
controller.quorum.bootstrap.servers에 정의된 호스트와 포트가 노출된 컨트롤러 리스너로 라우팅되어야 한다는 것이 요구사항이에요. 예를 들어, 여기서 CONTROLLER 리스너는 localhost:9093에 바인딩돼요. 그러면 controller.quorum.bootstrap.servers로 정의된 연결 문자열도 여기처럼 localhost:9093을 사용해야 해요.
컨트롤러는 controller.listener.names로 정의된 모든 리스너에서 요청을 수락해요. 보통은 컨트롤러 리스너가 하나뿐이지만, 더 많을 수도 있어요. 예를 들어, 이것은 클러스터의 롤(roll)을 통해 활성 리스너를 한 포트나 보안 프로토콜에서 다른 것으로 변경하는 방법을 제공해요(한 번의 롤로 새 리스너를 노출하고, 한 번의 롤로 이전 리스너를 제거). 여러 컨트롤러 리스너가 정의된 경우, 목록의 첫 번째가 아웃바운드 요청에 사용돼요.
카프카에서는 클라이언트에 별도의 리스너를 사용하는 것이 관례예요. 이렇게 하면 클러스터 내부 리스너를 네트워크 수준에서 격리할 수 있어요. KRaft의 컨트롤러 리스너 같은 경우, 어차피 클라이언트가 사용하지 않으므로 리스너를 격리해야 해요. 클라이언트는 브로커에 구성된 다른 리스너에 연결할 것으로 예상돼요. 컨트롤러로 향하는 요청은 아래에서 설명하는 것처럼 전달돼요.
다음 섹션에서는 암호화와 인증을 위해 리스너에서 SSL을 활성화하는 방법을 다루고, 그 다음 섹션에서는 SASL을 사용한 추가 인증 메커니즘을 다룰게요.
더 알아보기
- 보안 개요 — 카프카 보안 기능의 전체 그림을 봐요.
- 운영 중인 클러스터에 보안 기능 적용 — 이미 가동 중인 클러스터에 보안을 입힐 때 주의점을 봐요.
- SSL/SASL 인증과 암호화에 대한 상세 구성은 처리 관련 문서들을 참고해요.