diff --git a/website/raw-assets/l7-traffic-stages.fig b/website/raw-assets/l7-traffic-stages.fig
new file mode 100644
index 0000000000..7907af8e2b
Binary files /dev/null and b/website/raw-assets/l7-traffic-stages.fig differ
diff --git a/website/source/assets/images/l7-traffic-stages.svg b/website/source/assets/images/l7-traffic-stages.svg
new file mode 100644
index 0000000000..5f90fbf17c
--- /dev/null
+++ b/website/source/assets/images/l7-traffic-stages.svg
@@ -0,0 +1,49 @@
+
diff --git a/website/source/docs/agent/config-entries/proxy-defaults.html.md b/website/source/docs/agent/config-entries/proxy-defaults.html.md
new file mode 100644
index 0000000000..ba847bbb23
--- /dev/null
+++ b/website/source/docs/agent/config-entries/proxy-defaults.html.md
@@ -0,0 +1,60 @@
+---
+layout: "docs"
+page_title: "Configuration Entry Kind: Proxy Defaults"
+sidebar_current: "docs-agent-cfg_entries-proxy_defaults"
+description: |-
+ The proxy-defaults config entry kind allows for configuring global config defaults across all services for Connect proxy configuration. Currently, only one global entry is supported.
+---
+
+# Proxy Defaults
+
+The `proxy-defaults` config entry kind allows for configuring global config
+defaults across all services for Connect proxy configuration. Currently, only
+one global entry is supported.
+
+## Sample Config Entries
+
+Set the default protocol for all sidecar proxies:
+
+```hcl
+kind = "proxy-defaults"
+name = "global"
+config {
+ protocol = "http"
+}
+```
+
+Set proxy-specific defaults:
+
+```hcl
+kind = "proxy-defaults"
+name = "global"
+config {
+ local_connect_timeout_ms = 1000
+ handshake_timeout_ms = 10000
+}
+```
+
+## Available Fields
+
+- `Kind` - Must be set to `proxy-defaults`
+
+- `Name` - Must be set to `global`
+
+- `Config` `(map[string]arbitrary)` - An arbitrary map of configuration values used by Connect proxies.
+ The available configurations depend on the Connect proxy you use. Any values
+ that your proxy allows can be configured globally here. To
+ explore these options please see the documentation for your chosen proxy.
+
+ * [Envoy](/docs/connect/proxies/envoy.html#bootstrap-configuration)
+ * [Consul's built-in proxy](/docs/connect/proxies/built-in.html)
+
+## ACLs
+
+Configuration entries may be protected by
+[ACLs](https://learn.hashicorp.com/consul/security-networking/production-acls).
+
+Reading a `proxy-defaults` config entry requires no specific privileges.
+
+Creating, updating, or deleting a `proxy-defaults` config entry requires
+`operator:write`.
diff --git a/website/source/docs/agent/config-entries/service-defaults.html.md b/website/source/docs/agent/config-entries/service-defaults.html.md
new file mode 100644
index 0000000000..680276c74c
--- /dev/null
+++ b/website/source/docs/agent/config-entries/service-defaults.html.md
@@ -0,0 +1,46 @@
+---
+layout: "docs"
+page_title: "Configuration Entry Kind: Service Defaults"
+sidebar_current: "docs-agent-cfg_entries-service_defaults"
+description: |-
+ The service-defaults config entry kind controls default global values for a service, such as its protocol.
+---
+
+# Service Defaults
+
+The `service-defaults` config entry kind controls default global values for a
+service, such as its protocol.
+
+## Sample Config Entries
+
+Set the default protocol for a service to HTTP:
+
+```hcl
+Kind = "service-defaults"
+Name = "web"
+Protocol = "http"
+```
+
+## Available Fields
+
+- `Kind` - Must be set to `service-defaults`
+
+- `Name` `(string: )` - Set to the name of the service being configured.
+
+- `Protocol` `(string: "tcp")` - Sets the protocol of the service. This is used
+ by Connect proxies for things like observability features and to unlock usage
+ of the [`service-splitter`
+ (beta)](/docs/agent/config-entries/service-splitter.html) and
+ [`service-router`
+ (beta)](/docs/agent/config-entries/service-router.html) config
+ entries for a service.
+
+## ACLs
+
+Configuration entries may be protected by
+[ACLs](https://learn.hashicorp.com/consul/security-networking/production-acls).
+
+Reading a `service-defaults` config entry requires `service:read` on itself.
+
+Creating, updating, or deleting a `service-defaults` config entry requires
+`service:write` on itself.
diff --git a/website/source/docs/agent/config-entries/service-resolver.html.md b/website/source/docs/agent/config-entries/service-resolver.html.md
new file mode 100644
index 0000000000..d0a6a782d9
--- /dev/null
+++ b/website/source/docs/agent/config-entries/service-resolver.html.md
@@ -0,0 +1,185 @@
+---
+layout: "docs"
+page_title: "Configuration Entry Kind: Service Resolver (beta)"
+sidebar_current: "docs-agent-cfg_entries-service_resolver"
+description: |-
+ The `service-resolver` config entry kind controls which service instances should satisfy Connect upstream discovery requests for a given service name.
+---
+
+# Service Resolver (beta)
+
+The `service-resolver` config entry kind controls which service instances
+should satisfy Connect upstream discovery requests for a given service name.
+
+If no resolver config is defined the chain assumes 100% of traffic goes to the
+healthy instances of the default service in the current datacenter+namespace
+and discovery terminates.
+
+## Interaction with other Config Entries
+
+- Service resolver config entries are a component of [L7 Traffic
+ Management](/docs/connect/l7-traffic-management.html).
+
+## Sample Config Entries
+
+Create service subsets based on a version metadata and override the defaults:
+
+```hcl
+kind = "service-resolver"
+name = "web"
+default_subset = "v1"
+subsets = {
+ "v1" = {
+ filter = "Service.Meta.version == v1"
+ }
+ "v2" = {
+ filter = "Service.Meta.version == v2"
+ }
+}
+```
+
+Expose a set of services in another datacenter as a virtual service:
+
+```hcl
+kind = "service-resolver"
+name = "web-dc2"
+redirect {
+ service = "web"
+ datacenter = "dc2"
+}
+```
+
+Enable failover for all subsets:
+
+```hcl
+kind = "service-resolver"
+name = "web"
+connect_timeout = "15s"
+failover = {
+ "*" = {
+ datacenters = ["dc3", "dc4"]
+ }
+}
+```
+
+Representation of the defaults when a resolver is not configured:
+
+```hcl
+kind = "service-resolver"
+name = "web"
+```
+
+## Available Fields
+
+- `Kind` - Must be set to `service-resolver`
+
+- `Name` `(string: )` - Set to the name of the service being configured.
+
+- `ConnectTimeout` `(duration: 0s)` - The timeout for establishing new network
+ connections to this service.
+
+- `DefaultSubset` `(string: "")` - The subset to use when no explicit subset is
+ requested. If empty the unnamed subset is used.
+
+- `Subsets` `(map[string]ServiceResolverSubset)` - A map of subset name to
+ subset definition for all usable named subsets of this service. The map key
+ is the name of the subset and all names must be valid DNS subdomain elements.
+
+ This may be empty, in which case only the unnamed default subset will be
+ usable.
+
+ - `Filter` `(string: "")` - The
+ [filter expression](/api/features/filtering.html) to be used for selecting
+ instances of the requested service. If empty all healthy instances are
+ returned.
+
+ - `OnlyPassing` `(bool: false)` - Specifies the behavior of the resolver's
+ health check filtering. If this is set to false, the results will include
+ instances with checks in the passing as well as the warning states. If this
+ is set to true, only instances with checks in the passing state will be
+ returned.
+
+- `Redirect` `(ServiceResolverRedirect: )` - When configured, all
+ attempts to resolve the service this resolver defines will be substituted for
+ the supplied redirect EXCEPT when the redirect has already been applied.
+
+ When substituting the supplied redirect into the all other fields besides
+ `Kind`, `Name`, and `Redirect` will be ignored.
+
+ - `Service` `(string: "")` - A service to resolve instead of the current
+ service.
+
+ - `ServiceSubset` `(string: "")` - A named subset of the given service to
+ resolve instead of one defined as that service's DefaultSubset If empty the
+ default subset is used.
+
+ If this is specified at least one of Service, Datacenter, or Namespace
+ should be configured.
+
+ - `Namespace` `(string: "")` - The namespace to resolve the service from
+ instead of the current one.
+
+ - `Datacenter` `(string: "")` - The datacenter to resolve the service from
+ instead of the current one.
+
+- `Failover` `(map[string]ServiceResolverFailover`) - Controls when and how to
+ reroute traffic to an alternate pool of service instances.
+
+ The map is keyed by the service subset it applies to and the special
+ string `"*"` is a wildcard that applies to any subset not otherwise
+ specified here.
+
+ `Service`, `ServiceSubset`, `Namespace`, and `Datacenters` cannot all be
+ empty at once.
+
+ - `Service` `(string: "")` - The service to resolve instead of the default as
+ the failover group of instances during failover.
+
+ - `ServiceSubset` `(string: "")` - The named subset of the requested service
+ to resolve as the failover group of instances. If empty the default subset
+ for the requested service is used.
+
+ - `Namespace` `(string: "")` - The namespace to resolve the requested service
+ from to form the failover group of instances. If empty the current
+ namespace is used.
+
+ - `Datacenters` `(array)` - A fixed list of datacenters to try during
+ failover.
+
+ - `OverprovisioningFactor` `(int: 0)` - OverprovisioningFactor is a pass
+ through for envoy's
+ [`overprovisioning_factor`](https://www.envoyproxy.io/docs/envoy/v1.10.0/intro/arch_overview/load_balancing/priority)
+ value.
+
+ If omitted the overprovisioning factor value will be set so high as to
+ imply binary failover (all or nothing).
+
+## Service Subsets
+
+A service subset assigns a concrete name to a specific subset of discoverable
+service instances within a datacenter, such as `"version2"` or `"canary"`.
+
+A service subset name is useful only when composed with an actual service name,
+a specific datacenter, and namespace.
+
+All services have an unnamed default subset that will return all healthy
+instances unfiltered.
+
+Subsets are defined in `service-resolver` configuration entries, but are
+referenced by their names throughout the other configuration entry kinds.
+
+## ACLs
+
+Configuration entries may be protected by
+[ACLs](https://learn.hashicorp.com/consul/security-networking/production-acls).
+
+Reading a `service-resolver` config entry requires `service:read` on itself.
+
+Creating, updating, or deleting a `service-resolver` config entry requires
+`service:write` on itself and `service:read` on any other service referenced by
+name in these fields:
+
+- [`Redirect.Service`](#service)
+
+- [`Failover[].Service`](#service-1)
+
diff --git a/website/source/docs/agent/config-entries/service-router.html.md b/website/source/docs/agent/config-entries/service-router.html.md
new file mode 100644
index 0000000000..59860b6597
--- /dev/null
+++ b/website/source/docs/agent/config-entries/service-router.html.md
@@ -0,0 +1,233 @@
+---
+layout: "docs"
+page_title: "Configuration Entry Kind: Service Router (beta)"
+sidebar_current: "docs-agent-cfg_entries-service_router"
+description: |-
+ The service-router config entry kind controls Connect traffic routing and manipulation at networking layer 7 (e.g. HTTP).
+---
+
+# Service Router (beta)
+
+The `service-router` config entry kind controls Connect traffic routing and
+manipulation at networking layer 7 (e.g. HTTP).
+
+If a router is not explicitly configured or is configured with no routes then
+the system behaves as if a router were configured sending all traffic to a
+service of the same name.
+
+## Interaction with other Config Entries
+
+- Service router config entries are a component of [L7 Traffic
+ Management](/docs/connect/l7-traffic-management.html).
+
+- Service router config entries are restricted to only services that define
+ their protocol as http-based via a corresponding
+ [`service-defaults`](/docs/agent/config-entries/service-defaults.html) config
+ entry or globally via
+ [`proxy-defaults`](/docs/agent/config-entries/proxy-defaults.html) .
+
+- Any route destination that omits the `ServiceSubset` field is eligible for
+ splitting via a
+ [`service-splitter`](/docs/agent/config-entries/service-splitter.html) should
+ one be configured for that service, otherwise resolution proceeds according
+ to any configured
+ [`service-resolver`](/docs/agent/config-entries/service-resolver.html).
+
+## Sample Config Entries
+
+Route HTTP requests with a path starting with `/admin` to a different service:
+
+```hcl
+kind = "service-router"
+name = "web"
+routes = [
+ {
+ match {
+ http {
+ path_prefix = "/admin"
+ }
+ }
+
+ destination {
+ service = "admin"
+ }
+ },
+ # NOTE: a default catch-all will send unmatched traffic to "web"
+]
+```
+
+Route HTTP requests with a special url parameter or header to a canary subset:
+
+```hcl
+kind = "service-router"
+name = "web"
+routes = [
+ {
+ match {
+ http {
+ header = [
+ {
+ name = "x-debug"
+ exact = "1"
+ },
+ ]
+ }
+ }
+ destination {
+ service = "web"
+ service_subset = "canary"
+ }
+ },
+ {
+ match {
+ http {
+ query_param = [
+ {
+ name = "x-debug"
+ value = "1"
+ },
+ ]
+ }
+ }
+ destination {
+ service = "web"
+ service_subset = "canary"
+ }
+ },
+ # NOTE: a default catch-all will send unmatched traffic to "web"
+]
+```
+
+## Available Fields
+
+- `Kind` - Must be set to `service-router`
+
+- `Name` `(string: )` - Set to the name of the service being configured.
+
+- `Routes` `(array)` - The list of routes to consider when
+ processing L7 requests. The first route to match in the list is terminal and
+ stops further evaluation. Traffic that fails to match any of the provided
+ routes will be routed to the default service.
+
+ - `Match` `(ServiceRouteMatch: )` - A set of criteria that can
+ match incoming L7 requests. If empty or omitted it acts as a catch-all.
+
+ - `HTTP` `(ServiceRouteHTTPMatch: )` - A set of http-specific match criteria.
+
+ - `PathExact` `(string: "")` - Exact path to match on the HTTP request path.
+
+ At most only one of `PathExact`, `PathPrefix`, or `PathRegex` may be configured.
+
+ - `PathPrefix` `(string: "")` - Path prefix to match on the HTTP request path.
+
+ At most only one of `PathExact`, `PathPrefix`, or `PathRegex` may be configured.
+
+ - `PathRegex` `(string: "")` - Regular expression to match on the HTTP
+ request path.
+
+ The syntax when using the Envoy proxy is [documented here](https://en.cppreference.com/w/cpp/regex/ecmascript).
+
+ At most only one of `PathExact`, `PathPrefix`, or `PathRegex` may be configured.
+
+ - `Header` `(array)` - A set of criteria
+ that can match on HTTP request headers. If more than one is configured
+ all must match for the overall match to apply.
+
+ - `Name` `(string: )` - Name of the header to match on.
+
+ - `Present` `(bool: false)` - Match if the header with the given name
+ is present with any value.
+
+ At most only one of `Exact`, `Prefix`, `Suffix`, `Regex`, or
+ `Present` may be configured.
+
+ - `Exact` `(string: "")` - Match if the header with the given name is
+ this value.
+
+ At most only one of `Exact`, `Prefix`, `Suffix`, `Regex`, or
+ `Present` may be configured.
+
+ - `Prefix` `(string: "")` - Match if the header with the given name has
+ this prefix.
+
+ At most only one of `Exact`, `Prefix`, `Suffix`, `Regex`, or
+ `Present` may be configured.
+
+ - `Suffix` `(string: "")` - Match if the header with the given name has
+ this suffix.
+
+ At most only one of `Exact`, `Prefix`, `Suffix`, `Regex`, or
+ `Present` may be configured.
+
+ - `Regex` `(string: "")` - Match if the header with the given name
+ matches this pattern.
+
+ The syntax when using the Envoy proxy is [documented here](https://en.cppreference.com/w/cpp/regex/ecmascript).
+
+ At most only one of `Exact`, `Prefix`, `Suffix`, `Regex`, or
+ `Present` may be configured.
+
+ - `Invert` `(bool: false)` - Inverts the logic of the match.
+
+ - `QueryParam` `(array)` - A set of
+ criteria that can match on HTTP query parameters. If more than one is
+ configured all must match for the overall match to apply.
+
+ - `Name` `(string: )` - The name of the query parameter to
+ match on.
+
+ - `Value` `(string: )` - String to match against the query
+ parameter value. The behavior changes with the definition of the
+ `Regex` field.
+
+ - `Regex` `(bool: false)` - Controls how the `Value` field is used. If
+ `Regex` is `false` then `Value` matches exactly. If `Regex` is
+ `true` then `Value` matches as a regular expression pattern.
+
+ The syntax when using the Envoy proxy is [documented
+ here](https://en.cppreference.com/w/cpp/regex/ecmascript).
+
+ - `Destination` `(ServiceRouteDestination: )` - Controls how to
+ proxy the actual matching request to a service.
+
+ - `Service` `(string: "")` - The service to resolve instead of the default
+ service. If empty then the default service name is used.
+
+ - `ServiceSubset` `(string: "")` - A named subset of the given service to
+ resolve instead of one defined as that service's `DefaultSubset`. If
+ empty the default subset is used.
+
+ - `Namespace` `(string: "")` - The namespace to resolve the service from
+ instead of the current namespace. If empty the current namespace is
+ assumed.
+
+ - `PrefixRewrite` `(string: "")` - Defines how to rewrite the http request
+ path before proxying it to its final destination.
+
+ This requires that either `Match.HTTP.PathPrefix` or
+ `Match.HTTP.PathExact` be configured on this route.
+
+ - `RequestTimeout` `(duration: 0s)` - The total amount of time permitted
+ for the entire downstream request (and retries) to be processed.
+
+ - `NumRetries` `(int: 0)` - The number of times to retry the request when a
+ retryable result occurs.
+
+ - `RetryOnConnectFailure` `(bool: false)` - Allows for connection failure
+ errors to trigger a retry.
+
+ - `RetryOnStatusCodes` `(array)` - A flat list of http response status
+ codes that are eligible for retry.
+
+## ACLs
+
+Configuration entries may be protected by
+[ACLs](https://learn.hashicorp.com/consul/security-networking/production-acls).
+
+Reading a `service-router` config entry requires `service:read` on itself.
+
+Creating, updating, or deleting a `service-router` config entry requires
+`service:write` on itself and `service:read` on any other service referenced by
+name in these fields:
+
+- [`Routes[].Destination.Service`](#service)
diff --git a/website/source/docs/agent/config-entries/service-splitter.html.md b/website/source/docs/agent/config-entries/service-splitter.html.md
new file mode 100644
index 0000000000..778d24cf48
--- /dev/null
+++ b/website/source/docs/agent/config-entries/service-splitter.html.md
@@ -0,0 +1,108 @@
+---
+layout: "docs"
+page_title: "Configuration Entry Kind: Service Splitter (beta)"
+sidebar_current: "docs-agent-cfg_entries-service_splitter"
+description: |-
+ The service-splitter config entry kind controls how to split incoming Connect requests across different subsets of a single service (like during staged canary rollouts), or perhaps across different services (like during a v2 rewrite or other type of codebase migration).
+---
+
+# Service Splitter (beta)
+
+The `service-splitter` config entry kind controls how to split incoming Connect
+requests across different subsets of a single service (like during staged
+canary rollouts), or perhaps across different services (like during a v2
+rewrite or other type of codebase migration).
+
+If no splitter config is defined for a service it is assumed 100% of traffic
+flows to a service with the same name and discovery continues on to the
+resolution stage.
+
+## Interaction with other Config Entries
+
+- Service splitter config entries are a component of [L7 Traffic
+ Management](/docs/connect/l7-traffic-management.html).
+
+- Service splitter config entries are restricted to only services that define
+ their protocol as http-based via a corresponding
+ [`service-defaults`](/docs/agent/config-entries/service-defaults.html) config
+ entry or globally via
+ [`proxy-defaults`](/docs/agent/config-entries/proxy-defaults.html) .
+
+- Any split destination that specifies a different `Service` field and omits
+ the `ServiceSubset` field is eligible for further splitting should a splitter
+ be configured for that other service, otherwise resolution proceeds according
+ to any configured
+ [`service-resolver`](/docs/agent/config-entries/service-resolver.html).
+
+## Sample Config Entries
+
+Split traffic between two subsets of the same service:
+
+```hcl
+kind = "service-splitter"
+name = "web"
+splits = [
+ {
+ weight = 90
+ service_subset = "v1"
+ },
+ {
+ weight = 10
+ service_subset = "v2"
+ },
+]
+```
+
+Split traffic between two services:
+
+```hcl
+kind = "service-splitter"
+name = "web"
+splits = [
+ {
+ weight = 50
+ # will default to service with same name as config entry ("web")
+ },
+ {
+ weight = 10
+ service = "web-rewrite"
+ },
+]
+```
+
+## Available Fields
+
+- `Kind` - Must be set to `service-splitter`
+
+- `Name` `(string: )` - Set to the name of the service being configured.
+
+- `Splits` `(array)` - Defines how much traffic to send to which
+ set of service instances during a traffic split. The sum of weights across
+ all splits must add up to 100.
+
+ - `Weight` `(float32: 0)` - A value between 0 and 100 reflecting what portion
+ of traffic should be directed to this split. The smallest representable
+ weight is 1/10000 or .01%
+
+ - `Service` `(string: "")` - The service to resolve instead of the default.
+
+ - `ServiceSubset` `(string: "")` - A named subset of the given service to
+ resolve instead of one defined as that service's `DefaultSubset`. If empty
+ the default subset is used.
+
+ - `Namespace` `(string: "")` - The namespace to resolve the service from
+ instead of the current namespace. If empty the current namespace is
+ assumed.
+
+## ACLs
+
+Configuration entries may be protected by
+[ACLs](https://learn.hashicorp.com/consul/security-networking/production-acls).
+
+Reading a `service-splitter` config entry requires `service:read` on itself.
+
+Creating, updating, or deleting a `service-splitter` config entry requires
+`service:write` on itself and `service:read` on any other service referenced by
+name in these fields:
+
+- [`Splits[].Service`](#service)
diff --git a/website/source/docs/agent/config_entries.html.md b/website/source/docs/agent/config_entries.html.md
index 4135a33c26..7a6323e2ab 100644
--- a/website/source/docs/agent/config_entries.html.md
+++ b/website/source/docs/agent/config_entries.html.md
@@ -12,7 +12,8 @@ Configuration entries can be created to provide cluster-wide defaults for
various aspects of Consul. Every configuration entry has at least two fields:
`Kind` and `Name`. Those two fields are used to uniquely identify a
configuration entry. When put into configuration files, configuration entries
-can be specified as HCL or JSON objects.
+can be specified as HCL or JSON objects using either `snake_case` or `CamelCase`
+for key names.
Example:
@@ -21,53 +22,22 @@ Kind = ""
Name = ""
```
-The two supported `Kind` configuration entries are detailed below.
+The supported `Kind` names for configuration entries are:
-## Configuration Entry Kinds
+* [`service-router` (beta)](/docs/agent/config-entries/service-router.html) - defines
+where to send layer 7 traffic based on the HTTP route
-### Proxy Defaults - `proxy-defaults`
+* [`service-splitter` (beta)](/docs/agent/config-entries/service-splitter.html) - defines
+how to divide requests for a single HTTP route based on percentages
-Proxy defaults allow for configuring global config defaults across all services
-for Connect proxy configuration. Currently, only one global entry is supported.
+* [`service-resolver` (beta)](/docs/agent/config-entries/service-resolver.html) - matches
+service instances with a specific Connect upstream discovery requests
-```hcl
-Kind = "proxy-defaults"
-Name = "global"
-Config {
- local_connect_timeout_ms = 1000
- handshake_timeout_ms = 10000
-}
-```
+* [`service-defaults`](/docs/agent/config-entries/service-defaults.html) - configures
+defaults for all the instances of a given service
-* `Kind` - Must be set to `proxy-defaults`
-
-* `Name` - Must be set to `global`
-
-* `Config` - An arbitrary map of configuration values used by Connect proxies.
- The available configurations depend on the Connect proxy you use. Any values
- that your proxy allows can be configured globally here. To
- explore these options please see the documentation for your chosen proxy.
-
- * [Envoy](/docs/connect/proxies/envoy.html#bootstrap-configuration)
- * [Consul's Builtin Proxy](/docs/connect/proxies/built-in.html)
-
-### Service Defaults - `service-defaults`
-
-Service defaults control default global values for a service, such as its
-protocol.
-
-```hcl
-Kind = "service-defaults"
-Name = "web"
-Protocol = "http"
-```
-
-* `Kind` - Must be set to `service-defaults`
-
-* `Name` - Set to the name of the service being configured.
-
-* `Protocol` - Sets the protocol of the service. This is used by Connect proxies
- for things like observability features.
+* [`proxy-defaults`](/docs/agent/config-entries/proxy-defaults.html) - controls
+proxy configuration
## Managing Configuration Entries
diff --git a/website/source/docs/connect/l7-traffic-management.html.md b/website/source/docs/connect/l7-traffic-management.html.md
new file mode 100644
index 0000000000..0a2b2fa04a
--- /dev/null
+++ b/website/source/docs/connect/l7-traffic-management.html.md
@@ -0,0 +1,118 @@
+---
+layout: "docs"
+page_title: "Connect - L7 Traffic Management (beta)"
+sidebar_current: "docs-connect-l7_traffic_management"
+description: |-
+ Layer 7 traffic management allows operators to divide L7 traffic between different subsets of service instances when using Connect.
+---
+
+# L7 Traffic Management (beta)
+
+-> **Note:** This feature is not compatible with the
+[built-in proxy](/docs/connect/proxies/built-in.html)
+or [native proxies](/docs/connect/native.html).
+
+Layer 7 traffic management allows operators to divide L7 traffic between
+different
+[subsets](/docs/agent/config-entries/service-resolver.html#service-subsets) of
+service instances when using Connect.
+
+There are many ways you may wish to carve up a single datacenter's pool of
+services beyond simply returning all healthy instances for load balancing.
+Canary testing, A/B tests, blue/green deploys, and soft multi-tenancy
+(prod/qa/staging sharing compute resources) all require some mechanism of
+carving out portions of the Consul catalog smaller than the level of a single
+service and configuring when that subset should receive traffic.
+
+## Stages
+
+Connect proxy upstreams are discovered using a series of stages: routing,
+splitting, and resolution. These stages represent different ways of managing L7
+traffic.
+
+![diagram showing l7 traffic discovery stages: routing to splitting to resolution](/assets/images/l7-traffic-stages.svg)
+
+Each stage of this discovery process can be dynamically reconfigured via various
+[configuration entries](/docs/agent/config_entries.html). When a configuration
+entry is missing, that stage will fall back on reasonable default behavior.
+
+### Routing
+
+A [`service-router`](/docs/agent/config-entries/service-router.html) config
+entry kind is the first configurable stage.
+
+A router config entry allows for a user to intercept traffic using L7 criteria
+such as path prefixes or http headers, and change behavior such as by sending
+traffic to a different service or service subset.
+
+These config entries may only reference `service-splitter` or
+`service-resolver` entries.
+
+[Examples](/docs/agent/config-entries/service-router.html#sample-config-entries)
+can be found in the `service-router` documentation.
+
+### Splitting
+
+A [`service-splitter`](/docs/agent/config-entries/service-splitter.html) config
+entry kind is the next stage after routing.
+
+A splitter config entry allows for a user to choose to split incoming requests
+across different subsets of a single service (like during staged canary
+rollouts), or perhaps across different services (like during a v2 rewrite or
+other type of codebase migration).
+
+These config entries may only reference `service-splitter` or
+`service-resolver` entries.
+
+If one splitter references another splitter the overall effects are flattened
+into one effective splitter config entry which reflects the multiplicative
+union. For instance:
+
+ splitter[A]: A_v1=50%, A_v2=50%
+ splitter[B]: A=50%, B=50%
+ ---------------------
+ splitter[effective_B]: A_v1=25%, A_v2=25%, B=50%
+
+[Examples](/docs/agent/config-entries/service-splitter.html#sample-config-entries)
+can be found in the `service-splitter` documentation.
+
+### Resolution
+
+A [`service-resolver`](/docs/agent/config-entries/service-resolver.html) config
+entry kind is the last stage.
+
+A resolver config entry allows for a user to define which instances of a
+service should satisfy discovery requests for the provided name.
+
+Examples of things you can do with resolver config entries:
+
+- Control where to send traffic if all instances of `api` in the current
+datacenter are unhealthy.
+
+- Configure service subsets based on `Service.Meta.version` values.
+
+- Send all traffic for `web` that does not specify a service subset to the
+`version1` subset.
+
+- Send all traffic for `api` to `new-api`.
+
+- Send all traffic for `api` in all datacenters to instances of `api` in `dc2`.
+
+- Create a "virtual service" `api-dc2` that sends traffic to instances of `api`
+in `dc2`. This can be referenced in upstreams or in other config entries.
+
+If no resolver config is defined for a service it is assumed 100% of traffic
+flows to the healthy instances of a service with the same name in the current
+datacenter/namespace and discovery terminates.
+
+This should feel similar in spirit to various uses of Prepared Queries, but is
+not intended to be a drop-in replacement currently.
+
+These config entries may only reference other `service-resolver` entries.
+
+[Examples](/docs/agent/config-entries/service-resolver.html#sample-config-entries)
+can be found in the `service-resolver` documentation.
+
+-> **Note:** `service-resolver` config entries kinds function at L4 (unlike
+`service-router` and `service-splitter` kinds). These can be created for
+services of any protocol such as `tcp`.
diff --git a/website/source/docs/connect/observability.html.md b/website/source/docs/connect/observability.html.md
index 84af9b2b10..680655b662 100644
--- a/website/source/docs/connect/observability.html.md
+++ b/website/source/docs/connect/observability.html.md
@@ -7,7 +7,7 @@ description: |-
Consul Connect.
---
-## Observability
+# Observability
In order to take advantage of Connect's L7 observability features you will need
to:
@@ -44,7 +44,7 @@ Find other possible metrics syncs in the [Connect Envoy documentation](/docs/con
### Service Protocol
-You can specify the [service protocol](/docs/agent/config_entries.html#protocol)
+You can specify the [service protocol](/docs/agent/config-entries/service-defaults.html#protocol)
in the `service-defaults` configuration entry. You can override it in the
[service registration](/docs/agent/services.html). By default, proxies only give
you L4 metrics. This protocol allows proxies to handle requests at the right L7
diff --git a/website/source/docs/connect/proxies/envoy.md b/website/source/docs/connect/proxies/envoy.md
index 5f6dd44654..7afac49f85 100644
--- a/website/source/docs/connect/proxies/envoy.md
+++ b/website/source/docs/connect/proxies/envoy.md
@@ -95,7 +95,7 @@ the ability to control some parts of the bootstrap config via proxy
configuration options.
Users can add the following configuration items to the [global `proxy-defaults`
-configuration entry](/docs/agent/config_entries.html#proxy-defaults-proxy-defaults) or override them directly in the `proxy.config` field
+configuration entry](/docs/agent/config-entries/proxy-defaults.html) or override them directly in the `proxy.config` field
of a [proxy service
definition](/docs/connect/registration/service-registration.html) or
[`sidecar_service`](/docs/connect/registration/sidecar-service.html) block.
@@ -104,7 +104,7 @@ definition](/docs/connect/registration/service-registration.html) or
StatsD listener that Envoy should deliver metrics to. For example, this may be
`udp://127.0.0.1:8125` if every host has a local StatsD listener. In this case
users can configure this property once in the [global `proxy-defaults`
-configuration entry](/docs/agent/config_entries.html#proxy-defaults-proxy-defaults) for convenience. Currently, TCP is not supported.
+configuration entry](/docs/agent/config-entries/proxy-defaults.html) for convenience. Currently, TCP is not supported.
~> **Note:** currently the url **must use an ip address** not a dns name due
to the way Envoy is setup for StatsD.
@@ -115,7 +115,7 @@ configuration entry](/docs/agent/config_entries.html#proxy-defaults-proxy-defaul
pod in a Kubernetes cluster to learn of a pod-specific IP address for StatsD
when the Envoy instance is bootstrapped while still allowing global
configuration of all proxies to use StatsD in the [global `proxy-defaults`
-configuration entry](/docs/agent/config_entries.html#proxy-defaults-proxy-defaults). The env variable must contain a full valid URL
+configuration entry](/docs/agent/config-entries/proxy-defaults.html). The env variable must contain a full valid URL
value as specified above and nothing else. It is not currently possible to use
environment variables as only part of the URL.
@@ -153,7 +153,7 @@ to configure appropriate proxy settings for that service's proxies and also for
the upstream listeners of any downstream service.
Users can define a service's protocol in its [`service-defaults` configuration
-entry](/docs/agent/config_entries.html#service-defaults-service-defaults). Agents with
+entry](/docs/agent/config-entries/service-defaults.html). Agents with
[`enable_central_service_config`](/docs/agent/options.html#enable_central_service_config)
set to true will automatically discover the protocol when configuring a proxy
for a service. The proxy will discover the main protocol of the service it
@@ -171,7 +171,7 @@ actually registered.
These fields may also be overridden explicitly in the [proxy service
definition](/docs/connect/registration/service-registration.html), or defined in
the [global `proxy-defaults` configuration
-entry](/docs/agent/config_entries.html#proxy-defaults-proxy-defaults) to act as
+entry](/docs/agent/config-entries/proxy-defaults.html) to act as
defaults that are inherited by all services.
@@ -282,7 +282,7 @@ with no `@type` field.
Users may add the following configuration items to the [global `proxy-defaults`
configuration
-entry](/docs/agent/config_entries.html#proxy-defaults-proxy-defaults) or
+entry](/docs/agent/config-entries/proxy-defaults.html) or
override them directly in the `proxy.config` field of a [proxy service
definition](/docs/connect/registration/service-registration.html) or
[`sidecar_service`](/docs/connect/registration/sidecar-service.html) block.
@@ -318,7 +318,7 @@ definition](/docs/connect/registration/service-registration.html) or
Users may add the following configuration items to the [global `proxy-defaults`
configuration
-entry](/docs/agent/config_entries.html#proxy-defaults-proxy-defaults) or
+entry](/docs/agent/config-entries/proxy-defaults.html) or
override them directly in the `proxy.config` field of a [proxy service
definition](/docs/connect/registration/service-registration.html) or
[`sidecar_service`](/docs/connect/registration/sidecar-service.html) block.
diff --git a/website/source/layouts/docs.erb b/website/source/layouts/docs.erb
index 00fe1956b3..0063822e12 100644
--- a/website/source/layouts/docs.erb
+++ b/website/source/layouts/docs.erb
@@ -414,6 +414,23 @@