heming
直接删掉Pod触发其重新创建或许可以解决此问题,但我建议先进入Pod所在网络命名空间做一些测试后再销毁现场。

执行以下命令获取kube-proxy pod的进程号:

docker inspect $(docker ps | grep kube-proxy | grep pause | awk '{print $1}') | grep Pid

进入该网络命名空间:

nsenter -t 进程号 -n

查看网络接口信息与路由表

ip a
ip r

除此之外,还可查看节点上对应容器的相关日志,检查是否有异常输出

获取kube-proxy容器id

docker inspect $(docker ps | grep kube-proxy | grep pause | awk '{print $1}') | grep Id

查看相关日志:

less /var/log/messages

输入\容器Id查找相关日志

你好! 这是异常节点的kubeproxy的接口信息:

@kevendeng#28737 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:77:06:22 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.104/24 brd 192.168.0.255 scope global dynamic noprefixroute enp0s3
       valid_lft 172510sec preferred_lft 172510sec
    inet6 fe80::a00:27ff:fe77:622/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: zt7nner2ay: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 2800 qdisc fq_codel state UNKNOWN group default qlen 1000
    link/ether 82:5f:ee:29:26:84 brd ff:ff:ff:ff:ff:ff
    inet 10.147.20.50/24 brd 10.147.20.255 scope global zt7nner2ay
       valid_lft forever preferred_lft forever
    inet6 fe80::485a:2bff:feba:277f/64 scope link 
       valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:4d:65:a0:f0 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
5: nodelocaldns: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default 
    link/ether be:f1:45:9b:e6:c4 brd ff:ff:ff:ff:ff:ff
    inet 169.254.25.10/32 brd 169.254.25.10 scope global nodelocaldns
       valid_lft forever preferred_lft forever
6: kube-ipvs0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default 
    link/ether f2:f9:81:df:62:f1 brd ff:ff:ff:ff:ff:ff
    inet 10.233.0.3/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.233.61.65/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.233.19.231/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.233.48.17/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.233.29.149/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.233.25.27/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.233.8.25/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.233.29.2/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.233.48.209/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.233.24.220/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.233.16.230/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.233.0.1/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever

它的路由表:

我重启了异常节点的kubeproxy,也重启了异常节点还是一样的问题,
这是重启异常节点后的kubeproxy的日志:

    heming
    从路由表及kube-proxy的日志来看,它已经处于正常运行状态了,现在还有什么问题?

    heming
    现在kube-proxy已经正常运行了,应该检查calico的日志,理论上它应该可以通过10.233.0.1访问到kube-apiserver了。

      kevendeng 你好, calico 还是无法使用

      那个异常节点和calico的pod不能访问https://10.233.0.1:443, 但是都能访问https://主节点IP:6443, kube-proxy日志也没有异常信息,甚至日志从启动以来就没变化, 请问是什么原因会造成这种结果呢?

        heming
        10.233.0.1是K8s集群的虚拟Service IP,指向主节点的真实IP,而这个映射关系是由kube-proxy通过创建ipvs转发规则实现的。

        执行命令 ipvsadm -ln | grep 10.233.0.1 检查是否有从 10.233.0.1:443主节点IP:6443 的映射,若没有此规则,说明kube-proxy仍未正常工作,需要再次检查其日志是否有异常。

          kevendeng 你好! 感谢您的再次帮助,我发现了一个问题, ipvsadm -ln查看异常节点的转发规则:

          这个是指向master的内网地址的,不是服务器vpn地址, 请问需要如何解决?

            heming
            你所建立的VPN是否为整个集群所有节点共享的?
            如果是,将Service指向Master的VPN地址

            kubectl edit endpoints kubernetes

            将其中的内网地址修改为VPN地址

              heming
              是的,这应该是Endpoint Controller所控制的。

              尝试在Master节点上找到kubelet的启动参数配置文件,如果你是使用KubeKey安装的KS,这个文件应该位于/etc/systemd/system/kubelet.service.d/10-kubeadm.conf

              将其中的node-ip,目前应该是该节点的内网IP,修改为其在VPN中的IP,保存该文件,并重启kubelet与docker:

              systemctl daemon-reload
              systemctl restart kubelet
              systemctl restart docker

                kevendeng 好奇怪,我改了配置后,master的节点ip也变成VPN地址了, 但是修改kubectl edit endpoints kubernetes还是会变回来, ipvs还是把10.147.20.1 映射到 master内网ip, 我也重启了所有节点,还是这样…

                  heming
                  那或许这个endpoint对象是由另外的参数配置的,kubelet的node-ip参数仅仅是控制hostNetwork模式下pod的ip。

                  我能想到的两个地方还有kube-apiserver与kube-controller-manager,你可以先尝试把kube-apiserver中对应的地址改为VPN的IP,该文件位于主节点的/etc/kubernetes/manifests/kube-apiserver.yaml下,可以直接使用搜索与替换,保存后kube-apiserver会自动重启。

                    kevendeng 感谢dalao帮忙! 让我学到很多关于k8s网络的知识, 我总结了一下:

                    首先是两个网络, 节点网络pod网络(10.233.0.0/18)( k8s要求节点网络中所有节点都是互通的,
                    因为我是先在服务器内网部署k8s的, 所以主节点的ip就是它的内网ip, 节点网络就是服务器内网,
                    后来我搭建vpn想将本地机器添加进集群, 于是就多了一个vpn网络和主节点的vpnIP,
                    在我通过vpn在本地节点使用kubeadm join加入集群后,
                    kubeadm帮我安装和配置work节点需要的pod,
                    此处有误已由kevendeng在楼下补充:
                    在kubeadm配置kube-proxy的时候应该是需要从apiserver获取主节点ip的, ( apiserver使用的主节点IP通过 --advertise-address 参数设置 (/etc/kubernetes/manifests/kube-apiserver.yaml

                    于是就获取了主节点ip(内网ip)并设置进kube-proxy了,
                    我的kube-proxy再设置ipvs, 将10.233.0.1映射到主节点内网ip而不是vpn ip,
                    所以就导致本地节点的pod无法通过10.233.0.1去访问apiserver. ( 例如我的问题calico-node这个pod无法请求10.233.0.1:443 timeout.
                    于是在@kevendeng dalao的指导下,
                    我通过设置/etc/systemd/system/kubelet.service.d/10-kubeadm.conf和/etc/kubernetes/manifests/kube-apiserver.yaml将集群使用的节点网络从服务器内网切换成vpn就解决了.
                    最好确定集群节点使用的是什么网络, 要添加节点时要将节点加入进这个网络, 而不是新建一个网络.

                    在我理解的在pod网络中,不同节点的pod的通信路径:
                    节点1-pod1, 节点2-pod2

                    此处有误已由kevendeng在楼下补充:
                    pod1要访问pod2:
                    pod1 -> kube-proxy1 -> 节点2 -> kube-proxy2 -> pod2

                    如有错误请指出,非常感谢!
                    再次感谢@kevendeng dalao的帮助!!!

                      heming
                      不客气,每一次Debug让我自己对K8s的了解也多了一分。

                      你的理解大体上是正确的,有一些细节错误,如:

                      在kubeadm配置kube-proxy的时候应该是需要从apiserver获取主节点ip的, ( apiserver使用的主节点IP通过 –
                      advertise-address 参数设置 (/etc/kubernetes/manifests/kube-apiserver.yaml
                      于是就获取了主节点ip(内网ip)并设置进kube-proxy了,

                      实际上,此Endpoint对象是由apiserver定期更新的。
                      kubernetes Service IP 到 此Endpoint IP的IPVS转发规则是由kube-proxy观察到该对象后创建的。

                      以及:

                      pod1要访问pod2:
                      pod1 -> kube-proxy1 -> 节点2 -> kube-proxy2 -> pod2

                      这并不是全部情况。在K8s集群内部,主要有两个网段,一种是Pod,一种是Service,若Pod之间通过IP/(非Service)域名互相访问,并不会通过kube-proxy所设置的转发。

                      这些概念,以及底层运行原理,需要对K8s的网络模型更加熟悉,K8s的官方文档是一个很好的参考资料。

                      你提到的这一点:

                      最好确定集群节点使用的是什么网络, 要添加节点时要将节点加入进这个网络, 而不是新建一个网络.

                      确实应该这样做,网络规划应该在部署集群之前完成,如果不得不跨网络运行,VPN也应该在部署集群之前建立。

                      以及:建议你为此贴的标题补充上更加详细的描述,如“K8s集群部署后,通过建立VPN网络加入外部节点”,以便其他遇到类似问题的同学搜索。

                        heming 更改标题为「通过建立VPN网络向集群加入外部节点所遇到的问题

                        kevendeng 你好, 我有一点不太明白,pod之间通过它们ip相互访问的话, 如果不转发, 如何跨节点访问?

                        这并不是全部情况。在K8s集群内部,主要有两个网段,一种是Pod,一种是Service,若Pod之间通过IP/(非Service)域名互相访问,并不会通过kube-proxy所设置的转发。

                          heming
                          K8s要求不同容器,不同节点之间都能互相访问,但并不指定实现方式,不同的CNI插件实现各有不同,常见的如VXLAN或者BGP,具体内容可以学习下CNI相关知识。

                            6 天 后