Consul Service Mesh — Connect·Envoy·Intentions

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

HashiCorp Consul 마스터 노트 시리즈 6편. Service Mesh의 본질 — 사이드카 프록시 패턴, mTLS 자동 암호화·상호 인증, 업스트림 vs 다운스트림, Intentions로 서비스 간 접근 제어, Envoy 프록시 통합과 등록 vs 시작의 차이까지 — Objective 6 완전 정리.

이 글은 HashiCorp Consul 마스터 노트 시리즈의 여섯 번째 편입니다. 3편(Service Discovery)이 "어떤 서비스가 어디에 있는가"였다면, 6편은 그 서비스들이 어떻게 안전하게 통신하는가 — Service Mesh, Consul에서는 Connect.

마이크로서비스가 늘어날수록 IP 기반 방화벽으로는 통제 불가능해져요. 서비스 메시는 이 문제의 표준 해법.

Service Mesh의 본질

해결하는 5가지 문제:

  • 서비스 간 통신 암호화 (기본 평문)
  • 동적 환경의 IP 기반 방화벽 한계
  • 서비스 신원 확인 (인증)
  • 세밀한 접근 제어 (인가)
  • 트래픽 가시성 (Observability)

핵심 특징

  • 제로 트러스트 — 내부 네트워크도 신뢰 X
  • mTLS — 모든 서비스 간 암호화 + 상호 인증
  • 사이드카 프록시 — 애플리케이션 코드 수정 X
  • 플랫폼 무관 — 물리·클라우드·Kubernetes 모두
  • Intentions — 서비스 간 통신 허용/거부 정책

Connect 활성화

# /etc/consul.d/consul.hcl
connect {
  enabled = true
}
sudo systemctl restart consul

여기서 시험 함정이 하나 있어요. Connect는 기본 비활성. 명시 활성 + 재시작 필요. Dev 모드만 자동 활성.

consul agent -dev   # Connect 자동 활성

사이드카 프록시 패턴

┌─────────────────────────────────────────────────────────┐
│ 노드 A                                                   │
│  ┌──────────────┐     ┌─────────────────────────┐      │
│  │  Application │────▶│  Sidecar Proxy (Envoy)  │      │
│  │  (localhost) │◀────│  (mTLS, 정책 강제)      │      │
│  └──────────────┘     └────────────┬────────────┘      │
└──────────────────────────────────────│──────────────────┘
                                       │ mTLS 암호화
                                       ▼
┌─────────────────────────────────────────────────────────┐
│ 노드 B                                                   │
│  ┌─────────────────────────┐     ┌──────────────┐      │
│  │  Sidecar Proxy (Envoy)  │────▶│  Application │      │
│  │  (mTLS, 정책 강제)      │◀────│  (localhost) │      │
│  └─────────────────────────┘     └──────────────┘      │
└─────────────────────────────────────────────────────────┘

핵심 — 앱은 localhost로 프록시와 통신, 프록시가 mTLS 암호/복호화 + 정책 강제. 앱은 Consul 존재 모름.

Upstream vs Downstream

용어 역할 예시
Upstream 의존하는 대상 DB, API 서버
Downstream 대상에 의존 프론트엔드, 웹

"프론트엔드(downstream)가 DB(upstream)에 의존".

서비스 + 프록시 등록

기본 사이드카

service {
  name = "counting"
  port = 9003
  connect {
    sidecar_service {}   # 빈 블록 = 내장 프록시
  }
}

Upstream 포함

service {
  name = "dashboard"
  port = 9002

  connect {
    sidecar_service {
      proxy {
        upstreams = [
          {
            destination_name = "counting"
            local_bind_port  = 5000   # localhost:5000으로 접근
          }
        ]
      }
    }
  }
}

의미 — dashboard는 localhost:5000으로 counting에 접근. 프록시가 mTLS 터널로 전달.

여러 Upstream

service {
  name = "frontend"
  port = 8080
  connect {
    sidecar_service {
      proxy {
        upstreams = [
          { destination_name = "backend-api", local_bind_port = 5001 },
          { destination_name = "database",    local_bind_port = 5002 }
        ]
      }
    }
  }
}

등록 vs 시작은 별개

여기서 정말 중요한 시험 함정 — 등록만으로 프록시 시작 X.

# 1. 서비스 등록 (Consul에 알림)
consul services register /etc/consul.d/counting.hcl
consul services register /etc/consul.d/dashboard.hcl

# 2. 실제 앱 시작
./counting-service &
./dashboard-service &

# 3. 사이드카 프록시 시작 (별도)
consul connect proxy -sidecar-for counting &
consul connect proxy -sidecar-for dashboard &

운영에서는 systemd로 프록시도 관리.

mTLS와 인증서

동작 흐름

1. 서비스 A 프록시 → 서비스 B 프록시 연결 시도
2. 두 프록시가 CA 발급 mTLS 인증서 교환
3. 상호 인증 완료 → 암호화 채널
4. 서비스 B 프록시 → Consul API 인텐션 검사
5. 허용이면 연결 / 거부면 차단

CA 옵션

# 기본: Connect 내장 CA
connect {
  enabled = true
  # ca_provider = "consul"   # 기본
}

# Vault CA 사용
connect {
  enabled = true
  ca_provider = "vault"
  ca_config {
    address       = "https://vault.example.com:8200"
    token         = "<VAULT_TOKEN>"
    root_pki_path = "connect-root"
    intermediate_pki_path = "connect-intermediate"
  }
}

Intentions — 서비스 간 접근 제어

서비스 간 누가 누구에게 통신 가능한지 정의.

CLI 관리

# 허용
consul intention create web db
consul intention create dashboard counting

# 거부
consul intention create -deny web payment

# 모든 서비스 리스트 반환
consul intention list

# 매치 확인
consul intention check web db
# Allowed

와일드카드

# 모든 서비스가 web에 접근 허용
consul intention create '*' web

# 모든 web → 모든 다른 서비스 거부 (안전한 기본값)
consul intention create -deny web '*'

우선순위

1. 명시적 source/destination 매치
2. * 와일드카드보다 정확한 룰 우선
3. 충돌 시 deny 우선

여기서 정말 중요한 시험 함정 — Intentions 기본 정책:

  • default_policy = "deny" (ACL 활성·default deny일 때) — 명시 허용만 통신
  • default_policy = "allow" (또는 ACL 비활성) — 명시 거부만 차단

운영 = deny가 기본 (제로 트러스트).

L4 vs L7 Intentions

종류 적용
L4 (기본) 서비스 단위 허용/거부
L7 (Enterprise) HTTP path·method·header 단위

Associate 시험은 주로 L4.

DNS로 Connect 서비스 조회

# Connect 서비스 IP·포트
dig @127.0.0.1 -p 8600 counting.connect.consul

기본 service.consul이 아니라 connect.consul 도메인 — Connect 활성 서비스만.

Envoy 통합

Envoy를 사이드카로

# Consul 내장 프록시 대신 Envoy
consul connect envoy -sidecar-for counting

Envoy = 프로덕션 표준. 내장 프록시는 단순 사용·테스트.

Envoy 메트릭

# Prometheus 형식 메트릭 노출
curl http://localhost:19000/stats/prometheus

요청 수·지연·에러율·연결 풀 — 모든 트래픽 가시성.

Service Identity

Connect 사용 서비스는 자동 X.509 인증서 부여.

spiffe://<trust-domain>/ns/<namespace>/dc/<datacenter>/svc/<service>

예: spiffe://example.consul/ns/default/dc/dc1/svc/web.

이 신원으로 Intentions 정책 적용.

Ingress / Terminating Gateway (간단)

Gateway 역할
Ingress 외부 → Mesh 안 (인입 게이트웨이)
Terminating Mesh 안 → 외부 서비스 (메시 외 시스템)
Mesh Gateway 다른 DC와 통신

복잡한 토폴로지에서 사용. Associate는 개념 정도.

실습 — 단순 데모

# 1. counting 서비스 (포트 9003)
cat > /etc/consul.d/counting.hcl <<EOF
service {
  name = "counting"
  port = 9003
  connect { sidecar_service {} }
}
EOF

# 2. dashboard 서비스 (counting upstream)
cat > /etc/consul.d/dashboard.hcl <<EOF
service {
  name = "dashboard"
  port = 9002
  connect {
    sidecar_service {
      proxy {
        upstreams = [{ destination_name = "counting", local_bind_port = 5000 }]
      }
    }
  }
}
EOF

# 3. 등록
consul services register /etc/consul.d/counting.hcl
consul services register /etc/consul.d/dashboard.hcl

# 4. 앱 시작
./counting-service &
./dashboard-service &

# 5. 프록시 시작
consul connect proxy -sidecar-for counting &
consul connect proxy -sidecar-for dashboard &

# 6. Intention 허용
consul intention create dashboard counting

# 7. 테스트
curl http://localhost:9002   # dashboard UI에서 counting 표시

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

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

  • Service Mesh = 사이드카 프록시 + mTLS + Intentions
  • Consul Connect = HashiCorp의 Service Mesh 구현
  • 5가지 문제 — 암호화·IP 한계·인증·인가·가시성
  • 제로 트러스트 = 내부도 신뢰 X
  • Connect 기본 비활성connect { enabled = true } 명시
  • Dev 모드만 자동 활성
  • 사이드카 패턴 — 앱 ↔ 프록시 (localhost) ↔ mTLS ↔ 다른 프록시 ↔ 앱
  • 앱은 Consul 존재 모름 — 코드 수정 X
  • Upstream (의존 대상) / Downstream (의존하는 측)
  • 서비스 등록 = sidecar_service {} 빈 블록
  • Upstream 정의 = local_bind_port로 localhost 접근
  • 등록과 프록시 시작은 별개 — 시험 단골
  • consul connect proxy -sidecar-for <service> 별도 실행
  • mTLS = 인증서 교환 + 상호 인증 + 암호화
  • CA — 내장 / Vault / 외부
  • Intentions = 서비스 간 접근 제어
  • 와일드카드 * — 모든 서비스
  • 충돌 시 deny 우선
  • ACL deny 정책 = 명시 허용만 통신 (제로 트러스트)
  • L4 (서비스 단위) / L7 (Enterprise)
  • DNS = <service>.connect.consul
  • Envoy = 프로덕션 표준 프록시
  • 내장 프록시는 단순용
  • Service Identity = SPIFFE URI 기반 X.509
  • Gateway 3종 — Ingress / Terminating / Mesh

시리즈 다른 편

공식 문서: Consul Connect에서 더 깊이.

다음 글(7편 완결)에서는 보안 운영 — TLS 인증서 (verify_incoming/outgoing/server_hostname), ACL 시스템, Gossip 암호화·키 로테이션까지 — Objective 7·8·9 정리.

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

답글 남기기

error: Content is protected !!