资讯专栏INFORMATION COLUMN

【容器云 UK8S】服务发现:ULB属性修改的处理方法和获取真实客户端IP

Tecode / 2335人阅读

摘要:原因解释创建成功后,的将集群中的每个云主机节点作为自身的节点,端口为申明的值注意不是。如何获取源对于需要明确知道客户端来源地址的情况,我们需要显示地将的设置成如下修改。重新部署服务后,再用浏览器访问,可以发现正确获取了浏览器的访问。

ULB属性修改的处理方法

如没有实际需要,请避免修改ULB名称及注释

根据cloudprovider插件使用提醒,由UK8S cloudprovider创建的ULB不允许修改ULB名称,如果您修改过ULB名称,可以参考以下操作进行关联,避免影响线上业务。

操作方法

  1. 修改UK8S集群中的service注释,以下注释仅限由UK8S创建的ULB添加
# 增加ULB-id进行关联
service.beta.kubernetes.io/ucloud-load-balancer-id-provision:   
  1. 升级UK8S集群cloudprovider插件至最新版本。

    UK8S cloudprovider插件在20.10.1版本后已经默认支持关联ULB-id,避免用户修改ULB名称后影响cloudprovider重建ULB,升级文档

获取真实客户端IP

网络编程中如何获得对端IP

  1. 如果是HTTP1.1协议,一般的反向代理或者负载均衡设备(如ULB7)支持X-Forwarded-For头部字段,会在用户的请求报文中加入类似X-Forwarded-For:114.248.238.236的头部。Web应用程序只需要解析该头部即可获得用户真实IP。
  2. 如果是TCP或UDP自定义协议,可以客户端在协议字段里定义一个大端unsigned字段来保存自身IP,服务端把该字段解析出来然后调用inet_ntoa(3)等函数获得ipv4点分字符串。
  3. 如果2中协议不支持填写自身IP,则服务端可以通过socket系统调用getpeername(2)来获取对端地址。下文讨论此方式。

Kubernetes Loadbalancer ULB4碰到的问题

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

如何获取源IP?

对于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://docs.ucloud.cn/uk8s/service/change_ulb_name

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/126270.html

相关文章

  • 容器UK8S】新手指导

    摘要:详细请见产品价格产品概念使用须知名词解释漏洞修复记录集群节点配置推荐模式选择产品价格操作指南集群创建需要注意的几点分别是使用必读讲解使用需要赋予的权限模式切换的切换等。UK8S概览UK8S是一项基于Kubernetes的容器管理服务,你可以在UK8S上部署、管理、扩展你的容器化应用,而无需关心Kubernetes集群自身的搭建及维护等运维类工作。了解使用UK8S为了让您更快上手使用,享受UK...

    Tecode 评论0 收藏0
  • 容器 UK8S服务发现:通过ULB暴露Kubernetes DashboardIngress

    摘要:通过暴露是社区的一个开源项目,你可以通过来部署更新应用排查应用故障以及管理集群资源。执行以下命令安装,使用的镜像已经去掉了的证书限制。不支持的版本范围。通过ULB暴露Kubernetes DashboardDashboard是Kubernetes社区的一个Web开源项目,你可以通过Dashboard来部署更新应用、排查应用故障以及管理Kubernetes集群资源。另外,Dashboard还提...

    Tecode 评论0 收藏0
  • 容器 UK8S服务发现:Kubernetes重要概念Service(即服务,本文中两者等同)以

    摘要:介绍本章节主要为您简要介绍中的一个重要概念即服务,本文中两者等同,以及的相关知识。在每台的固定端口上暴露服务,选择的服务类型,集群会自动创建一个类型的服务,负责处理接收到的外部流量。集群外部的可以通过的方式访问该服务。Service 介绍本章节主要为您简要介绍 Kubernetes 中的一个重要概念 Service(即服务,本文中两者等同),以及ULB的相关知识。Service 介绍Serv...

    Tecode 评论0 收藏0
  • UK8S 集群常见问题 容器 UK8S

    摘要:为什么在节点直接起容器网络不通为什么在节点直接起容器网络不通为什么在节点直接起容器网络不通使用自己的插件,而直接用起的容器并不能使用该插件,因此网络不通。 UK8S 集群常见问题本篇目录1. UK8S 完全兼容原生 Kubernetes API吗?2. UK8S 人工支持3. UK8S对Node上发布的容器有限制吗?如何修改?4. 为什么我的容器一起来就退出了?5. Docker 如何调整日...

    ernest.wang 评论0 收藏1762
  • 容器 UK8S】镜像库容器常见问题:集群 ULB 误删处理

    摘要:集群误删处理前置操作负载均衡分内网和外网两种,在误删情况下,首先需要重建,并且保证原地址不变。集群误删创建时类型需要与的类型相匹配,服务类型为时指定报文转发,为时指定请求代理类型删除集群内原根据文档重新绑定和使用已有创建服务。集群 ULB 误删处理前置操作负载均衡(ULB)分内网和外网两种,在误删情况下,首先需要重建 ULB,并且保证原 ULB IP 地址不变。对于内网 ULB,需要联系技术...

    Tecode 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<