consul 配置/KV/ACL

[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 北京

该文章在以下平台同步

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容