Consul KV Store — CLI·API·Watch·Template

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

HashiCorp Consul 마스터 노트 시리즈 4편. KV Store의 CLI·HTTP API·UI 3가지 접근, prefix 계층 구조와 권한 관리, get/put/delete 기본 + recurse·json 출력, watch로 실시간 변경 감지, envconsul·consul-template으로 설정 자동 주입까지 — Objective 4 완전 정리.

이 글은 HashiCorp Consul 마스터 노트 시리즈의 네 번째 편입니다. 3편(Service Discovery)에서 서비스 등록·조회를 잡았다면, 이번엔 동적 설정·기능 플래그를 저장하는 Key/Value Store — Objective 4.

KV는 단순해 보여도 활용 폭이 매우 넓어요. 서비스 설정·기능 플래그·분산 락·리더 선거까지.

KV Store 기초

Consul KV는 계층적 키-값 저장소. 키는 /로 구분된 경로 형식.

/myapp/database/host
/myapp/database/port
/myapp/feature-flags/new-checkout
/myapp/feature-flags/dark-mode

용도:

  • 동적 애플리케이션 설정
  • 기능 플래그 (Feature Flags)
  • 분산 락·리더 선거
  • 서비스 디스커버리 메타데이터

여기서 시험 함정이 하나 있어요. 값(Value)은 최대 512KB. 큰 데이터(이미지·파일)는 다른 저장소(S3 등)에 두고 KV에는 참조만.

3가지 접근 방법

1. CLI

# 쓰기
consul kv put myapp/db/host "localhost"
consul kv put myapp/db/port "5432"
consul kv put myapp/feature/dark-mode "true"

# 읽기
consul kv get myapp/db/host
# localhost

# 메타데이터 포함
consul kv get -detailed myapp/db/host

# 재귀 조회 (prefix 하위 모두)
consul kv get -recurse myapp/

# JSON 출력
consul kv get -recurse -keys myapp/

# 삭제
consul kv delete myapp/feature/dark-mode

# Prefix 모두 삭제
consul kv delete -recurse myapp/feature/

2. HTTP API

# 쓰기
curl --request PUT --data 'localhost' http://localhost:8500/v1/kv/myapp/db/host

# 읽기 (Base64 인코딩된 응답)
curl http://localhost:8500/v1/kv/myapp/db/host
# [{"LockIndex":0,"Key":"myapp/db/host","Flags":0,"Value":"bG9jYWxob3N0",...}]

# 디코딩 후 보기
curl http://localhost:8500/v1/kv/myapp/db/host?raw
# localhost

# Prefix 재귀
curl http://localhost:8500/v1/kv/myapp/?recurse

# 삭제
curl --request DELETE http://localhost:8500/v1/kv/myapp/db/host

여기서 시험 함정이 하나 있어요. HTTP API 응답의 Value는 Base64 인코딩. 그대로 사용 X — ?raw 옵션이나 디코딩 필요.

3. UI

http://<consul-server>:8500/ui/<dc>/kv — 브라우저에서 트리 뷰.

Prefix 계층 구조 활용

/myapp/
├── /myapp/database/
│   ├── /myapp/database/host
│   └── /myapp/database/port
├── /myapp/feature-flags/
│   ├── /myapp/feature-flags/new-checkout
│   └── /myapp/feature-flags/dark-mode
└── /myapp/secrets/
    └── /myapp/secrets/api-key

/anotherapp/
└── ...

여기서 정말 중요한 시험 함정 — prefix 단위 ACL 권한 부여가 KV의 강점입니다. myapp/secrets/ 하위 prefix만 admin에 권한 줌, 나머지는 모든 팀에 read 허용 같은 패턴. 7편(보안)에서 자세히.

원자적 연산 — CAS

Check-And-Set — 조건부 쓰기. 동시성 문제 해결.

# 1. 현재 ModifyIndex 확인
consul kv get -detailed myapp/counter
# ModifyIndex 142

# 2. ModifyIndex 일치할 때만 쓰기
consul kv put -cas -modify-index=142 myapp/counter "new-value"

# 다른 사람이 그 사이 변경했으면 142가 아닌 다른 값 → 실패

용도:

  • 분산 락
  • 리더 선거
  • 동시 수정 충돌 방지

HTTP API CAS

curl --request PUT \
  --data 'new-value' \
  "http://localhost:8500/v1/kv/myapp/counter?cas=142"

응답 — true (성공) / false (실패).

Session — 분산 락

# 세션 생성 (TTL 30초)
SESSION_ID=$(curl --request PUT \
  --data '{"Name":"my-lock","TTL":"30s"}' \
  http://localhost:8500/v1/session/create | jq -r .ID)

# 세션으로 락 획득
curl --request PUT \
  --data 'locked-by-process-1' \
  "http://localhost:8500/v1/kv/locks/my-resource?acquire=$SESSION_ID"
# true (성공) / false (이미 잠김)

# 해제
curl --request PUT \
  "http://localhost:8500/v1/kv/locks/my-resource?release=$SESSION_ID"

여기서 시험 함정이 하나 있어요. 세션 TTL 만료 = 자동 락 해제. 프로세스 죽어도 락이 영원히 안 잡힘. 분산 시스템의 표준 패턴.

Watch — 실시간 변경 감지

KV·서비스·노드 변경을 감지해 명령 실행.

# Long Polling으로 변경 대기
consul watch -type=key -key=myapp/feature/dark-mode \
  /usr/local/bin/reload_app.sh

# 또는 prefix 단위
consul watch -type=keyprefix -prefix=myapp/feature/ \
  /usr/local/bin/reload_features.sh

Watch 종류

Type 감지 대상
key 단일 키
keyprefix prefix 하위
services 등록된 서비스 목록
service 특정 서비스의 인스턴스
nodes 노드 목록
node 특정 노드
checks 헬스 체크
event 사용자 이벤트

Long Polling

HTTP API에서 직접:

# index 142 이후 변경 대기 (최대 5분)
curl "http://localhost:8500/v1/kv/myapp/feature/dark-mode?index=142&wait=5m"

새 값 도착하면 즉시 응답. 없으면 5분 후 timeout.

envconsul — 환경 변수로 주입

# KV에 저장
consul kv put myapp/db/host "db.internal"
consul kv put myapp/db/password "secret123"

# envconsul로 앱 실행
envconsul -prefix=myapp/db -- /usr/local/bin/myapp

# 앱 안에서 환경 변수로 보임:
# DB_HOST=db.internal
# DB_PASSWORD=secret123

KV 변경 시 앱 자동 재시작 옵션도 있음.

consul-template — 파일 자동 생성

설정 파일·인증서를 KV·서비스 정보 기반으로 자동 생성.

# nginx.conf.tpl
upstream backend {
  {{ range service "backend|passing" }}
  server {{ .Address }}:{{ .Port }} max_fails={{ key "myapp/lb/max_fails" }};
  {{ end }}
}
consul-template \
  -template "nginx.conf.tpl:nginx.conf:nginx -s reload" \
  -consul-addr=localhost:8500

서비스·KV 변경 시 자동으로 nginx.conf 갱신 + nginx -s reload 실행.

트랜잭션 (Transactions)

여러 KV 연산을 원자적으로.

curl --request PUT \
  --data @transaction.json \
  http://localhost:8500/v1/txn
[
  { "KV": { "Verb": "set", "Key": "key1", "Value": "value1-base64" } },
  { "KV": { "Verb": "set", "Key": "key2", "Value": "value2-base64" } },
  { "KV": { "Verb": "delete", "Key": "key3" } }
]

모두 성공 OR 모두 실패. 일부 성공 X.

백업·복원

KV 데이터는 5편(백업·복구)에서 다루는 consul snapshot save에 포함.

consul snapshot save backup.snap
consul snapshot restore backup.snap

KV·서비스·ACL·세션 모두 한 스냅샷.

일반적 활용 패턴

기능 플래그 (Feature Flag)

consul kv put myapp/feature/new-checkout "true"
# 앱 코드
import consul
c = consul.Consul()

def is_feature_enabled(name):
    _, data = c.kv.get(f'myapp/feature/{name}')
    return data and data['Value'] == b'true'

if is_feature_enabled('new-checkout'):
    # 새 체크아웃 사용
    pass

동적 환경 변수

# 운영자가 KV 업데이트
consul kv put myapp/db/max_connections "200"

# 앱이 watch로 자동 적용
consul watch -type=key -key=myapp/db/max_connections \
  /usr/local/bin/apply_db_config.sh

리더 선거

# 모든 후보 노드가 같은 키에 락 시도
SESSION_ID=$(curl ... session/create)

# 한 명만 성공 = 그 노드가 리더
ACQUIRED=$(curl --request PUT \
  --data 'leader' \
  "http://localhost:8500/v1/kv/myapp/leader?acquire=$SESSION_ID")

if [ "$ACQUIRED" = "true" ]; then
    echo "I am the leader"
fi

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

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

  • KV = 계층적 key/value, /로 prefix 구분
  • 값 최대 512KB — 큰 데이터는 외부 + 참조
  • 3가지 접근 — CLI / HTTP API / UI
  • CLI — consul kv put / get / delete
  • -recurse = prefix 하위 모두
  • -detailed = 메타데이터 포함
  • HTTP API 응답 ValueBase64?raw로 평문
  • Prefix 단위 ACL = KV의 강점
  • CAS (Check-And-Set) = 조건부 쓰기, 동시성
  • ?cas=142 또는 -cas -modify-index=142
  • 응답 true (성공) / false (실패)
  • Session = 분산 락 표준
  • TTL 만료 = 자동 락 해제 (프로세스 죽어도)
  • Watch = 실시간 변경 감지 → 명령 실행
  • 종류 — key / keyprefix / services / service / node / checks / event
  • Long Polling = ?index=N&wait=5m
  • envconsul = KV → 환경 변수 주입
  • consul-template = 설정 파일·인증서 자동 생성
  • nginx config + reload 자동
  • Transaction = 여러 KV 연산 원자적
  • 백업 = consul snapshot save (KV·서비스·ACL 모두)
  • 활용 — Feature Flag / 동적 설정 / 분산 락 / 리더 선거

시리즈 다른 편

공식 문서: Consul KV Store에서 더 깊이.

다음 글(5편)에서는 백업·복구 — consul snapshot save/restore, 자동 백업 스케줄, 비활성 ACL 활성화 시 토큰까지 — Objective 5 정리.

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

답글 남기기

error: Content is protected !!