Using consul, this doc is from https://learn.hashicorp.com/consul/getting-started/agent
Get Started
Installing
- Download zip file from https://www.consul.io/downloads.html
- Move to your bin path folder (you can use
echo $PATH
to find the directory)
> sudo mv consul /usr/local/bin/
- Verify
> consul
Usage: consul [--version] [--help] []
Available commands are:
acl Interact with Consul's ACLs
agent Runs a Consul agent
catalog Interact with the catalog
...
Run the Consul Agent
- Two modes: server mode and client mode
- Client mode: A client must be running on every node in the Consul datacenter that runs services
Starting the Agent
> consul agent -dev // never use -dev on production
show members
> consul members
Node Address Status Type Build Protocol DC Segment
xxx-HP-Pavilion-14-Notebook-PC 127.0.0.1:8301 alive server 1.5.3 2 dc1
The output displays your agent, its IP address, its health state, its role in the datacenter, and some version information. You can discover additional metadata by providing the -detailed
flag.
check
- Get info by gossip api (HTTP protocol)
> curl localhost:8500/v1/catalog/nodes # Failed by curl command, succeed by postman
- Get info by DNS interface
> dig @127.0.0.1 -p 8600 xxx-HP-Pavilion-14-Notebook-PC.node.consul
... # 暂时理解不了输出
- You can also visit
localhost:8500
in you browser for checking with UI
(我这里 curl 不成功是因为配置了命令行的代理,去掉 http_proxy 这样的设置,就可以成功了)
Stop agent
> consul leave
Graceful leave complete
总结
本节学习了如何启动 consul 的 agent 模式,并了解到它提供了一些 http api 和 dns 接口供使用查询相关信息,最后优雅地关闭 consul。
Registering A Service And A Health Check
service discovery
Consul provides a DNS interface that downstream services can use to find the IP addresses of their upstream dependancies. (Consul 提供了一个 DNS 接口,让下游服务获取到上游依赖服务的 IP 地址。)
- 手动注册
- 配置管理工具在部署时注册
- 容器编排平台在集成时自动注册
You will register a service and health check manually by providing Consul with a configuration file, and use Consul discover its location using the DNS interface and HTTP API.
你将学到:
- 注册一个服务
- 健康检查
- 发现服务的地址。通过两种方式:
- DNS 接口
- HTTP API
Defining a Service
- (*) by providing a service definition (a configure file)
- by calling api
We use the first method to try:
- Create a common directory for config files
> mkdir ./consul.d
- Create and write the config file
web.json
, its content:
{
"service": {
"name": "web",
"tags": ["rails"], // optional, used to find the service later on
"port": 80
}
}
- Restart the agent, specify the configuration directory, and enable script checks
> consul agent -dev -enable-script-checks -config-dir=./consul.d
# ...
2019/08/11 12:11:06 [DEBUG] agent: Service "web" in sync
2019/08/11 12:11:06 [DEBUG] agent: Node info in sync
# ...
Note: We never started a web service in this example. Consul can register services that aren't running yet. It correlates each running service with its registration based on the service's port
注意:在这个例子中我们并没有启动一个 web 服务,即在 80 端口上并没有提供服务,但 consul 还是注册上了它。...
Query services
DNS Interface
NAME.service.consul
Consul runs by default on port 8600
> dig @127.0.0.1 -p 8600 web.service.consul
# ...
web.service.consul. 0 IN A 127.0.0.1
web.service.consul. 0 IN TXT "consul-network-segment="
# ...
You can also get the entire address/port pair as a SRV
record
> dig @127.0.0.1 -p 8600 web.service.consul SRV
# ...
web.service.consul. 0 IN SRV 1 1 80 robincai-HP-Pavilion-14-Notebook-PC.node.dc1.consul.
xxx-HP-Pavilion-14-Notebook-PC.node.dc1.consul. 0 IN A 127.0.0.1
xxx-HP-Pavilion-14-Notebook-PC.node.dc1.consul. 0 IN TXT "consul-network-segment="
# ...
The SRV
record says that the web service is running on port 80
and exists on the node xxx-HP-Pavilion-14-Notebook-PC.node.dc1.consul.
.
Finally, you can also use the DNS interface to filter services by tags. TAG.NAME.service.consul
> dig @127.0.0.1 -p 8600 rails.web.service.consul
# ...
;; 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="
HTTP API
- Lists all nodes hosting web service
> curl http://localhost:8500/v1/catalog/service/web
- Filter your query for only healthy service instances
> curl 'http://localhost:8500/v1/health/service/web?passing'
Updating Services
Next you'll update the web service by registering a health check for it. Because you never started a service on port 80 where you registered web, the health check you register will fail.
- Update service definitions
{
"service": {
"name": "web",
"tags": ["rails"],
"port": 80,
"check": { // scripts: every 10s call curl localhost to check
"args": ["curl", "localhost"],
"interval": "10s"
}
}
}
- reload consul
> consul reload
If the command exits with an exit code >= 2, the check will fail, and 1 will be considered as warning state.
DNS server only return healthy service, so now query by DNS will return no host.
总结
这一节学了如何注册一个服务,对它进行 health 检查(check
字段),并通过 api 去获取信息,主要是通过配置文件来实现。
Connect Service - Service Mesh
In addition to providing IP addresses directly to services with the DNS interface or HTTP API, Consul can connect services to each other via sidecar proxies that you deploy locally with each service instance. This type of deployment (local proxies that control network traffic between service instances) is a service mesh. Consul's service mesh feature is called Consul Connect.
除了通过 DNS 接口和 HTTP API 提供 IP 地址给服务, Consul 也能连接 services 通过边车代理,你可以在本地通过每一个服务实例部署这个边车代理。这种类型的部署就是服务网格。
In this guide you will:
- Start a service.
- Register it normally, but with an additional
connect
stanza. - Register a second proxy to communicate with the service.
- Start sidecar proxies.
- Practice blocking the connection to the service by creating an intention.
Start a Service
socat
是一个小工具,可以创建一个 Connect-unaware
的服务
- Start the socat service and specify that it will listen for TCP connections on port 8181
> socat -v tcp-l:8181,fork exec:"/bin/cat"
- Verify it works by
nc
(netcat) to connect directly to the echo service on the correct port. After connect, you can type whatever and it will echo back originally.
> nc 127.0.0.1 8181
Register the Service and Proxy with Consul
- 注册,同样是写配置文件的方式,不过有了
connect
字段。it will register a sidecar proxy to handle traffic for this backend service instance.
// ./consul.d/socat.json
{
"service": {
"name": "socat",
"port": 8181,
"connect": {
"sidecar_service": {}
}
}
}
- reload
> consul reload
Take a look at the "connect" stanza in the registration you just added. This empty configuration notifies Consul to register a sidecar proxy for this process on a dynamically allocated port. It also creates reasonable defaults that Consul will use to configure the proxy once you start it via the CLI. Consul does not automatically start the proxy process for you. This is because Consul Connect allows you to chose the proxy you'd like to use.
看上面的 connect
字段,它指定了一个空的 sidecar_service
,意思是通知 consul
为 这个进程 动态 注册一个 边车代理。但这个代理默认是不自动启动的,需要你通过 cli 来启动,这么做是因为 Consul Connect 允许你自己选择你想用的代理。虽然这个代理没有任何配置,但在你启动时,它会自动给一些合理的默认值进去。
You'll use the L4 proxy in this guide, because it comes with Consul and doesn't require any extra installation.
Run with consul connect proxy
, and specify service instance and proxy registration it corresponds to
> consul connect proxy -sidecar-for socat
After this, you can see:
Register a Dependent Service and Proxy
下面我们来注册一个下游服务 web
带有 connect
和 sidecar
, 并且指定 socat
为上游依赖,监听端口和代理。
更改 ./consul.d/web.json
{
"service": {
"name": "web",
"port": 8080,
"connect": {
"sidecar_service": {
"proxy": {
"upstreams": [
{
"destination_name": "socat",
"local_bind_port": 9191
}
]
}
}
}
}
}
This registers a sidecar proxy for the service "web", and will listen on port 9191 to establish mTLS connections to "socat".
> consul reload
如果我们起一个真实的服务去访问代理,代理将加密数据并通过网络发送给 socat 的 sidecar proxy,socat 的 sidecar proxy 会解密并发送线 socat 服务(8181端口)。 Because there is no web service running, you will pretend to be the web service by talking to its proxy on the port that we specified (9191).
所以现在是这样(通过 UI 查看的):
- socat 在 8181 端口运行
- socat proxy 是默认给了一个端口,在 21000
- web 运行在 8080
- web proxy 默认给的端口,是 21001
- web (下游服务) 依赖于(要调用) socat (上游服务),现在是配在监听 9191 去调 socat
此时,命令行中 run nc 127.0.0.1 9191
是连接不上的。执行下面的语句
> consul connect proxy -sidecar-for web
然后再执行 nc 127.0.0.1 9191
即可以连接上了。证明,配置文件生效了。
Control Communication with Intentions
intention
命令定义了哪些 services 之间允许交流,上面默认是用了 allow all
。它用的是 service name 进行操作,而不是 IP 和 端口。如:
- 创建 web, socat 的关系为 deny
> consul intention create -deny web socat
Created: web => socat (deny)
这个命令明确禁止了 web 与 socat 服务的访问关系。执行了后,再次尝试 nc 127.0.0.1 9191
进行访问将会失败
- 删除创建的 web, socat 关系
> consul intention delete web socat
此时再执行 nc 127.0.0.1 9191
又可以访问成功
总结
这里我们学习了如何配置一个服务的自动发现。
知道了 connect.sidecar_service
字段是设置边车服务,这个对象设置为空会使用默认值;里面再加上字段 proxy.upstreams
可以设置它的上游服务(会调用的,依赖的服务)指定了端口和服务名。(没理解这个 9191 是什么意思)
另外地,也学到了一些工具,如 socat
工具和 nc
工具。
参考: https://www.consul.io/docs/connect/registration/sidecar-service.html 其中,解释了 sidecar-service 的模式与等效配置,即相当于配了一个 "name": "web-sidecar-proxy", "kind": "connect-proxy"
的服务。
参考:https://www.consul.io/docs/connect/registration/service-registration.html#upstream-configuration-reference 中解释了 “ local_bind_port
(int:
- Specifies the port to bind a local listener to for the application to make outbound connections to this upstream.” 即, 这个字段为上游服务(在 8181)指定了一个新端口 (9191),因为现在是都在本地,所以 两者都是暴露的,之后用容器的话, 8181 应该是要隐藏在容器中的
这里只做了简单的入门操作,以便更能理解一些技术文章中的操作,可以再参考其他文章以加深理解:
- https://blog.csdn.net/buxiaoxia/article/details/69788114 (浅)
- https://blog.csdn.net/liuzhuchen/article/details/81913562 (深)
- https://legacy.gitbook.com/book/vincentmi/consul-guide/details (指导pdf)