如何设置 Consul
- 层级:Premium, Ultimate
- 提供方式:GitLab 自托管
Consul 集群由 服务器和客户端代理 组成。服务器运行在独立节点上,客户端则运行在其他节点上,并通过与服务器通信来工作。
GitLab Premium 包含一个捆绑版本的 Consul(一种服务网络解决方案),你可以通过 /etc/gitlab/gitlab.rb 来管理它。
前提条件
在配置 Consul 前:
配置 Consul 节点
在每个 Consul 服务器节点上:
-
按照 安装说明 选择你偏好的平台安装 GitLab,但在被要求输入
EXTERNAL_URL时不要填写该值。 -
编辑
/etc/gitlab/gitlab.rb,并按如下所示添加内容(替换retry_join部分标注的值)。下例中有三个节点,其中两个用 IP 表示,一个用 FQDN 表示,你可以任选一种表示方法:# 仅启用 Consul 组件,禁用其他组件 roles ['consul_role'] # Consul 节点:可以是 FQDN 或 IP,用空格分隔 consul['configuration'] = { server: true, retry_join: %w(10.10.10.1 consul1.gitlab.example.com 10.10.10.2) } # 禁用自动迁移 gitlab_rails['auto_migrate'] = false -
重新配置 GitLab,使更改生效。
-
运行以下命令,确认 Consul 配置正确且所有服务器节点正常通信:
sudo /opt/gitlab/embedded/bin/consul members输出应类似如下:
节点 地址 状态 类型 版本 协议 数据中心 CONSUL_NODE_ONE XXX.XXX.XXX.YYY:8301 正常 服务器 0.9.2 2 gitlab_consul CONSUL_NODE_TWO XXX.XXX.XXX.YYY:8301 正常 服务器 0.9.2 2 gitlab_consul CONSUL_NODE_THREE XXX.XXX.XXX.YYY:8301 正常 服务器 0.9.2 2 gitlab_consul如果结果中出现任何状态非
alive的节点,或缺少三个节点中的任何一个,请参阅 故障排除章节。
保护 Consul 节点
有两种方式可保护 Consul 节点间的通信:使用 TLS 或 gossip 加密。
TLS 加密
默认情况下,Consul 集群的 TLS 未启用,默认配置选项及其默认值如下:
consul['use_tls'] = false
consul['tls_ca_file'] = nil
consul['tls_certificate_file'] = nil
consul['tls_key_file'] = nil
consul['tls_verify_client'] = nil这些配置选项适用于服务器和客户端节点。
若要在 Consul 节点上启用 TLS,需从 consul['use_tls'] = true 开始。根据节点角色(服务器或客户端)及你的 TLS 偏好,你可能需要进一步配置:
- 在服务器节点上,至少需指定
tls_ca_file、tls_certificate_file和tls_key_file。 - 在客户端节点上,当服务器端未启用客户端 TLS 认证(默认启用)时,至少需指定
tls_ca_file;否则,必须通过tls_certificate_file和tls_key_file传递客户端 TLS 证书和密钥。
启用 TLS 后,服务器默认使用 mTLS 并监听 HTTPS 和 HTTP(以及 TLS 和非 TLS RPC)。它期望客户端使用 TLS 认证。可通过设置 consul['tls_verify_client'] = false 禁用客户端 TLS 认证。
另一方面,客户端仅对向服务器节点的出站连接使用 TLS,且仅监听 HTTP(和非 TLS RPC)处理入站请求。可通过将 consul['https_port'] 设置为非负整数(Consul 默认 HTTPS 端口为 8501)强制客户端 Consul 代理对入站连接使用 TLS。为此,你必须提供 tls_certificate_file 和 tls_key_file。当服务器节点使用客户端 TLS 认证时,客户端 TLS 证书和密钥将用于 TLS 认证和入站 HTTPS 连接。
Consul 客户端节点默认不使用客户端 TLS 认证(与服务器相反),若要明确指示其使用,需设置 consul['tls_verify_client'] = true。
以下是 TLS 加密的几个示例。
最小TLS支持
在以下示例中,服务器对入站连接使用TLS(无客户端TLS认证)。
-
编辑
/etc/gitlab/gitlab.rb:consul['enable'] = true consul['configuration'] = { 'server' => true } consul['use_tls'] = true consul['tls_ca_file'] = '/path/to/ca.crt.pem' consul['tls_certificate_file'] = '/path/to/server.crt.pem' consul['tls_key_file'] = '/path/to/server.key.pem' consul['tls_verify_client'] = false -
重新配置GitLab:
sudo gitlab-ctl reconfigure
以下配置可在Patroni节点上设置。
-
编辑
/etc/gitlab/gitlab.rb:consul['enable'] = true consul['use_tls'] = true consul['tls_ca_file'] = '/path/to/ca.crt.pem' patroni['consul']['url'] = 'http://localhost:8500' -
重新配置GitLab:
sudo gitlab-ctl reconfigure
Patroni与本地Consul代理通信,该代理对入站连接不使用TLS。因此patroni['consul']['url']使用HTTP URL。
默认TLS支持
在以下示例中,服务器使用双向TLS认证。
-
编辑
/etc/gitlab/gitlab.rb:consul['enable'] = true consul['configuration'] = { 'server' => true } consul['use_tls'] = true consul['tls_ca_file'] = '/path/to/ca.crt.pem' consul['tls_certificate_file'] = '/path/to/server.crt.pem' consul['tls_key_file'] = '/path/to/server.key.pem' -
重新配置GitLab:
sudo gitlab-ctl reconfigure
以下配置可在Patroni节点上设置。
-
编辑
/etc/gitlab/gitlab.rb:consul['enable'] = true consul['use_tls'] = true consul['tls_ca_file'] = '/path/to/ca.crt.pem' consul['tls_certificate_file'] = '/path/to/client.crt.pem' consul['tls_key_file'] = '/path/to/client.key.pem' patroni['consul']['url'] = 'http://localhost:8500' -
重新配置GitLab:
sudo gitlab-ctl reconfigure
Patroni与本地Consul代理通信,即使它对Consul服务节点使用TLS认证,该代理对入站连接仍不使用TLS。因此patroni['consul']['url']使用HTTP URL。
完整TLS支持
在以下示例中,客户端和服务端均使用双向TLS认证。
Consul服务端、客户端及Patroni客户端证书必须由同一CA签发,才能实现双向TLS认证。
-
编辑
/etc/gitlab/gitlab.rb:consul['enable'] = true consul['configuration'] = { 'server' => true } consul['use_tls'] = true consul['tls_ca_file'] = '/path/to/ca.crt.pem' consul['tls_certificate_file'] = '/path/to/server.crt.pem' consul['tls_key_file'] = '/path/to/server.key.pem' -
重新配置GitLab:
sudo gitlab-ctl reconfigure
以下配置可在Patroni节点上设置。
-
编辑
/etc/gitlab/gitlab.rb:consul['enable'] = true consul['use_tls'] = true consul['tls_verify_client'] = true consul['tls_ca_file'] = '/path/to/ca.crt.pem' consul['tls_certificate_file'] = '/path/to/client.crt.pem' consul['tls_key_file'] = '/path/to/client.key.pem' consul['https_port'] = 8501 patroni['consul']['url'] = 'https://localhost:8501' patroni['consul']['cacert'] = '/path/to/ca.crt.pem' patroni['consul']['cert'] = '/opt/tls/patroni.crt.pem' patroni['consul']['key'] = '/opt/tls/patroni.key.pem' patroni['consul']['verify'] = true -
重新配置GitLab:
sudo gitlab-ctl reconfigure
Gossip加密
Gossip协议可加密以保障Consul代理间的通信安全。默认未启用加密,若需启用则需共享加密密钥。为方便起见,可通过gitlab-ctl consul keygen命令生成密钥。密钥长度需为32字节,采用Base 64编码,且需在各代理间共享。
以下选项适用于客户端和服务端节点。
若要启用Gossip协议:
-
编辑
/etc/gitlab/gitlab.rb:consul['encryption_key'] = <base-64-key> consul['encryption_verify_incoming'] = true consul['encryption_verify_outgoing'] = true -
重新配置GitLab:
sudo gitlab-ctl reconfigure
若要在现有数据中心启用加密,需手动设置这些选项以完成滚动更新。
升级Consul节点
要升级您的Consul节点,请升级GitLab软件包。
节点应满足以下条件:
- 在升级Linux软件包之前,属于健康的集群。
- 一次只升级一个节点。
通过在每个节点上运行以下命令识别集群中现有的健康问题。若集群健康,该命令会返回空数组:
curl "http://127.0.0.1:8500/v1/health/state/critical"如果Consul版本已更改,您会在gitlab-ctl reconfigure结束时看到通知,提示您必须重启Consul才能使用新版本。
一次重启一个Consul节点:
sudo gitlab-ctl restart consulConsul节点通过RAFT协议进行通信。如果当前领导者离线,必须进行领导者选举。集群中必须存在领导者节点以促进同步。如果太多节点同时离线,集群会失去法定人数(quorum),无法选举领导者,原因是共识破坏。
若升级后集群无法恢复,请参阅故障排除部分。其中outage recovery可能特别有用。
GitLab仅使用Consul存储易于重新生成、临时的数据。如果捆绑的Consul未被除GitLab本身以外的任何进程使用,您可以从头重建集群。
故障排除Consul
以下是调试问题的操作步骤。
您可以通过运行以下命令查看错误日志:
sudo gitlab-ctl tail consul检查集群成员资格
要确定哪些节点属于集群,请在集群中的任意成员上运行以下命令:
sudo /opt/gitlab/embedded/bin/consul members输出应类似如下:
Node Address Status Type Build Protocol DC
consul-b XX.XX.X.Y:8301 alive server 0.9.0 2 gitlab_consul
consul-c XX.XX.X.Y:8301 alive server 0.9.0 2 gitlab_consul
consul-c XX.XX.X.Y:8301 alive server 0.9.0 2 gitlab_consul
db-a XX.XX.X.Y:8301 alive client 0.9.0 2 gitlab_consul
db-b XX.XX.X.Y:8301 alive client 0.9.0 2 gitlab_consul理想情况下,所有节点的Status均为alive。
重启Consul
若需重启Consul,需以受控方式进行以维持法定人数。若失去法定人数,恢复集群需遵循Consul outage recovery流程。
为确保安全,建议一次只重启一个Consul节点以保证集群完整。对于较大集群,可同时重启多个节点。有关可容忍的故障数量,请参见Consul共识文档,即能承受的同时重启次数。
重启Consul:
sudo gitlab-ctl restart consulConsul节点无法通信
默认情况下,Consul尝试绑定到0.0.0.0,但它会向其他Consul节点广告本节点的第一个私有IP地址以实现通信。若其他节点无法通过此地址与该节点通信,则集群状态异常。
若遇到此问题,gitlab-ctl tail consul会输出类似以下的消息:
2017-09-25_19:53:39.90821 2017/09/25 19:53:39 [WARN] raft: no known peers, aborting election
2017-09-25_19:53:41.74356 2017/09/25 19:53:41 [ERR] agent: failed to sync remote state: No cluster leader修复方法:
-
为每个节点选择一个地址,其他所有节点均可通过该地址访问此节点。
-
更新
/etc/gitlab/gitlab.rb:consul['configuration'] = { ... bind_addr: 'IP ADDRESS' } -
重新配置GitLab:
gitlab-ctl reconfigure
若仍出现错误,可能需要在受影响的节点上擦除Consul数据库并重新初始化。
Consul 无法启动 - 多个私有 IP 地址
如果一个节点有多个私有 IP 地址,Consul 不知道该广告哪个私有地址,随后在启动时立即退出。
在 gitlab-ctl tail consul 中会输出类似下面的消息:
2017-11-09_17:41:45.52876 ==> 启动 Consul 代理...
2017-11-09_17:41:45.53057 ==> 创建代理时出错:获取广告地址失败:发现多个私有 IP。请配置一个。修复方法如下:
-
选择一个该节点上的地址,其他所有节点都能通过这个地址访问此节点。
-
更新你的
/etc/gitlab/gitlab.rbconsul['configuration'] = { ... bind_addr: 'IP 地址' } -
重新配置 GitLab:
gitlab-ctl reconfigure
故障恢复
如果集群中丢失了足够多的 Consul 节点导致失去法定人数(quorum),则认为集群已失败,且无法在没有人工干预的情况下运行。
在这种情况下,你可以选择从头重新创建节点,或尝试恢复。
从头重新创建
默认情况下,GitLab 不会在 Consul 节点上存储任何无法重新创建的内容。若要擦除 Consul 数据库并重新初始化:
sudo gitlab-ctl stop consul
sudo rm -rf /var/opt/gitlab/consul/data
sudo gitlab-ctl start consul之后,该节点应重新启动,其余服务器代理会重新加入。不久后,客户端代理也应重新加入。
如果它们未加入,你可能还需要擦除客户端上的 Consul 数据:
sudo rm -rf /var/opt/gitlab/consul/data恢复失败的节点
如果你利用 Consul 存储了其他数据并想恢复失败的节点,请按照 Consul 指南 来恢复失败的集群。