java学习工作专题

consul 配置/KV/ACL

2017-10-24  本文已影响560人  Liberalman

[TOCM]

Consul版本 v0.9.2

1. 配置

1.1 CLI配置

Consul Agent有各种各样的配置项可以在命令行或者配置文件进行定义,所有的配置项都是可选择的,当加载配置文件的时候,Consul从配置文件或者配置目录加载配置。后面定义的配置会合并前面定义的配置,但是大多数情况下,合并的意思是后面定义的配置会覆盖前面定义的配置,但是有些情况,例如event句柄,合并仅仅是添加到前面定义的句柄后面。Consul重新加载配置文件也支持以信号的方式接收update信号。

root@server1:~# consul keygen
WAFhifMUpMk0IISXSOQnhw==

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"
    }
  ]
}

详细的配置文件参数:

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用来做客户端自定义标志,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,请自行百度吧

首先查询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的必须选项

按这个配置启动带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"}

返回这个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 北京

该文章在以下平台同步

上一篇下一篇

猜你喜欢

热点阅读