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

2023-10-30

为啥争吵,吵什么?

"你到底在说什么啊,我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使用这个注解http://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-svc
  namespace: default
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  type: LoadBalancer

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

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

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

此处我们只讨论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

作者: 郑明泉、余凯

点击立即免费试用云产品 开启云上实践之旅!

原文链接

本文为阿里云原创内容,未经允许不得转载

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

一次网络不通“争吵”引发的思考 的相关文章

  • stable diffusion实践操作-图片生文字到图片

    本文专门开一节写 文字图片相关的内容 在看之前 可以同步关注 stable diffusion实践操作 正文 1 png 图片提取信息 SD可以从png图片中提取信息 然后在来生成图片 1 1 保存png 到liblib网站 下载png图片
  • IDEA在Web项目部署时没有Artifact选项的解决方法

    1 现象 使用Intellij IDEA配置Web项目时 如下图所示 选择Deployment后点击 没有出现Artifact选项 2 解决方法 1 在Intellij IDEA开发菜单栏中 选择 File gt Project Struc
  • python requests post和get请求,并把结果写入json文件中

    今天在分析网页的时候 发现需要利用requests请求 得到数据 然后这会经常用到 虽然简单 但是容易忘记 所以我这里记录一下我用的python requests的demo文件 post请求 import requests json hea
  • zabbix数据库添加主从同步

    zabbix数据库正常运行的情况下 做mysql主从同步添加从库操作 一 在从库主机上安装mysql 注 版本与主库master一致 1 1 创建用户 groupadd mysql useradd r g mysql mysql 1 2 上

随机推荐

  • 服务器系列和酷睿系列,至强cpu与酷睿两个系列之间有什么区别?

    很多朋友选购英特尔处理器时 会纠结于酷睿与至强两个系列之间就 不知如何选择 标致左酷睿 右至强 酷睿系列CPU如i3 i5 i7是我们一般消费者最为熟悉的 它也是针对大部分家用桌面级消费者开发的中高端处理器 当然也包括低端的G系列的赛扬处理
  • (第一章)嵌入式linux之常用汇编指令

    1 处理器内部数据传输指令 数据传输指令分为 一般寄存器间的数据传输或者 特殊寄存器与一般寄存器间的数据传输 数据传输常用的指令有三个 MOV MRS 和 MSR 用法示例 1 MOV 指令 MOV R0 R1 将寄存器 R1 中的数据传递
  • 基于百度飞桨PaddlePaddle和PARL复现PPO强化学习算法

    文章目录 一 PPO训练效果展示 Mujoco HalfCheetah v2 二 策略优化算法发展回顾 三 PPO 算法论文阅读 1 Introduction 2 Background Policy Optimization 2 1 Pol
  • R语言使用RMySQL连接及读写Mysql数据库

    简单说下安装过程 一般不会有问题 重点是RMySQL的使用方式 系统环境说明 Redhat系统 Linux 460 42 6 32 431 29 2 el6 x86 64 系统编码 LANG zh CN UTF 8 中文UTF 8格式 my
  • Access Token是做什么的

    我们在访问很多大公司的开放 api 的时候 都会发现这些 api 要求传递一个 access token 参数 这个参数是什么呢 需要去哪里获取这个 access token 呢 access token 是在 Oauth2 0 协议中 客
  • ag-Grid的基本用法一(表格列的定义)

    最近在研究基于angular2 的表格的用法 发现一种非常好用的表格 就是ag grid ag grid不仅对angular1 x有支持 还支持react vue等目前主流的前端框架 这里我们只是对angular2 中的ag grid进行讲
  • 朴素贝叶斯分类器:R语言实现

    span style font family none background color rgb 255 255 255 span span style font family none background color rgb 255 2
  • flask中request.args和request.form区别

    app route ajaxget1 def ajax test get server name request args get server name server ip request args get server ip print
  • 前端的反单引号语法之`${}`

    es6中新增的字符串方法 可以配合反单引号完成拼接字符串的功能 1 反单引号怎么打出来 将输入法调整为英文输入法 单击键盘上数字键1左边的按键 2 用法 step1 定义需要拼接进去的字符串变量 step2 将字符串变量用 包起来 再写到需
  • c语言打开文本有什么作用,c语言文件打开方式有哪些

    c语言文件打开方式有哪些 ANSI C规定文件打开用函数fopen 关闭为fclose 1 调用方式通常为 FILE fp fp fopen 文件名 打开方式 2 参数说明 文件名 形如 myfile dat F data myfile d
  • 数据序列相关性-ACF,PACF和CCF

    引言 最近写论文关于预测的特征选择遇到一些问题 想把自己查询学习到的东西整理记录一下 理一理头绪 希望能加深自己对这些东西的理解 首先介绍引入几个概念 自相关函数 autocorrelation function ACF 偏自相关函数 pa
  • OLED透明屏全贴合技术:未来显示技术的突破性创新

    在现代科技发展的浪潮中 OLED透明屏全贴合技术以其独特的优势和无限的应用前景引起了广泛的关注 在这篇文章中 尼伽将深入探索OLED透明屏全贴合技术 介绍其优势和特点 并展望其在不同领域的应用前景 一 OLED透明屏全贴合技术 OLED透明
  • pytorch:批训练(batch_training)

    一 什么是批训练 批训练 意思是把整套训练数据分成数个批次进行训练 每个批次从数据中选取 n num 总数据 n batch 批次 个数据 直到把整套数据训练完成 举个例子 有10个输入训练数据 每个批次训练3个数据 这训练完成需要4个批次
  • 手机摄像头组成结构和工作原理

    手机摄像头的组成结构和工作原理 手机摄像头的组成结构和工作原理 手机摄像头由 PCB板 镜头 固定器和滤色片 DSP CCD用 传感器等部件组成 工作原理为 拍摄景物通过镜头 将生成的光学图像投射到传感器上 然后光学图像被转换成电信号 电信
  • html 分割线_html基础必备-分隔标记,前端小白一看就会

    分节 分区和分割线 这些标记用于将页面分成多个部分 熟练地掌握这些标记将意味着构建出具有良好的结构和布局的页面 使其更加友好和易于阅读 分区 div标记定义了HTML文件中的一个部分或分区 它通常包含需要组合在一起的标题 段落 表格或其他元
  • python写excel文件不覆盖_python向已存在的excel中新增表,不覆盖原数据的实例

    每月需更新某个excel表格 进行两项操作 且不覆盖原有的sheet 1 在原来的excel表中新增sheet 2 往原有的excel表中的某张sheet新增内容 基于python3 使用xlrd xlwt 具体代码如下 亲测有效 希望对大
  • 软件测试分级理论

    软件测试是软件工程当中不可或缺的一个过程 在软件工程中 测试者充当 虚拟用户 对软件产品进行检验 只有经过严格测试的软件产品 才能发布给用户使用 只要有软件的地方 就有软件测试 软件测试是一个包罗万象的话题 这种 包罗万象 的具体表现之一就
  • 工控安全PLC固件逆向一

    在工控领域 我们会遇到许多协议 为了进行安全研究 经常需要对协议的具体内容进行探索 今天我们就来聊聊关于工控协议逆向的问题 接下来会简单介绍一下常用的协议逆向方法并配合一些实战 当然 从未知到已知的探索过程不仅仅需要代码上的实践 还需要数学
  • React - getSnapshotBeforeUpdate() 的使用

    getSnapshotBeforeUpdate 方法 1 在render之前调用 state已更新 2 典型场景 获取render之前的dom状态 我们来看一个例子 每一秒钟都会加入一个新的 div msg number div 假如我们使
  • 一次网络不通“争吵”引发的思考

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