Migrate stellar-core Ingress to Gateway API HTTPRoute via a scalable nginx proxy#405
Open
Jonathan-Eid wants to merge 18 commits into
Open
Migrate stellar-core Ingress to Gateway API HTTPRoute via a scalable nginx proxy#405Jonathan-Eid wants to merge 18 commits into
Jonathan-Eid wants to merge 18 commits into
Conversation
Replace the nginx Ingress (ToIngress) with an HTTPRoute (ToHttpRoute) attached to the shared traefik-gateway-private gateway. Per-pod /<pod>/core|history PathPrefix matches with a ReplacePrefixMatch URLRewrite (equivalent to the old rewrite-target). - Add typed Gateway API models (GatewayApiModels) in CSLibrary; official KubernetesClient has no Gateway API types. - Create/track/delete + orphan-sweep the HTTPRoute via the custom-object API. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Highest version before the 18.x model-constructor breaking change (parameterized ctors removed). Builds clean + tests pass with no code changes; 18/19 would need a repo-wide constructor migration, left as separate work. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Traefik's Gateway provider rejects ExternalName services as HTTPRoute backends
('type ExternalName is not supported'), unlike the nginx Ingress path. Select the
target pod via its statefulset.kubernetes.io/pod-name label instead. Works for
both gateway and ingress; verified live on ssc-test (core /info + protocol
upgrade route through the gateway).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The generated object is now an HTTPRoute, not an Ingress; name it <nonce>-stellar-core-http-route.
…e rename Replace the per-pod ClusterIP services + fat multi-rule HTTPRoute with a single per-mission nginx proxy (Deployment + Service + ConfigMap) behind a one-rule HTTPRoute. The proxy demuxes /<pod>/core|history to the pod's in-cluster DNS name, so the route needs one rule regardless of node count -- fixing the HTTPRoute 16-rule cap and the CoreDNS amplification of the old ExternalName-per-pod design. Replica count auto-scales ceil(nodes/64), capped by --http-proxy-replicas (default 10, floor 1), with a readiness wait before the driver routes through it. Rename internal ingress* identifiers -> route* (CLI flag strings kept for Jenkinsfile compatibility); drop the now-dead --ingress-class. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
Contributor
There was a problem hiding this comment.
Pull request overview
Migrates Supercluster’s per-mission stellar-core HTTP exposure from per-pod Ingress + ExternalName services to a Gateway API HTTPRoute that fronts a scalable per-mission nginx proxy, and updates related mission/job-monitor routing and Kubernetes client dependencies.
Changes:
- Replace per-pod service + multi-rule Ingress with an nginx proxy (ConfigMap/Deployment/Service) behind a single-rule
HTTPRoute, plus a readiness wait before routing through the proxy. - Migrate parallel-catchup job-monitor from Ingress to
HTTPRouteand adjust Helm values and mission set-options accordingly. - Add typed Gateway API models (
GatewayApiModels) and bumpKubernetesClientfrom 15.x to 17.x; rename ingress-centric fields/identifiers to route-centric equivalents and add--http-proxy-replicas.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| src/MissionParallelCatchup/parallel_catchup_helm/values.yaml | Switch job-monitor routing config from ingress fields to Gateway API parent refs + path prefix. |
| src/MissionParallelCatchup/parallel_catchup_helm/templates/job_monitor.yaml | Replace Ingress with HTTPRoute and URLRewrite-based prefix stripping. |
| src/FSLibrary/StellarSupercluster.fs | Create proxy resources + HTTPRoute and wait for proxy readiness before proceeding. |
| src/FSLibrary/StellarOrphanSweep.fs | Switch orphan sweeping from Ingress to HTTPRoute via GenericClient. |
| src/FSLibrary/StellarNetworkCfg.fs | Introduce route/proxy naming and labels; rename ingress host fields to route host fields. |
| src/FSLibrary/StellarNamespaceContent.fs | Track and delete HTTPRoute resources instead of Ingress in namespace cleanup. |
| src/FSLibrary/StellarMissionContext.fs | Replace ingress-related mission context fields with route fields and add httpProxyReplicas. |
| src/FSLibrary/StellarKubeSpecs.fs | Add proxy ConfigMap/Deployment/Service generation and new HTTPRoute creation logic. |
| src/FSLibrary/StellarCoreHTTP.fs | Update Host header + URL construction to use route host fields instead of ingress host fields. |
| src/FSLibrary/StellarCoreCfg.fs | Add constants for Gateway target and proxy config file naming/ports. |
| src/FSLibrary/MissionHistoryPubnetParallelCatchupV2.fs | Update Helm set-option key from monitor.path to monitor.path_prefix. |
| src/FSLibrary/FSLibrary.fsproj | Bump KubernetesClient dependency to 17.0.14. |
| src/FSLibrary.Tests/Tests.fs | Update MissionContext test construction for route fields + proxy replicas. |
| src/CSLibrary/GatewayApi.cs | Add typed POCO models for HTTPRoute/HTTPRouteList used with GenericClient. |
| src/CSLibrary/CSLibrary.csproj | Bump KubernetesClient dependency to 17.0.14. |
| src/App/Program.fs | Remove --ingress-class, rename options to route fields, and add --http-proxy-replicas (while keeping ingress-* flag strings). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- waitProxyReady: treat null Deployment.Status as 0 ready (status is populated
asynchronously; don't NPE mission startup).
- Orphan sweep: also reap legacy Ingresses (pre-migration orphans), alongside
HTTPRoutes.
- job_monitor HTTPRoute: omit spec.hostnames when monitor.hostname is empty
(avoids invalid hostnames: [""]).
- Clarify --ingress-{internal-domain,external-host,external-port} help text to
describe the gateway route (flag names kept for Jenkinsfile compat).
- Run fantomas over the changed files (fixes the failing format check).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the nginx-ingress setup with gateway-api CRDs + traefik as the Gateway API controller + a traefik-gateway-private Gateway (matching CfgVal), so the migrated BootAndSync smoke mission (which creates an HTTPRoute) works. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…o IngressClass) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…amespace) Restore the configurability the old --ingress-class flag provided: instead of hardcoding traefik-gateway-private/traefik in CfgVal, take --gateway-name and --gateway-namespace (same defaults). Lets each cluster / CI point the route at whits own gateway. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The migrated BootAndSync creates an HTTPRoute, so CI needs a gateway-api env. Traefik-in-k3s proved a version-compat maze (bundled-traefik conflict, chart value drift, missing TLSRoute CRD, CEL/k8s-version mismatches). Envoy Gateway ships matching CRDs + controller in one chart and programs cleanly. Recipe validated on local k3d (k3s 1.31, bundled traefik disabled, envoy-gateway v1.2.6, Gateway 'ssc-gateway'): BootAndSync brought up 3 nodes and synced, driver reaching them via the gateway -> proxy. Uses the new --gateway-name / --gateway-namespace flags. Also bump checkout@v2->v4, setup-dotnet@v1->v4. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Use 'use ... = new GenericClient(...)' so the client is disposed and the FS0760 IDisposable warning is cleared. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The previous 'use gc = new GenericClient' disposed the shared mission kube client (GenericClient wraps it), NPEing the next API call. Use 'let ... = new': clears FS0760 via the 'new' keyword without disposing the shared client. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Migrate the per-mission stellar-core Ingress → Gateway API HTTPRoute, fronted by a scalable per-mission nginx proxy:
ExternalName/ClusterIP services + fat multi-rule Ingress with one nginx proxy (Deployment + Service + ConfigMap) behind a single-rule HTTPRoute. The proxy demuxes/<pod>/core|historyto the pod's in-cluster DNS, so the route needs one rule regardless of node count.ceil(nodes/64), capped by--http-proxy-replicas(default 10, floor 1), with a readiness wait before the driver routes through it.CSLibrary/GatewayApi.cs).ingress*identifiers →route*(CLI flag strings kept for Jenkinsfile compat); drop the now-dead--ingress-class.Why
ExternalName-per-pod + nginx-ingress design overloaded CoreDNS (per Improve ingress handling #197) — the ingress controller re-resolving N ExternalNames + NXDOMAIN during pod startup. The proxy creates zero ExternalName services.HTTPRoutehas a hard 16-rule cap; a one-rule-per-pod route breaks past ~8 nodes. The single-rule proxy route is unaffected at any scale.Testing
🤖 Generated with Claude Code