"kubernetesIngress" provider does not detect protocol for backend pods correctly #5164
Closed
1 of 2 tasks
Labels
area/provider/k8s/crd
area/provider/k8s/ingress
kind/bug/confirmed
a confirmed bug (reproducible).
priority/P2
need to be fixed in the future
status/5-frozen-due-to-age
Milestone
Do you want to request a feature or report a bug?
Bug
Did you try using a 1.7.x configuration for the version 2.0?
What did you do?
Per the discussion in the Discourse "Traefik v2" topic Kubernetes Ingress annotation doesn't force HTTPS to backend pods, the three ways supported by earlier versions of Traefik to indicate that a Kubernetes Ingress object requires HTTPS communication don't work properly in Traefik version 2 (as of version 2.0.0-beta1). The only method that works as advertised is detecting that a Kubernetes Service port has a name and the name starts with "https."
Suppose you have a Kubernetes Ingress object pointing at a Service for which the backing server pods speak HTTPS. You want Traefik to use HTTPS for its proxy connections to these upstream servers. If your Service port either lacks a name or has a name that doesn't start with "https," you want to fall back to one of the other two methods that used to work in earlier versions of Traefik.
First, the Ingress annotation "ingress.kubernetes.io/protocol" with a value of "https" would allow you to request use of HTTPS regardless of your Service ports; neither the name nor the port value should matter. Traefik no longer honors this annotation.
However, if your Service port—not the target port on the backing pod container, but rather the port on which the Service listens to receive connections—is 443, and if that port is selected by the Ingress rule, then Traefik should use HTTPS. Traefik tries here, but gets the implementation wrong.
What did you expect to see?
An Ingress object annotated with a key of "ingress.kubernetes.io/protocol" and a value of "https" pointing at a Service port that lacks a name—or has a name that doesn't start with "https"—should use HTTPS.
Alternately, an Ingress object pointing at a Service port that's not named but has a value of 443—regardless of the target port used by the selected pods—should use HTTPS.
What did you see instead?
Traefik both ignores the aforementioned annotation and looks at the wrong port to decide whether it sees 443; it looks at the Endpoints object's ports, which are the target pod's ports, and not the ports used by the Service sitting in front of those pods.
Output of
traefik version
: (What version of Traefik are you using?)What is your environment & configuration (arguments, toml, provider, platform, ...)?
The "kubernetesIngress" provider is active.
Detailed Problem Analysis
Let's review the first Ingress inspection predicate, as written for the previous version of Traefik:
At present, the documentation for Traefik version 2's "kubernetesIngress" provider makes no such promise, but the code is adapted from the earlier version of Traefik, and is clearly trying to implement this promise.
In file pkg/provider/kubernetes/ingress/kubernetes.go, rather than inspecting the
EndpointPort.Port
field at line 228, we should instead inspect theServicePort.Port
field, available in functionloadService
as the expressionportSpec.Port
. In other words, line 228 could read as follows:That's still not addressing taking the "ingress.kubernetes.io/protocol" annotation into account, but it's an improvement.
The test fixtures don't capture this case. The one that exercises this port 443 detection uses a Kubernetes Service whose service port is equivalent to its target port.
Note that this same problem afflicts the "kubernetesCRD" provider in file pkg/provider/kubernetes/crd/kubernetes.go, in the similarly named
loadServers
function here.The text was updated successfully, but these errors were encountered: