一次网络不通“争吵“引发的思考

作者: 郑明泉、余凯

为啥争吵,吵什么?

“你到底在说什么啊,我K8s的ecs节点要访问clb的地址不通和本地网卡有什么关系…” 气愤语气都从电话那头传了过来,这时电话两端都沉默了。过了好一会传来地铁小姐姐甜美的播报声打断了刚刚的沉寂「乘坐地铁必须全程佩戴口罩,下一站西湖文化广场…」。

pod需要访问clb的443的监听, 但是如果是集群内(集群内后面都指的K8s的节点或者POD)访问就会出现如下报错Connection refused:

在这里插入图片描述

所以就捋了一下客户链路如下:

在这里插入图片描述

具体现象是什么

无论是节点node还是pod里访问192.168.1.200:443都是不通的,但是访问192.168.1.200:80却是正常的。同时集群外的ECS192.168.3.100访问192.168.1.200:443和192.168.1.200:80都是正常的。

进一步分析看看

CLB1的IP192.168.1.200被绑定到了K8s的node节点的kube-ipvs0网卡上,这个是一张dummy 网卡,参考dummy interface。由于 SVC1 是LoadBalancer类型的,同时复用了这个CLB1,关联endpoint是POD1192.168.1.101:80,那么就可以解释为何访问192.168.1.200:80是正常,是由于kube-proxy根据SVC1的配置创建ipvs规则同时挂载了可被访问的后端服务。而集群里访问192.168.1.200:443都是不通的,因为IP被绑定到dummy网卡后,就不会再出节点去访问到CLB1,同时没有443对应ipvs规则,所以直接是拒绝的。

这个时候如果节点里没有ipvs规则(ipvs优先于监听)但是又能访问通的话, 可以检查一下是否本地有监听0.0.0.0:443的服务,那么这个时候所有网卡IP+443都能通,但是访问的是本地服务,而不是真正的CLB后端的服务。

在这里插入图片描述

是否有办法解决呢

最建议的方式

最好的方式拆分, 集群内和集群外的服务分开两个CLB使用。

阿里云svc注解的方式

SVC1使用这个注解service.beta.kubernetes.io/alibaba-cloud-loadbalancer-hostname,进行占位,这样就不会绑定CLB的IP到kube-ipvs0的网卡上,集群内访问CLB的IP就会出集群访问CLB,但是需要注意如果监听协议为TCP或UDP,集群内访问CLB IP时将会存在回环访问问题。详细信息,请参见客户端无法访问负载均衡CLB [ 1]

需要CCM版本在 v2.3.0及以上版本才支持这个注解, 具体参考:通过Annotation配置传统型负载均衡CLB [ 2]

在这里插入图片描述

demo:

apiVersion: v1
kind: Service
metadata:annotations:service.beta.kubernetes.io/alibaba-cloud-loadbalancer-hostname: "${your_service_hostname}"name: nginx-svcnamespace: default
spec:ports:- name: httpport: 80protocol: TCPtargetPort: 80selector:app: nginxtype: LoadBalancer

集群内访问 ExternalTrafficPolicy 策略有影响吗?

我们都知道K8s的nodeport和loadbalancer模式是可以调整外部流量策略的,那么图中的「外部策略为Local/Cluster,所有集群节点创建IPVS规则是有区别的」该如何解释呢, 以及集群内访问nodePort/CLBIP的时候会发生什么。

在这里插入图片描述

以下都是针对svc的internalTrafficPolicy都是Cluster或者缺省的情况,这个ServiceInternalTrafficPolicy特性在1.22的K8s中默认开启,具体参考service-traffic-policy [ 3]

具体到阿里云容器在不同网络CNI情况下的数据链路,可以参考下面的文章:

  • 全景剖析阿里云容器网络数据链路(一)—— Flannel
  • 全景剖析阿里云容器网络数据链路(二)—— Terway ENI
  • 全景剖析阿里云容器网络数据链路(三)—— Terway ENIIP
  • 全景剖析阿里云容器网络数据链路(四)—— Terway IPVLAN+EBPF
  • 全景剖析阿里云容器网络数据链路(五)—— Terway ENI-Trunking
  • 全景剖析阿里云容器网络数据链路(六)—— ASM Istio

此处我们只讨论ipvs TrafficPolicy Local在Kubernetes 从1.22升级到1.24的行为变化。

Kubernetes 1.24 IPVS的变化

以下均以kube-proxy的IPVS模式为例:

  • 当externalTrafficPolicy为Cluster模式或缺省的时候,ipvs规则里的nodePort/CLBIP后端会挂载所有的Endpoint的IP,这时候集群内访问会丢失源IP,因为节点会做一层SNAT。
  • 当externalTrafficPolicy是Local的时候
    • 当节点上有对应service的Endpoint的时候,ipvs规则里的nodePort/CLBIP后端只挂载自己节点的Endpoint的IP,集群内访问会保留源IP。
    • 当节点上没有对应service的Endpoint的时候
    • 在1.24之前的版本是会挂空的后端的,集群内访问会拒绝。
    • 在1.24之后的K8s集群里,当节点上没有对应service的Endpoint的时候,ipvs规则里的nodePort/CLB IP后端会挂载所有的Endpoint的IP,这时候集群内访问会丢失源IP,因为节点会做一层SNAT。社区调整了Local策略后端服务的规则挂载策略,具体参考社区PR [ 4]

https://github.com/kubernetes/kubernetes/pull/97081/commits/61085a75899a820b5eebfa71801e17423c1ca4da

集群外访问SLB

集群外访问SLB的话,CCM只会挂载Local类型的节点,情况跟1.24 kubernetes前一样,这里不做过多阐述,请见上面连接。

集群外访问NodePort

1.24 Kubernetes之前版本

  • 访问有Endpoint的节点的NodePort,可以通,可以保留源IP

Nginx分布在cn-hongkong.10.0.4.174和cn-hongkong.10.0.2.84节点。

在这里插入图片描述

从外部10.0.3.72节点访问有后端pod所在节点的cn-hongkong.10.0.2.84的30479端口,可以访问。

在这里插入图片描述

cn-hongkong.10.0.0.140节点上是有相关的IPVS的规则的,但是只有该节点上后端Pod IP。

在这里插入图片描述

通过conntrack表可以到,这是由于在cn-hongkong.10.0.0.140节点上,相关的链路被dnat,最后是由pod cn-hongkong.10.0.2.84节点上的 的nginx-7d6877d777-tzbf7 10.0.2.87返回源,所有的相关转化都在该节点上,所以TCP四层建连可以成功。

在这里插入图片描述

  • 访问没有Endpoint的节点的NodePort,不能通,因为节点上没有相关的ipvs转发规则

从外部10.0.3.72节点访问无后端pod所在节点的cn-hongkong.10.0.0.140的30479端口,不可以访问。

在这里插入图片描述

查看该cn-hongkong.10.0.0.140节点,并没有相关的ipvs转发规则,所以无法进行dnat,访问会失败。

在这里插入图片描述

1.24 Kubernetes版本之后(含)

访问有Endpoint节点的NodePort,可以通,可以保留源IP

访问没有Endpoint节点的NodePort:

  • terway ENIIP or host网络:不通

Nginx分布在cn-hongkong.10.0.2.77和cn-hongkong.10.0.0.171 节点。

在这里插入图片描述

从外部10.0.3.72节点访问无后端pod所在节点的cn-hongkong.10.0.5.168的30745端口,可以看到,访问失败。

在这里插入图片描述

cn-hongkong.10.0.5.168节点上是有相关的IPVS的规则的,并且会把所有的后端Pod IP加到IPVS规则中。

在这里插入图片描述

通过conntrack表可以到,这是由于在cn-hongkong.10.0.5.168节点上,相关的链路被dnat,最后是由pod cn-hongkong.10.0.2.77节点上的nginx-79fc6bc6d-8vctc 10.0.2.78返回源,源在接受这个链路后,会发现和自己的五元组不匹配,直接丢弃,三次握手必然失败,所以建连失败。

在这里插入图片描述

  • flannel网络:可以通,但是保留不了源IP

Nginx分布在cn-hongkong.10.0.2.86。

在这里插入图片描述

从外部访问cn-hongkong.10.0.4.176的31218端口,可以访问成功。

在这里插入图片描述

cn-hongkong.10.0.4.176记录了src是10.0.3.72,并做了dnat为172.16.160.135,期望它返回给10.0.4.176的58825端口。

在这里插入图片描述

后端ep所在节点cn-hongkong.10.0.2.86,conntrack表记录了src是10.0.4.176,sport是58825。所以可以看到应用pod是记录的源IP是10.0.4.176,丢失了源IP。

在这里插入图片描述

集群内访问SLB或者NodePort

1.24 Kubernetes之前版本

  • 有Endpoint的节点上访问,可以通,可以保留源IP

Nginx分布在ap-southeast-1.192.168.100.209和ap-southeast-1.192.168.100.208节点,ap-southeast-1.192.168.100.210节点没有Nginx pod。

在这里插入图片描述

从集群任意节点(本例就在209节点)访问有后端pod所在节点的ap-southeast-1.192.168.100.209的NodePort 31565端口,可以访问。

在这里插入图片描述

从有后端pod所在节点ap-southeast-1.192.168.100.209访问SLB 8.222.252.252 的80端口,可以访问。

在这里插入图片描述

ap-southeast-1.192.168.100.209节点上是有NodePort 和SLB 的IPVS的规则的,但是只有该节点上后端Pod IP。

在这里插入图片描述

通过conntrack表可以到,这是由于在ap-southeast-1.192.168.100.209 节点上,相关的链路被dnat,最后是由pod 在ap-southeast-1.192.168.100.209 节点上的 的nginx-7d6877d777-2wh4s 192.168.100.222返回源,所有的相关转化都在该节点上,所以TCP四层建连可以成功。

在这里插入图片描述

  • 没有Endpoint的节点上访问,不能通,因为节点上没有相关的ipvs转发规则

从集群任意节点(本例就在210节点)访问没有后端pod所在节点的ap-southeast-1.192.168.100.210 的NodePort 31565端口或者SLB,不可以访问。

也进一步证实,集群内访问关联svc的SLB不出节点,即使SLB有其他监听端口,访问SLB其他端口也会拒绝。

在这里插入图片描述

查看该ap-southeast-1.192.168.100.210 节点,并没有相关的ipvs转发规则,所以无法进行dnat,访问会失败。

在这里插入图片描述

1.24 Kubernetes版本之后(含)

  • 有Endpoint节点上访问,可以通,可以保留源IP

与上文的1.24 Kubernetes之前版本集群内访问一致,可以参考上文描述。

  • 没有Endpoint节点上访问:

Nginx分布在cn-hongkong.10.0.2.77和cn-hongkong.10.0.0.171节点,所以在没有Nginx的cn-hongkong.10.0.4.141节点上测试。

在这里插入图片描述

分别有以下几种情况:

  • terway或后端为hostNetwork
    • 节点访问的通 NodePort(源 IP 是 ECS IP,不需要做 SNAT),无法保留源IP

可以看到没有Endpoint的节点的NodePort 110.0.4.141:30745 的IPVS 的规则添加的Nginx的所有后端POD nginx-79fc6bc6d-8vctc 10.0.2.78 和 nginx-79fc6bc6d-j587w 10.0.0.172。

在这里插入图片描述

集群内节点自身访问没有后端pod所在节点的cn-hongkong.10.0.4.141 的NodePort 30745/TCP端口,可以访问。

在这里插入图片描述

通过conntrack表可以到,在cn-hongkong.10.0.4.141节点上,相关的链路被dnat,最后是由后盾Nginx pod nginx-79fc6bc6d-8vctc 10.0.2.78返回源。

在这里插入图片描述

而在nginx-79fc6bc6d-8vctc 10.0.2.78 所在的节点cn-hongkong.10.0.2.77上的conntrack表记录的是10.04.141访问10.0.2.78,并期望10.0.2.78直接返回10.0.4.141的的39530端口。

在这里插入图片描述

集群内有endpoint 节点访问没有后端pod所在节点的ap-southeast-1.192.168.100.131 的NodePort 32292端口,不可以访问,与上文1.24 Kubernetes版本之后(含) 集群外访问一致,可以参考上文描述。

    • 节点访问不通 SLB IP(源 IP 是 SLB IP,没有人做 SNAT)

可以看到没有Endpoint的节点的SLB IP 的IPVS 的规则添加的Nginx的所有后端POD nginx-79fc6bc6d-8vctc 10.0.2.78 和 nginx-79fc6bc6d-j587w 10.0.0.172。

在这里插入图片描述

没有Endpoint的节点上访问 SLB 47.243.247.219,访问确是超时。

在这里插入图片描述

通过conntrack表可以到,在没有ep的节点访问SLB的IP,可以看到期望的是后端pod返回给SLB IP。而SLB IP 在节点上已经被kube-ipvs虚拟占位了,所以没有做snat,造成无法访问。

在这里插入图片描述

  • flannel并且后端为普通pod,可以访问通,但是保留不了源IP

Nginx分布在cn-hongkong.10.0.2.86。

在这里插入图片描述

在cn-hongkong.10.0.4.176访问SLB 47.242.86.39 是可以访问成功的。

在这里插入图片描述

cn-hongkong.10.0.4.176节点的conntrack表可以看到是src和dst都是47.242.86.39,但是期望的是 nginx pod172.16.160.135 返回给 10.0.4.176 的54988端口,47.242.86.39 snat成10.0.4.176。

在这里插入图片描述

后端ep所在节点cn-hongkong.10.0.2.86,conntrack表记录了src是10.0.4.176,sport是54988。所以可以看到应用pod是记录的源IP是10.0.4.176,丢失了源IP。

在这里插入图片描述

相关链接:

[1] 客户端无法访问负载均衡CLB

https://help.aliyun.com/document_detail/55206.htm

[2] 通过Annotation配置传统型负载均衡CLB

https://www.yuque.com/r/goto?url=https%3A%2F%2Fhelp.aliyun.com%2Fzh%2Fack%2Fack-managed-and-ack-dedicated%2Fuser-guide%2Fadd-annotations-to-the-yaml-file-of-a-service-to-configure-clb-instances

[3] service-traffic-policy

https://kubernetes.io/zh-cn/docs/concepts/services-networking/service-traffic-policy/

[4] 社区PR

https://github.com/kubernetes/kubernetes/pull/97081/commits/61085a75899a820b5eebfa71801e17423c1ca4da

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/40730.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

iview默认样式覆盖

scoped 属性是 HTML5 中的新属性。 当style标签拥有scoped属性时,它的css样式只能用于当前的Vue组件,可以使组件的样式不相互污染。 如果一个项目的所有style标签都加上了scoped属性,相当于实现了样式的模块化。 1、全页面覆盖 不添加scoped…

【一】ubuntu20.04上搭建containerd版( 1.2.4 以上)k8s及kuboard V3

k8s 部署全程在超级用户下进行 sudo su本文请根据大纲顺序阅读! 一、配置基础环境(在全部节点执行) 1、安装docker 使用apt安装containerd 新版k8s已经弃用docker转为containerd,如果要将docker改为containerd详见&#xff1a…

对dubbo的DubboReference.check的参数进行剖析

背景 在使用dubbo的时候,发现当消费者启动的时候,如果提供者没有启动,即使提供者后来启动了,消费者也调不通提供者提供的接口了。 注册中心使用都是nacos dubbo版本是3.0.4 例子 接口 public interface DemoService {String…

“深入解析JVM内部机制:探秘Java虚拟机的奥秘“

标题:深入解析JVM内部机制:探秘Java虚拟机的奥秘 摘要:本文将深入解析JVM(Java虚拟机)的内部机制,从字节码执行到垃圾回收,逐步揭示Java程序运行的奥秘。通过理论分析和示例代码,读…

thinkphp5.1 trace 不显示sql语句

config/app.php app_debug > true,//线上环境为 false // 应用Trace app_trace > true,//线上环境为 false config/database.php debug > true, config/log.php close > false, thinkphp5.1x 设计非常奇怪 必须开启…

使用dockerfile手动构建JDK11镜像运行容器并校验

Docker官方维护镜像的公共仓库网站 Docker Hub 国内无法访问了,大部分镜像无法下载,准备逐步构建自己的镜像库。【转载aliyun官方-容器镜像服务 ACR】Docker常见问题 阿里云容器镜像服务ACR(Alibaba Cloud Container Registry)是面…

内网穿透-外远程连接中的RabbitMQ服务

文章目录 前言1.安装erlang 语言2.安装rabbitMQ3. 内网穿透3.1 安装cpolar内网穿透(支持一键自动安装脚本)3.2 创建HTTP隧道 4. 公网远程连接5.固定公网TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 前言 RabbitMQ是一个在 AMQP(高级消息队列协议)基…

Linux:shell脚本:基础使用(4)《正则表达式-grep工具》

正则表达式定义: 使用单个字符串来描述,匹配一系列符合某个句法规则的字符串 正则表达式的组成: 普通字符串: 大小写字母,数字,标点符号及一些其他符号 元字符:在正则表达式中具有特殊意义的专用字符 正则表…

python中__main__的解释

源自于:https://zhuanlan.zhihu.com/p/340997807 Python程序运行时是从模块顶行开始,最顶层(没有被缩进)的代码都会被执行,所以Python中并不需要一个统一的main()作为程序的入口。 __name__是Python的内置变量&#…

蓝桥杯嵌入式省一教程:(三)按键扫描与定时器中断

在第一讲中曾经提到,GPIO有输入输出两种模式。在点亮LED时,我们已经使用了GPIO输出模式,在按键识别中,我们将要使用GPIO输入模式。首先来看看按键的电路原理图(下图在选手资源数据包——CT117E-M4产品手册中&#xff0…

Android CCodec (二十) CCodec Native服务实现分析

1、C2解码服务registerAsService注册流程 google实现CCodec的vendor默认解码服务代码路径是在frameworks/av/media/codec2/hidl/services/vendor.cpp中,而其注册的是HIDL服务,本文就对HIDL服务注册做简要分析。首先看下vendor.cpp中的代码注册流程。 int main(int /* argc *…

高等数学教材重难点题型总结(三)微分中值定理和导数的应用

第三章,微分中值定理的证明题等,非常重要,需要牢牢掌握 1.证明中值定理对某函数在给定区间上的正确性 2.与中值定理有关的证明题 3.微分中值定理应用于求证不等式 4.洛必达法则求极限 5.洛必达的经典错误反例 6.按某项实现多项式幂展开 7.求带…

以 Java NIO 的角度理解 Netty

文章目录 前言Java NIO 工作原理Selector 的创建ServerSocketChannel 的创建ServerSocketChannel 注册 Selector对事件的处理总结 前言 上篇文章《Netty 入门指南》主要涵盖了 Netty 的入门知识,包括 Netty 的发展历程、核心功能与组件,并且通过实例演示…

rabbitmq的发布确认

生产者将信道设置成 confirm 模式,一旦信道进入 confirm 模式, 所有在该信道上面发布的 消息都将会被指派一个唯一的 ID (从 1 开始),一旦消息被投递到所有匹配的队列之后,broker 就会发送一个确认给生产者(包含消息的唯一 ID)&…

AI巨浪下,数据技术如何驱动智能未来?

引言 数据技术是大数据时代的核心驱动力,也是推动各行各业数字化转型和智能化升级的关键因素。随着云计算、人工智能、区块链等新兴技术的不断发展和融合,数据技术也呈现出多模态、混合处理、自动化管理等新的趋势和特点。 8 月 19 日(周六&…

域名和ip的关系

域名和ip的关系 一:什么是域名 域名,简称域名、网域,是由一串用点分隔的名字组成的上某一台计算机或计算机组的名称,用于在数据传输时标识 计算机的电子方位(有时也指地理位置)。网域名称系统,有时也简称为域名…

【宝藏系列】嵌入式 C 语言代码优化技巧【超详细版】

【宝藏系列】嵌入式 C 语言代码优化技巧【超详细版】 文章目录 【宝藏系列】嵌入式 C 语言代码优化技巧【超详细版】前言整形数除法和取余数合并除法和取余数通过2的幂次进行除法和取余数取模的一种替代方法使用数组下标全局变量使用别名变量的生命周期分割变量类型局部变量指针…

Centos下的tcpdump抓包用法

先查一下是否安装, 无的话装一下 (版本低的用yum install) : rpm -qa tcpdump dnf install tcpdump 1. 列出能抓包的网卡: tcpdump -D | --list-interfaces 2. 在eth0网卡上抓来源为10.1.1.1 的包, 只抓一个包 (-n这里是不解析DNS) : tcpdump -i eth0 -n src 10.1.1.1 -…

STM32 F103C8T6学习笔记3:串口配置—串口收发—自定义Printf函数

今日学习使用STM32 C8T6的串口,我们在经过学习笔记2的总结归纳可知,STM32 C8T6最小系统板上有三路串口,如下图: 今日我们就着手学习如何配置开通这些串口进行收发,这里不讲串口通信概念与基础,可以自行网上…

一文读懂HTML

文章目录 HTML的历史HTML的作用HTML的基本语言 HTML的历史 HTML(HyperText Markup Language)的历史可以追溯到20世纪90年代早期,它是互联网发展的重要里程碑之一。以下是HTML的历史概述: 早期阶段(1980年代末 - 1990年…