잡 스펙의 `gateway` 블록
잡 스펙의 gateway 블록
gateway 블록은 Consul 서비스 메시 게이트웨이를 설정하게 해 주는 블록이에요. Nomad가 필요한 Gateway Configuration Entry를 자동으로 만들고, 게이트웨이 역할을 하는 Envoy 프록시 태스크를 Nomad 잡에 주입해요.
출처: 문서
본문
| 배치 | job -> group -> service -> connect -> **gateway** |
|---|
gateway 설정은 connect 블록 안에서만 유효해요. 게이트웨이 설정에 대한 더 자세한 내용은 Consul의 Connect Gateways 문서에서 확인할 수 있어요.
참고: Ingress 게이트웨이는 주로 같은 네트워크 안에서 Consul 서비스 메시로 접근을 허용하는 용도로 쓰여요. NGINX 같은 공개 인그레스 제품은 더 적합한 기능을 제공하므로, 퍼블릭 인그레스에는 그쪽을 쓰는 게 좋아요.
service {
connect {
gateway {
# ...
}
}
}
매개변수 (Parameters)
ingress, terminating, mesh 중 정확히 하나를 반드시 설정해야 해요.
proxy([proxy]: nil)- 태스크 그룹에 주입될 Envoy 프록시 설정.ingress([ingress]: nil)- 서비스에 연결될ingress-gateway타입의 Configuration Entry.terminating([terminating]: nil)- 서비스에 연결될terminating-gateway타입의 Configuration Entry.mesh([mesh]: nil)- 메시 게이트웨이가 서비스에 연결됨을 나타냄.
proxy 매개변수
-
connect_timeout(string: "5s")- 업스트림 연결을 만들 때 타임아웃될 때까지 허용하는 시간. 기본값은 5초. 업스트림 서비스가service-resolver에connect_timeout_ms설정을 갖고 있다면 그 타임아웃 값이 이 게이트웨이 프록시 옵션보다 우선해요. -
envoy_gateway_bind_tagged_addresses(bool: false)- 게이트웨이 서비스의 태그된 주소가 기본 리스너 주소에 추가로 리스너에 바인딩되어야 함을 나타냄. -
envoy_gateway_bind_addresses(map<string|[address]>: nil)- 추가로 바인딩할 주소의 맵. 이 맵의 키는 생성할 리스너의 이름과 같고, 값은 address와 port 두 키를 가진 맵이라 이 둘이 합쳐져 리스너를 바인딩할 주소가 돼요. 기본 주소에 추가로 바인딩돼요.bridge네트워킹을 쓰고 있다면 이 맵에 Envoy 프록시가 네트워크 네임스페이스 안에서 동작하도록 하는 추가 리스너가 자동으로 채워져요.
envoy_gateway_bind_addresses "<service>" {
address = "0.0.0.0"
port = <port>
}
-
envoy_gateway_no_default_bind(bool: false)- 게이트웨이 서비스의 기본 주소에 바인딩하지 않도록 막아요. 게이트웨이 바인딩 주소를 설정하는 다른 옵션 중 하나와 함께 써야 해요.bridge네트워킹을 쓰고 있다면 Envoy 프록시가 네트워크 네임스페이스 안에서 서비스 주소에 바인딩할 필요가 없으므로 이 값은 기본적으로true가 돼요. -
envoy_dns_discovery_type(string: optional)- Envoy가 호스트네임을 어떻게 해석할지 결정. 기본값은LOGICAL_DNS.STRICT_DNS또는LOGICAL_DNS중 하나여야 해요. 각 타입에 대한 자세한 내용은 Envoy 문서에서 확인할 수 있어요. 이 옵션은 호스트네임으로 주소가 지정된 서비스로 라우팅하는 terminating 게이트웨이에 적용돼요. -
config(map: nil)- Envoy의 고급 설정을 위한 탈출구(escape hatch). 키와 값은 런타임 변수 보간을 지원해요.
address 매개변수
ingress 매개변수
-
listener(array<[listener]> : required)- 인그레스 게이트웨이가 설정해야 하는 리스너 하나 이상. 포트 번호로 고유하게 식별돼요. -
tls([tls]: nil)- 이 게이트웨이의 TLS 설정.
listener 매개변수
-
port(int: required)- 리스너가 트래픽을 받을 포트. -
protocol(string: "tcp")- 리스너와 연결된 프로토콜.tcp,http,http2,grpc중 하나.
참고: tcp가 아닌 프로토콜(예: http나 grpc)을 쓰는 경우, 오픈 이슈 때문에 Consul에서 service-default를 미리 설정해 서비스의 Protocol을 원하는 프로토콜로 맞춰 두는 게 필수예요.
service(array<[listener-service]>: required)- 이 리스너를 통해 노출할 서비스 하나 이상.tcp리스너에는 서비스 하나만 허용돼요.
Listener service 매개변수
ingress 게이트웨이 아래 listener의 service 블록은 다음 매개변수를 받아요. 이건 terminating 게이트웨이 아래의 service 블록과 다르다는 점 주의하세요.
-
name(string: required)- 이 리스너를 통해 노출할 서비스 이름. 카탈로그에 등록된 서비스, 다른 config entry가 정의한 서비스, 또는 Nomad가 설정할 서비스일 수 있어요. 와일드카드*를 제공하면 모든 서비스가 이 리스너를 통해 노출돼요. 프로토콜이tcp인 리스너에서는 지원되지 않아요. -
hosts(array<string>: nil)- 이 서비스와 매칭할 요청을 지정하는 호스트 목록.tcp리스너와는 함께 쓸 수 없고, 와일드카드(*) 서비스 이름과도 함께 지정할 수 없어요. 지정하지 않으면 기본 도메인<service-name>.ingress.*로 서비스를 매칭해요. 요청은 정의된 서비스로 라우팅되려면 올바른 호스트를 반드시 보내야 해요.
와일드카드 *는 TLS가 활성화되어 있지 않다면 인그레스 게이트웨이로 들어오는 모든 트래픽을 매칭하기 위해 단독으로도 쓸 수 있어요. 이렇게 하면 호스트를 지정하지 않고도 모든 트래픽을 하나의 서비스로 라우팅할 수 있어서 테스트와 데모가 간단해져요. 그 외에는 와일드카드를 호스트의 일부로 써서 여러 호스트를 매칭할 수 있는데, 가장 왼쪽 DNS 레이블에서만 가능해요. 이렇게 해야 정의된 모든 호스트가 유효한 DNS 레코드가 돼요. 예를 들어 *.example.com은 유효하지만 example.*나 *-suffix.example.com은 유효하지 않아요.
-
request_headers([header modifiers]: <optional>)- 이 서비스로 라우팅되는 요청에 적용할 HTTP 전용 헤더 수정 규칙 묶음. tcp 리스너와는 쓸 수 없어요. -
response_headers([header modifiers]: <optional>)- 이 서비스에서 오는 응답에 적용할 HTTP 전용 헤더 수정 규칙 묶음. tcp 리스너와는 쓸 수 없어요. -
max_concurrent_requests(int: <optional>)- 한 시점에 허용되는 동시 HTTP/2 트래픽 요청 최대 수. 설정하지 않으면 Envoy 프록시 기본값을 사용해요. -
max_connections(int: <optional>)- 서비스 인스턴스 하나가 업스트림에 대해 맺을 수 있는 HTTP/1.1 연결 최대 수. 설정하지 않으면 Envoy 프록시 기본값을 사용해요. -
max_pending_requests(int: <optional>)- 연결을 맺기 위해 대기하는 동안 큐에 머무를 수 있는 요청 최대 수. 설정하지 않으면 Envoy 프록시 기본값을 사용해요. -
tls([tls]: nil)- 이 서비스의 TLS 설정.
Header modifier 매개변수
ingress.service 블록의 request_headers와 response_headers 블록은 다음 매개변수를 받아요. 더 자세한 내용은 Consul 문서를 참고하세요.
-
add(map<string|string>: optional)- 헤더에 추가할 키-값 쌍 묶음. 헤더 이름이 키, 헤더 값이 값이에요. 헤더 이름은 대소문자를 구분하지 않아요. 같은 이름의 헤더 값이 이미 있으면 값을 추가하고 Consul이 두 헤더를 모두 적용해요. -
set(map<string|string>: optional)- 응답 헤더에 추가하거나 기존 헤더 값을 대체할 키-값 쌍 묶음. 키로 헤더 이름을 사용해요. 헤더 이름은 대소문자를 구분하지 않아요. 같은 이름의 헤더 값이 이미 있으면 Consul이 헤더 값을 대체해요. -
removearray(string): optional- 제거할 헤더 목록. Consul은 정확히 일치하는 헤더만 제거해요. 헤더 이름은 대소문자를 구분하지 않아요.
tls 매개변수
-
enabled(bool: false)- 게이트웨이의 모든 리스너에 TLS를 활성화하려면 이 설정을 켜요. TLS가 활성화되면host필드에 정의된 각 호스트가 게이트웨이의 x509 인증서에 DNS SAN으로 추가돼요. -
cipher_suites(array<string>: optional)- 게이트웨이 리스너의 기본 TLS cipher suite 목록. 지원되는 cipher suite는 Consul 문서의CipherSuites를 참고하세요. -
sds(block: optional)- 외부 Secret Discovery Service(SDS)에서 TLS 인증서를 로드하도록 리스너를 설정하는 매개변수 묶음.cluster_name(string)- 인증서를 가져오기 위해 연결할 SDS 클러스터 이름.cert_resource(string)- SDS 서비스에서 인증서를 가져올 때 요청할 SDS 리소스 이름.
-
tls_max_version(string: optional)- 게이트웨이가 지원하는 기본 최대 TLS 버전. 지원 버전은 Consul 문서의TLSMaxVersion을 참고하세요. -
tls_min_version(string: optional)- 게이트웨이가 지원하는 기본 최소 TLS 버전. 지원 버전은 Consul 문서의TLSMinVersion을 참고하세요.
terminating 매개변수
service(array<[linked-service]>: required)- 게이트웨이와 연결할 서비스 하나 이상. 게이트웨이는 이 서비스들로 트래픽을 프록시해요. 이 연결된 서비스들은 게이트웨이가 주소를 찾을 수 있도록 Consul에 등록되어 있어야 해요. 또한 terminating 게이트웨이와 같은 Consul 데이터센터에 등록되어 있어야 해요.
linked service 매개변수
terminating 게이트웨이의 service 블록은 다음 매개변수를 받아요. 이건 ingress 게이트웨이 아래 리스너의 service 블록과 다르다는 점 주의하세요.
-
name(string: required)- 게이트웨이와 연결할 서비스 이름. 와일드카드*를 제공하면 Consul 네임스페이스 안의 모든 서비스가 게이트웨이와 연결돼요. -
ca_file(string: <optional>)- PEM 인코딩 인증 기관(certificate authority)의 파일 경로. 게이트웨이 태스크가 접근할 수 있어야 해요. 인증 기관은 게이트웨이와 연결된 서비스의 진위를 검증하는 데 사용돼요. 상호 TLS 인증을 위해cert_file과key_file과 함께 제공하거나, 단방향 TLS 인증을 위해 단독으로 제공할 수 있어요. 아무것도 제공하지 않으면 게이트웨이는 대상으로의 트래픽을 암호화하지 않아요. -
cert_file(string: <optional>)- PEM 인코딩 인증서의 파일 경로. 게이트웨이 태스크가 접근할 수 있어야 해요. 인증서는 게이트웨이의 진위를 검증하기 위해 서버에 제공돼요.key_file이 제공되면 반드시 제공해야 해요. -
key_file(string: <optional>)- PEM 인코딩 개인 키의 파일 경로. 게이트웨이 태스크가 접근할 수 있어야 해요. 키는 인증서와 함께 게이트웨이의 진위를 검증하는 데 사용돼요.cert_file이 제공되면 반드시 제공해야 해요. -
sni(string: <optional>)- TLS 핸드셰이크 중 지정할 선택적 호스트네임 또는 도메인 이름.
mesh 매개변수
mesh 블록은 현재 설정 가능한 매개변수가 없어요.
참고: 메시 게이트웨이를 WAN Federation에 쓰는 경우, 추가 서비스 메타데이터 {"consul-wan-federation":"1"}를 적용해야 해요. 이건 서비스 meta 매개변수로 할 수 있어요.
호스트 네트워킹을 사용하는 게이트웨이 (Gateway with host networking)
Nomad는 호스트 네트워킹을 사용하는 게이트웨이 실행을 지원해요. Envoy 관리 인터페이스가 사용할 정적 포트를 할당하고 프록시 서비스 정의에 지정해야 해요.
경고: Envoy 관리 인터페이스를 비활성화할 방법은 없으며, 같은 Nomad 클라이언트에서 실행 중인 모든 워크로드가 접근할 수 있어요. 관리 인터페이스는 프록시에 대한 정보를 노출하는데, Consul ACL이 활성화되어 있으면 Consul Service Identity 토큰도 포함돼요.
Envoy 이미지 지정 (Specify Envoy image)
Connect 게이트웨이 태스크에 사용되는 Docker 이미지는 기본적으로 공식 Envoy Docker 이미지 docker.io/envoyproxy/envoy:v${NOMAD_envoy_version}이고, 여기서 ${NOMAD_envoy_version}은 Consul에 대한 쿼리로 자동 해석돼요. 사용할 이미지는 Nomad 잡에서 meta.connect.gateway_image를 설정해 지정할 수 있어요. 커스텀 이미지에서도 envoy 버전 보간을 사용할 수 있어요. 예:
meta.connect.gateway_image = custom/envoy-${NOMAD_envoy_version}:latest
커스텀 게이트웨이 태스크 (Custom gateway task)
게이트웨이를 위해 생성되는 태스크는 sidecar_task 블록으로 수동 구성할 수 있어요.
connect {
gateway {
# ...
}
sidecar_task {
# see /docs/job-specification/sidecar_task for more details
}
}
예시 (Examples)
ingress 게이트웨이
job "ingress-demo" {
datacenters = ["dc1"]
# 이 그룹에는 Nomad가 자동으로 만든 태스크가 있어 인그레스 게이트웨이를 제공해요.
# 인그레스 게이트웨이는 docker 드라이버가 관리하는 Envoy 프록시를 기반으로 해요.
group "ingress-group" {
network {
mode = "bridge"
# 이 예시는 일반 HTTP 트래픽이 8080 포트에서 uuid-api connect 네이티브
# 예시 서비스에 접근할 수 있게 해요.
port "inbound" {
static = 8080
to = 8080
}
}
service {
name = "my-ingress-service"
port = "8080"
connect {
gateway {
# Consul gateway [envoy] proxy options.
proxy {
# 다음 옵션은 bridge 네트워킹을 쓸 때 명시적으로 구성하지 않으면
# Nomad가 자동으로 설정해요.
#
# envoy_gateway_no_default_bind = true
# envoy_gateway_bind_addresses "uuid-api" {
# address = "0.0.0.0"
# port = <associated listener.port>
# }
#
# 추가 옵션은 다음에서 문서화되어 있어요.
# https://developer.hashicorp.com/nomad/docs/job-specification/gateway#proxy-parameters
}
# Consul Ingress Gateway Configuration Entry.
ingress {
# Nomad는 ingress 블록의 매개변수에 따라 Consul의 Configuration Entry를
# 자동으로 관리해요.
#
# 추가 옵션은 다음에서 문서화되어 있어요.
# https://developer.hashicorp.com/nomad/docs/job-specification/gateway#ingress-parameters
listener {
port = 8080
protocol = "tcp"
service {
name = "uuid-api"
}
}
}
}
}
}
}
# connect-native 데모의 UUID 생성기가 예시 서비스로 사용돼요.
# 위의 인그레스 게이트웨이는 일반 HTTP로 서비스에 접근할 수 있게 해요.
# 예를 들어,
#
# $ curl $(dig +short @127.0.0.1 -p 8600 uuid-api.ingress.dc1.consul. ANY):8080
group "generator" {
network {
mode = "host"
port "api" {}
}
service {
name = "uuid-api"
port = "api"
connect {
native = true
}
}
task "generate" {
driver = "docker"
config {
image = "hashicorpdev/uuid-api:v5"
network_mode = "host"
}
env {
BIND = "0.0.0.0"
PORT = "${NOMAD_PORT_api}"
}
}
}
}
terminating 게이트웨이
job "countdash-terminating" {
datacenters = ["dc1"]
# 이 그룹은 Consul 서비스 메시 밖에 존재하는 서비스를 제공해요.
# 호스트 네트워킹을 쓰고 정적으로 할당된 포트에서 리슨해요.
group "api" {
network {
mode = "host"
port "port" {
static = "9001"
}
}
# 이 예시는 서비스 메시 안의 서비스가 terminating 게이트웨이를 통해
# 요청을 보내어 메시에 없는 이 서비스에 접근할 수 있게 해요.
service {
name = "count-api"
port = "port"
}
task "api" {
driver = "docker"
config {
image = "hashicorpdev/counter-api:v3"
network_mode = "host"
}
}
}
group "gateway" {
network {
mode = "bridge"
}
service {
name = "api-gateway"
connect {
gateway {
# Consul gateway [envoy] proxy options.
proxy {
# 다음 옵션은 bridge 네트워킹을 쓸 때 명시적으로 구성하지 않으면
# Nomad가 자동으로 설정해요.
#
# envoy_gateway_no_default_bind = true
# envoy_gateway_bind_addresses "default" {
# address = "0.0.0.0"
# port = <generated listener port>
# }
# 추가 옵션은 다음에서 문서화되어 있어요.
# https://developer.hashicorp.com/nomad/docs/job-specification/gateway#proxy-parameters
}
# Consul Terminating Gateway Configuration Entry.
terminating {
# Nomad는 terminating 블록의 매개변수에 따라 Consul의 Configuration Entry를
# 자동으로 관리해요.
#
# 추가 옵션은 다음에서 문서화되어 있어요.
# https://developer.hashicorp.com/nomad/docs/job-specification/gateway#terminating-parameters
service {
name = "count-api"
}
}
}
}
}
}
# 대시보드 서비스는 서비스 메시 안에 있고, bridge 네트워크 모드와
# connect.sidecar_service를 사용해요. 실행되면 대시보드는 웹 브라우저에서
# localhost:9002로 접근할 수 있어요.
group "dashboard" {
network {
mode = "bridge"
port "http" {
static = 9002
to = 9002
}
}
service {
name = "count-dashboard"
port = "9002"
connect {
sidecar_service {
proxy {
upstreams {
# terminating 게이트웨이의 연결된 서비스로 업스트림 대상(destination)을
# 구성하면 대시보드가 게이트웨이를 통해 count-api 서비스로
# 요청할 수 있어요.
destination_name = "count-api"
local_bind_port = 8080
}
}
}
}
}
task "dashboard" {
driver = "docker"
env {
COUNTING_SERVICE_URL = "http://${NOMAD_UPSTREAM_ADDR_count_api}"
}
config {
image = "hashicorpdev/counter-dashboard:v3"
}
}
}
}
mesh 게이트웨이
Mesh 게이트웨이는 Connect 서비스가 교차 데이터센터 요청을 해야 하는데 각 데이터센터의 모든 노드가 완전한 연결성을 갖지 못할 때 유용해요. 이 예시는 mesh 게이트웨이를 사용해 데이터센터 one과 two 사이에 요청을 주고받도록 하는 방법을 보여줘요. 각 mesh 게이트웨이는 각 데이터센터의 Nomad 클라이언트 하나 이상에 구성된 public 호스트 네트워크에 바인딩돼요.
데이터센터 one에서 Nomad와 Consul이 실행되는 잡:
job "countdash-mesh-one" {
datacenters = ["one"]
group "mesh-gateway-one" {
network {
mode = "bridge"
# mesh 게이트웨이는 교차 데이터센터 연결을 맺을 수 있는 Nomad 클라이언트
# 하나 이상에 host_network가 구성되어 있어야 해요. Nomad는 mesh 게이트웨이
# 태스크를 호환 가능한 Nomad 클라이언트에 자동으로 스케줄링해요.
port "mesh_wan" {
host_network = "public"
}
}
service {
name = "mesh-gateway"
# mesh 게이트웨이 connect 서비스는 교차 데이터센터 연결이 가능한
# host_network의 포트를 사용하도록 구성해야 해요.
port = "mesh_wan"
connect {
gateway {
mesh {
# mesh 블록에는 설정 옵션이 없어요.
}
# Consul gateway [envoy] proxy options.
proxy {
# 다음 옵션은 bridge 네트워킹을 쓸 때 명시적으로 구성하지 않으면
# Nomad가 자동으로 설정해요.
#
# envoy_gateway_no_default_bind = true
# envoy_gateway_bind_addresses "lan" {
# address = "0.0.0.0"
# port = <generated dynamic port>
# }
# envoy_gateway_bind_addresses "wan" {
# address = "0.0.0.0"
# port = <configured service port>
# }
# 추가 옵션은 다음에서 문서화되어 있어요.
# https://developer.hashicorp.com/nomad/docs/job-specification/gateway#proxy-parameters
}
}
}
}
}
group "dashboard" {
network {
mode = "bridge"
port "http" {
static = 9002
to = 9002
}
}
service {
name = "count-dashboard"
port = "9002"
connect {
sidecar_service {
proxy {
upstreams {
destination_name = "count-api"
local_bind_port = 8080
# 이 대시보드 서비스는 데이터센터 "one"에서 실행되고, 각 데이터센터의
# mesh 게이트웨이를 통해 데이터센터 "two"에서 실행되는 "count-api"
# 서비스로 요청을 보내요.
datacenter = "two"
mesh_gateway {
# "local" 모드를 쓰면 요청이 mesh 게이트웨이를 통해 이 데이터센터에서
# 나가고, 대상 데이터센터의 mesh 게이트웨이를 통해 들어와요.
# "remote" 모드를 쓰면 로컬 mesh 게이트웨이를 우회해서 대상
# 데이터센터의 mesh 게이트웨이에 직접 연결해요.
mode = "local"
}
}
}
}
}
}
task "dashboard" {
driver = "docker"
env {
COUNTING_SERVICE_URL = "http://${NOMAD_UPSTREAM_ADDR_count_api}"
}
config {
image = "hashicorpdev/counter-dashboard:v3"
}
}
}
}
데이터센터 two에서 Nomad와 Consul이 실행되는 잡:
job "countdash-mesh-two" {
datacenters = ["two"]
group "mesh-gateway-two" {
network {
mode = "bridge"
# mesh 게이트웨이는 교차 데이터센터 연결을 맺을 수 있는 Nomad 클라이언트
# 하나 이상에 host_network가 구성되어 있어야 해요. Nomad는 mesh 게이트웨이
# 태스크를 호환 가능한 Nomad 클라이언트에 자동으로 스케줄링해요.
port "mesh_wan" {
host_network = "public"
}
}
service {
name = "mesh-gateway"
# mesh 게이트웨이 connect 서비스는 교차 데이터센터 연결이 가능한
# host_network의 포트를 사용하도록 구성해야 해요.
port = "mesh_wan"
connect {
gateway {
mesh {
# mesh 블록에는 설정 옵션이 없어요.
}
# Consul gateway [envoy] proxy options.
proxy {
# 다음 옵션은 bridge 네트워킹을 쓸 때 명시적으로 구성하지 않으면
# Nomad가 자동으로 설정해요.
#
# envoy_gateway_no_default_bind = true
# envoy_gateway_bind_addresses "lan" {
# address = "0.0.0.0"
# port = <generated dynamic port>
# }
# envoy_gateway_bind_addresses "wan" {
# address = "0.0.0.0"
# port = <configured service port>
# }
# 추가 옵션은 다음에서 문서화되어 있어요.
# https://developer.hashicorp.com/nomad/docs/job-specification/gateway#proxy-parameters
}
}
}
}
}
group "api" {
network {
mode = "bridge"
}
service {
name = "count-api"
port = "9001"
connect {
sidecar_service {}
}
}
task "api" {
driver = "docker"
config {
image = "hashicorpdev/counter-api:v3"
}
}
}
}
더 알아보기 (Learn more)
- Consul Connect Gateways - Consul 게이트웨이 개념과 설정
- Envoy Documentation - Envoy DNS 디스커버리 타입