53

高可用的SSL consul cluster实践

 4 years ago
source link: https://www.tuicool.com/articles/yA36Nzy
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

同事dnsmasq + consul 整服务自动发现,但是不是tls且consul server是单点,而且进程启动用的nohub而不是systemd,这里查了下资料实践了下

开了五台云主机,总体规划为下面,角色那有条件的可以分开,例如client单独一台

IP Hostname CPU Memory role nodeName 172.19.0.3 consul1 4 8G server consul 172.19.0.6 consul2 4 8G server consul2 172.19.0.8 consul3 4 8G server consul3 172.19.0.4 consul4 2 4G client client1 172.19.0.10 consul5 2 4G client client2

利用Consul提供的服务实现服务的注册与发现,需要建立Consul Cluster。在Consul方案中,每个提供服务的节点上都要部署和运行Consul的agent,所有运行Consul agent节点的集合构成Consul Cluster。Consul agent有两种运行模式:Server和Client。这里的Server和Client只是Consul集群层面的区分,与搭建在Cluster之上 的应用服务无关。以Server模式运行的Consul agent节点用于维护Consul集群的状态,官方建议每个Consul Cluster至少有3个或以上的运行在Server mode的Agent,Client节点不限。

文章很多步骤基本上都是在 172.19.0.3 上执行的,文件到其他机器的copy和配置文件修改自行整

下载最新版本并解压

目前最新版是1.6.1,下载页面 https://www.consul.io/downloads.html

wget https://releases.hashicorp.com/consul/1.6.1/consul_1.6.1_linux_amd64.zip
unzip -x consul_1.6.1_linux_amd64.zip
mv consul /usr/local/bin/

tls

step 1: 创建ca

为了简单起见,这里我使用Consul的内置TLS助手来创建基本的CA。您只需为数据中心创建一个CA。您应该在用于创建CA的同一服务器上生成所有证书。

ca默认五年,其他的证书默认1年,这里需要带参数 -days= 设置长点的日期

consul tls ca create -days=36500
==> Saved consul-agent-ca.pem
==> Saved consul-agent-ca-key.pem
  • CA证书consul-agent-ca.pem包含验证Consul证书所需的公钥,因此必须分发给运行consul代理的每个节点。
  • CA密钥,consul-agent-ca-key.pem将用于为Consul节点签署证书,并且必须保持私有。拥有此密钥,任何人都可以将Consul作为受信任的服务器运行,并访问所有Consul数据,包括ACL令牌。

step2: 创建server角色的证书

这里数据中心默认名字为dc1,其他的自行选项赋值。在创建CA的同一台服务器上重复此过程,直到每台服务器都有一个单独的证书。该命令可以反复调用,它将自动增加证书和密钥号。您将需要将证书分发到服务器。

因为我有三个consul server,所以执行三次

$ consul tls cert create -server -dc=dc1 -days=36500
==> WARNING: Server Certificates grants authority to become a
    server and access all state in the cluster including root keys
    and all ACL tokens. Do not distribute them to production hosts
    that are not server nodes. Store them as securely as CA keys.
==> Using consul-agent-ca.pem and consul-agent-ca-key.pem
==> Saved dc1-server-consul-0.pem
==> Saved dc1-server-consul-0-key.pem
$ consul tls cert create -server -dc=dc1 -days=36500
==> WARNING: Server Certificates grants authority to become a
    server and access all state in the cluster including root keys
    and all ACL tokens. Do not distribute them to production hosts
    that are not server nodes. Store them as securely as CA keys.
==> Using consul-agent-ca.pem and consul-agent-ca-key.pem
==> Saved dc1-server-consul-1.pem
==> Saved dc1-server-consul-1-key.pem
$ consul tls cert create -server -dc=dc1 -days=36500
==> WARNING: Server Certificates grants authority to become a
    server and access all state in the cluster including root keys
    and all ACL tokens. Do not distribute them to production hosts
    that are not server nodes. Store them as securely as CA keys.
==> Using consul-agent-ca.pem and consul-agent-ca-key.pem
==> Saved dc1-server-consul-2.pem
==> Saved dc1-server-consul-2-key.pem
  • 为了对Consul服务器进行身份验证,服务器会提供一种特殊的证书-包含server.dc1.consul在中 Subject Alternative Name 。如果启用 verify_server_hostname ,则仅允许提供此类证书的代理作为服务器引导。没有 verify_server_hostname = true 攻击者,可能会破坏Consul客户端代理,并以服务器身份重新启动该代理,以便访问您数据中心中的所有数据!这就是服务器证书很特殊的原因,只有服务器才应配置它们。

step3: 创建client角色的证书

在Consul 1.5.2中,您可以使用替代过程来自动将证书分发给客户端。要启用此新功能,请设置 auto_encrypt

您可以继续使用生成证书 consul tls cert create -client 并手动分发证书。对于需要高度保护的数据中心,仍然需要现有的工作流程。

如果您正在运行Consul 1.5.1或更早版本,则需要使用来为每个客户端创建单独的证书 consul tls cert create -client 。客户端证书也由您的CA签名,但是它们没有特殊性 Subject Alternative Name ,这意味着如果 verify_server_hostname 启用,则它们不能作为server角色启动。

这里我是高于1.5.2的,不需要为每个客户端创建证书,客户端只需要拥有 consul-agent-ca.pem 这个ca下,会自动从server获取证书存在内存中,并且不会持久保存。但是我测试了并没有成功,还是生成了证书

$ consul tls cert create -client -days=36500
==> Using consul-agent-ca.pem and consul-agent-ca-key.pem
==> Saved dc1-client-consul-0.pem
==> Saved dc1-client-consul-0-key.pem
$ consul tls cert create -client -days=36500
==> Using consul-agent-ca.pem and consul-agent-ca-key.pem
==> Saved dc1-client-consul-1.pem
==> Saved dc1-client-consul-1-key.pem

文件列表

$ ll
total 39088
-rw-r--r-- 1 root root 39965581 Sep 13 04:30 consul_1.6.1_linux_amd64.zip
-rw-r--r-- 1 root root      227 Oct 11 10:36 consul-agent-ca-key.pem
-rw-r--r-- 1 root root     1249 Oct 11 10:36 consul-agent-ca.pem
-rw-r--r-- 1 root root      227 Oct 11 11:47 dc1-cli-consul-0-key.pem
-rw-r--r-- 1 root root     1082 Oct 11 11:47 dc1-cli-consul-0.pem
-rw-r--r-- 1 root root      227 Oct 11 14:13 dc1-client-consul-0-key.pem
-rw-r--r-- 1 root root     1139 Oct 11 14:13 dc1-client-consul-0.pem
-rw-r--r-- 1 root root      227 Oct 11 17:35 dc1-client-consul-1-key.pem
-rw-r--r-- 1 root root     1143 Oct 11 17:35 dc1-client-consul-1.pem
-rw-r--r-- 1 root root      227 Oct 11 10:42 dc1-server-consul-0-key.pem
-rw-r--r-- 1 root root     1139 Oct 11 10:42 dc1-server-consul-0.pem
-rw-r--r-- 1 root root      227 Oct 11 10:43 dc1-server-consul-1-key.pem
-rw-r--r-- 1 root root     1139 Oct 11 10:43 dc1-server-consul-1.pem
-rw-r--r-- 1 root root      227 Oct 11 10:43 dc1-server-consul-2-key.pem
-rw-r--r-- 1 root root     1139 Oct 11 10:43 dc1-server-consul-2.pem

server和client以及cli的配置

配置优先级按以下顺序评估:

  • 命令行参数
  • 环境变量
  • 配置文件
    加载配置时,Consul会以词法顺序从文件和目录中加载配置。例如,配置文件 basic_config.json 将在之前处理 extra_config.json 。配置可以采用HCL或JSON格式。HCL支持在Consul 1.0和更高版本中可用,现在需要在所有配置文件上使用.hcl或 .json扩展名以指定其格式。
    consul默认从路径 /consul/config 读取配置信息,为了规范,配置文件我路径定义为 /etc/consul.d/ ,数据目录定义为 /var/lib/consul/
    所有flag的解释可以参考 https://www.cnblogs.com/sunsky303/p/9209024.html
    consul的参数可以命令行指定,也可以写json文件里,为了规范,命令行参数尽量少写,大体的配置信息都写json文件里。总体目录结构为下面,这里
    $ tree /etc/consul.d/
    /etc/consul.d/
    ├── cli
    │   ├── path.sh //cli需要的环境变量
    │   └── ssl
    │       ├── dc1-cli-consul-0-key.pem
    │       └── dc1-cli-consul-0.pem
    ├── consul-agent-ca.pem
    └── server
        ├── conf.json
        └── ssl
            ├── dc1-server-consul-0-key.pem //第一台server对应0的证书,第二个就是1
            └── dc1-server-consul-0.pem     //同上,下面的配置文件里指定的文件名也要一致
    

server

/etc/consul.d/server/conf.json 配置内容为,缺省client_addr为127.0.0.1,如果是专门的机器跑consul这里需要修改为bind住 0.0.0.0 或者多网卡下专门指定的ip

关于bootstrap的解释见文档 https://www.consul.io/docs/install/bootstrapping.html

{
  "data_dir": "/var/lib/consul/server",
  "datacenter": "dc1",
  "log_level": "INFO",
  "bootstrap_expect": 3, //数量等同于期望组件集群的最小数量
  "bind_addr": "0.0.0.0",
  "client_addr": "0.0.0.0",
  "verify_incoming": true,
  "verify_outgoing": true,
  "verify_server_hostname": true,
  "auto_encrypt": {
    "allow_tls": true
  },
  "ca_file": "/etc/consul.d/consul-agent-ca.pem",
  "cert_file": "/etc/consul.d/ssl/dc1-server-consul-0.pem",
  "key_file": "/etc/consul.d/ssl/dc1-server-consul-0-key.pem",
  "ports": {
    "http": -1,
    "https": 8501
  }
}

client

client的配置 /etc/consul.d/client/conf.json

{
 "data_dir": "/var/lib/consul/client",
 "datacenter": "dc1",
 "bind_addr": "0.0.0.0",
 "retry_join": ["172.19.0.3"],
 "retry_interval": "3s",
 "rejoin_after_leave": true,
 "enable_script_checks": true,
 "verify_incoming": true,
 "ca_file": "/etc/consul.d/consul-agent-ca.pem",
 "cert_file": "/etc/consul.d/client/ssl/dc1-client-consul-0.pem",
 "key_file": "/etc/consul.d/client/ssl/dc1-client-consul-0-key.pem",
 "auto_encrypt": {
    "tls": true
  },
  "ports": {
    "http": -1,
    "https": 8501
  }
}

cli

consul当作cli使用的时候也得走tls,不然会下面报错

$ consul members
Error retrieving members: Get http://127.0.0.1:8500/v1/agent/members?segment=_all: dial tcp 127.0.0.1:8500: connect: connection refused

路径根据实际来,证书最好是绝对路径,cli默认操作localhost上运行的consul,例如使用 consul leave 会让当前的consul退出集群

export CONSUL_HTTP_ADDR=https://localhost:8501
export CONSUL_CACERT=consul-agent-ca.pem
export CONSUL_CLIENT_CERT=dc1-cli-consul-0.pem
export CONSUL_CLIENT_KEY=dc1-cli-consul-0-key.pem
CONSUL_HTTP_ADDR
CONSUL_CACERT
CONSUL_CLIENT_CERT
CONSUL_CLIENT_KEY

启动

server启动参数为

consul agent -server -config-dir=/etc/consul.d/server -node $nodeName

设置的 bootstrap_expect 为3,所以server达到了3以上的时候才会选举

client启动参数为

consul agent  -config-dir=/etc/consul.d/client -node $nodeName

建议写成systemd而不是使用lowb的nohub啥的

$ consul members
Node     Address          Status  Type    Build  Protocol  DC   Segment
consul   172.19.0.3:8301  alive   server  1.6.1  2         dc1  <all>
consul2  172.19.0.6:8301  alive   server  1.6.1  2         dc1  <all>
consul3  172.19.0.8:8301  alive   server  1.6.1  2         dc1  <all>
client1  172.19.0.4:8301  alive   client  1.6.1  2         dc1  <default>
client2  172.19.0.10:8301  alive   client  1.6.1  2         dc1  <default>
$ consul operator raft list-peers
Node     ID                                    Address          State     Voter  RaftProtocol
consul3  323391a3-4063-5518-b178-777bc7d9104c  172.19.0.8:8300  leader    true   3
consul   30101b0f-24e5-841e-3ce6-92696363a70d  172.19.0.3:8300  follower  true   3
consul2  47a0d401-82fb-cf9b-29fa-3670d587442b  172.19.0.6:8300  follower  true   3

服务发现

client+服务发现的配置可以直接写 /etc/consul.d/client 下面json文件,例如mysql.json

{
  "services": [
    {
      "name": "r-3306-mysql",
      "tags": [
        "slave-3306"
      ],
      "address": "172.16.0.2",
      "port": 3306,
      "checks": [
        {
          "args": ["echo"], //实际应该写健康检查脚本
          "interval": "10s"
        }
      ]
    }
  ]
}

consul client相关日志

2019/10/11 16:28:20 [INFO] agent: Synced service "r-3306-mysql"
2019/10/11 16:28:21 [INFO] agent: Synced node info
2019/10/11 16:28:25 [INFO] agent: Synced check "service:r-3306-mysql"

测试域名解析

$ dig @172.19.0.3 -p 8600 r-3306-mysql.service.consul +short
172.16.0.2

可配置其他的dns server转发到consul上,参考文档 https://learn.hashicorp.com/consul/security-networking/forwarding

参考:

tls步骤参考 https://learn.hashicorp.com/consul/security-networking/certificates

tls官方的文档(太过简陋可以不看) https://www.consul.io/docs/commands/tls/cert.html

集群搭建&简单功能测试&故障恢复: https://blog.csdn.net/chenchong08/article/details/77885989

token+openssl的tls: https://www.digitalocean.com/community/tutorials/how-to-secure-consul-with-tls-encryption-on-ubuntu-14-04


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK