hashicorp / hashicorp/consul

Expose Paths: Merge on listener port or support path prefix/regex

Open
#11,254 0 comments 3 reactions 0 assignees View on GitHub
theme/envoy/xds type/enhancement
Dominant language
Go
Stars
30.1k
Forks
4.6k
Avg merge
1d 18h
Merged PRs (30d)
39

Description

#### Feature Description

When using the [*Expose Paths*](https://www.consul.io/docs/connect/registration/service-registration#expose-paths-configuration-reference) feature, I've stumbled of the following issue:

I have two endpoints on port 7979, for the kubernetes liveness and readiness probe respectively.
One is `/actuator/health/liveness` and the other is `/actuator/health/readiness`.

What I tried:

##### Path prefix

The docs don't really mention how the path matching works:

> The HTTP path to expose. The path must be prefixed by a slash. ie: /metrics.
>
> https://www.consul.io/docs/connect/registration/service-registration#path

This doesn't work unfortunately:

```yaml
{
"Kind": "service-defaults",
"Protocol": "http",
"Name": "my-service",
"Expose": {
"Paths": [
{
"LocalPathPort": "7979",
"Path": "/actuator/health", # 💥 Matches exactly, and not on prefix
"Protocol": "http",
"ListenerPort": 21250
}
]
}
}
```

##### Re-using listener port

The next attempt was to have two expose paths with the same listener port.
As stated in the docs, this doesn't work right now:

> This port must be available for the listener to be set up. If the port is not free then Envoy will not expose a listener for the path, but the proxy registration will not fail.
>
> https://www.consul.io/docs/connect/registration/service-registration#listener_port

```yaml
{
"Kind": "service-defaults",
"Protocol": "http",
"Name": "my-service",
"Expose": {
"Paths": [
{
"LocalPathPort": "7979",
"Path": "/actuator/health/liveness",
"Protocol": "http",
"ListenerPort": 21250
},
{
"LocalPathPort": "7979",
"Path": "/actuator/health/readiness",
"Protocol": "http",
"ListenerPort": 21250 # 💥 Exposed path will be ignored because port is already in use
}
]
}
}
```

##### Workaround

```yaml
{
"Kind": "service-defaults",
"Protocol": "http",
"Name": "my-service",
"Expose": {
"Paths": [
{
"LocalPathPort": "7979",
"Path": "/actuator/health/liveness",
"Protocol": "http",
"ListenerPort": 21250
},
{
"LocalPathPort": "7979",
"Path": "/actuator/health/readiness",
"Protocol": "http",
"ListenerPort": 21251
}
]
}
}
```

It would be nice if either (or both) of those approaches would work:

1. Add support for path prefix or regex matching to reduce the need to have two expose paths with different ports.
2. Merge expose paths on listener port if the paths don't conflict.

#### Use Case(s)

My use case is to expose (Spring Boot Actuator) Kubernetes liveness/startup and readiness probe endpoints.
I'm not using the transparent proxy.

Contributor guide

Open the contributing guide

Research direction

Start with the Expose Paths configuration reference and trace the current listener-port handling for multiple paths. Compare path prefix or regex matching with merging non-conflicting paths on one listener port; done means both liveness and readiness endpoints can be exposed without separate listener ports.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, kubernetes, spring-boot
Domain
networking
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.