kubernetes系列之四:kubernetes的源地址保持(source IP preserve)

一、前言

kubernetes提供服务的实体(POD)具有内部网络空间的地址,外部无法直接访问,所以kubernetes提供了多种对外暴露POD服务的方法。这些方法都借助于kubernetes的service的概念,将一系列具有等同服务能力的POD组成一个抽象的服务实体,这个服务实体具有一个虚IP,这个虚IP可以是kubernetes cluster内部网络可达的IP(对应cluster service),也可以是外部可达的IP(对应node port 和external load balancer)。

kubernetes service借助iptables将一组POD抽象成可达的网络服务,并且由于kubernetes要保证service在任何node的可达性,所以使用iptables rule将所有后端POD组成一个基于概率访问的组合,使用iptables的SNAT和DNAT技术在不同POD之间进行基于概率的请求转发。这样的模式带来了一个副作用:经过SNAT操作之后,客户端的IP消失在了请求的接入node,应用程序POD只能看到node的IP,对于一些对源IP有需求的应用来讲,需要kubernetes提供解决这个问题的机制。而kubernetes的source preserve的功能(https://kubernetes.io/docs/tutorials/services/source-ip/)就是为解决这个问题而引入的。

转载自https://blog.csdn.net/cloudvtech



二、kubernetes的服务和SNAT

在文章《Kubernetes如何利用iptables对外暴露service》中,可以看到基于概率对后端POD组进行访问的时候,如果选择的POD不在本地的node上面,则需要进行一次DNAT,将请求的目标地址设置成所选择的POD的IP,之后会进行路由选择,确定这是一个egress的数据包。在路由之后,还有一个POST ROUTING的规则如下:

-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -m mark --mark 0x4000/0x4000 -j MASQUERADE

对于所有出去的数据包,需要进行MASQUERADE(基于接口动态IP的SNAT)处理,在这种情况下,source IP就丢失了,POD里面的应用程序看到的就是node的IP或者CNI互联设备的IP(比如bridge或者vxlan设备)。

转载自https://blog.csdn.net/cloudvtech



三、源IP保持的实现

通过上面的分析可以发现,如果不存在从一个node向另外一个node的请求转发,只在本地选择POD服务请求,则不会存在SNAT,进而可以保持源地址IP,kubernetes正式借助这一思路来实现源IP的保持。

在建立node port或者external load balancer service的时候,在1.7及以上版本中可以在service的定义的时候加入如下控制来保证只向属于这个service的本地的POD转发请求(如果本地没有POD能服务这个请求,请求将被iptables DROP掉,客户端会发现请求超时没有响应):

"externalTrafficPolicy": "Local"

在较老的v1.5 ~ v1.6版本中,可以使用annotation使能这个功能:

service.beta.kubernetes.io/external-traffic: OnlyLocal

in release notes:

* When switching from the service.beta.kubernetes.io/external-traffic annotation to the new ([#46716](https://github.com/kubernetes/kubernetes/pull/46716), [@thockin](https://github.com/thockin)) externalTrafficPolicy field, the values chnag as follows: * "OnlyLocal" becomes "Local" * "Global" becomes "Cluster".

https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip

相关的code如下:

https://github.com/kubernetes/kubernetes/blob/master/pkg/proxy/iptables/proxier.go


...


...


node port service的例子yaml如下:

apiVersion: v1
kind: Service
metadata:
  name: myapp
  namespace: myapp
  labels:
    run: myapp
    app: myapp
spec:
  type: NodePort
 
externalTrafficPolicy: Local
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 80
  selector:
    app: myapp

根据这样的yaml生成的node port service如果本地存在对应的POD,则会出现如下iptables规则:

-A KUBE-XLB-N6IVUAXVQRPD4SQY -m comment --comment "Balancing rule 0 for namespace/svc-name:port" -j KUBE-SEP-V4WM6D5AHKHRR3SB

-A KUBE-XLB-EYNESMNWSNIVJYVW -m comment --comment "Balancing rule 1 for namespace/svc-name:port" -j KUBE-SEP-V4WM6D5AHKHRR3SB

如果本地不存在对应的POD,则会出现如下iptables规则:

-A KUBE-XLB-SB3VYBOWAYZV3VAW -m comment --comment " namespace/svc-name:port has no local endpoints" -j KUBE-MARK-DROP


转载自https://blog.csdn.net/cloudvtech





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值