Gap
The scheme-aware subnet injection in policies/kyverno/networking/base/inject-adopt-lb-subnets.yaml decides internal vs. internet-facing from a single source per object:
- Ingress:
alb.ingress.kubernetes.io/scheme (lines 61, 95)
- Service:
service.beta.kubernetes.io/aws-load-balancer-scheme (lines 128, 164)
defaulting to internal when absent. Two ways a load balancer's real scheme can diverge from those annotations are not accounted for:
-
Legacy Service annotation. service.beta.kubernetes.io/aws-load-balancer-internal ("true"/"false") is still honored by the AWS Load Balancer Controller. A Service that sets -internal: "false" but no -scheme reads as internal here (the default) and gets the private-subnet CSV, while the controller provisions it internet-facing — on the private subnets we injected.
-
IngressClassParams override. IngressClassParams.spec.scheme overrides the object-level alb.ingress.kubernetes.io/scheme annotation entirely. An Ingress whose IngressClass points at an IngressClassParams with scheme: internet-facing and no object annotation reads as internal here, gets the private-subnet CSV, and the controller wants public.
Blast radius
Both are adopt-only, and both fail loud at LB provisioning (the controller rejects a scheme/subnet mismatch) — no worse than today's zero-discovery baseline on an adopt cluster, and not a regression. But "scheme-aware" is currently narrower than the phrase implies.
Possible directions
- Fold the legacy
-internal annotation into the Service scheme context (treat -internal: "false" as internet-facing when -scheme is absent).
- IngressClassParams is harder — it needs a second
context lookup resolving the Ingress's ingressClassName -> IngressClass -> spec.parameters -> IngressClassParams spec.scheme. Worth scoping whether the added context cost is justified versus documenting the object annotation as the supported path.
Gap
The scheme-aware subnet injection in
policies/kyverno/networking/base/inject-adopt-lb-subnets.yamldecides internal vs. internet-facing from a single source per object:alb.ingress.kubernetes.io/scheme(lines 61, 95)service.beta.kubernetes.io/aws-load-balancer-scheme(lines 128, 164)defaulting to
internalwhen absent. Two ways a load balancer's real scheme can diverge from those annotations are not accounted for:Legacy Service annotation.
service.beta.kubernetes.io/aws-load-balancer-internal("true"/"false") is still honored by the AWS Load Balancer Controller. A Service that sets-internal: "false"but no-schemereads asinternalhere (the default) and gets the private-subnet CSV, while the controller provisions it internet-facing — on the private subnets we injected.IngressClassParams override.
IngressClassParams.spec.schemeoverrides the object-levelalb.ingress.kubernetes.io/schemeannotation entirely. An Ingress whose IngressClass points at an IngressClassParams withscheme: internet-facingand no object annotation reads asinternalhere, gets the private-subnet CSV, and the controller wants public.Blast radius
Both are adopt-only, and both fail loud at LB provisioning (the controller rejects a scheme/subnet mismatch) — no worse than today's zero-discovery baseline on an adopt cluster, and not a regression. But "scheme-aware" is currently narrower than the phrase implies.
Possible directions
-internalannotation into the Service scheme context (treat-internal: "false"as internet-facing when-schemeis absent).contextlookup resolving the Ingress'singressClassName-> IngressClass ->spec.parameters-> IngressClassParamsspec.scheme. Worth scoping whether the added context cost is justified versus documenting the object annotation as the supported path.