Consul 기반 서비스 디스커버리
Consul 기반 서비스 디스커버리
druid-consul-extensions 확장은 HashiCorp Consul을 사용해 노드를 발견(discovery)할 수 있게 해주는 Apache Druid 확장이에요. ZooKeeper나 Kubernetes 기반 디스커버리 대신 Consul의 서비스 카탈로그를 사용해 Druid 클러스터 노드를 발견할 수 있어요.
출처: 문서
본문
Quick Start
이 Apache Druid 확장을 사용하려면 extensions load list에 druid-consul-extensions를 포함해 주세요.
# Load the extension
druid.extensions.loadList=["druid-consul-extensions"]
# Minimal Consul configuration
druid.discovery.type=consul
druid.discovery.consul.connection.host=localhost
druid.discovery.consul.connection.port=8500
druid.discovery.consul.service.servicePrefix=druid
# Required HTTP-based configurations
druid.serverview.type=http
druid.indexer.runner.type=httpRemote
# Enable Consul-based leader election
druid.coordinator.selector.type=consul
druid.indexer.selector.type=consul
프로덕션 배포에 대해서는 보안, TLS, 고급 옵션에 대한 아래의 Configuration 섹션을 확인해 주세요.
Configuration
이 확장은 Druid의 HTTP 기반 세그먼트 및 태스크 관리와 함께 동작해요. 다음 구성은 모든 Druid 노드에 설정해야 해요.
druid.serverview.type=http
druid.indexer.runner.type=httpRemote
druid.discovery.type=consul
druid.coordinator.selector.type=consul
druid.indexer.selector.type=consul
참고: 이 확장은 Coordinator와 Overlord 역할의 서비스 디스커버리와 leader election을 모두 포함한 완전한 ZooKeeper 대체물을 제공해요.
Common Properties
| 속성 | 가능한 값 | 설명 | 기본값 | 필수 |
|---|---|---|---|---|
druid.discovery.consul.connection.host |
String | Consul agent hostname 또는 IP 주소. | localhost |
No |
druid.discovery.consul.connection.port |
Integer | Consul agent HTTP API 포트. | 8500 |
No |
druid.discovery.consul.connection.connectTimeout |
ISO8601 Duration | Consul client의 연결 타임아웃. | PT10S |
No |
druid.discovery.consul.connection.socketTimeout |
ISO8601 Duration | Consul client의 소켓 읽기 타임아웃. watchSeconds보다 커야 해요. | PT75S (75s) |
No |
druid.discovery.consul.connection.maxTotalConnections |
Integer | 연결 풀의 최대 총 HTTP 연결 수. | 50 |
No |
druid.discovery.consul.connection.maxConnectionsPerRoute |
Integer | 라우트(host)당 최대 HTTP 연결 수. | 20 |
No |
druid.discovery.consul.service.servicePrefix |
String | Consul 서비스 이름의 접두사. 클러스터를 네임스페이스로 구분해요. | None | Yes |
druid.discovery.consul.service.datacenter |
String | 등록 및 발견을 위한 Consul datacenter. | 기본 datacenter | No |
druid.discovery.consul.service.healthCheckInterval |
ISO8601 Duration | Consul health check 갱신 간격. | PT10S |
No |
druid.discovery.consul.service.deregisterAfter |
ISO8601 Duration | health check 실패 후 서비스 등록 해제. | PT90S |
No |
druid.discovery.consul.service.serviceTags.* |
String | 추가 Consul 서비스 tag를 key/value 쌍으로 (key:value로 렌더링). AZ/tier/version에 유용. |
None | No |
druid.discovery.consul.auth.aclToken |
String | 인증용 Consul ACL token. | None | No |
druid.discovery.consul.auth.basicAuthUser |
String | HTTP basic authentication용 사용자 이름 (선제적 Basic Auth). | None | No |
druid.discovery.consul.auth.basicAuthPassword |
String | HTTP basic authentication용 비밀번호. | None | No |
druid.discovery.consul.auth.allowBasicAuthOverHttp |
Boolean | 암호화되지 않은 HTTP를 통한 basic auth 자격 증명 허용. 기본적으로 basic auth는 TLS를 요구하며 TLS가 구성되지 않으면 빠르게 실패해요. sidecar TLS 종료 시나리오에서만 true로 설정하세요. |
false |
No |
druid.discovery.consul.watch.watchSeconds |
ISO8601 Duration | 서비스 변경을 위한 blocking query 타임아웃. | PT60S |
No |
druid.discovery.consul.watch.maxWatchRetries |
Long | 회로 차단기(circuit breaker)가 활성화되기 전 최대 연속 watch 실패 수. 무제한 재시도(기본값)는 -1 또는 0 사용. |
unlimited |
No |
druid.discovery.consul.watch.watchRetryDelay |
ISO8601 Duration | 실패한 watch를 재시도하기 전 대기 시간. | PT10S |
No |
druid.discovery.consul.watch.circuitBreakerSleep |
ISO8601 Duration | maxWatchRetries를 초과한 후 회로 차단기가 트립될 때의 수면 시간. | PT2M (2 minutes) |
No |
druid.discovery.consul.leader.coordinatorLeaderLockPath |
String | Coordinator leader lock용 Consul KV 경로. | druid/leader/coordinator |
No |
druid.discovery.consul.leader.overlordLeaderLockPath |
String | Overlord leader lock용 Consul KV 경로. | druid/leader/overlord |
No |
druid.discovery.consul.leader.leaderMaxErrorRetries |
Long | leader election 시도를 중지하기 전 최대 연속 오류 수. 무제한 재시도(기본값)는 -1 또는 0 사용. leader election은 포기하면 클러스터 운영이 깨지므로 기본적으로 무기한 재시도하며, 지수 백오프(최대 leaderRetryBackoffMax)가 일시적 실패 중 Consul을 압도하는 것을 방지해요. |
unlimited |
No |
druid.discovery.consul.leader.leaderRetryBackoffMax |
ISO8601 Duration | leader election 재시도 사이에 적용되는 최대 backoff. | PT5M |
No |
druid.discovery.consul.leader.leaderSessionTtl |
ISO8601 Duration | leader election 세션의 TTL. 설정하지 않으면 자동 계산. | max(45s, 3 * healthCheckInterval) |
No |
TLS Configuration
이 확장은 Consul로의 보안 HTTPS 연결을 위해 Druid의 표준 TLS 구성을 사용해요. TLS를 활성화하려면 druid.discovery.consul.connection.sslClientConfig.* 아래에 SSL client 속성을 구성해 주세요.
보안 참고:
sslClientConfig가 제공됐는데 TLS 초기화가 실패하면(예: 잘못된 truststore), Consul client는 빠르게 실패하고 일반 HTTP로 폴백하지 않아요.- Basic Auth 보안: 기본적으로 basic authentication(
basicAuthUser와basicAuthPassword)을 TLS 없이 구성하면 클라이언트는 오류와 함께 빠르게 실패해요. 이는 자격 증명이 평문으로 우발적으로 전송되는 것을 방지해요. HTTP를 통한 basic auth를 명시적으로 허용하려면(예: sidecar TLS 종료 시나리오),allowBasicAuthOverHttp=true로 설정해 주세요. 활성화하면 평문 자격 증명 전송에 대한 경고가 로그로 기록돼요.
TLS 속성:
| 속성 | 설명 | 기본값 |
|---|---|---|
druid.discovery.consul.connection.sslClientConfig.protocol |
사용할 SSL/TLS 프로토콜. | TLSv1.2 |
druid.discovery.consul.connection.sslClientConfig.trustStoreType |
truststore 타입 (PKCS12, JKS 등). | java.security.KeyStore.getDefaultType() |
druid.discovery.consul.connection.sslClientConfig.trustStorePath |
Consul 서버 인증서를 검증하기 위한 truststore 경로. [TLS에 필수] | None |
druid.discovery.consul.connection.sslClientConfig.trustStoreAlgorithm |
TrustManagerFactory용 알고리즘. | javax.net.ssl.TrustManagerFactory.getDefaultAlgorithm() |
druid.discovery.consul.connection.sslClientConfig.trustStorePassword |
truststore 비밀번호. password providers를 사용할 수 있어요. | None |
druid.discovery.consul.connection.sslClientConfig.keyStoreType |
클라이언트 인증서용 keystore 타입 (PKCS12, JKS 등). | java.security.KeyStore.getDefaultType() |
druid.discovery.consul.connection.sslClientConfig.keyStorePath |
mTLS용 클라이언트 인증서가 있는 keystore 경로. [선택] | None |
druid.discovery.consul.connection.sslClientConfig.keyStorePassword |
keystore 비밀번호. password providers를 사용할 수 있어요. | None |
druid.discovery.consul.connection.sslClientConfig.keyManagerPassword |
keystore 내 key manager 비밀번호. password providers를 사용할 수 있어요. | None |
druid.discovery.consul.connection.sslClientConfig.keyManagerFactoryAlgorithm |
KeyManagerFactory용 알고리즘. | javax.net.ssl.KeyManagerFactory.getDefaultAlgorithm() |
druid.discovery.consul.connection.sslClientConfig.certAlias |
mTLS용 keystore에서 사용할 인증서의 alias. [선택] | None |
druid.discovery.consul.connection.sslClientConfig.validateHostnames |
인증서에서 Consul 서버 hostname 검증. | true |
지원되는 keystore 형식과 추가 구성 옵션에 대한 자세한 내용은 Simple Client SSL Context 확장 문서를 참고해 주세요.
Example Configuration
전형적인 배포의 경우:
# Extension loading
druid.extensions.loadList=["druid-consul-extensions", ...]
# Discovery configuration
druid.discovery.type=consul
druid.discovery.consul.connection.host=consul.example.com
druid.discovery.consul.connection.port=8500
druid.discovery.consul.service.servicePrefix=druid-prod
# HTTP-based segment and task management
druid.serverview.type=http
druid.indexer.runner.type=httpRemote
# Leader election using Consul (replaces ZooKeeper)
druid.coordinator.selector.type=consul
druid.indexer.selector.type=consul
# Optional: discovery watch retry behavior
# Use -1 for unlimited retries (default). Set a positive number to stop after N consecutive failures.
# druid.discovery.consul.watch.maxWatchRetries=-1
# Optional: leader election retry behavior (also defaults to -1/unlimited)
# druid.discovery.consul.leader.leaderMaxErrorRetries=-1
# druid.discovery.consul.leader.leaderRetryBackoffMax=PT5M
ACL이 있는 보안 Consul 클러스터의 경우:
druid.discovery.type=consul
druid.discovery.consul.connection.host=consul.example.com
druid.discovery.consul.connection.port=8500
druid.discovery.consul.service.servicePrefix=druid-prod
druid.discovery.consul.auth.aclToken=your-secret-acl-token
druid.discovery.consul.service.datacenter=dc1
서버 인증서 검증이 있는 TLS 지원 Consul의 경우:
druid.discovery.type=consul
druid.discovery.consul.connection.host=consul.example.com
druid.discovery.consul.connection.port=8501
druid.discovery.consul.service.servicePrefix=druid-prod
druid.discovery.consul.auth.aclToken=your-secret-acl-token
# TLS configuration (standard Druid properties)
druid.discovery.consul.connection.sslClientConfig.trustStorePath=/etc/druid/certs/consul-ca-truststore.jks
druid.discovery.consul.connection.sslClientConfig.trustStorePassword=truststore-password
druid.discovery.consul.connection.sslClientConfig.validateHostnames=true
상호 TLS(mTLS) 인증이 있는 Consul의 경우:
druid.discovery.type=consul
druid.discovery.consul.connection.host=consul.example.com
druid.discovery.consul.connection.port=8501
druid.discovery.consul.service.servicePrefix=druid-prod
druid.discovery.consul.auth.aclToken=your-secret-acl-token
# TLS with client certificates (mutual TLS)
druid.discovery.consul.connection.sslClientConfig.trustStorePath=/etc/druid/certs/consul-ca-truststore.jks
druid.discovery.consul.connection.sslClientConfig.trustStorePassword=truststore-password
druid.discovery.consul.connection.sslClientConfig.keyStorePath=/etc/druid/certs/druid-client-keystore.p12
druid.discovery.consul.connection.sslClientConfig.keyStorePassword=keystore-password
druid.discovery.consul.connection.sslClientConfig.validateHostnames=true
Datacenter Scope
- Consul datacenter 범위: 서비스 카탈로그, KV, 세션, 잠금.
- Leader election은 DC 범위로 지정돼요.
datacenter구성으로 여러 DC 지원.- region당 단일 DC 권장.
Health Check TTL Behavior
- 서비스 health check TTL = 3 *
healthCheckInterval(최소 30s). - Heartbeat는 매
healthCheckInterval마다 전송돼요.
Operational Verification
확장을 활성화한 후, 모든 것이 연결됐는지 Consul에 대한 빠른 "sanity walk"를 실행해 보세요.
- 등록 확인
consul catalog services -service druid-prod-broker -tag role:broker
druid-prod-broker를 servicePrefix-role로 바꿔 주세요. 노드의 host:port와 커스텀 tag들이 보일 거예요.
- TTL 상태 확인
consul health service druid-prod-broker
정상 health check는 Status: passing과 TTL 메모("Druid node is healthy")를 보여줘야 해요.
- Leader KV 검사
consul kv get -detailed druid/leader/coordinator
출력에는 세션 ID와 저장된 leader URI(예: http://host:8081)가 포함돼요. 값이 반환되지 않으면 아직 leader가 등록되지 않은 거예요.
- 업데이트 감시
consul watch -type=service -service=druid-prod-broker
Druid 노드를 시작/중지하면 Consul이 확장의 로그와 메트릭과 일치하는 변경 알림을 내보내야 해요.
명령이 빈 출력을 반환하면 로컬 Consul agent로의 네트워크 연결, ACL 권한, servicePrefix 철자를 다시 확인해 주세요.
Implementation Details
Service Registration
- 서비스 이름:
{servicePrefix}-{nodeRole} - 서비스 ID:
{servicePrefix}-{nodeRole}-{host}-{port} - 서비스 tag:
druid,role:{nodeRole} - 서비스 메타데이터:
DiscoveryDruidNodeJSON - Health check: TTL 기반, 매
healthCheckInterval마다 갱신
Service Discovery
- 역할별 서비스에 대해 Consul health service API 조회
- blocking query로 변경 감시
- 노드 추가/제거에 대해 리스너에 알림
Leader Election
Consul 세션과 KV 잠금을 사용해요.
- 세션 TTL:
max(45s, healthCheckInterval * 3) - 잠금 지연: 5초
- 페일오버 시간: 15~45초 (healthCheckInterval에 따라 다름)
Authentication Methods
확장은 Consul과의 통신을 보호하기 위한 여러 인증 방법을 지원해요.
1. ACL Token Authentication (권장)
프로덕션 배포에서 가장 흔한 방법:
druid.discovery.consul.auth.aclToken=your-secret-token
토큰은 적절한 권한을 가져야 해요 (아래 Consul ACL Permissions 섹션 참고).
2. TLS/HTTPS with Certificate Verification
암호화된 통신과 서버 검증을 위해 Consul의 CA 인증서를 담은 truststore를 구성해 주세요.
# TLS configuration using truststore
druid.discovery.consul.connection.sslClientConfig.protocol=TLSv1.3
druid.discovery.consul.connection.sslClientConfig.trustStoreType=PKCS12
druid.discovery.consul.connection.sslClientConfig.trustStorePath=/path/to/truststore.p12
druid.discovery.consul.connection.sslClientConfig.trustStorePassword=truststore-password
druid.discovery.consul.connection.sslClientConfig.validateHostnames=true
3. Mutual TLS (mTLS) Authentication
가장 강력한 보안을 위해 서버 검증에 더해 클라이언트 인증서를 사용해 주세요.
# TLS with both truststore and keystore (mTLS)
druid.discovery.consul.connection.sslClientConfig.protocol=TLSv1.3
# Server verification (truststore with Consul CA)
druid.discovery.consul.connection.sslClientConfig.trustStoreType=PKCS12
druid.discovery.consul.connection.sslClientConfig.trustStorePath=/path/to/truststore.p12
druid.discovery.consul.connection.sslClientConfig.trustStorePassword=truststore-password
# Client authentication (keystore with client certificate)
druid.discovery.consul.connection.sslClientConfig.keyStoreType=PKCS12
druid.discovery.consul.connection.sslClientConfig.keyStorePath=/path/to/client-keystore.p12
druid.discovery.consul.connection.sslClientConfig.keyStorePassword=keystore-password
druid.discovery.consul.connection.sslClientConfig.certAlias=client
# Hostname verification
druid.discovery.consul.connection.sslClientConfig.validateHostnames=true
PEM 파일에서 Keystore 만들기:
PEM 인증서와 키 파일이 있다면 PKCS12 keystore로 변환해 주세요.
# 1. Create client keystore from PEM certificate and private key
openssl pkcs12 -export \
-in client-cert.pem \
-inkey client-key.pem \
-out client-keystore.p12 \
-name client \
-passout pass:keystore-password
# 2. Create truststore from Consul CA certificate
keytool -import \
-file consul-ca.pem \
-alias consul-ca \
-keystore truststore.p12 \
-storetype PKCS12 \
-storepass truststore-password \
-noprompt
참고:
- JKS와 PKCS12 keystore 타입 모두 지원돼요.
- PKCS12는 업계 표준으로 권장돼요.
- Keystore는 암호화되거나 암호화되지 않은 개인 키를 모두 담을 수 있어요.
certAlias는 keystore를 만들 때 사용한 alias(위 예시의 "client")와 일치해야 해요.- hostname 검증이 필요 없다면(예: 실험실 환경),
validateHostnames=false로 설정해 주세요.
4. Basic Authentication
간단한 HTTP basic auth의 경우(덜 흔함). 보안 요구 사항: Basic authentication은 자격 증명 노출을 막기 위해 기본적으로 TLS를 요구해요.
TLS 포함(권장):
# Basic auth over TLS (secure)
druid.discovery.consul.auth.basicAuthUser=username
druid.discovery.consul.auth.basicAuthPassword=password
druid.discovery.consul.connection.sslClientConfig.trustStorePath=/path/to/truststore.p12
druid.discovery.consul.connection.sslClientConfig.trustStorePassword=truststore-password
TLS 없음(sidecar TLS 종료 전용):
# Basic auth over HTTP (requires explicit opt-in)
druid.discovery.consul.auth.basicAuthUser=username
druid.discovery.consul.auth.basicAuthPassword=password
druid.discovery.consul.auth.allowBasicAuthOverHttp=true
중요: TLS 없이 allowBasicAuthOverHttp=true를 설정하지 않고 basic auth 자격 증명을 구성하면 클라이언트는 오류 메시지와 함께 시작에 실패할 거예요. 이 fail-fast 동작은 우발적인 평문 자격 증명 전송을 방지해요. allowBasicAuthOverHttp=true는 트래픽이 Consul에 도달하기 전에 sidecar TLS 종료(예: Envoy, nginx)가 암호화를 처리할 때만 사용하세요.
5. Combined Authentication
심층 방어(defense-in-depth)를 위해 방법들을 결합할 수 있어요. 예를 들어 TLS/mTLS + ACL token(권장):
# TLS + ACL token
druid.discovery.consul.auth.aclToken=your-token
druid.discovery.consul.connection.sslClientConfig.trustStorePath=/path/to/truststore.p12
druid.discovery.consul.connection.sslClientConfig.trustStorePassword=truststore-password
# Optional: mTLS (client certificate)
druid.discovery.consul.connection.sslClientConfig.keyStorePath=/path/to/client-keystore.p12
druid.discovery.consul.connection.sslClientConfig.keyStorePassword=keystore-password
druid.discovery.consul.connection.sslClientConfig.certAlias=client
Requirements
- Consul 1.0.0 이상.
- 모든 Druid 노드에서 Consul agent로의 네트워크 연결.
- Consul ACL을 사용한다면, 다음 권한을 가진 적절한 ACL token:
- 서비스 등록 및 등록 해제
- 서비스 카탈로그 읽기
- health check 갱신
- TLS/mTLS를 사용한다면:
- 신뢰할 수 있는 CA가 발급한 유효한 인증서
- Druid 프로세스가 접근할 수 있는 인증서 파일
- TLS 연결을 수락하도록 구성된 Consul
Consul ACL Permissions
Consul ACL이 활성화된 경우, ACL token은 다음 권한을 가져야 해요.
서비스 디스커버리 전용:
service "{servicePrefix}-" {
policy = "write"
}
service_prefix "" {
policy = "read"
}
Leader Election(Coordinator/Overlord)의 경우:
서비스 권한에 더해, Coordinator와 Overlord 노드는 leader election을 위해 KV와 세션 권한이 필요해요.
# KV permissions for leader election locks
key_prefix "druid/leader/" {
policy = "write"
}
# Session permissions for creating and managing Consul sessions
session_prefix "" {
policy = "write"
}
완전한 ACL 정책 예시:
디스커버리와 leader election 둘 다에 Consul을 사용하는 완전한 Druid 배포:
# Service discovery permissions (all nodes)
service "druid-prod-" {
policy = "write"
}
service_prefix "" {
policy = "read"
}
# Leader election permissions (Coordinator and Overlord only)
key_prefix "druid/leader/" {
policy = "write"
}
session_prefix "" {
policy = "write"
}
참고: 노드 타입별로 별도의 ACL token을 만들 수 있어요.
- Broker, Historical, MiddleManager: 서비스 권한만 필요.
- Coordinator, Overlord: 서비스와 leader election 권한 둘 다 필요.
Monitoring
Consul Monitoring
Consul 클러스터에서 다음을 모니터링하세요.
- 각 Druid 노드 역할에 대한 서비스 등록
- 모든 Druid 서비스의 health check 상태
- Consul agent 연결
- KV store의 leader election 잠금 (
druid/leader/coordinator와druid/leader/overlord아래 키) - Coordinator와 Overlord 노드의 세션 상태
Druid Logs
Druid 로그에서 다음을 확인하세요.
Successfully announced DiscoveryDruidNode- 노드 등록 성공Failed to announce- 등록 오류Exception while watching for role- 디스커버리 오류Created Consul session [%s] for leader election- leader election 세션 생성Failed to renew session- 세션 갱신 실패 (네트워크 문제를 나타낼 수 있음)Became leader/Lost leadership- leader election 상태 변경
Metrics and Observability
확장은 ServiceEmitter를 사용할 수 있을 때 경량 Druid 메트릭을 내보내요.
consul/announce/success|failure— 노드 announce/unannounce 결과consul/healthcheck/failure— TTL heartbeat 갱신 실패consul/watch/error|added|removed— 디스커버리 watch 오류와 변경consul/watch/lifecycle— watcher 스레드 시작/중지 이벤트consul/leader/become|stop|renew/fail— leader election 전환consul/leader/ownership_mismatch— 세션 불일치로 승격 건너뜀consul/leader/loop— leader election 루프 수명 주기consul/leader/giveup— leader 루프가 재시도 예산을 초과
다음도 모니터링해야 해요.
- Consul의 내장 메트릭과 health check
- Druid 애플리케이션 로그
- 서비스 상태와 등록을 시각화하는 Consul UI
권장 알림:
- Druid 서비스가 Consul 카탈로그에서 사라질 때 알림
- health check가 오랫동안 실패할 때 알림
- 잦은 leader election 변경(불안정을 나타냄) 시 알림
- Consul agent가 Druid 노드에서 도달 불가능해질 때 알림
Prometheus Mapping (example)
Prometheus emitter를 사용한다면 다음을 metrics config(dimension map)에 추가해서 Consul 메트릭이 유용한 label로 노출되게 해 주세요.
{
"consul/announce/success": {
"dimensions": ["role"],
"type": "count",
"help": "Druid Consul announce success"
},
"consul/announce/failure": {
"dimensions": ["role"],
"type": "count",
"help": "Druid Consul announce failure"
},
"consul/healthcheck/failure": {
"dimensions": [],
"type": "count",
"help": "Druid Consul TTL heartbeat failures"
},
"consul/watch/error": {
"dimensions": ["role"],
"type": "count",
"help": "Druid Consul discovery watch errors"
},
"consul/watch/added": {
"dimensions": ["role"],
"type": "count",
"help": "Druid nodes added by Consul watch"
},
"consul/watch/removed": {
"dimensions": ["role"],
"type": "count",
"help": "Druid nodes removed by Consul watch"
},
"consul/watch/lifecycle": {
"dimensions": ["role", "state"],
"type": "count",
"help": "Consul watch thread start/stop events"
},
"consul/leader/become": {
"dimensions": ["lock"],
"type": "count",
"help": "Leader elected"
},
"consul/leader/stop": {
"dimensions": ["lock"],
"type": "count",
"help": "Leadership lost/stopped"
},
"consul/leader/loop": {
"dimensions": ["lock", "state"],
"type": "count",
"help": "Leader election loop lifecycle events"
},
"consul/leader/renew/fail": {
"dimensions": ["lock"],
"type": "count",
"help": "Leader session renew failures"
},
"consul/leader/ownership_mismatch": {
"dimensions": ["lock"],
"type": "count",
"help": "Attempts blocked because Consul lock session changed unexpectedly"
},
"consul/leader/giveup": {
"dimensions": ["lock"],
"type": "count",
"help": "Leader election aborted after exceeding retry budget"
}
}
Lifecycle 메트릭(consul/watch/lifecycle, consul/leader/loop)은 state dimension(start 또는 stop)을 내보내므로, Prometheus에서 start 카운터에서 stop 카운터를 빼서 gauge를 만들 수 있어요.
Prometheus에서 예를 들어 스파이크에 대해 알림을 걸 수 있어요.
sum by (role) (rate(druid_consul_watch_error[5m])) > 0
sum by (lock) (rate(druid_consul_leader_renew_fail[5m])) > 0
참고: 이름은 Prometheus emitter가 정규화해서 consul/watch/error는 구성된 namespace로 druid_consul_watch_error가 돼요.
Production Checklist
- 단일 DC 내 AZ 전반에 Consul 서버를 실행하고, 모든 Druid 노드는 그 DC의 로컬 agent와 통신.
- 최소 권한 정책으로 ACL token 사용 (원하면 leader와 나머지를 위한 별도 token).
- Consul HTTP API에 TLS/mTLS 활성화. CA truststore와 선택적 클라이언트 keystore 배포.
healthCheckInterval와deregisterAfter를 네트워크 지연에 맞게 설정 (예: 고지연 시 30s/180s).- 대규모 클러스터에서 Consul 부하를 줄이려면
watchSeconds증가 (예: 120s). - 모든 노드에서 시간 동기화(NTP) 보장. 세션 TTL은 정확한 시계에 의존.
- 관측성과 필터링을 위해 서비스 tag(AZ, tier, version) 추가 고려.
Limitations
- 모든 Druid 노드가 Consul agent에 도달할 수 있어야 해요.
- 서비스 메타데이터 크기는 Consul의 한계(일반적으로 512KB)로 제한돼요.
- 여러 클러스터를 실행한다면 leader election 경로는 클러스터별로 고유해야 해요 (
coordinatorLeaderLockPath와overlordLeaderLockPath로 구성). - TLS 구성의 경우, 더 나은 호환성을 위해 PEM 파일보다 Java keystore(PKCS12 또는 JKS)를 권장해요.
Implementation Details (추가)
Current Approach: Service Registration
확장은 다음 설계로 Consul의 Service Catalog를 사용해요.
- 각 Druid 노드는 Consul 서비스로 등록돼요.
- 서비스 이름 형식:
{servicePrefix}-{nodeRole}(예:druid-prod-broker). - 전체
DiscoveryDruidNodeJSON이 서비스 메타데이터에 저장돼요. - TTL 기반 health check와 자동 갱신.
- 효율적인 변경 감지를 위한 blocking query.
장점:
- 네이티브 Consul 통합
- Consul UI에서 보임
- 내장 health checking
- 표준 Consul 패턴
한계:
- 서비스 메타데이터 크기 한계(~512KB 일반적으로)
- 정기적인 health check 갱신 필요
Alternative Approaches
고려할 수 있는 다른 유효한 구현 패턴:
-
Key-Value Store Approach - Consul의 KV store에 노드 정보 저장:
/druid/{cluster}/{role}/{host:port} = DiscoveryDruidNode JSON- ephemeral key(자동 정리)에 Consul 세션 사용
- 변경 감시를 위해 KV prefix watch
- ZooKeeper에 더 가까운 동작
- 메타데이터 크기 한계 없음
-
Hybrid Approach - 디스커버리를 위한 서비스 + 상세 메타데이터를 위한 KV 결합:
- 최소 정보로 서비스 등록
- 전체 세부 정보를 KV store에 저장
- 두 세계의 장점이지만 더 복잡
-
Service + Tags - 필터링을 위해 광범위한 Consul 서비스 tag 사용:
- tag 기반 필터링으로 더 빠른 쿼리
- 서비스 자체의 메타데이터는 제한적
- 매우 큰 클러스터에서 더 잘 확장
현재 구현(Service Catalog)은 단순성, 네이티브 Consul 통합, Consul 모범 사례와의 정렬 때문에 선택됐어요.
더 알아보기 (Learn more)
- 서버 디스커버리 문서에서 Druid 노드 발견 구조를 살펴볼 수 있어요.
- Simple Client SSL Context 문서에서 TLS 구성 옵션을 확인해 보세요.
- Consul의 서비스 디스커버리, KV, ACL 기능은 HashiCorp Consul 문서를 참고해 주세요.