Skip to content

Moves health and metrics endpoints to dedicated listener on separate port#910

Merged
gtema merged 4 commits into
openstack-experimental:mainfrom
mcblake27:health-endpoint
Jul 16, 2026
Merged

Moves health and metrics endpoints to dedicated listener on separate port#910
gtema merged 4 commits into
openstack-experimental:mainfrom
mcblake27:health-endpoint

Conversation

@mcblake27

Copy link
Copy Markdown
Collaborator

Health and metrics endpoints were previously attached to the public API router, allowing end users to access /health, /ready, and /metrics directly, which is a potential DDoS vector. This change moves them to a dedicated listener on port 8082, separate from the public API on port 8080. Also updates relevant tests to work with new structure/naming schema. Adds modular spawn_metrics_listener function to crates/keystone/src/bin/keystone.rs and API interface structure MetricsInterface in crates/config/src/interface.rs, as well as updating pathways in crates/config/src/lib.rs, crates/keystone/src/api/mod.rs, and crates/keystone/src/api/health.rs.

Closes #719.

This contribution was developed with the assistance of AI tools.

@gtema gtema left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have updated the original issue with bit more details of the target setup how the new endpoint should work and combine healthz with otel metrics. Part of this change you do not need to implement OTEL service, but build an endpoint that will be further extended with it. Otherwise the change goes in the correct direction.
You need to fix commit message, formatting, and once you fix the deployment manifest the k3s test should also pass

Comment thread crates/config/src/lib.rs
pub interface_internal: Option<InternalInterface>,

/// Server listener configuration for the internal interface.
/// Server listener configuration for the public interface.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hehe, nice spot

}

/// Prometheus scrape endpoint — returns the three audit counters in text
/// exposition format (v0.0.4). No authentication required; operators are

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the metrics handler that you need to merge with the health endpoint so that at the new listener we have

  • /health - the health endpoint
  • /metrics - prometheus metrics

In one of the next steps we would evaluate how to populate metrics endpoint with the real data.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way I am currently handling this is that when I define the router metrics_app in spawn_metrics_listener, I call .route("/metrics", axum::routing::get(metrics_handler)) to add this metrics handler as a route on the router. Is that satisfactory for what you're describing here, or is there a different way I am supposed to be doing this? My understanding is that that is what you are asking, but I may be misunderstanding.

Comment thread crates/config/src/interface.rs Outdated
}

fn default_metrics_tcp_address() -> SocketAddr {
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 8082)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now that you moved the health endpoint to the different address the k3s test fails since the keystone statefulset in kubernetes cannot reach it: https://github.com/openstack-experimental/keystone/blob/main/tools/k8s/keystone/base/statefulset-rs.yaml#L47C1-L72C1 - that place need to be adapted to point at the new place. Keep in mind the potential port conflict since keystone operates with many other components and systems (it does not conflict now, but any decision on changing ports is tricky - keycloak is also running on 8082, just in the different container). Let's maybe use 8099 as something less standard

@mcblake27
mcblake27 force-pushed the health-endpoint branch 2 times, most recently from a0d979d to e56b4f2 Compare July 5, 2026 01:46

@gtema gtema left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

few nits, otherwise good

Comment thread crates/config/src/interface.rs Outdated
/// Keystone health/metrics API interface.
#[derive(Debug, Deserialize, Clone)]
pub struct MetricsInterface {
/// Default address for the health/metrics endpoint. Defaults to `0.0.0.0:8082`.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the docstring still says 8082 while the code does 8099

name: keystone-raft
protocol: TCP
- containerPort: 8099
name: keystone-metrics

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as the k3s job log says kubernetes has length limitations (15 chars). Let's just use "metrics" here

@gtema
gtema force-pushed the health-endpoint branch 2 times, most recently from 87fb297 to 7d7d932 Compare July 14, 2026 07:39
@gtema

gtema commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

@mcblake27 please sync your fork repository so that it can be rebased solving the merge conflict

@mcblake27
mcblake27 force-pushed the health-endpoint branch 2 times, most recently from e7c325b to 6b011fd Compare July 15, 2026 15:17
@mcblake27

Copy link
Copy Markdown
Collaborator Author

@gtema Apologies, was having rebasing issues on my end but I believe it is okay now, let me know if there are still issues

@gtema

gtema commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

@mcblake27 format failure is genuine

@mcblake27
mcblake27 force-pushed the health-endpoint branch 2 times, most recently from c3efc75 to ae539ee Compare July 15, 2026 19:27
Health and metrics endpoints were previously attached to the
public API router, allowing end users to access /health,
/ready, and /metrics directly, which is a potential DDoS
vector.

This moves them to a dedicated listener on port 8099,
separate from the public API on port 8080. Adds a new
 config section to configure the
address. Updates the k8s StatefulSet manifest to point
liveness, readiness, and startup probes at the new port.

Co-developed-by: Claude (Anthropic)

Closes openstack-experimental#719

Signed-off-by: Milo Blake <mcblake@andrew.cmu.edu>
Health and metrics endpoints were previously attached to the
public API router, allowing end users to access /health,
/ready, and /metrics directly, which is a potential DDoS
vector.

This moves them to a dedicated listener on port 8099,
separate from the public API on port 8080. Adds a new
`[interface_metrics]` config section to configure the
address. Updates the k8s StatefulSet manifest to point
liveness, readiness, and startup probes at the new port.

Co-developed-by: Claude (Anthropic)

Closes openstack-experimental#719

Signed-off-by: Milo Blake <mcblake@andrew.cmu.edu>
Signed-off-by: Milo Blake <mcblake@andrew.cmu.edu>
Signed-off-by: Milo Blake <mcblake@andrew.cmu.edu>
@gtema
gtema force-pushed the health-endpoint branch from ae539ee to 49a56ee Compare July 16, 2026 07:43
@gtema
gtema enabled auto-merge (squash) July 16, 2026 07:44
@gtema
gtema merged commit 78f8eb2 into openstack-experimental:main Jul 16, 2026
28 checks passed
konac-hamza pushed a commit to konac-hamza/keystone that referenced this pull request Jul 16, 2026
…port (openstack-experimental#910)

* feat: Move health and metrics to dedicated port

Health and metrics endpoints were previously attached to the
public API router, allowing end users to access /health,
/ready, and /metrics directly, which is a potential DDoS
vector.

This moves them to a dedicated listener on port 8099,
separate from the public API on port 8080. Adds a new
 config section to configure the
address. Updates the k8s StatefulSet manifest to point
liveness, readiness, and startup probes at the new port.

Co-developed-by: Claude (Anthropic)

Closes openstack-experimental#719

Signed-off-by: Milo Blake <mcblake@andrew.cmu.edu>

* feat: Move health and metrics to dedicated port

Health and metrics endpoints were previously attached to the
public API router, allowing end users to access /health,
/ready, and /metrics directly, which is a potential DDoS
vector.

This moves them to a dedicated listener on port 8099,
separate from the public API on port 8080. Adds a new
`[interface_metrics]` config section to configure the
address. Updates the k8s StatefulSet manifest to point
liveness, readiness, and startup probes at the new port.

Co-developed-by: Claude (Anthropic)

Closes openstack-experimental#719

Signed-off-by: Milo Blake <mcblake@andrew.cmu.edu>

* Fix: Apply rustfmt formatting

Signed-off-by: Milo Blake <mcblake@andrew.cmu.edu>

* fix: Updated URL port in start-api.sh to 8099

Signed-off-by: Milo Blake <mcblake@andrew.cmu.edu>

---------

Signed-off-by: Milo Blake <mcblake@andrew.cmu.edu>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Move health endpoint to a dedicated app

2 participants