【K8s教程】 Services -- 使用 Source IP

参考:https://kubernetes.io/zh/docs/tutorials/services/source-ip/

Kubernetes 集群中运行的应用通过 Service 抽象来互相查找、通信和与外部世界沟通。本文介绍被发送到不同类型 Services 的数据包源 IP 的变化过程,你可以根据你的需求改变这些行为。

术语表

本文使用了下列术语:

NAT: 网络地址转换
Source NAT: 替换数据包的源 IP, 通常为节点的 IP
Destination NAT: 替换数据包的目的 IP, 通常为 Pod 的 IP
VIP: 一个虚拟 IP, 例如分配给每个 Kubernetes Service 的 IP
Kube-proxy: 一个网络守护程序,在每个节点上协调 Service VIP 管理

Type=ClusterIP 类型 Services 的 Source IP

如果你的 kube-proxy 运行在 iptables 模式下,从集群内部发送到 ClusterIP 的包永远不会进行源地址 NAT,这从 Kubernetes 1.2 开始是默认选项。Kube-proxy 通过一个 proxyMode endpoint 暴露它的模式。

从其中一个节点中得到代理模式

kubernetes-node-6jst $ curl localhost:10249/proxyMode

输出结果为:

iptables

Type=NodePort 类型 Services 的 Source IP

从 Kubernetes 1.5 开始,发送给类型为 Type=NodePort Services 的数据包默认进行源地址 NAT。

客户端发送数据包到 node2:nodePort
node2 使用它自己的 IP 地址替换数据包的源 IP 地址(SNAT)
node2 使用 pod IP 地址替换数据包的目的 IP 地址
数据包被路由到 node 1,然后交给 endpoint
Pod 的回复被路由回 node2
Pod 的回复被发送回给客户端

为了防止这种情况发生,Kubernetes 提供了一个特性来保留客户端的源 IP 地址(点击此处查看可用特性)。设置 service.spec.externalTrafficPolicy 的值为 Local,请求就只会被代理到本地 endpoints 而不会被转发到其它节点。这样就保留了最初的源 IP 地址。如果没有本地 endpoints,发送到这个节点的数据包将会被丢弃。这样在应用到数据包的任何包处理规则下,你都能依赖这个正确的 source-ip 使数据包通过并到达 endpoint。

设置 service.spec.externalTrafficPolicy 字段如下:

kubectl patch svc nodeport -p '{"spec":{"externalTrafficPolicy":"Local"}}'

客户端发送数据包到 node2:nodePort,它没有任何 endpoints
数据包被丢弃
客户端发送数据包到 node1:nodePort,它有endpoints
node1 使用正确的源 IP 地址将数据包路由到 endpoint

Type=LoadBalancer 类型 Services 的 Source IP

从Kubernetes1.5开始,发送给类型为 Type=LoadBalancer Services 的数据包默认进行源地址 NAT,这是因为所有处于 Ready 状态的可调度 Kubernetes 节点对于负载均衡的流量都是符合条件的。所以如果数据包到达一个没有 endpoint 的节点,系统将把这个包代理到有 endpoint 的节点,并替换数据包的源 IP 为节点的 IP(如前面章节所述)。

然而,如果你的集群运行在 Google Kubernetes Engine/GCE 上,可以通过设置 service.spec.externalTrafficPolicy 字段值为 Local ,故意导致健康检查失败来强制使没有 endpoints 的节点把自己从负载均衡流量的可选节点列表中删除。

用图表示:

posted @ 2021-08-02 14:08  Varden  阅读(337)  评论(0)    收藏  举报