Tuesday, 7 January 2020

Service Discovery với Consul - từ con tới sồ

### Consul là gì


https://www.consul.io/
Cách đọc: /ˈkänsəl/ /ˈkɑnsəl/ - không phải con sun

```
$ apt-cache search consul | grep ^consul
consul - tool for service discovery, monitoring and configuration
```
Consul là một phần mềm còn khá mới (bản 1.0 từ 2017
https://github.com/hashicorp/consul/tree/v1.0.0), được ra đời ban đầu như một
giải  pháp cho "Service Discovery", kèm KeyValue storage. Sau này phát triển
thêm nhiều tính năng khác như Service Mesh.




 

#### Service Discovery là gì

Khái niệm service discovery không mới mẻ, nhưng chỉ thực sự phổ biến vói từ khóa này
khi Microservices trở thành trào lưu (~ từ 2015).
Service Discovery là việc tìm địa chỉ IP/port của một service trong hệ thống, trở nên
phức tạp khi trong hệ thống có nhiều service. Đặc biệt khi chạy trên cloud (AWS, Azure, GCP...), IP của các service thay đổi thường xuyên hơn do việc tạo/xóa máy ảo (hay container) là chuyện thường ngày trong môi trường cloud.

Việc tìm từ tên ra IP không đâu xa lạ, chính là việc DNS server đã làm từ khi có internet
tới giờ. Thay vì gõ địa chỉ IP để vào 1 website, người dùng gõ 1 cái tên (domain), các
dịch vụ DNS sẽ đổi từ tên đó ra địa chỉ IP tương ứng. Các phần mềm DNS server phổ biến trên
`*NIX` là BIND, Unbound, ...

Chuyện thay đổi "động" IP khi thêm service hay thay đổi máy chạy service cũng đã được giải
quyết với DNS server truyền thống qua một cơ chế có tên "Dynamic DNS", nhưng việc sử dụng
cũng không dễ tới mức gọi là "đơn giản".

Consul ban đầu là một Dynamic DNS server giúp cho việc này trở thành cực kỳ đơn giản.
Ngoài consul, một phần mềm khác cũng không kém phổ biến trong lĩnh vực này là
`etcd` kết hợp với `SkyDNS` (bộ đôi này được dùng trong core của Kubernetes).

Consul có chức năng `HealthCheck`, nó liên tục kiểm tra xem service có truy cập được không,
và chỉ trả về các service "sống" khi được hỏi. Tưởng tượng có 10 máy chạy service web,
khi 3 máy down, service worker hỏi `consul` sẽ chỉ nhận về danh sách 7 máy còn sống.

Consul nằm trong bộ software của Hashicorp, cùng những cái tên đình đám khác như: Vault,
Terraform, Nomad. Consul đã được dùng trong production của nhiều công ty lớn,
ví dụ như
[GitLab](https://about.gitlab.com/blog/2019/11/08/the-consul-outage-that-never-happened/).



#### Ai cần dùng Service Discovery

Khi cần quản lý nhiều service tương tác với nhau. Khi địa chỉ các máy thay đổi thưởng xuyên.
Hay đơn giản khi cần quản lý các thiết bị trong nhà (Raspberry Pi cũng có thể chạy consul).

### Cài đặt

Mặc dù có thể cài bằng apt nhưng phiên bản trên apt rất cũ, không nên dùng.

```
$ apt-cache policy consul
consul:
  Installed: (none)
  Candidate: 0.6.4~dfsg-3
  Version table:
     0.6.4~dfsg-3 500
        500 http://vn.archive.ubuntu.com/ubuntu bionic/universe amd64 Packages
```

Phiên bản mới nhất hiện tại

```
 $ curl -L api.github.com/repos/hashicorp/consul/tags 2>/dev/null | /usr/bin/python -c 'import sys,json; print([i["name"] for i in json.load(sys.stdin) if "beta" not in i["name"]][0])'
v1.6.2
```

Tải bản mới nhất qua https://www.consul.io/downloads.html

```
$ curl -LO https://releases.hashicorp.com/consul/1.6.2/consul_1.6.2_linux_amd64.zip
100 38.2M  100 38.2M    0     0  2382k      0  0:00:16  0:00:16 --:--:-- 3591k
$ unzip -l consul_1.6.2_linux_amd64.zip
Archive:  consul_1.6.2_linux_amd64.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
108053286  2019-11-14 04:31   consul
---------                     -------
108053286                     1 file
```

`consul` được viết bằng Golang, nên sản phẩm để mang đi deploy chỉ là 1 file binary duy nhất. File này giải nén ra
có kích thước ~ 100M (yeahhhh)

```
$ unzip consul_1.6.2_linux_amd64.zip
Archive:  consul_1.6.2_linux_amd64.zip
  inflating: consul                 
$ du consul -h
104M    consul
```

### Chạy ở dev mode

Consul khi chạy service có 2 chế độ: server hoặc agent.
Một chế độ đặc biệt thứ 3 là `dev` dùng để chạy thử nghiệm.

```
$ ./consul version
Consul v1.6.2
Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol >2 when speaking to compatible agents)

$ ./consul agent -dev
==> Starting Consul agent...
           Version: 'v1.6.2'
           Node ID: 'a7e68a9a-77bd-6559-ae17-a302860a6e0d'
         Node name: 'hvnzen'
        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
...
    2020/01/05 01:02:17 [INFO] serf: EventMemberJoin: hvnzen.dc1 127.0.0.1
    2020/01/05 01:02:17 [INFO] serf: EventMemberJoin: hvnzen 127.0.0.1
    2020/01/05 01:02:17 [INFO] consul: Adding LAN server hvnzen (Addr: tcp/127.0.0.1:8300) (DC: dc1)
...
    2020/01/05 01:02:17 [INFO] agent: Started DNS server 127.0.0.1:8600 (tcp)
    2020/01/05 01:02:17 [INFO] agent: Started DNS server 127.0.0.1:8600 (udp)
    2020/01/05 01:02:17 [INFO] agent: Started HTTP server on 127.0.0.1:8500 (tcp)
    2020/01/05 01:02:17 [INFO] agent: Started gRPC server on 127.0.0.1:8502 (tcp)
==> Consul agent running!
    2020/01/05 01:02:17 [INFO]  raft: Node at 127.0.0.1:8300 [Candidate] entering Candidate state in term 2
...
    2020/01/05 01:02:17 [INFO]  raft: Node at 127.0.0.1:8300 [Leader] entering Leader state
...
```

Chú ý: consul sử dụng các port sau:

```
 $ lsof -n -P -p `pgrep consul`
COMMAND   PID USER   FD      TYPE  DEVICE  SIZE/OFF    NODE NAME
consul  24079  hvn  cwd       DIR   259,6      4096 5641002 /home/hvn/me/consullab
consul  24079  hvn  rtd       DIR   259,4      4096       2 /
consul  24079  hvn  txt       REG   259,6 108053286 5641005 /home/hvn/me/consullab/consul
consul  24079  hvn    0u      CHR   136,1       0t0       4 /dev/pts/1
consul  24079  hvn    1u      CHR   136,1       0t0       4 /dev/pts/1
consul  24079  hvn    2u      CHR   136,1       0t0       4 /dev/pts/1
consul  24079  hvn    3u     IPv4 1340781       0t0     TCP 127.0.0.1:8300 (LISTEN)
consul  24079  hvn    4u  a_inode    0,13         0   11931 [eventpoll]
consul  24079  hvn    5u     IPv4 1340782       0t0     TCP 127.0.0.1:8302 (LISTEN)
consul  24079  hvn    6u     IPv4 1340783       0t0     UDP 127.0.0.1:8302
consul  24079  hvn    7u     IPv4 1340784       0t0     TCP 127.0.0.1:8301 (LISTEN)
consul  24079  hvn    8u     IPv4 1340785       0t0     UDP 127.0.0.1:8301
consul  24079  hvn    9u     IPv4 1340786       0t0     UDP 127.0.0.1:8600
consul  24079  hvn   10u     IPv4 1339562       0t0     TCP 127.0.0.1:8600 (LISTEN)
consul  24079  hvn   11u     IPv4 1339564       0t0     TCP 127.0.0.1:8500 (LISTEN)
consul  24079  hvn   12u     IPv4 1339566       0t0     TCP 127.0.0.1:8502 (LISTEN)
consul  24079  hvn   13u     IPv4 1340787       0t0     TCP 127.0.0.1:42547->127.0.0.1:8300 (ESTABLISHED)
consul  24079  hvn   14u     IPv4 1337143       0t0     TCP 127.0.0.1:8300->127.0.0.1:42547 (ESTABLISHED)
```

### Ports

- TCP 8300: Consul RPC Server / Raft Server
- TCP 8500: WebUI / HTTP API
- TCP 8502: gRPC
- TCP|UDP 8301: LAN
- TCP|UDP 8302: WAN
- TCP|UDP 8600: DNS

### DNS


Dùng lệnh `dig` để tra cứu thông tin về service tên `consul` xem nó chạy
ở đâu, dùng port nào:

```
$ dig @127.0.0.1 -p8600 consul.service.consul SRV

; <<>> DiG 9.11.3-1ubuntu1.11-Ubuntu <<>> @127.0.0.1 -p8600 consul.service.consul SRV
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 17727
;; 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:
;consul.service.consul.   IN  SRV

;; ANSWER SECTION:
consul.service.consul.  0 IN  SRV 1 1 8300 hvnzen.node.dc1.consul.

;; ADDITIONAL SECTION:
hvnzen.node.dc1.consul. 0 IN  A 127.0.0.1
hvnzen.node.dc1.consul. 0 IN  TXT "consul-network-segment="

;; Query time: 0 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Tue Jan 07 16:50:41 +07 2020
;; MSG SIZE  rcvd: 144
```

Dòng ANSWER SECTION đã ghi rõ port 8300, ADDITION SECTION ghi địa chỉ IPv4 127.0.0.1


### HTTP


Dùng `curl` truy cập HTTP API của consul xem thông tin về chính service này:

```
$ curl http://localhost:8500/v1/catalog/service/consul?passing
[
    {
        "ID": "6cf38528-6566-b630-10db-cf7dbc993571",
        "Node": "hvnzen",
        "Address": "127.0.0.1",
        "Datacenter": "dc1",
        "TaggedAddresses": {
            "lan": "127.0.0.1",
            "wan": "127.0.0.1"
        },
        "NodeMeta": {
            "consul-network-segment": ""
        },
        "ServiceKind": "",
        "ServiceID": "consul",
        "ServiceName": "consul",
        "ServiceTags": [],
        "ServiceAddress": "",
        "ServiceWeights": {
            "Passing": 1,
            "Warning": 1
        },
        "ServiceMeta": {
            "raft_version": "3",
            "serf_protocol_current": "2",
            "serf_protocol_max": "5",
            "serf_protocol_min": "1",
            "version": "1.6.2"
        },
        "ServicePort": 8300,
        "ServiceEnableTagOverride": false,
        "ServiceProxy": {
            "MeshGateway": {},
            "Expose": {}
        },
        "ServiceConnect": {},
        "CreateIndex": 9,
        "ModifyIndex": 9
    }
]
]
```

Cũng thấy Address 127.0.0.1 và ServicePort 8300.

`?passing` để lọc ra các service pass HealthCheck, với DNS, mặc định
lọc điều kiện này.

## TODO Phần 2: consul server & agent

### Hết

HVN at https://pymi.vn and https://www.familug.org

No comments:

Post a Comment