Consul

一、简介

Consul是一个服务网格(service mesh)解决方案,提供具有服务发现、配置和分段功能的全功能控制平面。这些功能中的每一个都可以根据需要单独使用,也可以一起使用来构建完整的服务网格。Consul需要数据平面并支持代理和原生集成模型。Consul附带一个简单的内置代理开箱即用,也支持Envoy等第三方代理集成。

consul主要特点:

  • Service DiscoveryConsul client可以注册服务,其他client可以使用Consul来发现特定服务的提供者。 使用DNS或HTTP,应用程序可以轻松找到它们所依赖的服务。

  • Health CheckingConsul client可以提供任何数量的健康检查,要么与特定的服务相关("网络服务器是否返回200 OK"),要么与本地节点相关("内存利用率是否低于90%")可以使用此信息来监控集群的健康状况,服务发现组件也可以使用它来路由流量,使其远离不健康的主机。

  • KV Store:应用程序可以利用Consul的分层键/值存储来达到任何目的,包括动态配置、特征标记、协调、leader选举等等。简单的HTTP API使其易于使用。

  • Secure Service Communication:Consul可以为服务生成和分发TLS证书,以建立相互的TLS连接。Intentions可用于定义允许通信的服务。可以用实时改变的intentions来轻松管理服务分割,而不是使用复杂的网络拓扑结构和静态防火墙规则。

  • Multi Datacenter:Consul支持开箱即用的多个数据中心。这意味着Consul的用户不必担心建立额外的抽象层来发展到多个区域。

二、Consul基础架构

生产部署可以参照下面多数据中心架构图进行:

每个为Consul提供服务的节点都运行一个Consul agent。发现其他服务或获取/设置键值数据不需要运行agent。agent负责对节点上的服务以及节点本身进行健康检查。

agent与一个或多个Consul server通信。Consul server是数据存储和复制的地方。这些server自己选出一个leader。虽然Consul可以在一台server上运行,但建议3到5台,以避免导致数据丢失的故障情况。建议每个数据中心有一个Consul server集群。

Consul的服务发现由服务目录(catalog)支持,该目录(catalog)是由agent提交的信息汇总而成的。目录维护集群的高层视图,包括哪些服务是可用的,哪些节点运行这些服务,健康信息等等。该目录用于通过Consul提供的各种接口暴露这些信息,包括DNS和HTTP。与agent相比,目录上下文中的服务和检查的字段更为有限。这是因为目录只负责记录和返回有关服务、节点和健康的信息。目录只由server节点维护。这是因为目录是通过Raft日志复制的,以提供集群的统一和一致的视图。

需要发现其他服务或节点的基础架构组件,可以查询任何Consul server或任何Consul agent。agent会自动将查询转发给server。

每个数据中心运行一个Consul server集群。当一个跨数据中心的服务发现或配置请求被提出时,本地Consul server将请求转发到远程数据中心并返回结果。

一个数据中心中的所有agent都参与了gossip协议。有一个特定的gossip池,包含了一个数据中心的所有agent。这样有几个效果:1、不需要为client配置server的地址;发现是自动完成的。2、检测agent故障的工作不是放在server上,而是分布式的,这使得故障检测比简单的心跳方案更具可扩展性。它还为节点提供了故障检测,如果无法访问agent,则节点可能已发生故障。3、还能用作信息传递层,在发生leader选举等重要事件时进行通知。

每个数据中心的server都是单个Raft对等集的一部分,它们一起工作来选举一个leader。一个被选中的server拥有额外的职责,leader负责处理所有查询和事务。作为consensus协议的一部分,还必须将事务复制到所有对等体,由于这一要求,当非leader的server收到一个RPC请求时,它会转发给集群leader。

server agents也作为WAN gossip池的一部分运行,它与LAN池不同,因为它针对互联网的高延迟进行了优化,预计只包含其他Consul server agents。这个池子的目的是允许数据中心以低接触的方式相互发现。将一个新的数据中心加入集群,只需将它加入现有的WAN gossip池,由于server都在这个池里运行,还可以实现跨数据中心的请求。当一个server收到对不同数据中心的请求时,它会将其转发到正确的数据中心中的一个随机server。然后,该server可以转发到本地leader。

一般来说,数据不会在不同的Consul数据中心之间进行复制。当对另一个数据中心的资源发出请求时,本地Consul server会将RPC请求转发给远程Consul server并返回结果。如果远程数据中心不可用,那么这些资源也将不可用,但这不会影响本地数据中心。

三、Service Mesh(服务网格)

服务网格是一个专用网络层,可在基础架构内和跨基础架构(包括本地和云环境)提供安全的服务到服务通信。服务网格通常与微服务架构模式一起使用,在涉及复杂网络的任何场景中提供价值。

1、优点

从安全性到提高应用程序弹性,服务网络能带来以下好处:

  • 服务发现

  • 应用程序健康监控

  • 负载均衡

  • 自动故障转移

  • 流量管理

  • 加密

  • 可观察性和可追溯性

  • 认证和授权

  • 网络自动化

2、工作原理

Consul Connect 是Consul附带的组件,用于启用服务网格功能。

服务网格通常由控制平面和数据平面组成。控制平面维护一个中央注册表,用于跟踪所有服务及其各自的 IP 地址,这称为服务发现。只要应用程序在控制平面上注册,控制平面就能够与网格的其他成员共享如何与应用程序通信,并强制执行谁可以相互通信的规则。

控制平面负责保护网格、促进服务发现、健康检查、策略实施和其他类似的操作问题。

数据平面处理服务之间的通信。许多服务网格解决方案使用sidecar代理来处理数据平面通信,因此限制了服务对网络环境所需的感知水平。

四、端口详解

Consul需要多达6个不同的端口才能正常工作,其中一些在TCP、UDP或两种协议上。

名称 默认端口 source dest 说明
DNS 8600 client & server client & server DNS接口用于解析DNS查询。(TCP和UDP)
HTTP 8500 client & server client & server HTTP API客户端端口。(TCP)
HTTPS 8501 client & server client & server 默认关闭,HTTPS API客户端端口
gRPC 8502 Envoy proxy 管理 sidecar agent服务注册的client或server 目前gRPC仅用于向Envoy代理公开xDS API,默认关闭。
Serf LAN 8301 client & server client & server 用于LAN gossip通信端口。(TCP和UDP)
Serf WAN 8302 server server server使用该端口通过WAN向server进行gossip通信。(TCP和UDP)
RPC 8300 client & server server server使用该端口处理来自其他agent的传入请求。(TCP)
Sidecar Proxy 21000 client & server 管理 sidecar agent服务注册的client或server 用于自动分配的sidecar服务注册的最小端口号。
Sidecar Proxy 21255 client & server 管理 sidecar agent服务注册的client或server 用于自动分配的sidecar服务注册的最大端口号。

五、安装部署

1、Server端部署

环境准备:

节点名称 IP
consul-server01 10.81.0.101
consul-server02 10.81.0.102
consul-server03 10.81.0.103

  • 安装Consul

    cd /usr/local/src && wget https://releases.hashicorp.com/consul/1.12.0/consul_1.12.0_linux_amd64.zip
    unzip -q consul_1.12.0_linux_amd64.zip -d /usr/bin
    
  • 创建配置文件

    此配置文件只列举常用配置项,更多配置查看官网配置文件详解

    {
        //内部集群通信绑定的地址。集群中所有其他节点都应该可以访问的IP地址。默认是"0.0.0.0"
        "bind_addr": "0.0.0.0",
        //绑定客户端接口的地址,包括HTTP和DNS服务器,默认为"127.0.0.1"
        "client_addr": "0.0.0.0",
        //命名agent运行的数据中心名称,默认dc1,同一数据中心的节点应该在一个LAN上
        "datacenter": "fbg-test-shenzhen",
        //指定存储状态的数据目录,目录属主属组应与consul运行用户一致
        "data_dir": "/data/data/consul",
        //禁用任何传入的远程执行请求
        "disable_remote_exec": true,
        //仅允许在本地配置文件中定义脚本检查。不允许在HTTP API注册中定义的脚本检查。
        "enable_local_script_checks": true,
        "http_config": {
            "response_headers": {
                "Access-Control-Allow-Origin": "*"
            },
            //允许调用agent写入端点的ip列表
            "allow_write_http_from": ["127.0.0.1/32", "10.81.0.0/24", "10.81.32.0/24"]
        },
        //当agent收到TERM信号时,它将向集群的其余部分发送离开消息并优雅地离开。在client模式下,默认true,server模式下,默认false。
        "leave_on_terminate": false,
        //server性能调整
        "performance": {
            //server优雅离开期间停留的持续时间,以便允许对其他server重试请求。
            "leave_drain_time": "10s",
            //调整心跳超时和快速选主的缩放因子
            "raft_multiplier": 3,
            //client或server在领导选举期间重试内部RPC请求的持续时间。
            "rpc_hold_timeout": "10s"
        },
        //控制agent是处于server模式还是client模式,建议每个数据中心server不超过5台
        "server": true,
        //通告地址用于更改我们向集群中其他节点通告的地址。默认bind地址
        "advertise_addr": "10.81.0.101",
        //通告WAN地址用于更改我们向server节点通告的地址
        "advertise_addr_wan": "47.254.131.144",
        //数据中心中预期的server的数量,Consul会等待指定数量的server可用,然后引导集群自动选举初始leader,只能在server模式下
        "bootstrap_expect": 3,
        //是否允许使用以前的状态来重新加入集群。
        "rejoin_after_leave": true,
        //启动时要加入的另一个agent的地址。可以指定多个agent加入,允许重新尝试加入,直到成功。
        "retry_join": ["10.81.0.102", "10.81.0.103"],
        //启动时要加入的另一个WAN agent的地址。可以指定多个agent加入,允许重新尝试加入,直到成功。
        "retry_join_wan": [""],
        //将所有Consul代理的日志信息写到一个文件中。
        "log_file": "/data/logs/consul/",
        //指定要保留的旧日志文件存档的最大数量。
        "log_rotate_max_files": 7,
        //日志级别
        "log_level": "INFO",
        //集群中此节点的名称。必须是唯一的。默认是节点主机名。    
        "node_name": "consul-server01",
        //UI设置
        "ui_config": {
            //是否启用WEB UI,默认false。
            "enabled": true,
            //指定了网络用户界面应该被提供的HTTP路径。默认为/ui/。
            "content_path": "/consului/"
        },    
        //提供上游 DNS 服务器的地址,如果它们不在Consul的服务域内,则用于递归解析查询。
        "recursors": ["192.168.94.94"],
    }
    
  • 创建数据目录/日志目录并授权

    groupadd consul
    useradd -g consul -M -s /sbin/nologin consul
    mkdir -p /data/data/consul
    mkdir -p /data/logs/consul
    chown -R consul. /data/data/consul
    chown -R consul. /data/logs/consul
    
  • 设置systemd管理

    cat >/etc/systemd/system/consul.service <<'EOF'
    [Unit]
    Description="HashiCorp Consul - A service mesh solution"
    Documentation=https://www.consul.io/
    Requires=network-online.target
    After=network-online.target
    ConditionFileNotEmpty=/etc/consul/agent.json
    
    [Service]
    EnvironmentFile=-/etc/consul.d/consul.env
    User=consul
    Group=consul
    ExecStart=/usr/bin/consul agent -config-dir=/etc/consul/
    ExecReload=/bin/kill --signal HUP $MAINPID
    KillMode=process
    KillSignal=SIGTERM
    Restart=on-failure
    LimitNOFILE=65535
    
    [Install]
    WantedBy=multi-user.target
    EOF
    
    systemctl daemon-reload
    systemctl start consul
    systemctl enable consul
    

2、Client端部署

步骤与server端相同,此处列举不同处

  • 创建配置文件

    {
        //内部集群通信绑定的地址。集群中所有其他节点都应该可以访问的IP地址。默认是"0.0.0.0"
        "bind_addr": "0.0.0.0",
        //绑定客户端接口的地址,包括HTTP和DNS服务器,默认为"127.0.0.1"
        "client_addr": "0.0.0.0",
        //命名agent运行的数据中心名称,默认dc1,同一数据中心的节点应该在一个LAN上
        "datacenter": "fbg-test-shenzhen",
        //指定存储状态的数据目录,目录属主属组应与consul运行用户一致
        "data_dir": "/data/data/consul",
        //禁用任何传入的远程执行请求
        "disable_remote_exec": true,
        //仅允许在本地配置文件中定义脚本检查。不允许在HTTP API注册中定义的脚本检查。
        "enable_local_script_checks": true,
        "http_config": {
            "response_headers": {
                "Access-Control-Allow-Origin": "*"
            },
            //允许调用agent写入端点的ip列表
            "allow_write_http_from": ["127.0.0.1/32", "10.81.0.0/24", "10.81.32.0/24"]
        },
        //当agent收到TERM信号时,它将向集群的其余部分发送离开消息并优雅地离开。在client模式下,默认true,server模式下,默认false。
        "leave_on_terminate": true,
        //控制agent是处于server模式还是client模式,建议每个数据中心server不超过5台
        "server": false,
        //通告地址用于更改我们向集群中其他节点通告的地址。默认bind地址
        "advertise_addr": "10.81.32.43",
        //是否允许使用以前的状态来重新加入集群。
        "rejoin_after_leave": true,
        //启动时要加入的另一个agent的地址。可以指定多个agent加入,允许重新尝试加入,直到成功。
        "retry_join": ["10.81.0.101", "10.81.0.102", "10.81.0.103"],
        //将所有Consul代理的日志信息写到一个文件中。
        "log_file": "/data/logs/consul/",
        //指定要保留的旧日志文件存档的最大数量。
        "log_rotate_max_files": 7,
        //日志级别
        "log_level": "INFO",
        //集群中此节点的名称。必须是唯一的。默认是节点主机名。    
        "node_name": "szch-fbg-fps-web-test",    
        //提供上游 DNS 服务器的地址,如果它们不在Consul的服务域内,则用于递归解析查询。
        "recursors": ["192.168.94.94"],
    }
    

3、加密通信

加密通信主要分为两类:gossip加密和TLS。TLS用于保护agent之间的RPC调用,因agent之间的goosip是通过UDP完成的,所以gossip通信用对称密钥来保护。

  • gossip加密

    在任意一个agent上执行consul keygen命令生成加密密钥

    $ consul keygen
    FgGqMYHcKdtd3Fk4bm+RpJFsP2fcqC8s1ydm740R+uU=
    

    在新增agent中启用

    vim /etc/consul/agent.json
    {
        ...
        "encrypt": "FgGqMYHcKdtd3Fk4bm+RpJFsP2fcqC8s1ydm740R+uU="
        ...
    }
    
    systemctl start consul
    

    在现有集群中启用

    vim /etc/consul/agent.json
    {
        ...
        "encrypt": "FgGqMYHcKdtd3Fk4bm+RpJFsP2fcqC8s1ydm740R+uU=",
        "encrypt_verify_incoming": false,
        "encrypt_verify_outgoing": false
        ...
    }
    
    systemctl restart consul
    

    encrypt_verify_outgoing设置更新为true,然后滚动更新Consul集群 ==>

    vim /etc/consul/agent.json
    {
        ...
        "encrypt": "FgGqMYHcKdtd3Fk4bm+RpJFsP2fcqC8s1ydm740R+uU=",
        "encrypt_verify_incoming": false,
        "encrypt_verify_outgoing": true
        ...
    }
    
    systemctl restart consul
    

    encrypt_verify_incoming更新为true,滚动更新Consul集群 ==>

    vim /etc/consul/agent.json
    {
        ...
        "encrypt": "FgGqMYHcKdtd3Fk4bm+RpJFsP2fcqC8s1ydm740R+uU=",
        "encrypt_verify_incoming": true,
        "encrypt_verify_outgoing": true
        ...
    }
    
    systemctl restart consul
    
  • TLS

    使用TLS加密保护数据中心是生产部署的重要步骤。Consul支持使用TLS来验证server和client的真实性。 要启用TLS,Consul要求所有server都具有由单个证书颁发机构 (CA) 签名的证书。 client还应该具有使用相同CA进行身份验证的证书。

    • 初始化内置CA

      为Consul配置TLS的第一个步骤是生成证书。为了防止未经授权的数据中心访问,Consul要求所有证书都由同一个证书颁发机构(CA)签署。这应该是一个私有CA,而不是一个公共CA,因为由这个CA签署的任何证书都将被允许与数据中心通信。consul-agent-ca.pem证书必须分发到每个节点的agent

      mkdir /etc/consul/certs
      cd /etc/consul/certs && consul tls ca create -days=36500
      
    • 创建server证书

      为指定数据中心和域创建server证书,在同一个节点重复这个操作,直到每台server都有一个单独的证书。

      consul tls cert create -server -dc fbg-test-shenzhen -days=36500
      consul tls cert create -server -dc fbg-test-shenzhen -days=36500
      consul tls cert create -server -dc fbg-test-shenzhen -days=36500
      
    • 分发CA证书

      rsync -avzP consul-agent-ca.pem [IP]:/etc/consul/certs/
      
    • 分发server证书

      consul-agent-ca.pemfbg-test-shenzhen-server-consul-*-key.pemfbg-test-shenzhen-server-consul-*.pem三个证书分发到所有server节点。注意,要现在其他server节点上先创建/etc/consul/certs目录。

      rsync -avzP fbg-test-shenzhen-server-consul-1* 10.81.0.102:/etc/consul/certs/
      rsync -avzP fbg-test-shenzhen-server-consul-2* 10.81.0.103:/etc/consul/certs/
      rsync -avzP consul-agent-ca.pem 10.81.0.102:/etc/consul/certs/
      rsync -avzP consul-agent-ca.pem 10.81.0.103:/etc/consul/certs/
      
    • 分发client证书

      分发client证书有两种方法:手动加密和自动加密。Consul在1.5.2版本中引入了自动加密方式,这个方法使用Connect CA命名生成客户端证书,然后Consul会将证书自动分发给所有客户端

      vim /etc/consul/server.json
      {
          ...
          "verify_incoming": true,
          "verify_outgoing": true,
          "verify_server_hostname": true,
          "ca_file": "/etc/consul/certs/consul-agent-ca.pem",
          "cert_file": "/etc/consul/certs/fbg-test-shenzhen-server-consul-0.pem",
          "key_file": "/etc/consul/certs/fbg-test-shenzhen-server-consul-0-key.pem",
          "auto_encrypt": {
              "allow_tls": true
          }
      }
      
      chown -R consul. /etc/consul/certs
      systemctl restart consul
      

      vim /etc/consul/client.json
      {
          ...
          "verify_incoming": false,
          "verify_outgoing": true,
          "verify_server_hostname": true,
          "ca_file": "/etc/consul/certs/consul-agent-ca.pem",
          "auto_encrypt": {
              "tls": true
          }
      }
      
      chown -R consul. /etc/consul/certs
      systemctl restart consul
      

六、动态应用配置

Consul KV是Consul的一个核心功能,与Consul agent一起安装。Consul KV允许用户存储索引对象,尽管其主要用途是存储配置参数和元数据。它只是一个简单的KV存储,并不是一个全功能的数据存储。可以使用它来动态配置应用程序、协调服务、管理leader选举或用作 Vault的数据后端,以及其他用途。

Consul KV数据存储位于server上,但可以由任何agent(client或server)访问。原生集成的RPC功能允许client向server转发请求,包括键/值的读取和写入。Consul允许数据在所有server上自动复制。为了确保在完全中断的情况下不会丢失数据,请使用consul snapshot功能来备份数据。

七、服务发现

服务发现的主要目标之一是提供可用服务的目录。为此,agent提供了一种简单的服务定义格式,以声明服务的可用性,并可能将其与健康检查联系起来。与服务相关联的健康检查被认为是应用程序级的检查。在配置文件中定义服务或在运行时使用HTTP接口添加服务。

1、注册服务

服务定义文件要存放在-config-dir目录下以.json或.hcl结尾命名,使用consul reload命令更新注册服务。或者通过HTTP API动态注册。还可以Python、Java、.Net Core等的SDK进行注册。

以下是官方服务定义模板:

{
  "service": {
    //每个节点的服务必须具有唯一的ID,如果未指定,则该值将使用name字段。
    "id": "redis",
    //必须指定的服务名称
    "name": "redis",
    //添加服务标签
    "tags": ["primary"],
    //指定服务的IP地址或主机名,默认为agent节点的IP
    "address": "",
    //定义服务元数据,最多64个键值对的映射的对象,默认none
    "meta": {
      "meta": "for my service"
    },
    //标签地址是可以为节点或服务定义的额外地址。标签地址可以被远程agent和服务用作与给定节点或服务进行通信的替代地址,默认none
    "tagged_addresses": {
      //LAN标签地址
      "lan": {
        "address": "192.168.0.55",
        "port": 8000,
      },
      //WAN标签地址
      "wan": {
        "address": "198.18.0.23",
        "port": 80
      }
    },
    //指定服务特定端口号
    "port": 8000,
    //指定服务Unix域套接字路径,默认none
    "socket_path": "/tmp/redis.sock",
    //如果设置为 true,则外部agent可以更新目录中的此服务并修改标签。默认false
    "enable_tag_override": false,
    //定义服务健康检查,默认none
    "checks": [
      {
        "args": ["/usr/local/bin/check_redis.py"],
        "interval": "10s"
      }
    ],
    //用于标识服务是一个Connect代理。默认none
    "kind": "connect-proxy",
    //用于指定当前正在配置的服务所代理的目标服务的名称。默认none
    "proxy_destination_service": "redis",
    //服务定义允许一个可选的代理注册,默认none
    "proxy": {
      "destination_service_name": "redis",
      "destination_service_id": "redis1",
      "local_service_address": "127.0.0.1",
      "local_service_port": 9090,
      "local_service_socket_path": "/tmp/redis.sock",
      "mode": "transparent",
      "transparent_proxy": {
        "outbound_listener_port": 22500
      },
      "config": {},
      "upstreams": [],
      "mesh_gateway": {
        "mode": "local"
      },
      "expose": {
        "checks": true,
        "paths": [
          {
            "path": "/healthz",
            "local_path_port": 8080,
            "listener_port": 21500,
            "protocol": "http2"
          }
       ]
      }
    },
    //Consul Connect服务网格连接的对象,默认none
    "connect": {
      "native": false,
      "sidecar_service": {}
      "proxy": {  // Deprecated
        "command": [],
        "config": {}
      }
    },
    //根据其DNS服务(SRV)响应配置服务的权重。默认none
    "weights": {
      "passing": 5,
      "warning": 1
    },
    //指定用于注册服务的ACL令牌,默认none
    "token": "233b604b-b92e-48c8-a253-5f11514e4b50",
    //指定注册服务的Consul命名空间。默认none
    "namespace": "foo"
  }
}

使用Spring Cloud Consul进行服务注册:

  1. 添加consul发现客户端相应版本依赖

  2. 修改代码,application文件添加consul注册配置

    #连接consul agent节点地址
    spring.cloud.consul.host = localhost
    #连接consul agent节点端口
    spring.cloud.consul.port = 8500
    #是否启用spring cloud consul
    spring.cloud.consul.enabled = true
    #是否启用consul发现客户端
    spring.cloud.consul.discovery.enable = true
    #是否启用服务注册
    spring.cloud.consul.discovery.register = true
    #注册服务时使用的标签
    spring.cloud.consul.discovery.tags = live,prometheus
    #定义在服务列表中查询的标签
    spring.cloud.consul.discovery.default-query-tag = live
    #是否在consul中禁用自动注销服务。
    spring.cloud.consul.discovery.deregister = true
    #HTTP健康检查路径
    spring.cloud.consul.discovery.health-check-path = /actuator/health
    #执行HTTP健康检查的频率
    spring.cloud.consul.discovery.health-check-interval = 10s
    #HTTP健康检查超时时间
    spring.cloud.consul.discovery.health-check-timeout = 10s
    #HTTP健康检查失败多长时间后,会取消注册服务
    spring.cloud.consul.discovery.health-check-critical-timeout = 30m
    #是否启用TTL心跳检测,默认false
    spring.cloud.consul.discovery.heartbeat.enabled = false
    #心跳检测失败时重新注册服务
    spring.cloud.consul.discovery.heartbeat.reregister-service-on-failure = false
    #ttl存活时间
    spring.cloud.consul.discovery.heartbeat.ttl = 30s
    #是否注册时使用ip地址而不是主机名。
    spring.cloud.consul.discovery.prefer-ip-address = true
    #访问服务时使用的IP地址
    spring.cloud.consul.discovery.ip-address = ${spring.cloud.client.ipaddress}
    #唯一的服务实例ID
    spring.cloud.consul.discovery.instance-id = ${spring.application.name}:${spring.cloud.client.ipaddress}:${spring.application.instance_id:${server.port}}
    #注册服务的端口,默认为监听端口
    spring.cloud.consul.discovery.port = ${server.port}
    #初始重试时间间隔,以毫秒为单位
    spring.cloud.consul.retry.initial-interval = 10000
    

2、健康检查

agent的主要角色之一是管理系统级和应用程序级健康检查。如果健康检查与服务相关联,则它被认为是应用程序级别的。如果未与服务关联,则检查会监控整个节点的运行状况。

可以在你的服务定义中添加健康检查。健康检查执行若干安全功能,例如允许WEB均衡器优雅地移除故障节点,允许数据库替换故障的二级数据库。健康检查功能也被强烈地集成到DNS界面中。如果一个服务的健康检查失败或一个节点有任何失败的系统级检查,则DNS接口将从任何服务查询中忽略该节点。

健康检查名称会自动生成为service:。如果注册了多个服务检查,ID将被生成为service::,其中是一个从1开始的递增数字。

  • Script + Interval

    这些检查依赖于调用执行健康检查的外部应用程序,以适当的退出代码退出,并可能生成一些输出。脚本检查的输出被限制在4KB以内。大于此的输出将被截断。默认情况下,脚本检查的超时时间将被配置为30秒。可以通过在检查定义中指定超时字段来配置一个自定义的脚本检查超时值。当在Windows上达到超时时,Consul将等待脚本产生的任何子进程完成。对于其他系统,一旦超时,Consul将试图强制杀死脚本和它所产生的任何子进程。在Consul 0.9.0及以后的版本中,脚本检查默认是不启用的。要使用它们,可以使用 :enable_local_script_checksenable_script_checks参数启用。

  • HTTP + Interval

    此检查向指定的URL发出HTTP GET请求,在两次请求之间等待指定的时间间隔。服务的状态取决于HTTP响应码:任何2xx代码都被认为是通过,429 Too ManyRequests是一个警告,其他都是失败。这种类型的检查应该优先于使用curl或其他外部进程来检查简单HTTP操作的脚本。默认情况下,HTTP检查是GET请求,除非方法字段指定了一个不同的方法。默认情况下,HTTP检查将被配置成一个等于10秒的请求超时。

    通过在检查定义中指定超时字段,可以配置一个自定义的HTTP检查超时值。检查的输出被限制在大约4KB的范围内,大于此的响应将被截断。HTTP检查也支持TLS。默认情况下,需要一个有效的TLS证书。可以通过在检查定义中设置tls_skip_verify字段为true来关闭证书验证。当使用TLS时,如果使用主机名(而不是IP地址),SNI将从URL中自动设置;该值可以通过设置tls_server_name覆盖。

    Consul默认遵循HTTP重定向。 将disable_redirects字段设置为true以禁用重定向。

  • TCP + Interval

    此检查对指定的IP/主机名和端口进行TCP连接尝试,等待尝试之间的间隔时间。如果没有指定主机名,默认为 "localhost"。服务的状态取决于连接尝试是否成功。如果连接被接受,状态为success,否则状态为critical。在主机名同时解析为IPv4和IPv6地址的情况下,将对两个地址进行尝试,第一次成功的连接尝试将导致检查成功。这种类型的检查应该优于使用netcat或其他外部进程检查简单套接字操作的脚本。默认情况下,TCP检查将被配置为10秒的请求超时。可以通过在检查定义中指定超时字段来配置一个自定义的TCP检查超时值。

  • TTL(Time to Live)

    对于给定的TTL,该检查会保留它们最后的已知状态。检查的状态必须通过HTTP接口定期更新。如果外部系统未能在给定的TTL内更新状态,则将检查设置为失败状态。这种机制依赖于应用程序直接报告其健康状况。例如,一个健康的应用程序可以定期向HTTP端点PUT一个状态更新;如果应用程序失败,TTL将过期,健康检查进入critical状态。用于更新特定检查的健康信息的端点是:pass, warn, fail, update。TTL检查也会将其最后的已知状态持久化到磁盘上。这允许Consul代理在重新启动时恢复检查的最后已知状态。持久的检查状态在最后一次检查时的TTL结束时有效。

  • Docker + Interval

    该检查依赖于调用打包在Docker容器中的外部应用程序。该应用程序在运行的容器中通过Docker Exec API被触发。Consul agent用户要能够访问Docker HTTP API或unix socket。Consul使用$DOCKER_HOST来确定Docker API端点。应用程序应该运行,对容器内运行的服务进行健康检查,并以适当的退出代码退出。在Consul 0.9.0及以后的版本中,agent必须配置enable_script_checks为true,才能启用Docker健康检查。

以上是常用的健康检查类型,更多类型请参考官网checks。

3、查找服务

  • HTTP API方式

    curl http://127.0.0.1:8500/v1/health/service/my-service?passing=true
    
  • DNS接口

    使用此方式,主机可以通过redis.service.us-east-1.consul这样的名称查询直接使用DNS服务器,而不是向Consul发出HTTP API请求。这个查询会自动转化为提供redis服务的节点的查询,这些节点位于us-east-1数据中心,并且健康检查正常。

    有几种方法来使用DNS接口。一种选择是使用自定义DNS解析库并将其指向Consul;另一种选择是将Consul设置为节点的DNS服务器,并提供递归配置,以便非Consul的查询也能被解析。最后一种方法是将"consul. "域名的所有查询从现有的DNS服务器转发到Consul agent。

    这里使用dnsmasq工具来转发查询,更多方式查看官网DNS Forwarding tutorial。

    vim /etc/dnsmasq.conf
    ...
    # Enable forward lookup of the 'consul' domain:
    server=/consul/10.81.0.102#8600
    ...
    
    systemctl restart dnsmasq
    

    标准查找格式:

    [tag.].service[.datacenter].
    
  • Spring Cloud Gateway集成Consul

    建立网关服务

    pom.xml文件

    
            
                org.springframework.cloud
                spring-cloud-starter-gateway
            
            
                org.springframework.boot
                spring-boot-starter-webflux
            
    
            
                org.springframework.boot
                spring-boot-starter-actuator
            
            
            
                org.springframework.cloud
                spring-cloud-starter-consul-discovery
            
    
    

    application文件

    server.port = 8080
    spring.application.name = bms-gateway-server
    
    spring.cloud.consul.host = localhost
    spring.cloud.consul.port = 8500
    spring.cloud.consul.enabled = true
    spring.cloud.consul.discovery.enable = true
    spring.cloud.consul.discovery.register = true
    spring.cloud.consul.discovery.tags = live,prometheus
    spring.cloud.consul.discovery.default-query-tag = live
    spring.cloud.consul.discovery.deregister = true
    spring.cloud.consul.discovery.health-check-path = /actuator/health
    spring.cloud.consul.discovery.health-check-interval = 10s
    spring.cloud.consul.discovery.health-check-timeout = 10s
    spring.cloud.consul.discovery.health-check-critical-timeout = 30m
    spring.cloud.consul.discovery.heartbeat.enabled = false
    spring.cloud.consul.discovery.heartbeat.reregister-service-on-failure = false
    spring.cloud.consul.discovery.heartbeat.ttl = 30s
    spring.cloud.consul.discovery.prefer-ip-address = true
    spring.cloud.consul.discovery.ip-address = ${spring.cloud.client.ipaddress}
    spring.cloud.consul.discovery.instance-id = ${spring.application.name}:${spring.cloud.client.ipaddress}:${spring.application.instance_id:${server.port}}
    spring.cloud.consul.discovery.port = ${server.port}
    spring.cloud.consul.retry.initial-interval = 10000
    
    #启用DiscoveryClient网关集成的标志
    #使用http://localhost:8080/service_name/user/info访问服务,网关即可对服务进行路由转发
    spring.cloud.gateway.discovery.locator.enabled = true
    spring.cloud.gateway.discovery.locator.lower-case-service-id = true
    
    #使用http://localhost:8080/sys/...访问服务,会路由到consul上bms-sys-server服务
    spring.cloud.gateway.routes.0.id = bms-sys-server
    spring.cloud.gateway.routes.0.uri = lb://bms-sys-server
    spring.cloud.gateway.routes.0.order = 1
    spring.cloud.gateway.routes.0.predicates.0 = Path=/sys/**
    spring.cloud.gateway.routes.0.filters.0 = StripPrefix=0
    

八、负载均衡集成

  • 使用nginx和consul template进行负载均衡

    工作原理图如下:

NGINX将通过CONSUL TEMPLATE从Consul服务发现中获得一个健康的服务器列表,并根据自己的配置均衡互联网流量到这些服务器。

Consul Template是一个简单而又强大的工具。启动时,它会读取一个或多个模板文件,并查询Consul以获取渲染它们所需的所有数据。通常,可以把consul-template作为一个守护程序运行,它将获取初始值,然后继续观察更新,每当数据中心发生相关更改时,就重新渲染模板。你也可以使用-once标志来获取并渲染一次模板,这对测试和设置脚本很有用。最后,模板还可以在更新过程完成后运行任意命令。例如,它可以在配置更改后向负载均衡器服务发送HUP信号。

部署流程如下:

  1. 将对应服务注册到consul中

  2. 在nginx节点上安装consul client及nginx

  3. 在nginx节点安装consul template

    wget https://releases.hashicorp.com/consul-template/0.29.0/consul-template_0.29.0_linux_amd64.zip
    unzip consul-template_0.29.0_linux_amd64.zip -d /usr/bin/
    
  4. 创建consul template配置文件

    可参考官方配置文件详解

    mkdir /etc/consul-template
    mkdir -p /data/logs/consul-template
    cat > /etc/consul-template/config.json <<'EOF'
    {
      "log_level": "info",
      "wait": {
        "min": "1s",
        "max": "3s"
      },
      "syslog": {
        "enabled": false
      },
      "template_error_fatal": false,
      "log_file": {
        "path": "/data/logs/consul-template/info.log",
        "log_rotate_bytes": 1024000000,
        "log_rotate_duration": "24h",
        "log_rotate_max_files": 7
      },
      "consul": {
        "address": "127.0.0.1:8500",
        "retry": {
          "enabled": true,
          "attempts": 12,
          "backoff": "250ms"
        },
        "transport": {
          "disable_keep_alives": false,
          "dial_keep_alive": "30s",
          "max_idle_conns_per_host": 256
        },
        "ssl": {
          "enabled": false,
        }
      },
      "template": {
        "source": "/usr/local/nginx-1.16.1/conf/vhosts/fps-task-worker.conf.ctmpl",
        "destination": "/usr/local/nginx-1.16.1/conf/vhosts/fps-task-worker.conf",
        "create_dest_dirs": true,
        "perms": "0644",
        "command": "/usr/local/nginx-1.16.1/sbin/nginx -s reload"
      }
    }
    EOF
    
  5. 创建模板文件

    upstream fpstaskworker {
    {{- range service "fps-task-worker" }}
      server {{ .Address }}:{{ .Port }};
    {{- end }}
    }
    server {
      listen          9102;
      server_name    localhost;
      charset utf-8;
      client_max_body_size    10m;
      client_body_buffer_size 128k;  
      location / {
        proxy_pass http://fpstaskworker;
        proxy_connect_timeout  600;
        proxy_send_timeout     600;
        proxy_read_timeout     600;
        proxy_buffer_size      4k;
        proxy_buffers          4 32k;
        proxy_busy_buffers_size 64k;
        proxy_temp_file_write_size 64k;
      }
    }
    
  6. 设置systemd管理consul-template

    cat >/etc/systemd/system/consul-template.service <<'EOF'
    [Unit]
    Description=consul-template
    Requires=network-online.target
    After=network-online.target consul.service vault.service
    
    [Service]
    EnvironmentFile=-/etc/consul-template
    User=root
    Group=root
    ExecStart=/usr/bin/consul-template $OPTIONS -config=/etc/consul-template/config.json
    Restart=on-failure
    KillSignal=SIGINT
    
    [Install]
    WantedBy=multi-user.target
    EOF
    
    systemctl daemon-reload
    systemctl start consul-template
    systemctl enable consul-template
    

你可能感兴趣的:(Consul)