Table of Contents

1. 前言

Consul一般用来作为服务注册和服务发现软件。官方介绍如下:

Consul is a service mesh solution providing a full featured control plane with service discovery, configuration, and segmentation functionality. Each of these features can be used individually as needed, or they can be used together to build a full service mesh. Consul requires a data plane and supports both a proxy and native integration model. Consul ships with a simple built-in proxy so that everything works out of the box, but also supports 3rd party proxy integrations such as Envoy.

文档资料:

2. 选型

市面上常用的开源服务发现软件主要有:consuletcdzookeeper。前两者都是用golang研发的,而zookeeper则是java研发的(你懂我意思吧)。

这里就有选型的问题了,不过了解下来相互之间的差异不能说很大,基本上都在可接受范围内。特别是consul和etcd都使用raft作为分布式一致性协议,可以说非常趋同了。etcd关注度更高(特别是K8S官方使用了它),功能简单,主要在大型系统中作为分布式K/V存储使用;而consul的功能更强大(完整、开箱即用)且易用性更高。

相关资料:

3. 架构

官方的架构介绍在:Consul Architecture

简单来说:

  • 节点分为clientserver
  • server负责存储数据,并形成集群,使用raft保证集群一致性
  • client负责直接和业务对象连接,并将数据同步到server上
  • 所有的节点都是通过gossip连接起来的

4. 使用

4.1 启动

一般直接使用docker镜像:consul

启动方面非常简单,全部都是用agent命令,参数细节放在后面的附录部分,太长了:consul agent –help

常用参数:

  • --node=$name指定节点名称
  • --server表示节点是server节点
  • --bootstrap表示节点以bootstrap模式启动
  • --ui表示当前节点会提供管理UI界面
  • --client=0.0.0.0指定监听地址
  • --join=$host指定启动时尝试加入集群时连接的目标节点

下面给个例子,集群3个server节点,2个client节点:

  fullstack_consul_server1:
    image: consul:1.6.1
    container_name: fullstack_consul_server1
    hostname: fullstack_consul_server1
    networks:
      - net
    ports:
      - 18500:8500
    expose:
      - 8600 # DNS
      - 8500 # HTTP API
      - 8501 # HTTPS API
      - 8502 # gRPC API
      - 8301 # LAN Serf
      - 8302 # Wan Serf
      - 8300 # Server RPC address
    logging:
      driver: json-file
      options:
        max-size: 512m
    restart: always
    healthcheck:
      test: wget http://127.0.0.1:8500/v1/health/node/consul-server1 -q -O - > /dev/null 2>&1
      interval: 10s
      timeout: 20s
      retries: 10
    volumes:
      - consul_server1_data:/consul/data
    environment:
      - CONSUL_BIND_INTERFACE=eth0
    command: [
      agent,
      --node=consul-server1,
      --server,
      --bootstrap,
      --client=0.0.0.0,
      --ui
    ]
  fullstack_consul_server2:
    image: consul:1.6.1
    container_name: fullstack_consul_server2
    hostname: fullstack_consul_server2
    networks:
      - net
    expose:
      - 8600 # DNS
      - 8500 # HTTP API
      - 8501 # HTTPS API
      - 8502 # gRPC API
      - 8301 # LAN Serf
      - 8302 # Wan Serf
      - 8300 # Server RPC address
    depends_on:
      fullstack_consul_server1:
        condition: service_healthy
    logging:
      driver: json-file
      options:
        max-size: 512m
    restart: always
    healthcheck:
      test: wget http://127.0.0.1:8500/v1/health/node/consul-server2 -q -O - > /dev/null 2>&1
      interval: 10s
      timeout: 20s
      retries: 10
    volumes:
      - consul_server2_data:/consul/data
    environment:
      - CONSUL_BIND_INTERFACE=eth0
    command: [
      agent,
      --node=consul-server2,
      --server,
      --client=0.0.0.0,
      --join=fullstack_consul_server1
    ]
  fullstack_consul_server3:
    image: consul:1.6.1
    container_name: fullstack_consul_server3
    hostname: fullstack_consul_server3
    networks:
      - net
    expose:
      - 8600 # DNS
      - 8500 # HTTP API
      - 8501 # HTTPS API
      - 8502 # gRPC API
      - 8301 # LAN Serf
      - 8302 # Wan Serf
      - 8300 # Server RPC address
    depends_on:
      fullstack_consul_server1:
        condition: service_healthy
    logging:
      driver: json-file
      options:
        max-size: 512m
    restart: always
    healthcheck:
      test: wget http://127.0.0.1:8500/v1/health/node/consul-server3 -q -O - > /dev/null 2>&1
      interval: 10s
      timeout: 20s
      retries: 10
    volumes:
      - consul_server3_data:/consul/data
    environment:
      - CONSUL_BIND_INTERFACE=eth0
    command: [
      agent,
      --node=consul-server3,
      --server,
      --client=0.0.0.0,
      --join=fullstack_consul_server1
    ]
  fullstack_consul_client1:
    image: consul:1.6.1
    container_name: fullstack_consul_client1
    hostname: fullstack_consul_client1
    networks:
      - net
    expose:
      - 8600 # DNS
      - 8500 # HTTP API
      - 8501 # HTTPS API
      - 8502 # gRPC API
      - 8301 # LAN Serf
      - 8302 # Wan Serf
      - 8300 # Server RPC address
    depends_on:
      fullstack_consul_server1:
        condition: service_healthy
      fullstack_consul_server2:
        condition: service_healthy
      fullstack_consul_server3:
        condition: service_healthy
    logging:
      driver: json-file
      options:
        max-size: 512m
    restart: always
    healthcheck:
      test: wget http://127.0.0.1:8500/v1/health/node/consul-client -q -O - > /dev/null 2>&1
      interval: 10s
      timeout: 20s
      retries: 10
    volumes:
      - consul_client1_data:/consul/data
    environment:
      - CONSUL_BIND_INTERFACE=eth0
    command: [
      agent,
      --node=consul-client1,
      --client=0.0.0.0,
      --join=fullstack_consul_server1
    ]
  fullstack_consul_client2:
    image: consul:1.6.1
    container_name: fullstack_consul_client2
    hostname: fullstack_consul_client2
    networks:
      - net
    expose:
      - 8600 # DNS
      - 8500 # HTTP API
      - 8501 # HTTPS API
      - 8502 # gRPC API
      - 8301 # LAN Serf
      - 8302 # Wan Serf
      - 8300 # Server RPC address
    depends_on:
      fullstack_consul_server1:
        condition: service_healthy
      fullstack_consul_server2:
        condition: service_healthy
      fullstack_consul_server3:
        condition: service_healthy
    logging:
      driver: json-file
      options:
        max-size: 512m
    restart: always
    healthcheck:
      test: wget http://127.0.0.1:8500/v1/health/node/consul-client -q -O - > /dev/null 2>&1
      interval: 10s
      timeout: 20s
      retries: 10
    volumes:
      - consul_client2_data:/consul/data
    environment:
      - CONSUL_BIND_INTERFACE=eth0
    command: [
      agent,
      --node=consul-client2,
      --client=0.0.0.0,
      --join=fullstack_consul_server1
    ]

部署完成后节点如下:

4.2 API

官方API文档在:API Introduction。Consul使用RESTful的HTTP请求来提供服务,所有的客户端或命令行工具无非就是RESTful API的封装。所以如果有需要,可以直接使用curl来发送HTTP请求调用接口。

下面的例子中会涉及到一些demo应用程序的节点:

  • app server 3个节点
  • app gateway 3个节点

client1连接了:

client2连接了:

4.2.1 根据节点健康状态获取节点

文档:List Checks in State

这个接口可以有效过滤掉已经失效的节点。

$ curl http://127.0.0.1:18500/v1/health/state/any | jq .

结果:

[
  {
    "Node": "consul-client1",
    "CheckID": "serfHealth",
    "Name": "Serf Health Status",
    "Status": "passing",
    "Notes": "",
    "Output": "Agent alive and reachable",
    "ServiceID": "",
    "ServiceName": "",
    "ServiceTags": [],
    "Definition": {},
    "CreateIndex": 15,
    "ModifyIndex": 15
  },
  {
    "Node": "consul-client1",
    "CheckID": "service:1fw20gk4kq30tk",
    "Name": "Service 'server' check",
    "Status": "passing",
    "Notes": "",
    "Output": "HTTP GET http://fullstack_server2:50052/health: 200 OK Output: OK",
    "ServiceID": "1fw20gk4kq30tk",
    "ServiceName": "server",
    "ServiceTags": [],
    "Definition": {},
    "CreateIndex": 26,
    "ModifyIndex": 29
  },
  {
    "Node": "consul-client1",
    "CheckID": "service:1fw20gk4kq35py",
    "Name": "Service 'gateway' check",
    "Status": "passing",
    "Notes": "",
    "Output": "HTTP GET http://fullstack_gateway3:3000/health: 200 OK Output: OK",
    "ServiceID": "1fw20gk4kq35py",
    "ServiceName": "gateway",
    "ServiceTags": [],
    "Definition": {},
    "CreateIndex": 30,
    "ModifyIndex": 32
  },
  {
    "Node": "consul-client1",
    "CheckID": "service:1fw20hk4kq5i2h",
    "Name": "Service 'gateway' check",
    "Status": "passing",
    "Notes": "",
    "Output": "HTTP GET http://fullstack_gateway1:3000/health: 200 OK Output: OK",
    "ServiceID": "1fw20hk4kq5i2h",
    "ServiceName": "gateway",
    "ServiceTags": [],
    "Definition": {},
    "CreateIndex": 48,
    "ModifyIndex": 49
  },
  {
    "Node": "consul-client2",
    "CheckID": "serfHealth",
    "Name": "Serf Health Status",
    "Status": "passing",
    "Notes": "",
    "Output": "Agent alive and reachable",
    "ServiceID": "",
    "ServiceName": "",
    "ServiceTags": [],
    "Definition": {},
    "CreateIndex": 13,
    "ModifyIndex": 13
  },
  {
    "Node": "consul-client2",
    "CheckID": "service:1fw20hk4kq30n8",
    "Name": "Service 'server' check",
    "Status": "passing",
    "Notes": "",
    "Output": "HTTP GET http://fullstack_server3:50052/health: 200 OK Output: OK",
    "ServiceID": "1fw20hk4kq30n8",
    "ServiceName": "server",
    "ServiceTags": [],
    "Definition": {},
    "CreateIndex": 24,
    "ModifyIndex": 27
  },
  {
    "Node": "consul-client2",
    "CheckID": "service:1fw20ik4kq35th",
    "Name": "Service 'gateway' check",
    "Status": "passing",
    "Notes": "",
    "Output": "HTTP GET http://fullstack_gateway2:3000/health: 200 OK Output: OK",
    "ServiceID": "1fw20ik4kq35th",
    "ServiceName": "gateway",
    "ServiceTags": [],
    "Definition": {},
    "CreateIndex": 31,
    "ModifyIndex": 34
  },
  {
    "Node": "consul-client2",
    "CheckID": "service:eewk9hk4kq2uvy",
    "Name": "Service 'server' check",
    "Status": "passing",
    "Notes": "",
    "Output": "HTTP GET http://fullstack_server1:50052/health: 200 OK Output: OK",
    "ServiceID": "eewk9hk4kq2uvy",
    "ServiceName": "server",
    "ServiceTags": [],
    "Definition": {},
    "CreateIndex": 22,
    "ModifyIndex": 23
  },
  {
    "Node": "consul-server1",
    "CheckID": "serfHealth",
    "Name": "Serf Health Status",
    "Status": "passing",
    "Notes": "",
    "Output": "Agent alive and reachable",
    "ServiceID": "",
    "ServiceName": "",
    "ServiceTags": [],
    "Definition": {},
    "CreateIndex": 5,
    "ModifyIndex": 5
  },
  {
    "Node": "consul-server2",
    "CheckID": "serfHealth",
    "Name": "Serf Health Status",
    "Status": "passing",
    "Notes": "",
    "Output": "Agent alive and reachable",
    "ServiceID": "",
    "ServiceName": "",
    "ServiceTags": [],
    "Definition": {},
    "CreateIndex": 10,
    "ModifyIndex": 10
  },
  {
    "Node": "consul-server3",
    "CheckID": "serfHealth",
    "Name": "Serf Health Status",
    "Status": "passing",
    "Notes": "",
    "Output": "Agent alive and reachable",
    "ServiceID": "",
    "ServiceName": "",
    "ServiceTags": [],
    "Definition": {},
    "CreateIndex": 8,
    "ModifyIndex": 8
  }
]

any可以更换成其他状态:any, passing, warning, or critical

4.2.2 获取所有服务

文档:List Services

$ curl http://127.0.0.1:18500/v1/catalog/services | jq . 

结果:

{
  "consul": [],
  "gateway": [],
  "server": []
}

The keys are the service names, and the array values provide all known tags for a given service.

4.2.3 根据服务名获取所有对应的服务节点

文档:List Nodes for Service

$ curl http://127.0.0.1:18500/v1/catalog/service/:service_name | jq . 

server的结果:

[
  {
    "ID": "f33332e4-3881-b975-d647-bc21a4ca41da",
    "Node": "consul-client1",
    "Address": "172.26.0.8",
    "Datacenter": "dc1",
    "TaggedAddresses": {
      "lan": "172.26.0.8",
      "wan": "172.26.0.8"
    },
    "NodeMeta": {
      "consul-network-segment": ""
    },
    "ServiceKind": "",
    "ServiceID": "1fw20gk4kq30tk",
    "ServiceName": "server",
    "ServiceTags": [],
    "ServiceAddress": "fullstack_server2",
    "ServiceWeights": {
      "Passing": 1,
      "Warning": 1
    },
    "ServiceMeta": {},
    "ServicePort": 50051,
    "ServiceEnableTagOverride": false,
    "ServiceProxy": {
      "MeshGateway": {}
    },
    "ServiceConnect": {},
    "CreateIndex": 26,
    "ModifyIndex": 26
  },
  {
    "ID": "feaba61d-83ce-a7e6-3e99-f1b2fa889bf8",
    "Node": "consul-client2",
    "Address": "172.26.0.7",
    "Datacenter": "dc1",
    "TaggedAddresses": {
      "lan": "172.26.0.7",
      "wan": "172.26.0.7"
    },
    "NodeMeta": {
      "consul-network-segment": ""
    },
    "ServiceKind": "",
    "ServiceID": "1fw20hk4kq30n8",
    "ServiceName": "server",
    "ServiceTags": [],
    "ServiceAddress": "fullstack_server3",
    "ServiceWeights": {
      "Passing": 1,
      "Warning": 1
    },
    "ServiceMeta": {},
    "ServicePort": 50051,
    "ServiceEnableTagOverride": false,
    "ServiceProxy": {
      "MeshGateway": {}
    },
    "ServiceConnect": {},
    "CreateIndex": 24,
    "ModifyIndex": 24
  },
  {
    "ID": "feaba61d-83ce-a7e6-3e99-f1b2fa889bf8",
    "Node": "consul-client2",
    "Address": "172.26.0.7",
    "Datacenter": "dc1",
    "TaggedAddresses": {
      "lan": "172.26.0.7",
      "wan": "172.26.0.7"
    },
    "NodeMeta": {
      "consul-network-segment": ""
    },
    "ServiceKind": "",
    "ServiceID": "eewk9hk4kq2uvy",
    "ServiceName": "server",
    "ServiceTags": [],
    "ServiceAddress": "fullstack_server1",
    "ServiceWeights": {
      "Passing": 1,
      "Warning": 1
    },
    "ServiceMeta": {},
    "ServicePort": 50051,
    "ServiceEnableTagOverride": false,
    "ServiceProxy": {
      "MeshGateway": {}
    },
    "ServiceConnect": {},
    "CreateIndex": 22,
    "ModifyIndex": 22
  }
]

4.2.4 根据service id获取具体信息

文档:Get Service Configuration

需要注意,这个操作只能获取所查询agent(某个client)上注册的服务的信息。下面举两个例子,刚才有说到fullstack_server2是注册在fullstack_consul_client1上的;而fullstack_server3是注册在fullstack_consul_client2上的。

fullstack_server2

# 首先需要登入到docker network中的某台机器上,因为client都没有向主机暴露端口
# docker exec -it fullstack_consul_server1 /bin/sh
$ curl http://fullstack_consul_client1:8500/v1/agent/service/1fw20gk4kq30tk | jq .

结果:

{
  "ID": "1fw20gk4kq30tk",
  "Service": "server",
  "Tags": [],
  "Meta": {},
  "Port": 50051,
  "Address": "fullstack_server2",
  "Weights": {
    "Passing": 1,
    "Warning": 1
  },
  "EnableTagOverride": false,
  "ContentHash": "b13f5888fa84e5d"
}

fullstack_server3

# 首先需要登入到docker network中的某台机器上,因为client都没有向主机暴露端口
# docker exec -it fullstack_consul_server1 /bin/sh
$ curl http://fullstack_consul_client2:8500/v1/agent/service/1fw20hk4kq30n8 | jq .

结果:

{
  "ID": "1fw20hk4kq30n8",
  "Service": "server",
  "Tags": [],
  "Meta": {},
  "Port": 50051,
  "Address": "fullstack_server3",
  "Weights": {
    "Passing": 1,
    "Warning": 1
  },
  "EnableTagOverride": false,
  "ContentHash": "120b74b874209fe8"
}

4.2.5 删除某个服务的注册

文档:Deregister Service

做开发的时候,为了测试,有的时候需要手动删除某些服务,这时候就要用到这个接口了。

$ curl --request PUT http://127.0.0.1:18500/v1/agent/service/deregister/:service_id | jq .

4.3 UI

访问:http://127.0.0.1:18500,就会开启管理UI。

实际功能非常有限,主要是观察下集群及服务的状况。

4.4 Template

Consul有一个非常好用的功能就是能把注册的服务,通过一个模板,生成配置文件并输出到指定的位置。最常见的使用案例就是consul配合nginx,多个业务服务跑在后台,注册到consul,通过consul将业务后台的信息生成成nginx配置文件。同时,任何业务后台的变动都会触发配置文件的重新生成。consul的template还可以指定一个外部命令,在刚才提到的例子中就可以触发nginx的reload,使改变的配置文件生效。

template有单独的镜像:hashicorp/consul-template

范例nginx配置模板,文件位置:./vendor/consul/nginx

   
upstream gateway {
    server : max_fails=3 fail_timeout=60 weight=1;
    server 127.0.0.1:65535; # force a 502
}  

server {
    listen 80;
    server_name localhost;

    access_log /var/log/nginx/fullstack.access.log;
    error_log /var/log/nginx/fullstack.error.log;

    root /usr/share/nginx/html;

    index index.html index.htm index.nginx-debian.html;

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    location / {
        proxy_set_header x-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header HOST $http_host;
        proxy_set_header X-Forwarded-Proto https;
        proxy_redirect http:// https://;
        proxy_connect_timeout 240;
        proxy_send_timeout 240;
        proxy_read_timeout 240;
        proxy_pass http://gateway;
    }
}

template启动:

$ docker run --rm -it --name templateX \
    -v ./vendor/consul/nginx:/tmp/nginx.ctmpl \ # 将模板配置文件映射到容器内
    -v /tmp/template:/consul-template/data \    # 将主机的临时文件夹映射到容器内配置文件的生成位置,方便后续在主机上直接查看生成的配置文件
    hashicorp/consul-template:0.22.1-alpine \
    -dry \
    -log-level=debug \
    -consul-addr=host.docker.internal:18500 \
    -consul-retry \
    -consul-retry-attempts=5 \
    -consul-retry-backoff=500ms \
    -template=/tmp/nginx.ctmpl:/consul-template/data/default.conf

查看生成的:/tmp/template/default.conf

upstream gateway {
    server fullstack_gateway3:3000 max_fails=3 fail_timeout=60 weight=1;
    server fullstack_gateway1:3000 max_fails=3 fail_timeout=60 weight=1;
    server fullstack_gateway2:3000 max_fails=3 fail_timeout=60 weight=1;

}

server {
    listen 80;
    server_name localhost;

    access_log /var/log/nginx/fullstack.access.log;
    error_log /var/log/nginx/fullstack.error.log;

    root /usr/share/nginx/html;

    index index.html index.htm index.nginx-debian.html;

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    location / {
        proxy_set_header x-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header HOST $http_host;
        proxy_set_header X-Forwarded-Proto https;
        proxy_redirect http:// https://;
        proxy_connect_timeout 240;
        proxy_send_timeout 240;
        proxy_read_timeout 240;
        proxy_pass http://gateway;
    }
}

4.5 DNS

官方文档:DNS Interface

使用上应该说是非常简便了,而且基本上对业务没什么侵入性。我之前做的实验项目里没使用这个功能,主要是因为需要改动主机的DNS,比较麻烦。

4.6 Application

Consul有不少语言对应的客户端,我的实验项目用过node.js的:Consul

注册服务:

import * as Consul from "consul";
import * as exitHook from "async-exit-hook";

const serviceId: string = uniqid();
const consul = new Consul({
    host: CONSUL_HOST, // fullstack_consul_client2
    port: CONSUL_PORT, // 8500
    promisify: true,
});

const register = async () => {
    const serverConf = Config.get().getRaw().server;
    await consul.agent.service.register({
        name: serverConf.serviceName, // server
        id: serviceId,
        address: SERVICE_HOST,        // fullstack_server3
        port: serverConf.servicePort, // 50051
        check: {
            http: `http://${SERVICE_HOST}:${serverConf.webPort}/health`, // http://fullstack_server3:50052/health
            interval: "10s",
            ttl: "15s",
        },
    });
};

const cleanup = (done: () => void) => {
    consul.agent.service.deregister(serviceId)
        .then(() => {
            console.log("cleanup done");
            done();
        })
        .catch((err) => {
            console.log(err);
            done();
        });
};

// exit
exitHook.forceExitTimeout(500); // wait 0.5s before force exit
exitHook((done: () => void) => {
    console.log("Process::exitHook - Got exit signal");
    cleanup(done);
});

// start
startServer().then(() => startWeb()).then(() => register()).catch((err) => console.log(err));

在服务启动的时候进行注册,并且记得要处理程序退出,退出的时候需要将注册信息删除,否则即便应用程序退出了,在consul里那个服务还是存在的。

客户端获取可用节点

const consul = new Consul({
    host: CONSUL_HOST,
    port: CONSUL_PORT,
    promisify: true,
});

const servers = await consul.health.service({
    service: CONFIG.getRaw().server.serviceName, // server
    passing: true,                               // get only living nodes
}) as IResHealthService[];

// ...

4.7 Health Check

官方文档:Checks

在4.6的范例里也提到了,在注册服务的时候可以提供当前注册进consul的应用程序的健康检查设置,consul会使用HTTP请求来检查该URL,只要是200返回就表示该服务仍旧存活。

Appendix

资料

consul agent –help

docker run -it --rm consul:1.6.1 agent --help
Usage: consul agent [options]

  Starts the Consul agent and runs until an interrupt is received. The
  agent represents a single node in a cluster.

HTTP API Options

  -datacenter=<value>
     Datacenter of the agent.

Command Options

  -advertise=<value>
     Sets the advertise address to use.

  -advertise-wan=<value>
     Sets address to advertise on WAN instead of -advertise address.

  -allow-write-http-from=<value>
     Only allow write endpoint calls from given network. CIDR format,
     can be specified multiple times.

  -alt-domain=<value>
     Alternate domain to use for DNS interface.

  -bind=<value>
     Sets the bind address for cluster communication.

  -bootstrap
     Sets server to bootstrap mode.

  -bootstrap-expect=<value>
     Sets server to expect bootstrap mode.

  -check_output_max_size=<value>
     Sets the maximum output size for checks on this agent

  -client=<value>
     Sets the address to bind for client access. This includes RPC, DNS,
     HTTP, HTTPS and gRPC (if configured).

  -config-dir=<value>
     Path to a directory to read configuration files from. This
     will read every file ending in '.json' as configuration in this
     directory in alphabetical order. Can be specified multiple times.

  -config-file=<value>
     Path to a file in JSON or HCL format with a matching file
     extension. Can be specified multiple times.

  -config-format=<value>
     Config files are in this format irrespective of their extension.
     Must be 'hcl' or 'json'

  -data-dir=<value>
     Path to a data directory to store agent state.

  -dev
     Starts the agent in development mode.

  -disable-host-node-id
     Setting this to true will prevent Consul from using information
     from the host to generate a node ID, and will cause Consul to
     generate a random node ID instead.

  -disable-keyring-file
     Disables the backing up of the keyring to a file.

  -dns-port=<value>
     DNS port to use.

  -domain=<value>
     Domain to use for DNS interface.

  -enable-local-script-checks
     Enables health check scripts from configuration file.

  -enable-script-checks
     Enables health check scripts.

  -encrypt=<value>
     Provides the gossip encryption key.

  -grpc-port=<value>
     Sets the gRPC API port to listen on (currently needed for Envoy xDS
     only).

  -hcl=<value>
     hcl config fragment. Can be specified multiple times.

  -http-port=<value>
     Sets the HTTP API port to listen on.

  -join=<value>
     Address of an agent to join at start time. Can be specified
     multiple times.

  -join-wan=<value>
     Address of an agent to join -wan at start time. Can be specified
     multiple times.

  -log-file=<value>
     Path to the file the logs get written to

  -log-level=<value>
     Log level of the agent.

  -log-rotate-bytes=<value>
     Maximum number of bytes that should be written to a log file

  -log-rotate-duration=<value>
     Time after which log rotation needs to be performed

  -log-rotate-max-files=<value>
     Maximum number of log file archives to keep

  -node=<value>
     Name of this node. Must be unique in the cluster.

  -node-id=<value>
     A unique ID for this node across space and time. Defaults to a
     randomly-generated ID that persists in the data-dir.

  -node-meta=<key:value>
     An arbitrary metadata key/value pair for this node, of the format
     `key:value`. Can be specified multiple times.

  -non-voting-server
     (Enterprise-only) This flag is used to make the server not
     participate in the Raft quorum, and have it only receive the data
     replication stream. This can be used to add read scalability to
     a cluster in cases where a high volume of reads to servers are
     needed.

  -pid-file=<value>
     Path to file to store agent PID.

  -protocol=<value>
     Sets the protocol version. Defaults to latest.

  -raft-protocol=<value>
     Sets the Raft protocol version. Defaults to latest.

  -recursor=<value>
     Address of an upstream DNS server. Can be specified multiple times.

  -rejoin
     Ignores a previous leave and attempts to rejoin the cluster.

  -retry-interval=<value>
     Time to wait between join attempts.

  -retry-interval-wan=<value>
     Time to wait between join -wan attempts.

  -retry-join=<value>
     Address of an agent to join at start time with retries enabled. Can
     be specified multiple times.

  -retry-join-wan=<value>
     Address of an agent to join -wan at start time with retries
     enabled. Can be specified multiple times.

  -retry-max=<value>
     Maximum number of join attempts. Defaults to 0, which will retry
     indefinitely.

  -retry-max-wan=<value>
     Maximum number of join -wan attempts. Defaults to 0, which will
     retry indefinitely.

  -segment=<value>
     (Enterprise-only) Sets the network segment to join.

  -serf-lan-bind=<value>
     Address to bind Serf LAN listeners to.

  -serf-lan-port=<value>
     Sets the Serf LAN port to listen on.

  -serf-wan-bind=<value>
     Address to bind Serf WAN listeners to.

  -serf-wan-port=<value>
     Sets the Serf WAN port to listen on.

  -server
     Switches agent to server mode.

  -server-port=<value>
     Sets the server port to listen on.

  -syslog
     Enables logging to syslog.

  -ui
     Enables the built-in static web UI server.

  -ui-content-path=<value>
     Sets the external UI path to a string. Defaults to: /ui/

  -ui-dir=<value>
     Path to directory containing the web UI resources.

consul –help

$ docker run -it --rm consul:1.6.1 --help
Usage: consul [--version] [--help] <command> [<args>]

Available commands are:
    acl            Interact with Consul's ACLs
    agent          Runs a Consul agent
    catalog        Interact with the catalog
    config         Interact with Consul's Centralized Configurations
    connect        Interact with Consul Connect
    debug          Records a debugging archive for operators
    event          Fire a new event
    exec           Executes a command on Consul nodes
    force-leave    Forces a member of the cluster to enter the "left" state
    info           Provides debugging information for operators.
    intention      Interact with Connect service intentions
    join           Tell Consul agent to join cluster
    keygen         Generates a new encryption key
    keyring        Manages gossip layer encryption keys
    kv             Interact with the key-value store
    leave          Gracefully leaves the Consul cluster and shuts down
    lock           Execute a command holding a lock
    login          Login to Consul using an auth method
    logout         Destroy a Consul token created with login
    maint          Controls node or service maintenance mode
    members        Lists the members of a Consul cluster
    monitor        Stream logs from a Consul agent
    operator       Provides cluster-level tools for Consul operators
    reload         Triggers the agent to reload configuration files
    rtt            Estimates network round trip time between nodes
    services       Interact with services
    snapshot       Saves, restores and inspects snapshots of Consul server state
    tls            Builtin helpers for creating CAs and certificates
    validate       Validate config files/directories
    version        Prints the Consul version
    watch          Watch for changes in Consul

EOF