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"를 실행해 보세요.

  1. 등록 확인
consul catalog services -service druid-prod-broker -tag role:broker

druid-prod-broker를 servicePrefix-role로 바꿔 주세요. 노드의 host:port와 커스텀 tag들이 보일 거예요.

  1. TTL 상태 확인
consul health service druid-prod-broker

정상 health check는 Status: passing과 TTL 메모("Druid node is healthy")를 보여줘야 해요.

  1. Leader KV 검사
consul kv get -detailed druid/leader/coordinator

출력에는 세션 ID와 저장된 leader URI(예: http://host:8081)가 포함돼요. 값이 반환되지 않으면 아직 leader가 등록되지 않은 거예요.

  1. 업데이트 감시
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}
  • 서비스 메타데이터: DiscoveryDruidNode JSON
  • 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).
  • 전체 DiscoveryDruidNode JSON이 서비스 메타데이터에 저장돼요.
  • TTL 기반 health check와 자동 갱신.
  • 효율적인 변경 감지를 위한 blocking query.

장점:

  • 네이티브 Consul 통합
  • Consul UI에서 보임
  • 내장 health checking
  • 표준 Consul 패턴

한계:

  • 서비스 메타데이터 크기 한계(~512KB 일반적으로)
  • 정기적인 health check 갱신 필요

Alternative Approaches

고려할 수 있는 다른 유효한 구현 패턴:

  1. Key-Value Store Approach - Consul의 KV store에 노드 정보 저장:

    • /druid/{cluster}/{role}/{host:port} = DiscoveryDruidNode JSON
    • ephemeral key(자동 정리)에 Consul 세션 사용
    • 변경 감시를 위해 KV prefix watch
    • ZooKeeper에 더 가까운 동작
    • 메타데이터 크기 한계 없음
  2. Hybrid Approach - 디스커버리를 위한 서비스 + 상세 메타데이터를 위한 KV 결합:

    • 최소 정보로 서비스 등록
    • 전체 세부 정보를 KV store에 저장
    • 두 세계의 장점이지만 더 복잡
  3. Service + Tags - 필터링을 위해 광범위한 Consul 서비스 tag 사용:

    • tag 기반 필터링으로 더 빠른 쿼리
    • 서비스 자체의 메타데이터는 제한적
    • 매우 큰 클러스터에서 더 잘 확장

현재 구현(Service Catalog)은 단순성, 네이티브 Consul 통합, Consul 모범 사례와의 정렬 때문에 선택됐어요.

더 알아보기 (Learn more)