Chart fidelity
Values keys below match Universal Helm Chart application 0.4.3 (values.yaml, configuration.md). Chart templates: templates/8_ingress.yaml, templates/route.yaml. Replace hostnames and images.
Same hostname, two APIs: classic Ingress versus role-split Gateway API—and how Universal Helm Chart maps both without inventing a third DSL.
Values keys below match Universal Helm Chart application 0.4.3 (values.yaml, configuration.md). Chart templates: templates/8_ingress.yaml, templates/route.yaml. Replace hostnames and images.
args / multi-port / service.enabledFrom application 0.4.3: main container args (default []); Deployment revisionHistoryLimit (default 10); multi-port via containerPorts and service.ports; optional chart-managed Service via service.enabled (default true). When service.ports is set, Ingress / simple HTTPRoute / NOTES use the first entry (templates/_helpers.tpl application.servicePort). Legacy single-port service.name / service.port / service.protocol / service.appProtocol remain supported. Set service.enabled: false when the workload does not need a chart-managed Service. Do not invent other port keys.
route.specFrom application 0.4.3, set route.spec to a complete HTTPRoute.spec (parentRefs, hostnames, rules, filters, multi-backendRefs). When route.spec is non-empty, the chart renders it unchanged and ignores the simple route.hostname / route.path / route.gateway generator. Simple route.* remains the default path; route.gateway is required only when route.enabled: true and route.spec is empty. Do not invent shorthand keys like route.headers or route.cors.
service.appProtocolOptional service.appProtocol (default "") sets Service.spec.ports[].appProtocol on the chart-managed Service (templates/7_service.yaml). For Services created by ingressPlain paths with createService: true, set paths[].service.appProtocol (since 0.4.0). Leave empty when you do not need a protocol hint (for example grpc). Do not invent other service.* protocol keys.
application 0.4.3 (simple route.* path matches battle-test contract; route.spec is new in 0.3.9; battle cluster ran 0.3.5)sb-test-libvirt (2026-07-23)—not the disposable lab pinkindest/node:v1.33.1; Gateway API v1.6.1 channel standard; kgateway Helm v2.4.3 (oci://cr.kgateway.dev/kgateway-dev/charts/kgateway); controller install namespace kgateway-systemgateway.networking.k8s.io/v1 HTTPRoute / Gateway; Ingress networking.k8s.io/v1Ingress is one object owned by whoever can edit annotations. Controllers disagree on annotation semantics. TLS, canaries, rewrites, and auth become vendor strings instead of typed fields. Status is thin: “it works” or “it doesn’t,” with little portable condition language.
Gateway API splits roles: platform owns GatewayClass and Gateway listeners; app teams own HTTPRoute (and related routes) that attach via parentRefs. Policies that are not portable stay in implementation CRDs (for kgateway: TrafficPolicy, BackendConfigPolicy, GatewayExtension)—labelled as such, not as “Ingress annotations 2.0.”
GatewayClass — controller implementation (platform)Gateway — listeners, TLS termination at the edge, which namespaces may attach routes (allowedRoutes)HTTPRoute — hostnames, matches, filters, backendRefs (app or platform, depending on ownership)ReferenceGrant — cross-namespace Service/Secret references when requiredOfficial type reference: HTTPRoute, Gateway.
Defaults: ingress.enabled: false, route.enabled: false. Prefer one exposure path per release unless you intentionally dual-publish during migration.
networking.k8s.io/v1 Ingressservice:
port: 8080
ingress:
enabled: true
className: nginx
annotations: {}
hosts:
- host: app.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: app-example-tls
hosts:
- app.example.comgateway.networking.k8s.io/v1 HTTPRouteroute.gateway is required when route.enabled: true. The template sets parentRefs to that Gateway and backendRefs to the chart Service on service.port. Optional: gatewayNamespace, sectionName, path, pathMatchType (default PathPrefix), backendWeight (default 1), timeouts.request / timeouts.backendRequest.
service:
port: 8080
route:
enabled: true
gateway: external
gatewayNamespace: kgateway-system
sectionName: https
hostname: app.example.com
path: /
pathMatchType: PathPrefix
backendWeight: 1
timeouts:
request: 75s
backendRequest: 75sroute.gatewayNamespace must match where the platform Gateway lives. This series uses lab/platform namespace kgateway-system (kgateway Helm install). If your platform uses another NS, set the value accordingly—do not invent a chart default.
The chart does not create Gateway, GatewayClass, or kgateway policies. Those stay platform-owned (or separate manifests). Chart HTTPRoute is a single hostname + single path match per release—see Gateway API examples.
helm repo add universal https://chaser100.github.io/u-helm-chart helm repo update helm template app-ingress universal/application --version 0.4.3 -f values-ingress.yaml | rg -n 'kind: Ingress|host:' helm template app-route universal/application --version 0.4.3 -f values-route.yaml | rg -n 'kind: HTTPRoute|parentRefs|hostname'
ingress.tls[].secretName on the Ingress object (often app-namespace Secret).certificateRefs); HTTPRoute attaches to sectionName for the HTTPS listener. App values only need the correct route.gateway / sectionName. Provision the Secret out-of-band (cert-manager, External Secrets, or sealed)—never commit PEM material.allowedRoutes and any required ReferenceGrant. This is platform config, not a chart flag.# Gateway (platform NS)
kubectl get gateway -n kgateway-system
kubectl describe gateway -n kgateway-system external
# Expect: Accepted=True and Programmed=True
# Ingress
kubectl describe ingress -n apps app
# HTTPRoute (portable parent conditions)
kubectl get httproute -n apps
kubectl describe httproute -n apps app
# Expect parents: Accepted=True, ResolvedRefs=True
kubectl get httproute -n apps app -o jsonpath='{.status.parents}' ; echoBattle-test evidence: twelve HTTPRoutes reported Accepted=True and ResolvedRefs=True through an external kgateway Gateway with wildcard TLS. Always confirm the Gateway itself is Programmed=True before blaming the chart HTTPRoute.
route.enabled=true will render YAML that cannot reconcile.Gateway listeners.ingress.enabled to route.* (or dual-publish briefly).allowedRoutes on a Gateway → route hijack risk across namespaces.HTTPRoute hostnames (or overly broad matches) can steal traffic from more specific app routes—prefer exact hostnames on app routes.route.*—put those on reviewed HTTPRoute extras or kgateway policies, not fake values keys.route.path / route.pathMatchType.backendRefs HTTPRoutes or separate releases—chart exposes a single backendWeight on one Service.TrafficPolicy.Next: Ingress NGINX to kgateway → · Route conversions → · Chart HTTPRoute values → · Gateway API docs