[TOCM]
Consul版本 v0.9.2
1. 配置
1.1 CLI配置
Consul Agent有各种各样的配置项可以在命令行或者配置文件进行定义,所有的配置项都是可选择的,当加载配置文件的时候,Consul从配置文件或者配置目录加载配置。后面定义的配置会合并前面定义的配置,但是大多数情况下,合并的意思是后面定义的配置会覆盖前面定义的配置,但是有些情况,例如event句柄,合并仅仅是添加到前面定义的句柄后面。Consul重新加载配置文件也支持以信号的方式接收update信号。
- -advertise:通知展现地址用来改变我们给集群中的其他节点展现的地址,一般情况下-bind地址就是展现地址
- -bootstrap:用来控制一个server是否在bootstrap模式,在一个datacenter中只能有一个server处于bootstrap模式,当一个server处于bootstrap模式时,可以自己选举为raft leader。
- -bootstrap-expect:在一个datacenter中期望提供的server节点数目,当该值提供的时候,consul一直等到达到指定sever数目的时候才会引导整个集群,该标记不能和bootstrap公用
- -bind:该地址用来在集群内部的通讯,集群内的所有节点到地址都必须是可达的,默认是0.0.0.0
- -client:consul绑定在哪个client地址上,这个地址提供HTTP、DNS、RPC等服务,默认是127.0.0.1
- -config-file:明确的指定要加载哪个配置文件
- -config-dir:配置文件目录,里面所有以.json结尾的文件都会被加载
- -data-dir:提供一个目录用来存放agent的状态,所有的agent允许都需要该目录,该目录必须是稳定的,系统重启后都继续存在
- -dc:该标记控制agent允许的datacenter的名称,默认是dc1
- -encrypt:指定secret key,开启gossip加密,使consul在通讯时进行加密,同一个集群中的节点必须使用相同的key。
key必须是16bytes长度的base64加密,也可以通过consul keygen直接产生一个。生成secret key的方法
root@server1:~# consul keygen
WAFhifMUpMk0IISXSOQnhw==
- -join:加入一个已经启动的agent的ip地址,可以多次指定多个agent的地址。如果consul不能加入任何指定的地址中,则agent会启动失败,默认agent启动时不会加入任何节点。
- -retry-join:和join类似,但是允许你在第一次失败后进行尝试。
- -retry-interval:两次join之间的时间间隔,默认是30s
- -retry-max:尝试重复join的次数,默认是0,也就是无限次尝试
- -log-level:consul agent启动后显示的日志信息级别。默认是info,可选:trace、debug、info、warn、err。
- -node:节点在集群中的名称,在一个集群中必须是唯一的,默认是该节点的主机名
- -protocol:consul使用的协议版本
- -rejoin:使consul忽略先前的离开,在再次启动后仍旧尝试加入集群中。
- -server:定义agent运行在server模式,每个集群至少有一个server,建议每个集群的server不要超过5个
- -syslog:开启系统日志功能,只在linux/osx上生效
- -ui-dir:提供存放web ui资源的路径,该目录必须是可读的
- -pid-file:提供一个路径来存放pid文件,可以使用该文件进行SIGINT/SIGHUP(关闭/更新)agent
1.2 FILE配置
除了命令行参数外,配置也可以写入文件中,启动时候使用-config-file参数。
在某些情况下配置文件会更简单一些,例如:Consul被用来管理系统。配置文件是json格式的,很容易编写。配置文件不仅被用来设置Agent的启动,也可以用来提供健康检测和服务发现的定义。配置文件的一般格式如下:
{
"datacenter": "consul",
"data_dir": "/opt/consul",
"ui": true,
"log_level": "INFO",
"node_name": "consul",
"server": true,
"watches": [
{
"type": "checks",
"handler": "/usr/bin/health-check-handler.sh"
}
]
}
详细的配置文件参数:
- acl_datacenter:只用于server,指定的datacenter的权威ACL信息,所有的servers和datacenter必须同意ACL datacenter
- acl_default_policy:默认是allow
- acl_down_policy:
- acl_master_token:
- acl_token:agent会使用这个token和consul server进行请求
- acl_ttl:控制TTL的cache,默认是30s
- addresses:一个嵌套对象,可以设置以下key:dns、http、rpc
- advertise_addr:等同于-advertise
- bootstrap:等同于-bootstrap
- bootstrap_expect:等同于-bootstrap-expect
- bind_addr:等同于-bind
- ca_file:提供CA文件路径,用来检查客户端或者服务端的链接
- cert_file:必须和key_file一起
- check_update_interval:
- client_addr:等同于-client
- datacenter:等同于-dc
- data_dir:等同于-data-dir
- disable_anonymous_signature:在进行更新检查时禁止匿名签名
- disable_remote_exec:禁止支持远程执行,设置为true,agent会忽视所有进入的远程执行请求
- disable_update_check:禁止自动检查安全公告和新版本信息
- dns_config:是一个嵌套对象,可以设置以下参数:allow_stale、max_stale、node_ttl 、service_ttl、enable_truncate
- domain:默认情况下consul在进行DNS查询时,查询的是consul域,可以通过该参数进行修改
- enable_debug:开启debug模式
- enable_syslog:等同于-syslog
- encrypt:等同于-encrypt
- key_file:提供私钥的路径
- leave_on_terminate:默认是false,如果为true,当agent收到一个TERM信号的时候,它会发送leave信息到集群中的其他节点上。
- log_level:等同于-log-level
- node_name:等同于-node
- ports:这是一个嵌套对象,可以设置以下key:dns(dns地址:8600)、http(http api地址:8500)、rpc(rpc:8400)、serf_lan(lan port:8301)、serf_wan(wan port:8302)、server(server rpc:8300)
- protocol:等同于-protocol
- recursor:Address of an upstream DNS server. Can be specified multiple times.
- rejoin_after_leave:等同于-rejoin
- retry_join:等同于-retry-join
- retry_interval:等同于-retry-interval
- server:等同于-server
- server_name:会覆盖TLS CA的node_name,可以用来确认CA name和hostname相匹配
- skip_leave_on_interrupt:和leave_on_terminate比较类似,不过只影响当前句柄
- start_join:一个字符数组提供的节点地址会在启动时被加入
- statsd_addr:
- statsite_addr:
- syslog_facility:当enable_syslog被提供后,该参数控制哪个级别的信息被发送,默认Local0
- ui: 是否启用web ui,不能和底下的ui_dir同时启用,会报错。
- ui_dir:等同于-ui-dir
- verify_incoming:默认false,如果为true,则所有进入链接都需要使用TLS,需要客户端使用ca_file提供ca文件,只用于consul server端,因为client从来没有进入的链接
- verify_outgoing:默认false,如果为true,则所有出去链接都需要使用TLS,需要服务端使用ca_file提供ca文件,consul server和client都需要使用,因为两者都有出去的链接
- watches:watch一个详细名单
Consul Agent支持所有的网络通讯进行加密,关于加密的具体信息可以参考 官方描述 ,有两个分开的系统,一个是gossip流量,一个是RPC。
使用TLS为RPC加密,主要是上面介绍的verify_incoming和verify_outgoing参数来设置。
2. K/V 存储
除了提供服务发现和综合健康检查,Consul还提供了一个易于使用的键/值存储。这可以用来保存动态配置,协助服务协调,建立领导人选举,并启用其他开发人员可以想构建的任何其他内容。
有两种方法可以使用:通过HTTP API和通过CLI API。下面的例子显示使用CLI API
root@server1:~# consul kv get redis/config/minconns
Error! No key exists at: redis/config/minconns
你将看到没有结果返回,由于KV存储中没有该键返回了一个错误,接下来我们将插入或"put"一个值到KV存储中。
root@server1:~# consul kv put redis/config/minconns 1
Success! Data written to: redis/config/minconns
现在再次查询该键你将看到如下结果:
root@server1:~# consul kv get redis/config/minconns
1
Consul保留额外的元数据在该字段,你可以使用-detailed标志检索详细信息:
root@server1:~# consul kv get -detailed redis/config/minconns
CreateIndex 1049
Flags 0
Key redis/config/minconns
LockIndex 0
ModifyIndex 1049
Session -
Value 1
设置值的时候,还可以使用-flags标志
-
-flags=<uint>
Unsigned integer value to assign to this key-value pair. This value is not read by Consul, so clients can use this value however makes sense for their use case. The default value is 0 (no flags).
flags用来做客户端自定义标志,consul并不使用它,你可以在你自己的程序中随便定义
root@server1:~# consul kv put -flags=42 redis/config/users/admin abcd1234
Success! Data written to: redis/config/users/admin
设置flag值为42,想设置成什么就设置成什么.所有的键都支持设置一个64位的整型值。
使用-recurse选项可以列出KV存储中所有keys,返回的结果将按照字母排序。
root@server1:~# consul kv get -recurse
redis/config/minconns:1
redis/config/users/admin:abcd1234
使用delete命令删除KV存储中指定的key。
root@server1:~# consul kv delete redis/config/minconns
Success! Deleted key: redis/config/minconns
还可以使用recurse选项递归选项删除含某个前缀的所有keys:
root@server1:~# consul kv delete -recurse redis
Success! Deleted keys with prefix: redis
如果要更新一个存在键的值,可以put一个新值在同样的路径上。
root@server1:~# consul kv put foo bar
Success! Data written to: foo
root@server1:~# consul kv get foo
bar
root@server1:~# consul kv put foo zip
Success! Data written to: foo
root@server1:~# consul kv get foo
zip
Consul可以使用Check_And_Set提供原子键更新操作。执行CAS操作时需指定-cas标志。至于什么是CAS,请自行百度吧
-
-modify-index=<uint>
Unsigned integer representing the ModifyIndex of the key. This is used in combination with the -cas flag.
首先查询foo这个key的详细信息
root@server1:~# consul kv get -detailed foo
CreateIndex 1065
Flags 0
Key foo
LockIndex 0
ModifyIndex 1067
Session -
Value zip
看到foo的索引编号ModifyIndex是1067。然后使用CAS操作的方式来修改它
root@server1:~# consul kv put -cas -modify-index=1067 foo bar
Success! Data written to: foo
修改成功,再查询
root@server1:~# consul kv get -detailed foo
CreateIndex 1065
Flags 0
Key foo
LockIndex 0
ModifyIndex 1091
Session -
Value bar
ModifyIndex变成1091了。依然使用上面那个修改命令试试
root@server1:~# consul kv put -cas -modify-index=1067 foo bar
Error! Did not write to foo: CAS failed
失败了。原因是第一次CAS操作成功,因为ModifyIndex的值是1067,我们输入的也是-modify-index=1067。
第二次操作失败,ModifyIndex已经变成1091了,我们还用-modify-index=1067,Check_And_SetS中的Check这步就失败了,不会再Set了。
3. ACL
Access Control List,有没有发现consul web ui是可以直接访问做各种操作的,传说中的登录这种屏障都没有啊。so,需要一个ACL来限制操作权限,就像“登录”了一样。
官方文档:https://www.consul.io/docs/guides/acl.html
3.1 服务端ACL
1.启动consul的all模式时,我的核心配置文件:
{
"acl_datacenter": "dc1",
"acl_master_token": "xxxhelloworldxxx",
"acl_default_policy": "deny" //开启acl
......
}
这三个配置是使用ACL的必须选项
- acl_datacenter:数据中心名称。可填all表示所有的数据中心都启用acl。
- acl_master_token:服务端选举的令牌。这个是自己指定的,随便来一串字符串就可以了。当然如果正式上线则不能随便,可以使用
uuidgen | awk '{print tolower($0)}'
生成,每台主机都不相同。需要在每个server上配置,有management级别的权限,相当于一个种子token用来生成其余token。 - acl_default_policy:默认策略
不配置rule规则的情况下默认值是allow,即能够执行任何操作。(可配置为allow,deny)
当acl_default_policy为deny是,默认的api(写)行为都会被阻止,我们可以配置其子项,让比如配置key可写,这样在全部deny的情况下,出现了一个默认可写的行为,这就是白名单
黑名单反之,当acl_default_policy为allow时,默认行为都是允许的,我们可以配置子项使它某些行为为deny,这就是黑名单的概念
若要开启all,acl_default_policy需要设置成deny - acl_ttl:控制TTL的cache,默认是30s
按这个配置启动带web ui的consul server后,访问 http://10.111.152.242:8500/ui/#/dc1/services ,发现页面是空的,什么都没有,一片空白啊,连个字都没有。同时sever打印日志
2017/09/08 16:04:51 [ERR] http: Request GET /v1/internal/ui/nodes?dc=dc1&token=<hidden>, error: ACL not found from=10.111.152.150:61226
这下连web ui都不让我访问了,报403 forbidden。其实这是个bug,要清理浏览器缓存,然后才能访问web ui。
清理缓存后,可以进入web ui中,但是没法看到service、nodes、kv等信息了,点击ACL,提示
Access Denied
Your ACL token does not have the appropriate permissions to perform the expected action.
同时在server端日志显示
2017/09/08 18:31:10 [ERR] http: Request GET /v1/acl/list?dc=dc1&token=<hidden>, error: Permission denied from=10.111.152.150:57776
说明ACL已经生效了,目前阻止了我们的访问。
2.创建子token
要访问那些被阻止的信息,就要申请token
root@server1:~# curl -H "X-Consul-Token: secret" -X PUT -d '{"Name": "dc1", "Type": "management"}' http://10.111.152.242:8500/v1/acl/create?token=xxxhelloworldxxx
{"ID":"fc6cad19-4323-9a93-4e5a-9d2e00d91360"}
- Name:token的name
- Type:token的类型,有client跟management
- token:我们上面说到的master token
返回这个ID就是我们需要的子token,将这个management权限的token配置在web ui节点的server上,便于管理ACL、k/v、service等
{
"acl_datacenter": "dc1",
"acl_master_token": "xxxhelloworldxxx",
"acl_default_policy": "deny", //开启acl
"acl_token" : "dae1911a-a81f-136b-7ad2-20a65fe98d9d"
......
}
这次重启就可以访问acl了,浏览器缓存别忘了先清理下。这次再访问web ui,就能看到services和nodes都给访问了,点击ACL也能看到列表了。
当然也可以用命令行访问,要加上token
root@server1:~# curl "http://10.111.152.242:8500/v1/internal/ui/nodes?dc=dc1&token=fc6cad19-4323-9a93-4e5a-9d2e00d91360"
[{"ID":"27b5e48b-08f5-9605-434b-dfbfcb7acdb9","Node":"server1","Address":"10.111.152.242","TaggedAddresses":{"lan":"10.111.152.242","wan":"10.111.152.242"},"Meta":{},"Services":[{"ID":"consul","Service":"consul","Tags":null,"Address":"","Port":8300,"EnableTagOverride":false,"CreateIndex":5,"ModifyIndex":5}],"Checks":[{"Node":"server1","CheckID":"serfHealth","Name":"Serf Health Status","Status":"passing","Notes":"","Output":"Agent alive and reachable","ServiceID":"","ServiceName":"","ServiceTags":null,"CreateIndex":5,"ModifyIndex":5}]},{"ID":"ce41eb68-411b-a80f-4e8f-557fb838edb0","Node":"server3","Address":"10.111.152.246","TaggedAddresses":{"lan":"10.111.152.246","wan":"10.111.152.246"},"Meta":{},"Services":[{"ID":"registrator-3:root_web_1:80","Service":"my-web-server","Tags":["backend-3"],"Address":"10.111.152.246","Port":32768,"EnableTagOverride":false,"CreateIndex":9,"ModifyIndex":9}],"Checks":[{"Node":"server3","CheckID":"serfHealth","Name":"Serf Health Status","Status":"passing","Notes":"","Output":"Agent alive and reachable","ServiceID":"","ServiceName":"","ServiceTags":null,"CreateIndex":7,"ModifyIndex":7}]}]
后来我发现,直接把acl_master_token的值复制给acl_token也是可以访问的,哈哈,不用中间生成token那一步了,生了不少事啊。
3.2 客户端ACL
上面我们配置了server端的acl,客户端均链接不上去,日志报
[ERR] consul: RPC failed to server 192.168.56.101:8300: rpc error: Permission denied
这样的错误,显然被server给拒绝了,现在我们要在client节点上配置acl_token,以通过server的验证。
server ACL页面
先回到server的ACL页面。默认ACL有anonymous token,type是client;master token, type是management。现在我们添加一个自定义ACL,命名为client-1,type选择client,然后往rules里面写规则。
rules语法:
规则对象 "" { policy = "read" }
规则对象有:agent、event、key、keyring、node、operator、query、service、session。
read、write、deny是规则权限。
例如,往rules中填入
agent "" { policy = "read" }
这个意思是所有agent的请求都有读的权限。
如果要指定过滤某些特定的标签有写权限,类似白名单,可以这样
规则对象 "过滤名称" { policy = "write" }
例如,对-node=host-2的节点
agent "host-2" { policy = "write" }
多个规则,可以换行排列,例如我的配置
agent "" { policy = "read" }
agent "host-2" { policy = "write" }
service "" { policy = "read" } #
service "" { policy = "write" } #这个可以把client的Service上报到server上去。
node "" { policy = "write" }
event "" { policy = "write" }
query "" { policy = "write" }
看看效果
https://offical.b0.upaiyun.com/static/article/1508904606718228503.png
添加成功的时候,会生成一个token,我这里是a724b77f-1ad6-57e4-c553-127a51d6beda,把它给客户端,准备接入吧。
client节点
到客户端机器上,修改配置文件。acl_master_token只有server端可以配置,客户端只要配置这两个重启下,就可以通过认证了
{
"acl_datacenter": "dc1",
"acl_token": "a724b77f-1ad6-57e4-c553-127a51d6beda"
......
}
在server端的ui上就能看到重新链接上的client上报的信息了。
4. 常见问题
4.1 Failed to get advertise address
Error starting agent: Failed to get advertise address: Multiple private IPs found.
启动的时候加-bind参数绑定ip
consul agent -dev -bind 192.168.231.18
4.2 8500端口没开
检查一下是不是直接连这个端口就会拒绝呢?
ncat -v localhost 8500
或者
nc -v localhost 8500
如果这样连还是『connection refused』说明Consul服务有问题。
参考:
http://bbotte.com/server-config/consul-acl-rule-usage/
创建于 2017-09-08 北京,更新于 2017-10-25 北京
该文章在以下平台同步
- HICOOL.TOP: https://www.hicool.top/article/143
- CSDN:
- 简书: http://www.jianshu.com/p/05741685af33