网站开发研究综述,最近免费视频中文2019完整版,网站制作的要点和步骤详解,品牌网站建设有那两种模式作者#xff1a; 郑明泉、余凯
为啥争吵#xff0c;吵什么#xff1f;
“你到底在说什么啊#xff0c;我K8s的ecs节点要访问clb的地址不通和本地网卡有什么关系…” 气愤语气都从电话那头传了过来#xff0c;这时电话两端都沉默了。过了好一会传来地铁小姐姐甜美的播报声…作者 郑明泉、余凯
为啥争吵吵什么
“你到底在说什么啊我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的服务那么这个时候所有网卡IP443都能通但是访问的是本地服务而不是真正的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 IPVLANEBPF全景剖析阿里云容器网络数据链路五—— 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.86conntrack表记录了src是10.0.4.176sport是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.86conntrack表记录了src是10.0.4.176sport是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?urlhttps%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