摘要:原因解释创建成功后,的将集群中的每个云主机节点作为自身的节点,端口为申明的值注意不是。如何获取源对于需要明确知道客户端来源地址的情况,我们需要显示地将的设置成如下修改。重新部署服务后,再用浏览器访问,可以发现正确获取了浏览器的访问。
如没有实际需要,请避免修改ULB名称及注释
根据cloudprovider插件使用提醒,由UK8S cloudprovider创建的ULB不允许修改ULB名称,如果您修改过ULB名称,可以参考以下操作进行关联,避免影响线上业务。
# 增加ULB-id进行关联
service.beta.kubernetes.io/ucloud-load-balancer-id-provision:
UK8S cloudprovider插件在20.10.1版本后已经默认支持关联ULB-id,避免用户修改ULB名称后影响cloudprovider重建ULB,升级文档。
UK8S使用ULB4和ULB7来支持Loadbalancer类型的Service。对于ULB7,由于只支持HTTP协议且默认支持X-Forwarded-For头部,所以Web服务可以很容易获取客户端的真实IP。但对于使用ULB4接入的纯四层协议的服务来说,可能需要使用getpeername(2)来获取客户端真实IP。然而由于目前kube-proxy采用Iptables模式,后端pod内的应用程序的网络库调用getpeername(2)会无法获得正确的IP地址。以下例子可以说明问题。
部署一个简单的webserver,通过Loadbalancer ULB4外网模式接入。
apiVersion: v1
kind: Service
metadata:
name: ucloud-nginx
labels:
app: ucloud-nginx
annotations:
service.beta.kubernetes.io/ucloud-load-balancer-type: "outer"
service.beta.kubernetes.io/ucloud-load-balancer-vserver-method: "source"
spec:
type: LoadBalancer
ports:
- protocol: "TCP"
port: 80
targetPort: 12345
selector:
app: ucloud-nginx
---
apiVersion: v1
kind: Pod
metadata:
name: test-nginx
labels:
app: ucloud-nginx
spec:
containers:
- name: nginx
image: uhub.service.ucloud.cn/wxyz/uk8s-helloworld:1.8
ports:
- containerPort: 12345
部署完毕后,Service状态如下所示,可以通过EIP 117.50.3.206访问该服务。
# kubectl get svc ucloud-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ucloud-nginx LoadBalancer 172.17.179.247 117.50.3.206 80:43832/TCP 112s
服务本身的源码非常简单,只返回客户端地址,如下所示。
package main
import (
"fmt"
"io"
"log"
"net/http"
"net/http/httputil"
)
func main() {
log.Println("Server hello-world")
http.HandleFunc("/" AppRouter)
http.ListenAndServe(":12345" nil)
}
func AppRouter(w http.ResponseWriter r *http.Request) {
dump _ := httputil.DumpRequest(r false)
log.Printf("%q
" dump)
io.WriteString(w fmt.Sprintf("Guest come from %v
" r.RemoteAddr))
return
}
在外网通过浏览器访问该服务,如下所示。
结果显示用户的访问IP地址是一台云主机的内网IP地址,显然不正确。
Loadbalancer创建成功后,ULB4的VServer将UK8S集群中的每个Node云主机节点作为自身的RS节点,RS端口为Service申明的Port值(注意不是NodePort)。ULB4将访问流量转发到其中一个RS后,RS根据本机上kube-proxy生成的iptables规则将流量DNAT到后端Pod中,如下所示。
图中ULB4先将流量转发到Node1中,Node1中根据iptables DNAT规则,将流量转发给Node2中的Pod。
需要注意的是,Node1将IP包转发到Node2前,对这个包有一次SNAT操作。准确地说,是一次MASQUERADE操作,规则如下。
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -m mark --mark 0x4000/0x4000 -j MASQUERADE
这条规则将源地址改成Node1的本机地址,即10.9.31.26。当然,这个 SNAT 操作只针对本Service转发出来的包,否则普通的IP包也受到影响了,而判定IP包是否由本Service转发出来的依据是改包上是有有个"0x4000"标志,这个标志则是在DNAT操作前打上去的。
由于IP请求包的源地址被修改,Pod内的程序网络库通过getpeername(2)调用获取到的对端地址是Node1的IP地址而不是客户端真实的地址。
为什么需要对流出的包做SNAT操作呢?
原因比较简单。参考下图,当Node1上的Pod处理完请求后,需要发送响应包,如果没有SNAT操作,Pod收到的请求包源地址就是client的IP地址,这时候Pod会直接将响应包发给client的IP地址,但对于client程序来说,它明明没有往PodIP发送请求包,却收到来自Pod的IP包,这个包很可能会被client丢弃。而有了SNAT,Pod会将响应包发给Node1,Node1再根据DNAT规则产生的conntrack记录,将响应包通过返回给client。
client
^
v
ulb4
^
v
node 1 <--- node 2
| ^ SNAT
| | --->
v |
endpoint
对于Pod需要明确知道客户端来源地址的情况,我们需要显示地将Service的spec.externalTrafficPolicy设置成Local如下修改。
apiVersion: v1
kind: Service
metadata:
name: ucloud-nginx
labels:
app: ucloud-nginx
annotations:
service.beta.kubernetes.io/ucloud-load-balancer-type: "outer"
service.beta.kubernetes.io/ucloud-load-balancer-vserver-method: "source"
spec:
type: LoadBalancer
ports:
- protocol: "TCP"
port: 80
targetPort: 12345
selector:
app: ucloud-nginx
externalTrafficPolicy: Local
重新部署服务后,再用浏览器访问,可以发现Pod正确获取了浏览器的访问IP。
而这个机制的原理也很简单,当设置了externalTrafficPolicy为Local时,Node上的iptables规则会设置只将IP包转发到在本机上运行的Pod,如果本机上无对应Pod在运行,此包将被DROP。如下图,这样Pod可以直接使用client的源地址进行回包而不需要SNAT操作。
client
^
v
ulb4
^ /
/ / VServer健康检查失败
/ v X
node 1 node 2
^ |
| |
| v
endpoint
对于其他未运行Service对应Pod的Node节点来说,ULB VServer对其健康检查探测会因为iptables的DROP规则而失败,这样来自用户的请求永远不会被发往这些节点上,可以确保这些请求都能被正确响应。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/126270.html
摘要:详细请见产品价格产品概念使用须知名词解释漏洞修复记录集群节点配置推荐模式选择产品价格操作指南集群创建需要注意的几点分别是使用必读讲解使用需要赋予的权限模式切换的切换等。UK8S概览UK8S是一项基于Kubernetes的容器管理服务,你可以在UK8S上部署、管理、扩展你的容器化应用,而无需关心Kubernetes集群自身的搭建及维护等运维类工作。了解使用UK8S为了让您更快上手使用,享受UK...
摘要:通过暴露是社区的一个开源项目,你可以通过来部署更新应用排查应用故障以及管理集群资源。执行以下命令安装,使用的镜像已经去掉了的证书限制。不支持的版本范围。通过ULB暴露Kubernetes DashboardDashboard是Kubernetes社区的一个Web开源项目,你可以通过Dashboard来部署更新应用、排查应用故障以及管理Kubernetes集群资源。另外,Dashboard还提...
摘要:介绍本章节主要为您简要介绍中的一个重要概念即服务,本文中两者等同,以及的相关知识。在每台的固定端口上暴露服务,选择的服务类型,集群会自动创建一个类型的服务,负责处理接收到的外部流量。集群外部的可以通过的方式访问该服务。Service 介绍本章节主要为您简要介绍 Kubernetes 中的一个重要概念 Service(即服务,本文中两者等同),以及ULB的相关知识。Service 介绍Serv...
摘要:为什么在节点直接起容器网络不通为什么在节点直接起容器网络不通为什么在节点直接起容器网络不通使用自己的插件,而直接用起的容器并不能使用该插件,因此网络不通。 UK8S 集群常见问题本篇目录1. UK8S 完全兼容原生 Kubernetes API吗?2. UK8S 人工支持3. UK8S对Node上发布的容器有限制吗?如何修改?4. 为什么我的容器一起来就退出了?5. Docker 如何调整日...
摘要:集群误删处理前置操作负载均衡分内网和外网两种,在误删情况下,首先需要重建,并且保证原地址不变。集群误删创建时类型需要与的类型相匹配,服务类型为时指定报文转发,为时指定请求代理类型删除集群内原根据文档重新绑定和使用已有创建服务。集群 ULB 误删处理前置操作负载均衡(ULB)分内网和外网两种,在误删情况下,首先需要重建 ULB,并且保证原 ULB IP 地址不变。对于内网 ULB,需要联系技术...
阅读 3473·2023-04-25 20:09
阅读 3685·2022-06-28 19:00
阅读 2994·2022-06-28 19:00
阅读 2995·2022-06-28 19:00
阅读 3048·2022-06-28 19:00
阅读 2834·2022-06-28 19:00
阅读 2969·2022-06-28 19:00
阅读 2578·2022-06-28 19:00