MQTT 브로커 컨테이너화: Docker와 Kubernetes 배포
Docker와 Kubernetes 환경에서 MQTT 브로커를 컨테이너로 배포하고 운영하는 절차, 예제 구성 및 운영 고려사항을 정리한 전략
목차
소개
IoT 서비스에서 메시지 중계 역할을 하는 MQTT 브로커는 가용성과 확장성이 중요하다. 컨테이너화는 일관된 배포와 빠른 확장을 제공한다. 본문은 Docker와 Kubernetes를 사용한 MQTT 브로커 배포 과정을 단계별로 설명한다. 처음 접하는 사람도 이해할 수 있도록 구성과 명령 예제를 포함한다.
왜 컨테이너화인가
컨테이너는 환경 차이를 줄이고 배포 자동화를 쉽게 만든다. MQTT 브로커를 컨테이너화하면 다음과 같은 이점이 있다.
- 환경 일관성: 개발·테스트·운영에서 동일 이미지 사용
- 자동화된 배포: CI/CD 파이프라인과 연계 가능
- 손쉬운 스케일링: Kubernetes로 수평 확장 가능
- 격리된 런타임: 브로커 프로세스의 종속성 관리 용이
Docker로 MQTT 브로커 배포
이미지 선택
가장 널리 쓰이는 브로커는 Eclipse Mosquitto다. 공식 이미지를 사용하면 설정 파일과 볼륨만으로 간단히 운영할 수 있다. 다른 브로커(EMQX, HiveMQ 등)도 컨테이너화가 가능하다.
간단한 docker-compose 예제
아래 예제는 Mosquitto를 Docker Compose로 띄우고 설정 파일과 로그를 호스트에 마운트하는 구성이다.
version: '3.8'
services:
mosquitto:
image: eclipse-mosquitto:2.0
container_name: mosquitto
ports:
- "1883:1883"
- "9001:9001"
volumes:
- ./mosquitto/config:/mosquitto/config
- ./mosquitto/data:/mosquitto/data
- ./mosquitto/log:/mosquitto/log
restart: unless-stopped
config 폴더에 mosquitto.conf를 두면 포트, 인증, 브리지 등 설정을 반영할 수 있다. 운영 환경에서는 인증과 TLS 설정을 반드시 적용한다.
Kubernetes로 확장 배포
Kubernetes는 고가용성과 자동 복구를 제공한다. 쿠버네티스에서 MQTT 브로커를 운영할 때는 상태 저장(특히 메시지 지속성)과 서비스 노출 방식을 설계해야 한다.
간단한 Deployment와 Service
다음은 기본적인 Deployment와 ClusterIP/NodePort 서비스 예제다. 프로덕션에서는 LoadBalancer 또는 Ingress, 그리고 인증/인증서 구성이 필요하다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: mosquitto
spec:
replicas: 2
selector:
matchLabels:
app: mosquitto
template:
metadata:
labels:
app: mosquitto
spec:
containers:
- name: mosquitto
image: eclipse-mosquitto:2.0
ports:
- containerPort: 1883
volumeMounts:
- name: mosquitto-data
mountPath: /mosquitto/data
volumes:
- name: mosquitto-data
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: mosquitto-service
spec:
type: NodePort
selector:
app: mosquitto
ports:
- port: 1883
targetPort: 1883
nodePort: 30183
위 구성은 간단한 테스트용이다. 메시지 지속성이 필요한 경우 PersistentVolume을 사용하고 StatefulSet이나 외부 저장소 연동을 고려한다.
Helm으로 배포
Helm 차트는 복잡한 설정을 간단히 적용할 수 있게 해준다. mqtt k8s helm chart를 사용하면 TLS, 인증, 퍼시스턴스 옵션을 values.yaml로 관리할 수 있다. 설치 예시는 다음과 같다.
# 예: mosquitto 차트가 있다고 가정
helm repo add mycharts https://example.com/charts
helm install my-mqtt mycharts/mosquitto -f values.yaml
values.yaml에는 볼륨, 서비스 타입, 리소스 제한, 환경 변수 등을 정의한다. 운영 환경에서는 리소스 요청/제한과 PodDisruptionBudget을 설정해 안정성을 높인다.
운영 고려사항
영속성
MQTT 메시지 보존(retain)이나 QoS 1/2 처리를 위해 브로커는 디스크에 상태를 기록할 수 있다. Kubernetes에서는 PersistentVolume을 사용해 데이터를 보장한다. StatefulSet이나 외부 DB 연동도 대안이다.
보안
- TLS로 통신 암호화
- 클라이언트 인증 및 사용자별 권한 제어
- 네트워크 정책으로 접근 제어
- 이미지의 취약점 스캔과 최소 권한 실행
스케일링과 로드밸런싱
MQTT 브로커는 상태를 가질 수 있어 단순 수평 확장에 제한이 있다. 브로커 클러스터링(예: EMQX)이나 세션 스토어를 분리해 수평 확장을 구현한다. 로드밸런서는 TCP 레벨(1883)과 WebSocket(9001) 모두 지원하도록 구성한다.
문제 해결 팁
- 연결 실패: 포트와 네트워크 정책 확인
- 메시지 손실: 퍼시스턴스 설정과 QoS 확인
- 성능 저하: 리소스 제한과 스레드/파일 디스크립터 수 확인
- 로그 분석: 컨테이너 로그와 브로커 로그를 함께 확인
정리
mqtt docker 배포는 빠르고 간단한 시작을 제공하며, kubernetes mqtt broker 환경은 확장성과 가용성을 제공한다. mqtt k8s helm chart를 활용하면 복잡한 설정을 효율적으로 관리할 수 있다. 운영에서는 영속성, 보안, 스케일링 전략을 우선 고려한다. 단계적으로 테스트 환경에서 설정을 검증한 뒤 운영 환경으로 전환하는 방식을 권장한다.