Automate services and nodes relation

Hi community,

I am a bit confused by the consul documentation and training materials.
I also browsed this category for an answer without success.

I basically would like to register a prometeus service having two nodes automatically at the end of the consul cluster setup.

I followed the instructions of the https://learn.hashicorp.com/consul/getting-started/services leaning material.

cat /tmp/prometheus.json 
{
"services": [
  {
    "address": "10.0.0.42",
    "name": "prometheus",
    "tags": ["prometheus"],
    "port": 443,
    "id": "prometheus-dev-0"
  },
  {
    "address": "10.0.0.43",
    "name": "prometheus",
    "tags": ["prometheus"],
    "port": 443,
    "id": "prometheus-dev-1"
  }]
}

registering over the consul cli:

consul services register /tmp/prometheus.json
Registered service: prometheus
Registered service: prometheus

testing it out with ping also works fine balancing between 42 and 43 ips.
Yet the consul catalog nodes does not have appropriate nodes assigned, not prometheus-dev-0 neither prometheus-dev-1 are registered.

Searching about a way to then automate the node registration, I did not find anything in the consul cli.

After some more digging I found out that for registering external nodes, the following API documents it, https://www.consul.io/api/catalog.html#register-entity

cat /tmp/node0.json /tmp/node1.json 
{
  "Node": "prometheus-dev-0", 
  "Address": "10.0.0.42"
}
{
  "Node": "prometheus-dev-1", 
  "Address": "10.0.0.43"
}

# note we cannot register 2 nodes at the same time within one node.json file ?!
curl --header "X-Consul-Token: $CONSUL_HTTP_TOKEN" --request PUT --data @/tmp/node0.json https://localhost:8501/v1/catalog/register
curl --header "X-Consul-Token: $CONSUL_HTTP_TOKEN" --request PUT --data @/tmp/node1.json https://localhost:8501/v1/catalog/register

then I now can ping the nodes using the prometheus-dev-0.node.

Still when I dump the catalog configuration:

curl -sq https://consul.service.<fqdn>:8501/v1/catalog/service/prometheus | jq

I can see that the first section where the nodes are defined are holding the consul node ip not any external node ip related to the prometheus service:

[
  {
    "ID": "b9...",
    "Node": "consul-dev-1",
    "Address": "10.0.0.23",
    "Datacenter": "infra-dev",
    "TaggedAddresses": {
      "lan": "10.0.0.23",
      "wan": "10.0.0.23"
    },
    "NodeMeta": {
      "consul-network-segment": ""
    },
    "ServiceKind": "",
    "ServiceID": "prometheus-dev-0",
    "ServiceName": "prometheus",
    "ServiceTags": [
      "prometheus"
    ],
    "ServiceAddress": "10.0.0.42",
    "ServiceWeights": {
      "Passing": 1,
      "Warning": 1
    },
    "ServiceMeta": {},
    "ServicePort": 443,
    "ServiceEnableTagOverride": false,
    "ServiceProxy": {
      "MeshGateway": {}
    },
    "ServiceConnect": {},
    "CreateIndex": 5211,
    "ModifyIndex": 5211
  },
  {
    "ID": "b9...",
    "Node": "consul-dev-1",
    "Address": "10.0.0.23",
    "Datacenter": "infra-dev",
    "TaggedAddresses": {
      "lan": "10.0.0.23",
      "wan": "10.0.0.23"
    },
    "NodeMeta": {
      "consul-network-segment": ""
    },
    "ServiceKind": "",
    "ServiceID": "prometheus-dev-1",
    "ServiceName": "prometheus",
    "ServiceTags": [
      "prometheus"
    ],
    "ServiceAddress": "10.0.0.43",
    "ServiceWeights": {
      "Passing": 1,
      "Warning": 1
    },
    "ServiceMeta": {},
    "ServicePort": 443,
    "ServiceEnableTagOverride": false,
    "ServiceProxy": {
      "MeshGateway": {}
    },
    "ServiceConnect": {},
    "CreateIndex": 5212,
    "ModifyIndex": 5212
  }
]

In the ui the same the Node is the one consul agent.

inverting the order first registering the nodes and then the services does not change anything. What did I miss?

Concerning the automation, is there a way to register nodes and services within one json file, like importing the previously json output of https://consul.service.<fqdn>:8501/v1/catalog/service/prometheus in a nodes-services.json file and fire up:

curl --header "X-Consul-Token: $CONSUL_HTTP_TOKEN" --request PUT --data @nodes-services.json https://localhost:8501/v1/catalog/register

If possible would these json be part of the /etc/consul.d/ configuration directory?

I mean installing vault on top of the consul cluster seems to do some magic are the nodes and the services correspond, how can this be achieved?

I am glad for any help?

If I’m understanding correctly, you are registering two services on nodes that do not have Consul clients. If that is correct, we have a guide specifically for this common use case. You should be able to register the node and service in the same file at the same time.

Thanks for pointing out this documentation, I was now able to add some external nodes and assign them to services.
Still I had to separate them into two separate calls:

cat /etc/consul.d/prometheus-dev-0.json
{
  "Node": "prometheus-dev-0",
  "Address": "10.0.0.42",
  "NodeMeta": {
    "external-node": "true",
    "external-probe": "true"
  },
  "Service": {
    "ID": "prometheus-dev-0",
    "Service": "prometheus",
    "Port": 443
  },
  "Checks": [
    {
      "Name": "http-check",
      "status": "passing",
      "Definition": {
        "http": "https://prometheus-dev-0.node.infra-dev.consul",
        "interval": "30s"
      }
    }
  ]
}

executing curl:

curl --header "X-Consul-Token:$CONSUL_HTTP_TOKEN" --request PUT --data @/etc/consul.d/prometheus-dev-0.json https://localhost:8501/v1/catalog/register'
curl --header "X-Consul-Token:$CONSUL_HTTP_TOKEN" --request PUT --data @/etc/consul.d/prometheus-dev-1.json https://localhost:8501/v1/catalog/register'

resulted in the service declared accordingly in the ui

Note that the Address field seems to be incomplete as it just has the port definition, maybe it’s a “ServiceAddress” parameter missing in the definition…

Thanks for the help.