Consul 集群带ACL控制搭建

1.机器规划

我这里起了四台虚拟机,三台用作Server agent,一台用作Client agent。(说明:当然Client可以配置多个,这里由于开太多虚拟机比较耗费资源,就只设置了一个。)
机器ip(机器名) http端口(其他端口使用默认值) Agent类型 节点名称
10.211.55.28 node1 8500 server consul-server1
10.211.55.25 node2 8500 server consul-server2
10.211.55.26 node3 8500 server consul-server3
10.211.55.27 node4 7110 client 带ui consul-client1

2.先配置好三个Server,并启动一遍。

consul-server1.json
{
    "datacenter":"dc1",
    "primary_datacenter":"dc1",
    "bootstrap_expect":1,
    "start_join":[
        "10.211.55.25",
        "10.211.55.26"
    ],
    "retry_join":[
        "10.211.55.25",
        "10.211.55.26"
    ],
    "advertise_addr": "10.211.55.28",
    "bind_addr": "10.211.55.28",
    "server":true,
    "connect":{
        "enabled":true
    },
    "node_name":"consul-server1",
    "data_dir":"/opt/consul/data/",
    "enable_script_checks":false,
    "enable_local_script_checks":true,
    "log_file":"/opt/consul/log/",
    "log_level":"info",
    "log_rotate_bytes":100000000,
    "log_rotate_duration":"24h",
    "encrypt":"krCysDJnrQ8dtA7AbJav8g==",
    "acl":{
        "enabled":true,
        "default_policy":"deny",
        "enable_token_persistence":true,
        "tokens":{
            "master":"cd76a0f7-5535-40cc-8696-073462acc6c7"
           }
    }
}

consul-server2.json

{
    "datacenter":"dc1",
    "primary_datacenter":"dc1",
    "advertise_addr":  "10.211.55.25",
    "bind_addr": "10.211.55.25",
    "server":true,
    "connect":{
        "enabled":true
    },
    "node_name":"consul-server2",
    "data_dir":"/opt/consul/data/",
    "enable_script_checks":false,
    "enable_local_script_checks":true,
    "log_file":"/opt/consul/log/",
    "log_level":"info",
    "log_rotate_bytes":100000000,
    "log_rotate_duration":"24h",
    "encrypt":"krCysDJnrQ8dtA7AbJav8g==",
    "acl":{
        "enabled":true,
        "default_policy":"deny",
        "enable_token_persistence":true,
        "tokens":{
            "master":"cd76a0f7-5535-40cc-8696-073462acc6c7"
        }
    }
}

consul-server3.json

{
    "datacenter":"dc1",
    "primary_datacenter":"dc1",
    "advertise_addr":"10.211.55.26",
    "bind_addr":"10.211.55.26",
    "server":true,
    "connect":{
        "enabled":true
    },
    "node_name":"consul-server3",
    "data_dir":"/opt/consul/data/",
    "enable_script_checks":false,
    "enable_local_script_checks":true,
    "log_file":"/opt/consul/log/",
    "log_level":"info",
    "log_rotate_bytes":100000000,
    "log_rotate_duration":"24h",
    "encrypt":"krCysDJnrQ8dtA7AbJav8g==",
    "acl":{
        "enabled":true,
        "default_policy":"deny",
        "enable_token_persistence":true,
        "tokens":{
            "master":"cd76a0f7-5535-40cc-8696-073462acc6c7"
           }
    }
}


可以看到,consul-server2和consul-server3的配置类似,只是换了下ip和端口;另外consul-server1主要是多了开始连接和重试连接等配置。
接着,启动集群:
在机器10.2111.55.25 (node2)上执行,./consul agent -config-file start-conf/consul-server2.json
在机器10.2111.55.26 (node3)上执行,./consul agent -config-file start-conf/consul-server3.json
在机器10.2111.55.28 (node1)上执行,./consul agent -config-file start-conf/consul-server1.json

3.生成并配置agent-token,解决server agent ACL block问题

当上面的语句执行完之后,会发现协调更新由于ACL被阻塞。如下图:

经过查看官方文档,发现是由于未生成和配置agent-token导致。

在任意一台server上执行下面的语句来生成agent-token:

curl \
    --request PUT \
    --header "X-Consul-Token: cd76a0f7-5535-40cc-8696-073462acc6c7" \
    --data \
'{
  "Name": "Agent Token",
  "Type": "client",
  "Rules": "node \"\" { policy = \"write\" } service \"\" { policy = \"read\" }"
}' http://127.0.0.1:8500/v1/acl/create

此时会返回生成的agent-token

将生成的agent_token设置到每个server agent的配置文件中。
此时consul-server1.json, consul-server2.json, consul-server3.json中acl部分就变为:

"acl":{
        "enabled":true,
        "default_policy":"deny",
        "enable_token_persistence":true,
        "tokens":{
            "master":"cd76a0f7-5535-40cc-8696-073462acc6c7",
             "agent":"deaa315d-98c5-b9f6-6519-4c8f6574a551"
        }
    }

也就是多了agent这个配置。

接着一次重启各个server agent(把之前的进程先停掉)
在机器10.2111.55.25 (node2)上执行,./consul agent -config-file start-conf/consul-server2.json
在机器10.2111.55.26 (node3)上执行,./consul agent -config-file start-conf/consul-server3.json
在机器10.2111.55.28 (node1)上执行,./consul agent -config-file start-conf/consul-server1.json

等server agent集群稳定下来之后,我们会看到之前的ACL block已经解决。

4.启动一个带ui的client agent

{
    "datacenter":"dc1",
    "primary_datacenter":"dc1",
    "advertise_addr": "10.211.55.27",
    "start_join":[
         "10.211.55.25",
        "10.211.55.26",
        "10.211.55.28"
    ],
    "retry_join":[
         "10.211.55.25",
        "10.211.55.26",
        "10.211.55.28"
    ],
    "bind_addr":"10.211.55.27",
    "node_name":"consul-client1",
    "client_addr":"0.0.0.0",
    "connect":{
        "enabled":true
    },
    "data_dir":"/opt/consul/data/",
    "log_file":"/opt/consul/log/",
    "log_level":"info",
    "log_rotate_bytes":100000000,
    "log_rotate_duration":"24h",
    "encrypt":"krCysDJnrQ8dtA7AbJav8g==",
    "ui":true,
    "enable_script_checks":false,
    "enable_local_script_checks":true,
    "disable_remote_exec":true,
    "ports":{
        "http":7110
    },
    "acl":{
        "enabled":true,
        "default_policy":"deny",
        "enable_token_persistence":true,
        "tokens":{
	    "agent":"deaa315d-98c5-b9f6-6519-4c8f6574a551"
        }
    }
}

上面的配置主要是多了ui,表明带web-ui(可以在浏览器中查看)。
另外也是设置了第三步中生成的agent token。
在机器10.2111.55.27 (node4)上执行,./consul agent -config-file start-conf/consul-client1.json

5.配置环境变量。

经过前面一番配置,本以为已经搞定了所有东西,此时只想摸摸自己帅气的头发。 可一执行./consul members, 想看看我这里都有哪些成员,居然发现一个都没有

经过查看官方文档及搜索,发现是没有配置环境变量导致。
1.给三个server的环境变量添加CONSUL_HTTP_TOKEN, vim /etc/profile添加下面一句

export CONSUL_HTTP_TOKEN=cd76a0f7-5535-40cc-8696-073462acc6c7

然后,source /etc/profile一下。
为了简单方便,我这里配了最大的权限即master_token
此时发现./consul members已经有数据了

2.给client agent 设置环境变量
由于client agent 带web-ui,这里你的公司不一定对外开放8500端口,所以我这里把它改成了7110,方便在外网查看。
不过此时需要添加一个环境变量CONSUL_HTTP_ADDR,来告诉命令行不是使用默认的127.0.0.1:8500
更改client-agent的环境变量,在最后添加下面两行

#consul http-token
export CONSUL_HTTP_TOKEN=cd76a0f7-5535-40cc-8696-073462acc6c7
#only consul-client1 need, because http port has changed to 7110
export CONSUL_HTTP_ADDR=127.0.0.1:7110

此时发现在client agent上执行./consul members也是ok的。

6.给web-ui 设置master_token

在client-agent上,输入127.0.0.1:7110, 点击ACL, 输入master-token即可。如下图:

7.搭建单机3节点集群

在上一步的过程中,搭建了一个3节点集群,但是这种方式需要较多数量的服务器,成本方面来说不太友好。在使用过程中出于成本考虑,需要使用一个3节点集群,但因为在网上没有找到类似的教程来搭建单机3节点的教程,只能查看官方文档中一些配置详解来实现单机3节点,以下是搭建方式。

1、简单规划

节点用途 节点主机IP 节点客户端HTTP端口 节点DNS端口 节点serf_lan端口 节点serf_wan端口 节点server端口
Consul-Server1 10.100.0.2 8501 8601 8001 8002 8000
Consul-Server2 10.100.0.2 8502 8602 8101 8102 8100
Consul-Server3 10.100.0.2 8503 8603 8201 8202 8200
Consul-Agent 10.100.0.2 8500(默认) 8600(默认) - - -

a、创建相应目录,配置多节点
创建各节点目录:

cd /data/services/consul
mkdir -p node{1..3}/{bin,conf,data,log}
mkdir -p agent/{bin,conf,data,log}

创建完成后,目录结构大致如下:

tree
.
├── agent
│   ├── bin
│   ├── conf
│   ├── data
│   │   └── serf
│   └── log
├── node1
│   ├── bin
│   ├── conf
│   ├── data
│   │   ├── raft
│   │   │   └── snapshots
│   │   └── serf 
│   └── log
├── node2
│   ├── bin
│   ├── conf
│   ├── data
│   │   ├── raft
│   │   │   └── snapshots
│   │   └── serf 
│   └── log
└── node3
    ├── bin
    ├── conf
    ├── data
    │   ├── raft
    │   │   └── snapshots
    |   └── serf
    └── log

将可执行文件复制到各节点的bin目录:

cd /data/services/consul
cp consul node1/bin/
cp consul node1/bin/
cp consul node1/bin/
cp consul agent/bin/

b、创建Consul-Server服务配置文件
以Server1节点为例:

cd /data/services/consul/node1/conf
vim server.json
{
 "bind_addr": "10.100.0.2", 
 "client_addr": "127.0.0.1",
 "ports": {
 "http": 8501,  #其余server节点需要按照规划的端口进行配置
 "dns": 8601,  #其余server节点需要按照规划的端口进行配置
 "serf_lan": 8001,  #其余server节点需要按照规划的端口进行配置
 "serf_wan": 8002,  #其余server节点需要按照规划的端口进行配置
 "server": 8000  #其余server节点需要按照规划的端口进行配置
 },
 "datacenter": "dc1",
 "data_dir": "/data/services/consul/node1/data",  #此处注意目录名称,写对应server节点的目录名称,如:/data/services/consul/node2/data
 "encrypt": "EXz7LFN8hpQ4id8EDYiFoQ==",  #此处需要与其他节点一致
 "log_level": "INFO",
 "log_file": "/data/services/consul/node1/log/consul.log",  #此处注意目录名称,每个节点目录名称不一样
 "log_rotate_duration": "24h",
 "enable_syslog": false,
 "enable_debug": true,
 "node_name": "ConsulServer1",  #此处需要注意,按照规划的名称填写即可
 "disable_host_node_id": true,  #禁用主机信息生成节点ID
 "server": true,
 "ui": true,
 "bootstrap_expect": 3,
 "leave_on_terminate": false,
 "skip_leave_on_interrupt": true,
 "rejoin_after_leave": true,
 "retry_join": [ 
 "10.100.0.2:8001",
 "10.100.0.2:8101",
 "10.100.0.2:8201"
 ]
}

c、创建Consul-Agent配置文件

cd /data/services/consul/agent/conf
vim agent.json
{
 "bind_addr": "0.0.0.0",
 "client_addr": "0.0.0.0",
 "datacenter": "dc1",
 "data_dir": "/data/services/consul/agent/data",
 "encrypt": "EXz7LFN8hpQ4id8EDYiFoQ==",
 "log_level": "INFO",
 "log_file": "/data/services/consul/agent/log/consul.log",
 "log_rotate_duration": "24h",
 "enable_syslog": false,
 "enable_debug": true,
 "node_name": "ConsulClient",
 "ui": true,
 "disable_host_node_id": true,   #禁用主机信息生成的节点ID
 "server": false,
 "rejoin_after_leave": true,
 "retry_join": [
 "10.100.0.2:8001", 
 "10.100.0.2:8101", 
 "10.100.0.2:8201"
 ]
 }

以Server1节点为例,使用如下命令启动:

cd /data/services/consul/node1/bin  #此处注意目录,启动相应的节点需要切换到相应的目录
./consul agent -config-dir=/data/services/consul/node1/conf
==> Starting Consul agent...
 Version: 'v1.7.3'
 Node ID: '0e2d44c2-af33-e222-5eb5-58b2c1f903d5'
 Node name: 'Consul'
 Datacenter: 'dc1' (Segment: '<all>')
 Server: true (Bootstrap: false)
 Client Addr: [10.100.0.2] (HTTP: 8500, HTTPS: -1, gRPC: 8502, DNS: 8600)
 Cluster Addr: 10.100.0.2 (LAN: 8301, WAN: 8302)
 Encrypt: Gossip: true, TLS-Outgoing: false, TLS-Incoming: false, Auto-Encrypt-TLS: false
​
==> Log data will now stream in as it occurs:
​
 2020-06-18T15:11:48.435+0800 [INFO]  agent.server.raft: initial configuration: index=1 servers="[{Suffrage:Voter ID:0e2d44c2-af33-e222-5eb5-58b2c1f903d5 Address:10.100.0.2:8300}]"
​
#部分内容因篇幅被删除,仅保留开头部分

注意:

以上操作需要在每一台节点执行,执行的时候注意切换到相应节点的目录。

1、单节点启动server时不能选举出leader
针对此问题,需要在配置文件中添加如下参数(案例中已经添加):

bootstrap-expect
并且将该参数的值设置为1,如下:

"bootstrap_expect": 1

2、搭建单机3节点能成功启动,但日志中提示未选举出leader,客户端访问报500
此问题的原因是集群中的node节点都使用了同一个node_id(通过分析日志发现的,在节点的通信中都标识了同一个node_id),但在配置文件中又设定了bootstrap-expect的值为3,此时集群中没有足够的投票选举出leader。针对此问题有两种解决方法。

a、方法一:
修改节点data目录下的node-id文件,以Server1节点为例:

cd /data/services/consul/node1/data

使用tree命令查看,目录结构如下:

tree
.
├── checkpoint-signature
├── node-id
├── raft
│   ├── peers.info
│   ├── raft.db
│   └── snapshots
│       ├── 7-131089-1592693864841
│       │   ├── meta.json
│       │   └── state.bin
│       └── 7-147478-1592808873974
│           ├── meta.json
│           └── state.bin
└── serf 

编辑node-id文件:

vim node-id
6905298b-fd50-6423-2c42-1ddaf123e120

注意:

需要将每个Server节点的id改成唯一的,不可与其他Server节点重复。

b、方法二:
从产生问题的根本原因入手,之所以所有节点会有相同的node_id是因为Consul默认使用服务器的主机硬件信息等经过特定的算法生成一个node_id,因为3个Server节点都部署在同一台主机上,所以其node_id都使用了同一个。

解决此问题需要在服务启动时加入如下参数:

disable-host-node-id
在配置文件中添加该参数,并将其值设置为true,如下:

"disable_host_node_id": true

在本文档中搭建Consul单机3节点集群的配置中,已经加入了该配置。

3、使用agent客户端访问webUI查看节点信息,发现每一个节点在webUI中都被标记为leader
原因:webUI中默认使用IP标记leader,由于我们三个节点都在同一主机上,且只有一张网卡,服务监听的IP都是同一个IP,所以在webUI上显示每个节点都被标记成了leader。不影响使用。

排错与确定问题方法:

在主机的agent节点上执行命令行,通过命令行查看集群信息,命令如下:

cd /data/services/consul/agent/bin
./consul operator raft list-peers
Node           ID                                    Address          State     Voter  RaftProtocol
ConsulServer1  6905298b-fd50-6423-2c42-1ddaf123e120  10.100.0.2:8000  follower  true   3
ConsulServer3  e927bbfa-e067-a84f-93ea-6712cf1db7f8  10.100.0.2:8200  follower  true   3
ConsulServer2  38e5b263-b848-dfb6-d197-115ca2da40e7  10.100.0.2:8100  leader    true   3

通过命令行可以看到,集群中3个节点,只有一个节点是leader。

8.参考文章

https://www.consul.io/docs/acl/acl-legacy.html#bootstrapping-acls https://www.consul.io/docs/agent/options.html https://www.consul.io/docs/commands/index.html#environment-variables
posted @ 2020-11-16 18:13  miss520net  阅读(293)  评论(0编辑  收藏  举报