Help us learn about your current experience with the documentation. Take the survey.

如何设置 Consul

  • 层级:Premium, Ultimate
  • 提供方式:GitLab 自托管

Consul 集群由 服务器和客户端代理 组成。服务器运行在独立节点上,客户端则运行在其他节点上,并通过与服务器通信来工作。

GitLab Premium 包含一个捆绑版本的 Consul(一种服务网络解决方案),你可以通过 /etc/gitlab/gitlab.rb 来管理它。

前提条件

在配置 Consul 前:

  1. 查看 参考架构 文档,以确定所需的 Consul 服务器节点数量。
  2. 如有必要,确保防火墙中打开了 相应端口

配置 Consul 节点

在每个 Consul 服务器节点上:

  1. 按照 安装说明 选择你偏好的平台安装 GitLab,但在被要求输入 EXTERNAL_URL 时不要填写该值。

  2. 编辑 /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
  3. 重新配置 GitLab,使更改生效。

  4. 运行以下命令,确认 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_filetls_certificate_filetls_key_file
  • 在客户端节点上,当服务器端未启用客户端 TLS 认证(默认启用)时,至少需指定 tls_ca_file;否则,必须通过 tls_certificate_filetls_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_filetls_key_file。当服务器节点使用客户端 TLS 认证时,客户端 TLS 证书和密钥将用于 TLS 认证和入站 HTTPS 连接。

Consul 客户端节点默认不使用客户端 TLS 认证(与服务器相反),若要明确指示其使用,需设置 consul['tls_verify_client'] = true

以下是 TLS 加密的几个示例。

最小TLS支持

在以下示例中,服务器对入站连接使用TLS(无客户端TLS认证)。

  1. 编辑 /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
  2. 重新配置GitLab:

    sudo gitlab-ctl reconfigure

以下配置可在Patroni节点上设置。

  1. 编辑 /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'
  2. 重新配置GitLab:

    sudo gitlab-ctl reconfigure

Patroni与本地Consul代理通信,该代理对入站连接不使用TLS。因此patroni['consul']['url']使用HTTP URL。

默认TLS支持

在以下示例中,服务器使用双向TLS认证。

  1. 编辑 /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'
  2. 重新配置GitLab:

    sudo gitlab-ctl reconfigure

以下配置可在Patroni节点上设置。

  1. 编辑 /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'
  2. 重新配置GitLab:

    sudo gitlab-ctl reconfigure

Patroni与本地Consul代理通信,即使它对Consul服务节点使用TLS认证,该代理对入站连接仍不使用TLS。因此patroni['consul']['url']使用HTTP URL。

完整TLS支持

在以下示例中,客户端和服务端均使用双向TLS认证。

Consul服务端、客户端及Patroni客户端证书必须由同一CA签发,才能实现双向TLS认证。

  1. 编辑 /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'
  2. 重新配置GitLab:

    sudo gitlab-ctl reconfigure

以下配置可在Patroni节点上设置。

  1. 编辑 /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
  2. 重新配置GitLab:

    sudo gitlab-ctl reconfigure

Gossip加密

Gossip协议可加密以保障Consul代理间的通信安全。默认未启用加密,若需启用则需共享加密密钥。为方便起见,可通过gitlab-ctl consul keygen命令生成密钥。密钥长度需为32字节,采用Base 64编码,且需在各代理间共享。

以下选项适用于客户端和服务端节点。

若要启用Gossip协议:

  1. 编辑 /etc/gitlab/gitlab.rb

    consul['encryption_key'] = <base-64-key>
    consul['encryption_verify_incoming'] = true
    consul['encryption_verify_outgoing'] = true
  2. 重新配置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 consul

Consul节点通过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 consul

Consul节点无法通信

默认情况下,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

修复方法:

  1. 为每个节点选择一个地址,其他所有节点均可通过该地址访问此节点。

  2. 更新/etc/gitlab/gitlab.rb

    consul['configuration'] = {
      ...
      bind_addr: 'IP ADDRESS'
    }
  3. 重新配置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。请配置一个。

修复方法如下:

  1. 选择一个该节点上的地址,其他所有节点都能通过这个地址访问此节点。

  2. 更新你的 /etc/gitlab/gitlab.rb

    consul['configuration'] = {
      ...
      bind_addr: 'IP 地址'
    }
  3. 重新配置 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 指南 来恢复失败的集群。