代码之家  ›  专栏  ›  技术社区  ›  Kevin Keane

Kubernetes nginx入口控制器不可靠

  •  0
  • Kevin Keane  · 技术社区  · 3 年前

    我需要帮助详细了解ingress控制器,特别是ingress nginx ingress控制器的工作原理。在我看来,它就像一个黑匣子,应该在公共IP上监听,终止TLS,并将流量转发到pod。但这到底是怎么发生的对我来说是个谜。

    这里的首要目标是理解,次要目标是解决我面临的一个紧迫问题。

    我有一个有五个节点的集群,正在尝试让Jupyterhub应用程序在其上运行。在大多数情况下,它运行良好。我使用了一个非常标准的Rancher RKE设置,带有法兰绒/印花布的网络。节点运行RedHat 7.9,带有iptables和firewalld,以及docker 19.03。

    Jupyterhub代理是使用ClusterIP服务设置的(我还尝试了NodePort服务,也可以使用)。我还设置了入口。入口有时有效,但通常不响应(连接超时)。具体来说,如果我删除入口,然后重新部署我的舵图,入口将开始工作。此外,如果我重新启动一个节点,入口将再次开始工作。我还没有确定入口停止工作的情况。

    以下是我的相关服务:

    kubectl get services
    NAME                       TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
    hub                        ClusterIP   10.32.0.183   <none>        8081/TCP   378d
    proxy-api                  ClusterIP   10.32.0.11    <none>        8001/TCP   378d
    proxy-public               ClusterIP   10.32.0.30    <none>        80/TCP     378d
    

    这很有效;telnet 10.32.0.30 80的响应与预期一致(当然,仅来自其中一个节点)。我也可以直接远程登录到代理公共播客(我的情况是10.244.4.41:8000)。

    这是我的入口。

    kubectl describe ingress
    Name:             jupyterhub
    Labels:           app=jupyterhub
                      app.kubernetes.io/managed-by=Helm
                      chart=jupyterhub-1.2.0
                      component=ingress
                      heritage=Helm
                      release=jhub
    Namespace:        jhub
    Address:          k8s-node4.<redacted>,k8s-node5.<redacted>
    Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
    TLS:
      tls-jhub terminates jupyterhub.<redacted>
    Rules:
      Host                     Path  Backends
      ----                     ----  --------
      jupyterhub.<redacted>
                               /   proxy-public:http (10.244.4.41:8000)
    Annotations:               field.cattle.io/publicEndpoints:
                                 [{"addresses":["",""],"port":443,"protocol":"HTTPS","serviceName":"jhub:proxy-public","ingressName":"jhub:jupyterhub","hostname":"jupyterh...
                               meta.helm.sh/release-name: jhub
                               meta.helm.sh/release-namespace: jhub
    Events:                    <none>
    

    到目前为止,我对这种情况下的入侵的理解是:

    流量到达k8s-node4或k8s-node5的443端口。 一些magic(由入口控制器控制)接收该流量,终止TLS,并将未加密的流量发送到pod 8000端口的IP。这是我想更好地理解的部分。

    这个黑匣子似乎至少部分涉及了法兰绒/印花布和一些iptables魔法,而且在某些方面显然也涉及到nginx。

    使现代化 :与此同时,我发现了导致Kubernetes崩溃的原因:重新启动firewalld。

    据我所知,这抹去了所有iptables规则,而不仅仅是防火墙生成的规则。

    0 回复  |  直到 2 年前
        1
  •  0
  •   Kevin Keane    2 年前

    我在这里找到了问题的答案: https://www.stackrox.io/blog/kubernetes-networking-demystified/ 可能需要注意的是,这可能在一定程度上取决于您使用的网络CNI,尽管我看到的一切都与库伯内特斯本身密切相关。

    我仍在努力消化这个博客的内容,我强烈建议直接参考那个博客,而不是依赖于我的答案,这可能是一个糟糕的故事复述。

    下面是到达端口443的包的大致流程。

    您需要使用该命令来查看这些表。

    iptables -t nat -vnL | less
    

    其结果看起来相当吓人。

    下面的内容删除了许多其他链和呼叫,以切入主题。在本例中:

    • 该集群将CNI插件用于印花布/频道/法兰绒。
    • 听着,端口是443
    • nginx入口控制器的pod在10.244.0.183监听(以及其他)。

    在这种情况下,数据包是如何流动的:

    • 数据包进入预路由链。
    • 预路由链调用(除其他外)CNI-HOSTPORT-DNAT链。
    • POSTROUTING链也调用相同的链。
    • CNI-HOSTPORT-DNAT链依次调用多个CNI DN xxxx链。
    • CNI DN xxx链执行DNAT并将目标地址更改为10.244.0.183。
    • nginx入口控制器内的容器监听10.244.0.183。

    如果pod与到达的数据包位于不同的节点上,并且如果多个pod对同一端口进行负载平衡,则会带来一些额外的复杂性。负载平衡似乎是通过iptables统计模块随机选择一条或另一条iptables规则来处理的。

    从服务到pod的内部流量遵循类似的流程,但不相同。

    在本例中:

    • 该服务位于10.32.0.183端口8001
    • 吊舱位于10.244.6.112,端口8001。
    Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
    ...
    KUBE-SERVICES  all  --  *      *       0.0.0.0/0            0.0.0.0/0
    
    Chain KUBE-SERVICES (2 references)
    ...
    /* Traffic from within the cluster to 10.32.0.183:8001 */
    0 0 KUBE-SVC-ZHCKOT5PFJF4PASJ  tcp  --  *      *       0.0.0.0/0            10.32.0.183          tcp dpt:8001
    ...
    
    /* Mark the package */
    Chain KUBE-SVC-ZHCKOT5PFJF4PASJ (1 references)
     pkts bytes target     prot opt in     out     source               destination
        0     0 KUBE-MARK-MASQ  tcp  --  *      *      !10.244.0.0/16        10.32.0.183  tcp dpt:8081
        0     0 KUBE-SEP-RYU73S2VFHOHW4XO  all  --  *      *       0.0.0.0/0            0.0.0.0/0 
    
    /* Perform DNAT, redirecting from 10.32.0.183 to 10.244.6.12 */
    Chain KUBE-SEP-RYU73S2VFHOHW4XO (1 references)                                                                                                                                                                                                                                       0     0 KUBE-MARK-MASQ  all  --  *      *       10.244.6.112         0.0.0.0/0
    0     0 DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0 tcp to:10.244.6.112:8081
    
    

    问题的第二部分是关于如何让节点可靠地工作:

    • 禁用防火墙。
    • 改用Kubernetes网络策略(如果使用印花布,则使用印花布网络策略)。