DevOps/Kafka

NodePort 기반 Kafka 외부 접속 구성과 NGINX 연동 가이드

DEBTOLEE 2025. 4. 16. 13:46

Kafka를 Kubernetes 환경에서 운영할 때 흔히 맞닥뜨리는 과제 중 하나는 바로 외부에서 Kafka 브로커에 안전하게 접근하는 방식입니다. Helm Chart를 이용해 Kafka 클러스터를 구성하는 것만으로는 외부 애플리케이션에서 브로커에 연결하는 데에 필요한 네트워크 접근이 보장되지 않습니다.

이 글에서는 Helm Chart 기반 Kafka 설치 후 외부 접근을 NodePort와 NGINX를 통해 구성하는 전략을 정리해 봅니다. 운영 환경은 물론 테스트 환경에서도 유용하게 적용할 수 있어요.

1. 왜 외부 접근 설정이 필요할까?

Kafka는 기본적으로 클러스터 내부에서의 통신을 염두에 두고 설계되어 있습니다. 하지만 다음과 같은 상황에서는 외부 연결이 필수적입니다:

  • 외부에서 Kafka 메시지를 생산하거나 소비해야 할 때
  • Kafka에 데이터를 주고받는 마이크로서비스가 외부에 있을 때
  • 로컬 테스트 환경에서 클러스터에 접근하고자 할 때

이러한 경우 Kubernetes의 NodePort 방식을 활용하면 접근 경로를 열 수 있습니다.

2. Kafka Helm values.yaml에 NodePort 구성 추가하기

Bitnami Kafka Chart를 사용할 경우 values.yaml 파일에 다음과 같이 설정을 추가합니다:

externalAccess:
  enabled: true
  broker:
    service:
      type: NodePort
      nodePorts:
        - 30000
        - 30001
        - 30002

이 설정은 Kafka 브로커 각각에 대해 외부 노출 포트를 명시적으로 지정해 줍니다. 이로 인해 클러스터 외부에서도 각 브로커에 접근할 수 있게 됩니다.

3. NGINX로 외부 트래픽 분산 라우팅하기

NodePort는 외부에서의 접근을 가능하게 하지만, 사용자가 직접 브로커의 IP와 포트를 일일이 기억해야 하는 불편함이 존재합니다. 이를 보완하기 위해 NGINX의 Stream Proxy 모듈을 활용하면, 하나의 도메인과 포트로 Kafka 트래픽을 적절한 브로커로 라우팅할 수 있습니다.

stream {
  log_format proxy '$remote_addr [$time_local] '
                   '$protocol $status $bytes_sent $bytes_received '
                   '$session_time "$upstream_addr"';

  access_log /etc/nginx/logs/kafka-access.log proxy;
  error_log  /etc/nginx/logs/kafka-error.log;

  upstream kafka_broker_0 {
      server 192.168.0.101:30000;
  }
  upstream kafka_broker_1 {
      server 192.168.0.102:30001;
  }
  upstream kafka_broker_2 {
      server 192.168.0.103:30002;
  }

  server {
      listen 10094;
      proxy_pass kafka_broker_0;
  }
  server {
      listen 10194;
      proxy_pass kafka_broker_1;
  }
  server {
      listen 10294;
      proxy_pass kafka_broker_2;
  }
}
  • 192.168.0.101~103: 브로커가 배포된 각 노드의 IP
  • 30000~30002: 각 브로커의 NodePort
  • 10094~10294: 외부 클라이언트가 Kafka에 접속하는 데 사용하는 NGINX 포트

📌 이 구성을 통해 클라이언트는 단순히 kafka.example.com:10094 등으로 접속하면 되고, NGINX가 내부 브로커에 연결을 릴레이해 줍니다.

☝️ 참고: Kafka는 TCP 연결 유지가 중요한 시스템이기 때문에, 일반적인 HTTP Proxy 방식은 적합하지 않습니다. stream 모듈 기반 TCP 프록시 방식을 추천드립니다.

4. Kafka 클라이언트 설정 예시 (Node.js 기준)

외부에서 Kafka에 접속하는 클라이언트 예시는 다음과 같습니다:

const { Kafka } = require('kafkajs');

const kafka = new Kafka({
  clientId: 'external-client',
  brokers: ['kafka.example.com:10094'],
  ssl: false,
  connectionTimeout: 10000,
});

const consumer = kafka.consumer({ groupId: 'test-group' });

(async () => {
  await consumer.connect();
  await consumer.subscribe({ topic: 'my-topic', fromBeginning: true });

  await consumer.run({
    eachMessage: async ({ topic, partition, message }) => {
      console.log({
        key: message.key?.toString(),
        value: message.value.toString(),
      });
    },
  });
})();

5. 마무리하며 🌐

NodePort를 활용한 외부 노출과 NGINX의 TCP 프록시 연동을 통해 Kafka 클러스터를 외부에서 유연하게 사용할 수 있는 환경을 구축할 수 있습니다. 특히 서비스 메시 또는 인그레스 컨트롤러가 TCP를 직접 처리하지 못할 경우, 이 전략은 효과적인 대안이 됩니다.

다음 글에서는 Kafka 인증 설정과 토픽 자동 생성, 메시지 형식 정합성 검사 등 Kafka 운영 고도화에 대해서도 이어서 소개해 보겠습니다. Kafka 설정, 이제 어렵지 않죠? 😉