feat: add extraPortMappings support to ClusterSpec - #14
Conversation
54fd771 to
2ee643c
Compare
Full observability stack on KIND for benchmarking Praxis proxy OTel tracing overhead. Deploys Prometheus, Grafana, Tempo, Loki, OTel Collector, MLflow, Fortio echo, and llm-d inference-sim. Two benchmark scenarios: - Core proxy (2000 RPS, 10 spans/request, GET to echo) - AI proxy (500 RPS, 11 spans/request, POST /v1/chat/completions) Each runs baseline/otel-noop/otel-full configurations with vegeta. Includes 5 Grafana dashboards, benchmark scripts with automated report generation, and per-scenario config isolation. Requires praxis-forge with extraPortMappings support (praxis-proxy/forge#14). Signed-off-by: Ladislav Smola <lsmola@redhat.com>
praxis-bot
left a comment
There was a problem hiding this comment.
Review: feat: add extraPortMappings support to ClusterSpec
Clean feature addition overall. The CreateClusterConfig struct is a good refactor over the growing parameter list, validation is thorough (port ranges, protocol, bind address, cross-scope conflicts), and test coverage is solid. Two medium findings below.
| } | ||
| check_port_bind_address(&pm.bind_address, &ctx)?; | ||
| check_cluster_port_protocol(&pm.protocol, &ctx)?; | ||
| let key = (pm.host, pm.protocol.to_lowercase()); |
There was a problem hiding this comment.
[Medium] Intra-cluster duplicate detection ignores bind_address, inconsistent with check_cross_scope_port_conflicts which includes it in the key.
With the current key (pm.host, pm.protocol), two port mappings on different bind addresses within the same cluster (e.g. 127.0.0.1:8080/tcp and 10.0.0.1:8080/tcp) are rejected as duplicates even though they do not conflict. Meanwhile check_port_collision (used by check_cross_scope_port_conflicts) correctly allows this by including bind_address in the key.
Include bind_address in the intra-cluster duplicate key to match:
let key = (
pm.bind_address.clone().unwrap_or_default(),
pm.host,
pm.protocol.to_lowercase(),
);| #[test] | ||
| fn generate_kind_config_with_port_mappings() { | ||
| let nodes = NodeConfig::default(); | ||
| let ports = vec![ |
There was a problem hiding this comment.
[Medium] The listenAddress generation branch (line 160-162) is not covered by any unit test. Both port mappings here use bind_address: None, so the if let Some(addr) = &pm.bind_address path is never exercised.
Add a port with a bind_address to this test (or a dedicated test) and assert the generated YAML contains the expected listenAddress entry:
PortMapping {
bind_address: Some("127.0.0.1".to_owned()),
host: 9090,
container: 30909,
protocol: "tcp".to_owned(),
},then:
assert!(
yaml.contains("listenAddress: \"127.0.0.1\""),
"should include listenAddress for bind_address",
);2ee643c to
1f28043
Compare
Full observability stack on KIND for benchmarking Praxis experimental server OTel tracing overhead across two scenarios: - Core proxy (2000 RPS, 10 spans/request, GET to echo) - AI proxy (500 RPS, 11 spans/request, POST /v1/chat/completions) Each runs baseline/otel-noop/otel-full configurations with vegeta. Adds otel feature to praxis-experimental-server (forwarding praxis-core/otel + praxis-filter/otel), FEATURES build-arg to Containerfile, and patches praxis crates to main (1b439271) for the Tokio runtime fix and filter/otel feature not yet in v0.5.3. Stack: Prometheus, Grafana 11.x, Tempo, Loki, OTel Collector, MLflow, Fortio echo, llm-d inference-sim. Includes 5 Grafana dashboards, benchmark scripts with automated report generation, and per-scenario config isolation. Requires praxis-forge with extraPortMappings (praxis-proxy/forge#14). Signed-off-by: Ladislav Smola <lsmola@redhat.com>
Full observability stack on KIND for benchmarking Praxis experimental server OTel tracing overhead across two scenarios: - Core proxy (2000 RPS, 10 spans/request, GET to echo) - AI proxy (500 RPS, 11 spans/request, POST /v1/chat/completions) Each runs baseline/otel-noop/otel-full configurations with vegeta. Adds otel feature to praxis-experimental-server (forwarding praxis-core/otel + praxis-filter/otel), FEATURES build-arg to Containerfile, and patches praxis crates to main (1b439271) for the Tokio runtime fix and filter/otel feature not yet in v0.5.3. Stack: Prometheus, Grafana 11.x, Tempo, Loki, OTel Collector, MLflow, Fortio echo, llm-d inference-sim. Includes 5 Grafana dashboards, benchmark scripts with automated report generation, and per-scenario config isolation. Requires praxis-forge with extraPortMappings (praxis-proxy/forge#14). Signed-off-by: Ladislav Smola <lsmola@redhat.com>
Full observability stack on KIND for benchmarking Praxis experimental server OTel tracing overhead across two scenarios: - AI gateway (500 RPS, 11 spans/request, POST /v1/chat/completions) - Core proxy (2000 RPS, 10 spans/request, GET to echo backend) Each scenario runs baseline/otel-noop/otel-full configurations with vegeta load testing via a single parameterized benchmark.sh script. Stack: Prometheus, Grafana 11.x, Tempo, Loki, OTel Collector, MLflow, Fortio echo, llm-d inference-sim, plus 5 Grafana dashboards. Also adds: - otel feature to praxis-experimental-server (praxis-core/otel + praxis-filter/otel) with FEATURES build-arg in Containerfile - Patches praxis crates to main rev 1b439271 for Tokio runtime fix and filter/otel feature not yet in v0.5.3 - praxis-main feature on AI dep for log_level field compatibility Requires praxis-forge with extraPortMappings (praxis-proxy/forge#14). Signed-off-by: Ladislav Smola <lsmola@redhat.com>
Full observability stack on KIND for benchmarking Praxis experimental server OTel tracing overhead across two scenarios: - AI gateway (500 RPS, 11 spans/request, POST /v1/chat/completions) - Core proxy (2000 RPS, 10 spans/request, GET to echo backend) Each scenario runs baseline/otel-noop/otel-full configurations with vegeta load testing via a single parameterized benchmark.sh script. Stack: Prometheus, Grafana 11.x, Tempo, Loki, OTel Collector, MLflow, Fortio echo, llm-d inference-sim, plus 5 Grafana dashboards. Also adds: - otel feature to praxis-experimental-server (praxis-core/otel + praxis-filter/otel) with FEATURES build-arg in Containerfile - Patches praxis crates to main rev 1b439271 for Tokio runtime fix and filter/otel feature not yet in v0.5.3 - praxis-main feature on AI dep for log_level field compatibility Requires praxis-forge with extraPortMappings (praxis-proxy/forge#14). Signed-off-by: Ladislav Smola <lsmola@redhat.com>
Expose KIND extraPortMappings in the forge config schema so clusters can map host ports to container/NodePort ports. This enables accessing services like Grafana, Prometheus, and MLflow from the host. Includes config validation (unique host ports, valid ranges), KIND config generation, and integration test with a port-mappings fixture. Signed-off-by: Ladislav Smola <lsmola@redhat.com>
- Validate bind_address as a valid IP for cluster ports (parity with services) - Restrict protocol to tcp/udp for cluster ports - Check for host-port collisions across clusters and services - Extend test fixture with bindAddress and protocol: udp Signed-off-by: Ladislav Smola <lsmola@redhat.com>
The cross-scope collision check already uses (bind_address, host, protocol) but the intra-cluster check only used (host, protocol), rejecting valid configs with same host port on different bind addresses within one cluster. Signed-off-by: Ladislav Smola <lsmola@redhat.com>
1f28043 to
fdb4ef7
Compare
Full observability stack on KIND for benchmarking Praxis experimental server OTel tracing overhead across two scenarios: - AI gateway (500 RPS, 11 spans/request, POST /v1/chat/completions) - Core proxy (2000 RPS, 10 spans/request, GET to echo backend) Each scenario runs baseline/otel-noop/otel-full configurations with vegeta load testing via a single parameterized benchmark.sh script. Stack: Prometheus, Grafana 11.x, Tempo, Loki, OTel Collector, MLflow, Fortio echo, llm-d inference-sim, plus 5 Grafana dashboards. Also adds: - otel feature to praxis-experimental-server (praxis-core/otel + praxis-filter/otel) with FEATURES build-arg in Containerfile - Patches praxis crates to main rev 1b439271 for Tokio runtime fix and filter/otel feature not yet in v0.5.3 - praxis-main feature on AI dep for log_level field compatibility Requires praxis-forge with extraPortMappings (praxis-proxy/forge#14). Signed-off-by: Ladislav Smola <lsmola@redhat.com>
Full observability stack on KIND for benchmarking Praxis experimental server OTel tracing overhead across two scenarios: - AI gateway (500 RPS, 11 spans/request, POST /v1/chat/completions) - Core proxy (2000 RPS, 10 spans/request, GET to echo backend) Each scenario runs baseline/otel-noop/otel-full configurations with vegeta load testing via a single parameterized benchmark.sh script. Stack: Prometheus, Grafana 11.x, Tempo, Loki, OTel Collector, MLflow, Fortio echo, llm-d inference-sim, plus 5 Grafana dashboards. Also adds: - otel feature to praxis-experimental-server (praxis-core/otel + praxis-filter/otel) with FEATURES build-arg in Containerfile - Patches praxis crates to main rev 1b439271 for Tokio runtime fix and filter/otel feature not yet in v0.5.3 - praxis-main feature on AI dep for log_level field compatibility Requires praxis-forge with extraPortMappings (praxis-proxy/forge#14). Signed-off-by: Ladislav Smola <lsmola@redhat.com>
Summary
extraPortMappingsin the forge config schema via a newportsfield onClusterSpecContext
Split out from the closed #2 (OTel benchmark demo). The demo content moves to
praxis-proxy/experimental, but this forge CLI feature is needed independently — any forge environment that exposes NodePort services to the host needs it.Test plan
tests/fixtures/port-mappings.yamlextraPortMappingsentries