-
Notifications
You must be signed in to change notification settings - Fork 7.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
endless loop with unspecified port when using fallthrough #14443
Comments
I confirmed I can reproduce the issue, seems to only happen with pod IP |
Thanks for your reply!
yes, it only happen with request to POD_IP:Port when this Port is NOT in service. And i think it's because the |
Can we set iptables not to intercept these packet? |
It's hard to split these packet with others in this chain:
btw, i really don't know the meaning of this chain, in normal situation, what kind of packets will go through |
There is a ENV 'DISABLE_REDIRECTION_ON_LOCAL_LOOPBACK', set this will disable redirect on loopback |
Thanks for your reply ! I have tested this function, but there are several questions that confused me: Q1: I cannot find any place to set the ENV, how can i set the Q2: I delete this chain manually and do some test: it can actually prevent the infinite loop with POD_IP:2334 and the http response is OK; However, with this action, a pod can NOT calls to back itself: So i think maybe we should find some fine-grained solutions to solve this infinite loop. |
for Q1, i think it need to edit the configmap that sidecar-injector used, i can not remember its name, but you can check the pod yaml. For question2, i donot think too much |
This problem became more dangerous in 1.2.0 ... In out cluster, with the containerPort defined but no related svc port as shown above, in 1.2.0, when sending requests to POD_IP:port, envoy will take up more and more memory immediately and be OOM killed because it got the limit (1G); actually in my test, just send 2 requests from other pod to this POD_IP:port, then envoy memory will got 1G immediately. and the logs of envoy is very big than before:
So i'm wondering that does we do something in istio 1.2.0 or envoy than makes things worse ? And this infinite loop problem exists from 1.1.1 to now, is there any wonderful solutions we can made ? |
can we just exchange the order of first chain with second(and third) chain ? e.g. for now the ISTIO_OUTPUT looks like:
and the first chain(let's call it chain-0) may causes infinite loop as we talk in this issue and in: And in my opinion, the purpose of chain-0 is for a pod requests itself using POD_IP or SVC_IP; So if we modify the ISTIO_OUTPUT chains to:
that move chain-0 to line 3. And i have do some test to confirm that in this situation:
So I think it can solve these problems. @hzxuzhonghu @howardjohn ideas welcome ~ |
It seems not feasible, i have previously opened #14779 to change something, but i found all the rules orders are intended. |
the problem is introduced in 1.1.4 You can "fix" it by setting outbound Traffic policy to registry only or set the env var PILOT_ENABLE_FALLTHROUGH_ROUTE=0. (maybe not exactly that, on phone right now I can send the docs later if you need) |
Thanks for your opinion, I read #14779 and got your point. I will take a deep look into it. |
yes it's actually |
Current plan (tentative): For 1.2 - the options are:
|
In addition @fpesce is looking for 1.2 to add an extra iptables rule, to check:
This will let pod talk with itself without going trough envoy, when DISABLE_REDIRECTION_ON_LOCAL_LOOPBACK is set. Will not help for pod talking with itself using the VIP - this is where we don't have yet a solution. |
Moving back to 1.2 since that's the critical target. |
Why do we need to set DISABLE_REDIRECTION_ON_LOCAL_LOOPBACK ? Why can’t it always be set ? |
Here is a permanent fix. Add an option in envoy orig dst cluster to reuse orig dst port but rewrite the ip alone (call it orig_port). Then we could have a default inbound passthrough cluster for the VirtualInbound listener that will forward all traffic to 127.0.0.1:orig_port. This will permanently fix the issue without having to tweak iptables. It will also eliminate all inbound clusters as we now simply can use the inbound-passthrough cluster. It’s easy to add this feature to envoy. Cluster already has an options field for orig dst lb. |
We can't rewrite to 127.0.0.1:orig_port - would be a huge security vulnerability. Apps bind to 127 to prevent traffic from external addresses - this would automatically make all localhost-bound listeners exposed as if they were bound on 0.0.0.0 Regarding DISABLE_REDIRECTION - the reason it exists is to handle the case of app talking to the cluster VIP, which gets captured by Envoy and sent to a cluster with TLS enabled. If the EDS returns an endpoint running on the same pod, the request needs to be bounced trough envoy on the inbound path to handle the TLS decryption. Once we disable redirection we break this case. |
Also would be good to make clear the version - for 1.3 with split chains I believe the proposed solution handles all use cases. Traffic from local IP to local IP will bypass envoy at iptables level, and traffic sent to the VIP that is resolved to local IP will match an explicit filter in the inbound chain. So outbound chain will match VIP or send to original DST - which can be an external IP, or one of the container ports on the local IP. Same as today. Inbound chain will capture all traffic - from external IPs or from envoy sending to local IP. |
We are already routing to 127.0.0.1:port from podIP:port for container ports. This has been how things have operating since beginning. So what’s the new issue we have here? Why isn’t this an issue today with existing inbound clusters |
@rshriram |
I guess it's similar with UDS support: obviously you can't connect from the network to a UDS socket, but user can configure Istio to expose the UDS socket to the network. If user has an explicit config defining a service and container port for a 127.0.0.1 - it is considered intent to expose it. But with 'magic' automatic config for ports - i.e. the originalDst in the input chain - we can't automatically expose all 127.0.0.1. In original Istio 0.1 - before the containerPort requirement - we still used the Service definition, so |
This is fixed by #15833, to be backported to 1.2 and 1.1, and a duplicate (in terms of root cause -- thanks for all the details you provided @ckcd) of #14242. For future split listener plans we will need a better solution, but for now I think its best to close this and consolidate conversation in #14242 as we have two discussions going on here |
Bug description
If pod defines a port (assumed port-1) but service do NOT defines this port-1, then for a single request to POD_IP:port-1, we can see very very much logs of this single request, and it makes a loop between sidecar and iptables which will final use all 1024 connection-pool of envoy.
for example, for this service and deployment:
the pod defines port 80 and port 2334 but the service only defines 80, and if we do a request from another service to POD_IP:2334, i see plenty of logs in envoy:
which means somewhere makes a bad loop !
the reason, i guess, because of this commit and this commit add a default
passthrough cluster
, all traffic will be fallthrough, and in this case, the request to POD_IP:2334 will be fallthrough and go to iptables, and it will go to OUTPUT table because it's dst_ip is itself, and got this chain:and then go back to envoy, and be fallthrough, and go to iptables ... so the loop became.
Expected behavior
I think the correct behavior should be
404
or502
, but maybe we can find some perfect answer.Steps to reproduce the bug
as shown above.
Version (include the output of
istioctl version --remote
andkubectl version
)istio 1.1.7
kubernetes 1.12.7
How was Istio installed?
Environment where bug was observed (cloud vendor, OS, etc)
aws, ubuntu 16.04
The text was updated successfully, but these errors were encountered: