Consule는 서비스 디스커버리(Service discovery)와 설정을 관리하는 툴이다. Consule는 분산&클라우드 환경에 적응하기 위한 고가용성, 유연한 스케일링, 분산시스템의 특징을 가진다.
Consul의 핵심 기능은 아래와 같다.
서비스 디스커버리 : DNS 나 HTTP 인터페이스를 통해서 서비스를 찾을 수 있게 한다. 외부의 SaaS 서비스업체도 등록할 수 있다.
Health Checking : 클러스터의 건강 상태를 모니터링하며 문제가 생길 경우 신속하게 전파한다. 헬스체크는 서비스 디스커버리와 함께 작동하며, 문제가 생긴 호스트로 서비스 요청이 흐르는 걸 막는다. 이를 이용해서 서비스레벨에서의 서킷 브레이커(circuit breaker)를 구현 할 수 있다.
KV(Key/Value) 저장소(Store) : Consul은 계층적으로 구성 할 수 있는 KV 저장소를 제공한다. 애플리케이션은 설정, 플래그, 리더 선출 등 다양한 목적을 위해서 이 저장소를 사용 할 수 있다. 이 저장소는 HTTP API를 이용해서 간단하게 사용 할 수 있다.
멀티 데이터센터 대응 : 데이터센터 규모에서 사용 할 수 있으며, 복잡한 구성없이 여러 리전(region)을 지원 할 수 있다.
Service Segmentation : Consule Connect는 TLS를 이용 서비스와 서비스사이에 안전한 통신이 가능하게 한다.
이 문서는 아래의 순서로 진행한다.
로컬에 설치해서 기본적인 사용방법을 익힌다.
분산 환경(여러 노드에) 설치한다.
분산 환경에서 응용을 고민한다.
Consul 설치
환경
우분투 리눅스 19.04, 커널 5.0.0
# cat /etc/issue
Ubuntu 19.04 \n \l
#u name -sr
Linux 5.0.0-26-generic
도커 버전 18.06
# docker version
Client:
Version: 18.06.1-ce
API version: 1.38
Go version: go1.10.4
Git commit: e68fc7a
Built: Tue May 7 17:57:34 2019
OS/Arch: linux/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 18.09.6
API version: 1.39 (minimum version 1.12)
Go version: go1.10.8
Git commit: 481bc77
Built: Sat May 4 01:59:36 2019
OS/Arch: linux/amd64
Experimental: false
# wget https://releases.hashicorp.com/consul/1.5.3/consul_1.5.3_linux_amd64.zip
# unzip consul_1.5.3_linux_amd64.zip
Archive: consul_1.5.3_linux_amd64.zip
inflating: consul
# sudo cp consul /usr/local/bin
# consul version
Consul v1.5.3
Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol >2 when speaking to compatible agents)
Dockerizing
나는 consul 클러스터를 구성해서 테스트하고 싶었다. VM(KVM/QEMU) 기반으로 수행 할 수 있었지만 시간이 많이 걸릴 것 같아서 컨테이너 기반으로 테스트하기로 했다. 아래와 같이 Dockerfile을 만들었다. consul 실행파일 외에, consul을 테스트하기 위한 기본툴들도 함께 설치했다.
FROM ubuntu
MAINTAINER yundream
RUN apt-get update
RUN apt-get -y install vim
RUN apt-get -y install curl
RUN apt-get -y install dnsutils
ADD ./consul /usr/local/bin
CMD /bin/bash
# docker run --hostname=consul01 -it --name consul01 joinc/consul /bin/bash
root@consul01:/#
Agent 실행
일단 개발 모드로 실행해봤다.
root@consul01:/# consul agent -dev
==> Starting Consul agent...
Version: 'v1.5.3'
Node ID: '80115d27-e681-da61-1672-c994af0b0f2b'
Node name: 'consul01'
Datacenter: 'dc1' (Segment: '<all>')
Server: true (Bootstrap: false)
Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, gRPC: 8502, DNS: 8600)
Cluster Addr: 127.0.0.1 (LAN: 8301, WAN: 8302)
Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false, Auto-Encrypt-TLS: false
==> Log data will now stream in as it occurs:
실행됐다. 127.0.0.1로 바인드 했으니, 로컬에서만 테스트 할 수 있는 정도가 돼겠다. consul member 명령으로 consul 데이터센터의 멤버들을 확인해보자.
root@consul01:/# consul members
Node Address Status Type Build Protocol DC Segment
consul01 127.0.0.1:8301 alive server 1.5.3 2 dc1 <all>
지금은 단지 하나의 멤버만 보일 것이다. 멤버 정보로 IP 주소, heath 상태, 데이터센터에서(Datacenter, DC)의 롤을 확인 할 수 있다. --detailed 플래그를 이용하면 추가적인 메타정보를 확인 할 수 있다. HTTP API를 이용해서 consul 서버에 요청을 전달 할 수 있다. consule은 분산환경에서 데이터에 대한 consistent를 보장하는데, HTTP API를 이용하면 consistent가 보장된 정보를 읽을 수 있다.
root@consul01:/# dig @127.0.0.1 -p 8600 consul01.node.consul ANY
; <<>> DiG 9.11.3-1ubuntu1.8-Ubuntu <<>> @127.0.0.1 -p 8600 consul01.node.consul ANY
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 17324
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;consul01.node.consul. IN ANY
;; ANSWER SECTION:
consul01.node.consul. 0 IN A 127.0.0.1
consul01.node.consul. 0 IN TXT "consul-network-segment="
;; Query time: 0 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Wed Aug 21 13:51:43 UTC 2019
;; MSG SIZE rcvd: 101
Consul 중지
consul leave 명령으로 중지할 수 있다.
root@consul01:/# consul monitor
2019/08/21 13:24:25 [INFO] raft: Initial configuration (index=1): [{Suffrage:Voter ID:80115d27-e681-da61-1672-c994af0b0f2b Address:127.0.0.1:8300}]
2019/08/21 13:24:25 [INFO] raft: Node at 127.0.0.1:8300 [Follower] entering Follower state (Leader: "")
2019/08/21 13:24:25 [INFO] serf: EventMemberJoin: consul01.dc1 127.0.0.1
2019/08/21 13:24:25 [INFO] serf: EventMemberJoin: consul01 127.0.0.1
2019/08/21 13:24:25 [INFO] consul: Adding LAN server consul01 (Addr: tcp/127.0.0.1:8300) (DC: dc1)
2019/08/21 13:24:25 [INFO] consul: Handled member-join event for server "consul01.dc1" in area "wan"
2019/08/21 13:24:25 [WARN] agent/proxy: running as root, will not start managed proxies
2019/08/21 13:24:25 [INFO] agent: Started DNS server 127.0.0.1:8600 (tcp)
2019/08/21 13:24:25 [INFO] agent: Started DNS server 127.0.0.1:8600 (udp)
2019/08/21 13:24:25 [INFO] agent: Started HTTP server on 127.0.0.1:8500 (tcp)
2019/08/21 13:24:25 [INFO] agent: Started gRPC server on 127.0.0.1:8502 (tcp)
2019/08/21 13:24:25 [INFO] agent: started state syncer
2019/08/21 13:24:25 [WARN] raft: Heartbeat timeout from "" reached, starting election
2019/08/21 13:24:25 [INFO] raft: Node at 127.0.0.1:8300 [Candidate] entering Candidate state in term 2
2019/08/21 13:24:25 [INFO] raft: Election won. Tally: 1
2019/08/21 13:24:25 [INFO] raft: Node at 127.0.0.1:8300 [Leader] entering Leader state
2019/08/21 13:24:25 [INFO] consul: cluster leadership acquired
2019/08/21 13:24:25 [INFO] consul: New leader elected: consul01
2019/08/21 13:24:25 [INFO] connect: initialized primary datacenter CA with provider "consul"
2019/08/21 13:24:25 [INFO] consul: member 'consul01' joined, marking health alive
2019/08/21 13:24:25 [INFO] agent: Synced node info
Service Discovery
Consul의 주요 사용 목적 중 하나는 서비스 디스커버리다. Consul은 다운스트림 서비스(downstream service)가 그들의 업스트림 서비스(downstream service) 종속성을 찾기 위한 IP 주소를 찾는데 사용 할 수 있는 DNS 인터페이스를 제공한다. 서비스 디스커버리 테스트를 위해서 서비스를 등록하기로 했다. 등록 할 서비스는 레일즈(rails)로 만든 웹 애플리케이션 서버다.
먼저 Consul 설정 파일을 저장할 디렉토리 /etc/consul.d 를 만들었다. 여기에 레일즈 웹 애플리케이션 서비스를 위한 설정파일을 만들었다.
# consul agent -dev -enable-script-checks -config-dir=/consul.d/
==> Starting Consul agent...
Version: 'v1.5.3'
Node ID: '1fce03c0-f364-20b7-f837-3db917e75d6b'
Node name: 'consul01'
Datacenter: 'dc1' (Segment: '<all>')
Server: true (Bootstrap: false)
Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, gRPC: 8502, DNS: 8600)
Cluster Addr: 127.0.0.1 (LAN: 8301, WAN: 8302)
Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false, Auto-Encrypt-TLS: false
==> Log data will now stream in as it occurs:
DNS 인터페이스를 이용해서 서비스를 찾아보자.
# dig @127.0.0.1 -p 8600 web.service.consul
; <<>> DiG 9.11.3-1ubuntu1.8-Ubuntu <<>> @127.0.0.1 -p 8600 web.service.consul
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 44772
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 2
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;web.service.consul. IN A
;; ANSWER SECTION:
web.service.consul. 0 IN A 127.0.0.1
;; ADDITIONAL SECTION:
web.service.consul. 0 IN TXT "consul-network-segment="
;; Query time: 0 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Wed Aug 21 14:53:29 UTC 2019
;; MSG SIZE rcvd: 99
A 레코드에서 IP 주소를 확인 할 수 있다.
앞서 설정파일에 포트번호를 넣었던 것을 기억 할 것이다. 포트 정보는 DNS SRV 레코드에 저장된다.
# dig @127.0.0.1 -p 8600 web.service.consul SRV
; <<>> DiG 9.11.3-1ubuntu1.8-Ubuntu <<>> @127.0.0.1 -p 8600 web.service.consul SRV
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58287
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 3
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;web.service.consul. IN SRV
;; ANSWER SECTION:
web.service.consul. 0 IN SRV 1 1 80 consul01.node.dc1.consul.
;; ADDITIONAL SECTION:
consul01.node.dc1.consul. 0 IN A 127.0.0.1
consul01.node.dc1.consul. 0 IN TXT "consul-network-segment="
;; Query time: 0 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Wed Aug 21 15:05:06 UTC 2019
;; MSG SIZE rcvd: 143
SRV 레코드에 "1 1 80 consul01.node.dc1.consul."를 확인 할 수 있을 것이다. SRV 레코드는 서비스의 위치(호스트이름과 포트번호)를 저장하기 위해서 사용하는 레코드다. A 레코드와 SRV 레코드를 이용해서 web.serviceconsul 서비스가 127.0.0.1:80에서 서비스 한다는 것을 알 수 있다. SRV에 대한 자세한 내용은 DNS SRV 레코드문서를 참고하자.
설정파일의 TAG는 태그이름 기반으로 서비스를 찾을 수 있게 해준다. DNS 질의 형식은 TAG.NAME.service.consul이다. rails.web.service.consul 로 질의해보자.
# dig @127.0.0.1 -p 8600 rails.web.service.consul
; <<>> DiG 9.11.3-1ubuntu1.8-Ubuntu <<>> @127.0.0.1 -p 8600 rails.web.service.consul
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6954
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 2
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;rails.web.service.consul. IN A
;; ANSWER SECTION:
rails.web.service.consul. 0 IN A 127.0.0.1
;; ADDITIONAL SECTION:
rails.web.service.consul. 0 IN TXT "consul-network-segment="
;; Query time: 0 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Wed Aug 21 15:14:40 UTC 2019
;; MSG SIZE rcvd: 105
인터넷 웹 서비스는 여러 컴포넌트들로 구성이 되므로 태그이름을 잘 정의하면, 서비스를 잘 구조화 할 수 있다. 예컨데 아래와 같은 구성이 가능할 것이다.
Contents
Consul
Consul 설치
환경
Consul 다운로드
Dockerizing
Agent 실행
DNS 기반 node discovery
Consul 중지
Service Discovery
Recent Posts
Archive Posts
Tags