本文在Docker环境中试验,请自行准备好Docker环境。
下面我会从按照如下顺序进行描述整个过程:
- 构建Consul容器
- 安装Nginx作为测试服务
- 注册服务
- 发现服务
- 调用服务
过程可能过于详细,根据读者水平不同,可以自行跳跃阅读。有些地方我为了后面的方便,预留了一下设置,起初你可能不太明白,操作到最后你会发现我的用意。建议零基础的朋友,全篇照做。
一、 构建Consul容器
由于测试中我们需要多台服务器,部署太多实例会比较麻烦,所以本文推荐使用Docker。
1. 拉取Consul镜像
$ docker search consul
$ docker pull consul
$ docker run consul --help
# Usage: consul [--version] [--help] <command> [<args>]
2.Environment Variable(环境变量)
指令 | 功能 |
---|---|
CONSUL_BIND_INTERFACE=eth0 | 在容器启动时,自动绑定eth0端口的IP地址 |
CONSUL_UI_LEGACY | 使用旧版ui |
3. Command(命令)
指令 | 功能 |
---|---|
acl | Interact with Consul's ACLs |
agent | 运行Consul agent |
catalog | Interact with the catalog |
connect | Interact with Consul Connect |
debug | 记录操作者的错误日志 |
event | 构建一个事件 |
exec | Executes a command on Consul nodes |
force-leave | Forces a member of the cluster to enter the "left" state |
info | 向操作者提供错误信息 |
intention | Interact with Connect service intentions |
join | 告诉Consul agent加入哪个簇 |
keygen | Generates a new encryption key |
keyring | Manages gossip layer encryption keys |
kv | 启用顶层KV键值功能 |
leave | Gracefully leaves the Consul cluster and shuts down |
lock | Execute a command holding a lock |
maint | Controls node or service maintenance mode |
members | Lists the members of a Consul cluster |
monitor | Stream logs from a Consul agent |
operator | Provides cluster-level tools for Consul operators |
reload | Triggers the agent to reload configuration files |
rtt | Estimates network round trip time between nodes |
services | Interact with services |
snapshot | Saves, restores and inspects snapshots of Consul server state |
tls | Builtin helpers for creating CAs and certificates |
validate | Validate config files/directories |
version | Prints the Consul version |
watch | Watch for changes in Consul |
3. Args(参数)
Docker参数 | 功能 |
---|---|
-e | 将时区信息传入到容器内部。 |
-d | Daemon模式 |
-p | 绑定端口 |
--name | 指定实例名称 |
Consul参数 | 功能 |
---|---|
-data-dir | 指定agent储存状态的数据目录 |
-config-dir | 指定service的配置文件和检查定义所在的位置;通常会指定为"某一个路径/consul.d"(通常情况下,.d表示一系列配置文件存放的目录) |
-config-file | 指定一个要装载的配置文件;选项可以配置多次,进而配置多个配置文件(后边的会合并前边的,相同的值覆盖) |
-dev | 创建一个开发环境下的server节点;该参数配置下,不会有任何持久化操作,即不会有任何数据写入到磁盘 |
-bootstrap-expect | 该命令通知consul server我们现在准备加入的server节点个数,该参数是为了延迟日志复制的启动直到我们指定数量的server节点成功的加入后启动。 |
-node | 指定节点在集群中的名称;该名称在集群中必须是唯一的(默认采用机器的host);推荐直接采用机器的IP |
-bind | 指明节点的IP地址 |
-server | 指定节点为server;每个数据中心(DC)的server数推荐为3或5(理想的是,最多不要超过5) |
-client | consul服务侦听地址,这个地址提供HTTP、DNS、RPC等服务,默认是127.0.0.1所以不对外提供服务,如果你要对外提供服务改成0.0.0.0 |
-join | 将节点加入到集群 |
-domain | 绑定域名 |
-dc | 指定加入哪个数据中心 |
--retry-join [Server A的IP地址] | 通过连接Server A加入集群 |
--ui | 开启网页GUI |
4. 环境部署
1. 测试环境由3台Server和1台Client组成
# 开启第1台Server
# [-p=8900:8500]把8500端口映射到外部主机的8900端口,使用http://ip:8900/ui访问
# [-p=10080:80]把80端口映射到外部主机的10080端口,使用http://ip:80访问等会使用的nginx测试,这一步不是必须的
# [-client=0.0.0.0]表示响应所有外部请求,不开启的话会导致webgui无法访问
$ docker run -d --name=server_1 -p=8900:8500 -p=10080:80 -e CONSUL_BIND_INTERFACE=eth0 consul agent -server -bootstrap-expect=3 -client=0.0.0.0 -ui
# 查看所有docker的ip地址
$ docker inspect -f '{{.Name}} - {{.NetworkSettings.IPAddress }}' $(docker ps -aq)
# 启动第2台Server,join上面得到的server_1的IP地址
$ docker run -d --name=server_2 -e CONSUL_BIND_INTERFACE=eth0 consul agent -server -ui -join=172.17.0.2 -client=0.0.0.0
# 启动第3台Server
$ docker run -d --name=server_3 -e CONSUL_BIND_INTERFACE=eth0 consul agent -server -ui -join=172.17.0.2 -client=0.0.0.0
# 启动第1台Client
$ docker run -d --name=client_1 -e CONSUL_BIND_INTERFACE=eth0 consul agent -ui -join=172.17.0.2 -client=0.0.0.0
2. 检查一下Docker实例状况
$ docker ps -a
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# bdd6ba1a74ec consul "docker-entrypoint..." 19 minutes ago Up 19 minutes 8300-8302/tcp, 8500/tcp, 8301-8302/udp, 8600/tcp, 8600/udp client_1
# 48c194a2ef8d consul "docker-entrypoint..." 19 minutes ago Up 19 minutes 8300-8302/tcp, 8500/tcp, 8301-8302/udp, 8600/tcp, 8600/udp server_3
# 922ab3429e8b consul "docker-entrypoint..." 19 minutes ago Up 19 minutes 8300-8302/tcp, 8500/tcp, 8301-8302/udp, 8600/tcp, 8600/udp server_2
# 126e4631e775 consul "docker-entrypoint..." 23 minutes ago Up 23 minutes 8300-8302/tcp, 8301-8302/udp, 8600/tcp, 8600/udp, 0.0.0.0:8900->8500/tcp server_1
解释一下这里的端口
- 8300:consul agent服务relplaction、rpc(client-server)
- 8301:lan gossip
- 8302:wan gossip
- 8500:http api端口
- 8600:DNS服务端口
2. 检查一下Consul集群状况
$ docker exec -t server_1 consul members
# Node Address Status Type Build Protocol DC Segment
# 126e4631e775 172.17.0.2:8301 alive server 1.4.2 2 dc1 <all>
# 48c194a2ef8d 172.17.0.5:8301 alive server 1.4.2 2 dc1 <all>
# 922ab3429e8b 172.17.0.4:8301 alive server 1.4.2 2 dc1 <all>
# bdd6ba1a74ec 172.17.0.6:8301 alive client 1.4.2 2 dc1 <default>
3. 检查Web GUI
这些Consul节点在Docker的容器内是互通的,他们通过桥接的模式通信。但是如果主机要访问容器内的网络,需要做端口映射。在启动第一个容器时,将Consul的8500端口映射到了主机的8900端口,这样就可以方便的通过主机的浏览器查看集群信息。
4. 进出容器
# 进入容器( pwd此时是在Docker根目录下)
$ docker exec -it server_1 /bin/sh
# 退出容器
$ exit
5. 准备接口服务
5.1 运行环境
Consul的docker镜像基于alpine系统,我们可以使用apk命令来安装需要的服务
5.1.1 安装nginx
# 安装nginx
$ apk add nginx
# 测试nginx
$ nginx -t
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: [emerg] open() "/run/nginx/nginx.pid" failed (2: No such file or directory)
# nginx: configuration file /etc/nginx/nginx.conf test failed
# 解析:
# 1. 查看nginx.conf中设置的log目录文件权限
# $ chmod -R 777 /var/log/nginx
# 2. 查看/run/nginx目录是否存在且可读写
$ mkdir /run/nginx
$ chmod -R 777 /run/nginx
# 3. nginx.conf可能找不到,需要指定 -c [uri]
$ nginx -c /etc/nginx/nginx.conf
$ nginx -s reload
$ nginx -t #成功!
# 查看服务状态
$ ps -ef | grep nginx
#163 root 0:00 nginx: master process nginx -c /etc/nginx/nginx.conf
#171 nginx 0:00 nginx: worker process
#172 nginx 0:00 nginx: worker process
#174 root 0:00 grep nginx
5.1.2 配置nginx
$ vi /etc/nginx/nginx.conf
http{
...
server{
listen 80;
server_name 127.0.0.1;
location / {
root /etc/nginx/wwwroot;
index index.html;
}
}
...
}
# 重启nginx
$ nginx -s reload
5.1.3 新建html文件
$ mkdir /etc/nginx/wwwroot
$ vi /etc/nginx/wwwroot/index.html
<html>
<body>Hello world</body>
</html>
5.1.4 测试服务
Q1:我在外部绑定了这个主机的域名为vm1.my,只接访问vm1.my:10080会报404错误
A1:需要在server_name中添加vm1.my
Q3:本地测试curl localhost:80返回404
A3:就是不行
6. 注册服务
$ vi /consul/config/services.json
{
"service":[
{
"id":"hello1",
"name":"hello",
"tags":[
"primary"
],
"address":"172.17.0.2",
"port":80,
"checks":[
{
"http":"http://127.0.0.1:80",
"tls_skip_verify":false,
"method":"GET",
"interval":"10s",
"timeout":"1s"
}
]
}
]
}
FBI WARNING
- "method":"GET" 千万不能写成 "method":"Get" ,网上很多文章写的是这个
- "http":"http://127.0.0.1:80",这一条依然是无法解决localhsot域名的问题才出此下册,希望未来能解决
7. 服务发现
服务注册成功以后,调用方获取相应服务地址的过程就是服务发现
1. 常用命令
# 查看成员
$ consul members
# 查看节点:
$ curl 127.0.0.1:8500/v1/catalog/nodes
# 使用DNS协议查看节点信息
# alpine未安装dig:curl -L https://github.com/sequenceiq/docker-alpine-dig/releases/download/v9.10.2/dig.tgz|tar -xzv -C /usr/local/bin
$ dig @127.0.0.1 -p 8600 hello.service.dc1.consul. ANY
# 如果报错:parse of /etc/resolv.conf failed ,请将resolv.conf中的search那行删掉。
apk add busybox-extras