Consul Service Discovery — 등록·DNS·헬스 체크

2026-05-03확률과 통계 마스터 노트

HashiCorp Consul 마스터 노트 시리즈 3편. 서비스 등록의 두 방법(파일·HTTP API), DNS 8600 포트로 이름 조회, 헬스 체크 7종(Script·HTTP·TCP·gRPC·Docker·TTL·Alias)의 결정적 차이, 태그·메타데이터 활용, prepared query까지 — 시험 Objective 3 핵심.

이 글은 HashiCorp Consul 마스터 노트 시리즈의 세 번째 편입니다. 2편(배포)에서 클러스터 띄우는 법을 잡았다면, 이번엔 그 클러스터 위에 서비스를 등록하고 찾는 방법 — Objective 3.

서비스 디스커버리는 Consul의 가장 자주 쓰는 기능. 등록·조회·헬스 체크 세 단계를 정확히 익히면 마이크로서비스 간 동적 연결이 정리돼요.

서비스 등록 — 두 가지 방법

1. 구성 파일

# /etc/consul.d/web.hcl
service {
  name = "web"
  port = 8080
  tags = ["v1", "primary"]
  
  meta {
    version = "1.2.3"
    team    = "frontend"
  }
  
  check {
    id       = "web-http"
    name     = "HTTP Health Check"
    http     = "http://localhost:8080/health"
    method   = "GET"
    interval = "10s"
    timeout  = "1s"
  }
}
# 등록
consul services register /etc/consul.d/web.hcl

# 또는 에이전트 시작 시 자동 등록 (config-dir에 있으면)
sudo systemctl restart consul

2. HTTP API

curl --request PUT \
  --data @web.json \
  http://localhost:8500/v1/agent/service/register
{
  "Name": "web",
  "Port": 8080,
  "Tags": ["v1", "primary"],
  "Check": {
    "HTTP": "http://localhost:8080/health",
    "Interval": "10s"
  }
}

여기서 시험 함정이 하나 있어요. 에이전트가 등록된 서비스의 책임을 가짐. 노드 다운 시 그 노드의 서비스도 자동 비활성. 다른 노드에서 같은 서비스 = 다른 인스턴스로 인식.

서비스 조회 — 두 가지 방법

1. DNS (포트 8600)

dig @127.0.0.1 -p 8600 web.service.consul

# 출력:
# web.service.consul.    0  IN  A  10.0.1.20
# web.service.consul.    0  IN  A  10.0.1.21

기본 형식 — <service>.service.consul.

# 데이터센터 명시
dig @127.0.0.1 -p 8600 web.service.dc2.consul

# 태그 필터
dig @127.0.0.1 -p 8600 v1.web.service.consul

# SRV 레코드 (포트 포함)
dig @127.0.0.1 -p 8600 -t SRV web.service.consul

2. HTTP API

# 카탈로그 조회 (모든 인스턴스, 헬스 무관)
curl http://localhost:8500/v1/catalog/service/web

# 헬스 체크 통과한 인스턴스만
curl http://localhost:8500/v1/health/service/web?passing

여기서 정말 중요한 시험 함정 — /catalog/service는 모든 인스턴스, /health/service?passing은 통과한 것만. 운영 트래픽 라우팅엔 항상 passing 필터.

DNS 통합

호스트 OS DNS 위임

*.consul 쿼리만 Consul로.

# /etc/resolv.conf 위에 추가
nameserver 127.0.0.1
options ndots:5

또는 systemd-resolved/dnsmasq로 위임. web.service.consul 같은 이름을 직접 사용 가능 — 코드 수정 X.

짧은 이름 (alt_domain)

# /etc/consul.d/consul.hcl
domain = "internal"   # 기본 .consul 대신 .internal
alt_domain = "example.com"   # 추가 도메인

이러면 web.service.example.com 으로도 조회 가능.

헬스 체크 7종 — 시험 단골

1. HTTP

check {
  http     = "http://localhost:8080/health"
  method   = "GET"          # 기본 GET
  interval = "10s"
  timeout  = "1s"
  
  # 상태 코드: 200~299 = passing, 429 = warning, 그 외 = critical
}

2. TCP

check {
  tcp      = "localhost:5432"
  interval = "10s"
  timeout  = "1s"
}

연결 성공 = passing.

3. gRPC

check {
  grpc     = "localhost:9000"
  grpc_use_tls = true
  interval = "10s"
}

gRPC Health Checking 프로토콜.

4. Script

check {
  args     = ["/usr/local/bin/check_service.sh"]
  interval = "30s"
  timeout  = "5s"
}

스크립트 종료 코드 — 0=passing, 1=warning, 2=critical.

여기서 시험 함정이 하나 있어요. Script 체크는 보안 위험입니다. 임의 명령 실행 가능. enable_script_checks = false가 기본 — 의식적으로 활성 필요.

# 보안 강화
enable_local_script_checks = true   # 로컬 정의만
# enable_script_checks = true       # API로도 등록 가능 (위험)

5. Docker

check {
  docker_container_id = "abc123..."
  shell    = "/bin/bash"
  args     = ["health_check.sh"]
  interval = "10s"
}

컨테이너 안에서 명령 실행.

6. TTL

check {
  ttl    = "30s"
  notes  = "App pings periodically"
}

애플리케이션이 직접 PASS/FAIL을 푸시. TTL 안 갱신되면 자동 critical.

# 애플리케이션이 주기적으로 호출
curl http://localhost:8500/v1/agent/check/pass/<check-id>
curl http://localhost:8500/v1/agent/check/warn/<check-id>
curl http://localhost:8500/v1/agent/check/fail/<check-id>

7. Alias

check {
  alias_service = "redis"   # 다른 서비스 헬스 따라감
}

다른 서비스 상태를 그대로 따라감. 의존 서비스 함께 체크할 때.

7종 비교

종류 동작 적합
HTTP 엔드포인트 GET/POST 웹 앱·API
TCP 포트 연결 DB·미들웨어
gRPC gRPC Health 프로토콜 gRPC 서비스
Script 스크립트 실행 복잡 로직 (보안 주의)
Docker 컨테이너 안 명령 Docker 환경
TTL 앱이 푸시 외부 체크 어려운 자리
Alias 다른 서비스 따라감 의존 서비스

여기서 정말 중요한 시험 함정 — TTL 체크는 앱이 능동 푸시. 푸시 멈추면 자동 critical. 다른 모든 체크는 Consul이 능동 호출.

헬스 체크 상태 3종

상태 의미 트래픽
passing 정상 받음
warning 경고 받음 (기본)
critical 비정상 받지 않음
curl http://localhost:8500/v1/health/service/web?passing
# passing만 (warning·critical 제외)

curl http://localhost:8500/v1/health/service/web
# 모두

태그 (Tags)

서비스 분류·필터링.

service {
  name = "web"
  tags = ["v1", "primary", "production"]
}

태그로 DNS 조회

# v1 태그 가진 web 인스턴스만
dig @127.0.0.1 -p 8600 v1.web.service.consul

태그 활용

  • 버전 분리 — v1, v2
  • 환경 — production, staging
  • 역할 — primary, replica

메타데이터 (Meta)

태그보다 풍부한 키-값 정보.

service {
  name = "web"
  meta {
    version    = "1.2.3"
    team       = "frontend"
    deploy_at  = "2026-05-03"
  }
}

DNS 조회는 X (HTTP API로만).

Prepared Query — 고급 라우팅

복잡한 조회 룰을 미리 정의.

curl --request POST \
  --data @prepared-query.json \
  http://localhost:8500/v1/query
{
  "Name": "web-failover",
  "Service": {
    "Service": "web",
    "Failover": {
      "NearestN": 3,
      "Datacenters": ["dc2", "dc3"]
    },
    "OnlyPassing": true
  }
}

특징:

  • 자동 페일오버 (다른 DC로)
  • 가까운 DC 우선
  • 태그 필터링·메타 매칭

CLI vs DNS vs API

# CLI
consul catalog services
consul catalog nodes -service=web

# DNS
dig @127.0.0.1 -p 8600 web.service.consul

# HTTP API
curl http://localhost:8500/v1/catalog/services
curl http://localhost:8500/v1/health/service/web?passing

일반적 패턴

클라이언트 코드에서 사용

# Python — DNS 사용 (가장 단순)
import socket
ip = socket.gethostbyname('redis.service.consul')
# 자동으로 헬스 통과한 인스턴스 중 하나

# 또는 HTTP API
import requests
response = requests.get('http://localhost:8500/v1/health/service/redis?passing')
instances = response.json()
chosen = instances[0]
host = chosen['Service']['Address']
port = chosen['Service']['Port']

Consul Template

설정 파일 자동 갱신.

# nginx.conf.tpl
upstream backend {
  {{ range service "backend|passing" }}
  server {{ .Address }}:{{ .Port }};
  {{ end }}
}

서비스 변경 시 nginx config 자동 갱신·reload.

시험 직전 한 번 더 — 자주 헷갈리는 함정 모음

여기까지가 3편의 핵심입니다. 시험 직전 또는 실무에서 헷갈릴 때 다시 펼쳐 볼 수 있게 압축 노트로 마무리할게요.

  • 서비스 등록 2가지 — HCL 파일 / HTTP API PUT
  • 등록은 에이전트 책임 — 노드 다운 시 자동 비활성
  • 조회 2가지 — DNS (8600) / HTTP API
  • DNS 형식 — <service>.service.consul / <tag>.<service>.service.consul
  • /catalog/service = 모든 인스턴스
  • /health/service?passing = 통과만 (운영 트래픽 표준)
  • 헬스 체크 7종 — HTTP / TCP / gRPC / Script / Docker / TTL / Alias
  • HTTP — 200~299 passing / 429 warning / 그 외 critical
  • TCP — 연결 성공 = passing
  • Script 보안 주의enable_local_script_checks 권장 (enable_script_checks 위험)
  • TTL 체크 = 앱이 능동 푸시 (다른 체크는 Consul이 호출)
  • TTL 푸시 멈추면 자동 critical
  • Alias = 다른 서비스 헬스 따라감
  • 헬스 상태 — passing / warning / critical
  • warning은 기본 트래픽 받음
  • 태그 = tags = ["v1", "primary"] / DNS 필터 가능
  • 메타 = 풍부한 KV / DNS X (API만)
  • Prepared Query = 페일오버·가까운 DC·태그 매칭
  • DNS 위임 — *.consul 만 Consul로
  • domain / alt_domain 으로 짧은 이름
  • Consul Template = 설정 파일 자동 갱신

시리즈 다른 편

공식 문서: Consul Service Discovery에서 더 깊이.

다음 글(4편)에서는 KV 저장소 — CLI/HTTP API/UI 3가지 접근, prefix 기반 권한, watch·envconsul·consul-template 통합까지 풀어 갑니다.

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

답글 남기기

error: Content is protected !!