kubernetes: IPVS is not working with hostport

Is this a BUG REPORT or FEATURE REQUEST?

Choose one: BUG REPORT

Versions

kubeadm version (use kubeadm version):

Environment:

  • Kubernetes version (use kubectl version): 1.11.0
  • Cloud provider or hardware configuration: None
  • OS (e.g. from /etc/os-release): Ubuntu 16.04
  • Kernel (e.g. uname -a):
  • Others:

What happened?

I’m trying to set up a kubernetes (v1.11.0) cluster. Here is the setting of the cluster:

  1. Enable IPVS in kube-proxy
  2. Use hostport for nginx ingress controller. Deloy nginx ingress controller on the same node as kubenetes core services.

Host port 443 and 80 of nginx ingress controller is conflict with kubernetes (kube-apiserver) service’s port 443 and 80. Nginx ingress controller keeps crashloopback because failed to connect to kube-apiserver. I even cannot run telnet 10.0.0.1 443.

Try to find the root cause. Here is the iptable rules generated

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
cali-PREROUTING  all  --  anywhere             anywhere             /* cali:6gwbT8clXdHdC1b1 */
CNI-HOSTPORT-DNAT  all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL
KUBE-SERVICES  all  --  anywhere             anywhere             /* kubernetes service portals */
DOCKER     all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
cali-OUTPUT  all  --  anywhere             anywhere             /* cali:tVnHkvAo15HuiPy0 */
CNI-HOSTPORT-DNAT  all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL
KUBE-SERVICES  all  --  anywhere             anywhere             /* kubernetes service portals */
DOCKER     all  --  anywhere            !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
cali-POSTROUTING  all  --  anywhere             anywhere             /* cali:O3lYWMrLQYEMJtB5 */
CNI-HOSTPORT-SNAT  all  --  localhost           !localhost
KUBE-POSTROUTING  all  --  anywhere             anywhere             /* kubernetes postrouting rules */
MASQUERADE  all  --  172.17.0.0/16        anywhere

The CNI-HOSTPORT related iptable rules are on top of KUBE-SERVICES rule. As you seen the pre-routing rule

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
cali-PREROUTING  all  --  anywhere             anywhere             /* cali:6gwbT8clXdHdC1b1 */
CNI-HOSTPORT-DNAT  all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL
KUBE-SERVICES  all  --  anywhere             anywhere             /* kubernetes service portals */
DOCKER     all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL

Every time I call https://10.0.0.1:443 it will match CNI-HOSTPORT-DNAT rule to redirect to nginx ingress service. That’s why I got failure when calling kubernetes api with service ip.

What you expected to happen?

Should always take KUBE-SERVICES rule first rather than CNI-HOSTPORT-DNAT. So the pre-routing rule should be like

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
cali-PREROUTING  all  --  anywhere             anywhere             /* cali:6gwbT8clXdHdC1b1 */
KUBE-SERVICES  all  --  anywhere             anywhere             /* kubernetes service portals */
CNI-HOSTPORT-DNAT  all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL
DOCKER     all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL

How to reproduce it (as minimally and precisely as possible)?

See above append.

Anything else we need to know?

When I restarted kube-proxy, the iptable rules were generated correctly. Nginx ingress controller now started successfully.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 2
  • Comments: 38 (14 by maintainers)

Commits related to this issue

Most upvoted comments

@Lion-Wei Yes,Some cni plugin may think the service ip or host port should it self to generate a iptables chain and rule to hold this problem. If we just make the proxy’s iptables rule on the top of preroute chain.We may fix this problem but maybe cause other problems. In my opion,i want the @liqlin2015 to give us the ingress config . And would do you like to give us the whole iptables rule to let me know the calico’s rule. And the ipset list, ipvs? Let’s to find out why the calico chain above the KUBE-SERVICES make ur service wrong. In my env, i use contiv and ipvs dont have the problem. Thx.

iptables rule sequencing should be fixed now in all active branches.

NodePort is adding an additional LB hop that we would not have had with hostPort and would be kind of a shame to introduce this extra complexity.

Another way to avoid this hop, is to run nginx as

hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet

This way it does not conflict with kubernetes.deafult.svc.cluster.local:443 and still listening directly on Node:443.

@Lion-Wei I came across a merged PR (https://github.com/kubernetes/kubernetes/pull/62718) that you authored that seem to suggest that the issue of IPVS/hostPort incompatibility was fixed.

However this issue seems to suggest otherwise, I guess this is a different problem? though also related to IPVS/hostPort?

We use the nginx ingress controller on hostPorts 80, 443 + various TCP ports (for services that consume raw tcp) that are also exposed on clusterIP services (with same port numbers).

We’ve hit this issue during testing (K8s 1.13.2, kube-proxy IPVS mode and Calico 3.4.0) and can’t seem to find a solution/workaround.

Given our requirements, we may need to move back to kube-proxy iptables mode.

Would be great if you can share any details you know, or perhaps a workaround? 🙏

+1

ping @thockin 🙏

EDIT: wanted to share the details I got from @thockin in case anyone else wonders:

https://github.com/containernetworking/plugins/pull/269 is the one I think you want, which is released in https://github.com/containernetworking/plugins/releases/tag/v0.7.5 which is integrated in https://github.com/kubernetes/kubernetes/pulls?q=is%3Apr+CNI+0.7.5+is%3Aclosed

basically, ipvs nat mode will not do snat - i know it is confused but that is true.