Skip to content

Latest commit

 

History

History
578 lines (520 loc) · 15.6 KB

discovery-chain.mdx

File metadata and controls

578 lines (520 loc) · 15.6 KB
layout page_title description
api
Discovery Chain - HTTP API
The /discovery-chain endpoints are for interacting with the discovery chain.

Discovery Chain HTTP Endpoint

-> 1.6.0+: The discovery chain API is available in Consul versions 1.6.0 and newer.

~> This is a low-level API primarily targeted at developers building external Connect proxy integrations. Future high-level proxy integration APIs may obviate the need for this API over time.

The /discovery-chain endpoint returns the compiled discovery chain for a service.

This will fetch all related configuration entries and render them into a form suitable for use by a connect proxy implementation. This is a key component of L7 Traffic Management.

Read Compiled Discovery Chain

If overrides are needed they are passed as the JSON-encoded request body and the POST method must be used, otherwise GET is sufficient.

Method Path Produces
GET /discovery-chain/:service_name application/json
POST1 /discovery-chain/:service_name application/json

1 Both GET and POST are for read operations. GET requests do not permit request bodies so a POST is required if override parameters are needed.

The table below shows this endpoint's support for blocking queries, consistency modes, agent caching, and required ACLs.

Blocking Queries Consistency Modes Agent Caching ACL Required
YES all background refresh service:read

Path Parameters

  • service_name (string: <required>) - Specifies the service to query when compiling the discovery chain.

Query Parameters

JSON Request Body Schema

  • OverrideConnectTimeout (duration: 0s) - Overrides the final connect timeout for any service resolved in the compiled chain.

    This value comes from the connect_timeout_ms key in an upstream configuration opaque config parameter.

  • OverrideProtocol (string: "") - Overrides the final protocol used in the compiled discovery chain.

    If the chain ordinarily would be TCP and an L7 protocol is passed here the chain will still not include Routers or Splitters. If the chain ordinarily would be L7 and TCP is passed here the chain will not include Routers or Splitters.

    This value comes from the protocol key in an upstream configuration opaque config parameter.

  • OverrideMeshGateway (MeshGatewayConfig: <optional>) - Overrides the final mesh gateway configuration for this any service resolved in the compiled chain.

    This value comes from either the proxy configuration mesh_gateway parameter or an upstream configuration mesh_gateway parameter. If both are present the value defined on the upstream is used.

    • Mode (string: "") - One of none, local, or remote.

Sample Compilations

Full documentation for the output fields is found on the discovery chain internals page.

Multi-Datacenter Failover

Config entries defined:

kind            = "service-resolver"
name            = "web"
connect_timeout = "15s"
failover = {
  "*" = {
    datacenters = ["dc3", "dc4"]
  }
}

Request:

$ curl http://127.0.0.1:8500/v1/discovery-chain/web

Response:

{
  "Chain": {
    "ServiceName": "web",
    "Namespace": "default",
    "Datacenter": "dc1",
    "Protocol": "tcp",
    "StartNode": "resolver:web.default.dc1",
    "Nodes": {
      "resolver:web.default.dc1": {
        "Type": "resolver",
        "Name": "web.default.dc1",
        "Resolver": {
          "ConnectTimeout": "15s",
          "Target": "web.default.dc1",
          "Failover": {
            "Targets": ["web.default.dc3", "web.default.dc4"]
          }
        }
      }
    },
    "Targets": {
      "web.default.dc1": {
        "ID": "web.default.dc1",
        "Service": "web",
        "Namespace": "default",
        "Datacenter": "dc1",
        "MeshGateway": {},
        "Subset": {},
        "SNI": "web.default.dc1.internal.47e25151-6212-ba25-8b7e-81adbbbab461.consul",
        "Name": "web.default.dc1.internal.47e25151-6212-ba25-8b7e-81adbbbab461.consul"
      },
      "web.default.dc3": {
        "ID": "web.default.dc3",
        "Service": "web",
        "Namespace": "default",
        "Datacenter": "dc3",
        "MeshGateway": {},
        "Subset": {},
        "SNI": "web.default.dc3.internal.47e25151-6212-ba25-8b7e-81adbbbab461.consul",
        "Name": "web.default.dc3.internal.47e25151-6212-ba25-8b7e-81adbbbab461.consul"
      },
      "web.default.dc4": {
        "ID": "web.default.dc4",
        "Service": "web",
        "Namespace": "default",
        "Datacenter": "dc4",
        "MeshGateway": {},
        "Subset": {},
        "SNI": "web.default.dc4.internal.47e25151-6212-ba25-8b7e-81adbbbab461.consul",
        "Name": "web.default.dc4.internal.47e25151-6212-ba25-8b7e-81adbbbab461.consul"
      }
    }
  }
}

Datacenter Redirect with Overrides

Config entries defined:

kind            = "service-resolver"
name            = "web"
redirect {
  datacenter = "dc2"
}

Request:

$ curl --request POST \
    --data '
{
    "OverrideConnectTimeout": "7s",
    "OverrideProtocol": "grpc",
    "OverrideMeshGateway": {
        "Mode": "remote"
    }
}
' http://127.0.0.1:8500/v1/discovery-chain/web

Response:

{
  "Chain": {
    "ServiceName": "web",
    "Namespace": "default",
    "Datacenter": "dc1",
    "CustomizationHash": "b94f529a",
    "Protocol": "grpc",
    "StartNode": "resolver:web.default.dc2",
    "Nodes": {
      "resolver:web.default.dc2": {
        "Type": "resolver",
        "Name": "web.default.dc2",
        "Resolver": {
          "ConnectTimeout": "7s",
          "Target": "web.default.dc2"
        }
      }
    },
    "Targets": {
      "web.default.dc2": {
        "ID": "web.default.dc2",
        "Service": "web",
        "Namespace": "default",
        "Datacenter": "dc2",
        "MeshGateway": {
          "Mode": "remote"
        },
        "Subset": {},
        "SNI": "web.default.dc2.internal.59c17fd4-8dfa-f54a-ae71-855b26faf637.consul",
        "Name": "web.default.dc2.internal.59c17fd4-8dfa-f54a-ae71-855b26faf637.consul"
      }
    }
  }
}

Version Split For Alternate Datacenter

Config entries defined:

kind           = "service-resolver"
name           = "web"
default_subset = "v1"
subsets = {
  "v1" = {
    filter = "Service.Meta.version == v1"
  }
  "v2" = {
    filter = "Service.Meta.version == v2"
  }
}
# ---------------------------
kind = "service-defaults"
name = "web"
protocol = "http"
# ---------------------------
kind = "service-splitter"
name = "web"
splits = [
  {
    weight         = 90
    service_subset = "v1"
  },
  {
    weight         = 10
    service_subset = "v2"
  },
]

Request:

$ curl http://127.0.0.1:8500/v1/discovery-chain/web?compile-dc=dc2

Response:

{
  "Chain": {
    "ServiceName": "web",
    "Namespace": "default",
    "Datacenter": "dc2",
    "Protocol": "http",
    "StartNode": "splitter:web",
    "Nodes": {
      "resolver:v1.web.default.dc2": {
        "Type": "resolver",
        "Name": "v1.web.default.dc2",
        "Resolver": {
          "ConnectTimeout": "5s",
          "Target": "v1.web.default.dc2"
        }
      },
      "resolver:v2.web.default.dc2": {
        "Type": "resolver",
        "Name": "v2.web.default.dc2",
        "Resolver": {
          "ConnectTimeout": "5s",
          "Target": "v2.web.default.dc2"
        }
      },
      "splitter:web": {
        "Type": "splitter",
        "Name": "web",
        "Splits": [
          {
            "Weight": 90,
            "NextNode": "resolver:v1.web.default.dc2"
          },
          {
            "Weight": 10,
            "NextNode": "resolver:v2.web.default.dc2"
          }
        ]
      }
    },
    "Targets": {
      "v1.web.default.dc2": {
        "ID": "v1.web.default.dc2",
        "Service": "web",
        "ServiceSubset": "v1",
        "Namespace": "default",
        "Datacenter": "dc2",
        "MeshGateway": {},
        "Subset": {
          "Filter": "Service.Meta.version == v1"
        },
        "SNI": "v1.web.default.dc2.internal.6c9594ec-d798-28b9-d084-aa03e81cf078.consul",
        "Name": "v1.web.default.dc2.internal.6c9594ec-d798-28b9-d084-aa03e81cf078.consul"
      },
      "v2.web.default.dc2": {
        "ID": "v2.web.default.dc2",
        "Service": "web",
        "ServiceSubset": "v2",
        "Namespace": "default",
        "Datacenter": "dc2",
        "MeshGateway": {},
        "Subset": {
          "Filter": "Service.Meta.version == v2"
        },
        "SNI": "v2.web.default.dc2.internal.6c9594ec-d798-28b9-d084-aa03e81cf078.consul",
        "Name": "v2.web.default.dc2.internal.6c9594ec-d798-28b9-d084-aa03e81cf078.consul"
      }
    }
  }
}

HTTP Path Routing

Config entries defined:

kind           = "service-resolver"
name           = "web"
subsets = {
  "canary" = {
    filter = "Service.Meta.flavor == canary"
  }
}
# ---------------------------
kind = "proxy-defaults"
name = "web"
config {
  protocol = "http"
}
# ---------------------------
kind = "service-router"
name = "web"
routes = [
  {
    match {
      http {
        path_prefix = "/admin"
      }
    }
    destination {
      service         = "admin"
      prefix_rewrite  = "/"
      request_timeout = "15s"
    }
  },
  {
    match {
      http {
        header = [
          {
            name  = "x-debug"
            exact = "1"
          },
        ]
      }
    }
    destination {
      service                  = "web"
      service_subset           = "canary"
      num_retries              = 5
      retry_on_connect_failure = true
      retry_on_status_codes    = [401, 409]
    }
  },
]

Request:

$ curl http://127.0.0.1:8500/v1/discovery-chain/web

Response:

{
  "Chain": {
    "ServiceName": "web",
    "Namespace": "default",
    "Datacenter": "dc1",
    "Protocol": "http",
    "StartNode": "router:web",
    "Nodes": {
      "resolver:admin.default.dc1": {
        "Type": "resolver",
        "Name": "admin.default.dc1",
        "Resolver": {
          "ConnectTimeout": "5s",
          "Default": true,
          "Target": "admin.default.dc1"
        }
      },
      "resolver:canary.web.default.dc1": {
        "Type": "resolver",
        "Name": "canary.web.default.dc1",
        "Resolver": {
          "ConnectTimeout": "5s",
          "Target": "canary.web.default.dc1"
        }
      },
      "resolver:web.default.dc1": {
        "Type": "resolver",
        "Name": "web.default.dc1",
        "Resolver": {
          "ConnectTimeout": "5s",
          "Target": "web.default.dc1"
        }
      },
      "router:web": {
        "Type": "router",
        "Name": "web",
        "Routes": [
          {
            "Definition": {
              "Match": {
                "HTTP": {
                  "PathPrefix": "/admin"
                }
              },
              "Destination": {
                "RequestTimeout": "15s",
                "Service": "admin",
                "PrefixRewrite": "/"
              }
            },
            "NextNode": "resolver:admin.default.dc1"
          },
          {
            "Definition": {
              "Match": {
                "HTTP": {
                  "Header": [
                    {
                      "Name": "x-debug",
                      "Exact": "1"
                    }
                  ]
                }
              },
              "Destination": {
                "Service": "web",
                "ServiceSubset": "canary",
                "NumRetries": 5,
                "RetryOnConnectFailure": true,
                "RetryOnStatusCodes": [401, 409]
              }
            },
            "NextNode": "resolver:canary.web.default.dc1"
          },
          {
            "Definition": {
              "Match": {
                "HTTP": {
                  "PathPrefix": "/"
                }
              },
              "Destination": {
                "Service": "web"
              }
            },
            "NextNode": "resolver:web.default.dc1"
          }
        ]
      }
    },
    "Targets": {
      "admin.default.dc1": {
        "ID": "admin.default.dc1",
        "Service": "admin",
        "Namespace": "default",
        "Datacenter": "dc1",
        "MeshGateway": {},
        "Subset": {},
        "SNI": "admin.default.dc1.internal.fce8a058-0981-2c04-d23c-b7375af64ce8.consul",
        "Name": "admin.default.dc1.internal.fce8a058-0981-2c04-d23c-b7375af64ce8.consul"
      },
      "canary.web.default.dc1": {
        "ID": "canary.web.default.dc1",
        "Service": "web",
        "ServiceSubset": "canary",
        "Namespace": "default",
        "Datacenter": "dc1",
        "MeshGateway": {},
        "Subset": {
          "Filter": "Service.Meta.flavor == canary"
        },
        "SNI": "canary.web.default.dc1.internal.fce8a058-0981-2c04-d23c-b7375af64ce8.consul",
        "Name": "canary.web.default.dc1.internal.fce8a058-0981-2c04-d23c-b7375af64ce8.consul"
      },
      "web.default.dc1": {
        "ID": "web.default.dc1",
        "Service": "web",
        "Namespace": "default",
        "Datacenter": "dc1",
        "MeshGateway": {},
        "Subset": {},
        "SNI": "web.default.dc1.internal.fce8a058-0981-2c04-d23c-b7375af64ce8.consul",
        "Name": "web.default.dc1.internal.fce8a058-0981-2c04-d23c-b7375af64ce8.consul"
      }
    }
  }
}

Methods to Specify Namespace

The discovery chain endpoint supports several methods for specifying the namespace to use as the basis of discovery chain compilation with the following order of precedence:

  1. ns query parameter
  2. X-Consul-Namespace request header
  3. Namespace is inherited from the namespace of the request's ACL token (if any)
  4. The default namespace