前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Kubernetes(k8s)-externalTrafficPolicy介绍和应用

Kubernetes(k8s)-externalTrafficPolicy介绍和应用

作者头像
运维小路
发布2025-03-12 15:51:52
发布2025-03-12 15:51:52
5900
代码可运行
举报
文章被收录于专栏:运维小路运维小路
运行总次数:0
代码可运行

作者介绍:简历上没有一个精通的运维工程师,下面的思维导图也是预计更新的内容和当前进度(不定时更新)。

我们上一章介绍了Docker基本情况,目前在规模较大的容器集群基本都是Kubernetes,但是Kubernetes涉及的东西和概念确实是太多了,而且随着版本迭代功能在还增加,笔者有些功能也确实没用过,所以只能按照我自己的理解来讲解。

我们在svc的时候,svc有一种类型叫NodePort,它是会在每个node上都有对应的iptables规则去请求拦截,如果我们有20个,甚至200个节点的时候,我们应该去访问哪一个节点?或者当我们使用LoadBalance的时候,它必须要有后端RS,我们把这个200个节点都作为后端RS么,如果是这样管理就会比较复杂,好在Kubernetes给我们提供了一个字段叫做:externalTrafficPolicy,它不仅可以规定掉刚才问题,还可以规避掉经过NAT转换以后的源ip丢失的问题。

externalTrafficPolicy 是 Kubernetes 中 Service 资源的一个属性,它主要用于控制 Service 如何将流量路由到 Pod。这个属性对于类型为 LoadBalancer 和 NodePort 的服务特别重要,因为它影响客户端 IP 的保留以及流量的负载均衡方式。

externalTrafficPolicy 有两个可能的值:

  1. Cluster(默认)
    • externalTrafficPolicy 设置为 Cluster 时,Kubernetes 的代理会从所有健康节点接收流量,并将其转发到后端 Pod。
    • 这意味着流量可能会被路由到任何节点上的任意一个合适的 Pod,不论该 Pod 是否在接收到请求的那个节点上运行。
    • 客户端的真实 IP 可能会在转发过程中丢失,因为流量通常通过内部 IP 在集群内传输。
  2. Local
    • 如果 externalTrafficPolicy 设置为 Local,那么只有运行了属于该服务的 Pod 的节点才会接收来自外部的流量。
    • 这种设置可以确保客户端的真实源 IP 传递给后端 Pod,因为流量直接到达承载 Pod 的节点。
    • 如果没有 Pod 在某个节点上运行,而流量指向了该节点,流量会被丢弃。这可能导致较低的资源利用率,但提供了更好的网络性能和保持客户端 IP 地址的能力。
代码语言:javascript
代码运行次数:0
运行
复制
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: NodePort  # 添加此行以更改服务类型为 NodePort,未添加则是ClusterIP
  selector:
    app: myapp
  ports:
    - protocol: TCP
      port: 80        # 服务的集群内部端口
      targetPort: 80  # Pod 上的应用程序端口
      nodePort: 30008 # 可选:指定 NodePort 的端口号,如果不指定则自动分配

这里我们还是复用我们前面的配置,虽然我们并没有在svc的yaml文件里面定义externalTrafficPolicy,但是查看这个svc的详细信息,是可以看到这个字段的,并且自动给我们添加了默认值Cluster。

代码语言:javascript
代码运行次数:0
运行
复制
[root@master01 svc]# kubectl  get svc my-service -o yaml
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: "2025-01-15T15:30:12Z"
  name: my-service
  namespace: default
  resourceVersion: "801401"
  selfLink: /api/v1/namespaces/default/services/my-service
  uid: 0b347fa0-a571-41d6-9fd5-ce960114f4e8
spec:
  clusterIP: 10.111.230.179
  clusterIPs:
  - 10.111.230.179
  externalTrafficPolicy: Cluster #自动添加的字段
  internalTrafficPolicy: Cluster #也是自动添加的,但是今天不讲这个字段
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - nodePort: 30008
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: myapp
  sessionAffinity: None
  type: NodePort
status:
  loadBalancer: {}

我们无论通过集群外访问还是集群内外访问,后端nginx获取的客户端ip地址都是CNI插件给我们分配的节点ip地址,如果我们的应用,需要客户端真实ip,使用这个配置则无法满足要求。

代码语言:javascript
代码运行次数:0
运行
复制
10.244.0.0 - - [15/Jan/2025:15:37:58 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.29.0" "-"
10.244.0.0 - - [15/Jan/2025:15:38:07 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.29.0" "-"
10.244.1.1 - - [15/Jan/2025:15:38:22 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.29.0" "-"
10.244.1.1 - - [15/Jan/2025:15:38:23 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.29.0" "-"

当我们把externalTrafficPolicy修改成Local,集群外访问已经可以获得客户端真实ip地址,集群内访问还是无法获取真实ip,不过这个需求一般很少,有兴趣可以下去研究下。

代码语言:javascript
代码运行次数:0
运行
复制
192.168.31.201 - - [15/Jan/2025:15:41:53 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.29.0" "-"
10.244.0.0 - - [15/Jan/2025:15:42:04 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.29.0" "-"
10.244.0.0 - - [15/Jan/2025:15:42:49 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.29.0" "-"
代码语言:javascript
代码运行次数:0
运行
复制
#Pod所在节点iptables规则,正常转发
-A KUBE-XLB-FXIYY6OHUSNBITIX -m comment --comment "default/my-service" 
-j KUBE-SEP-RPL3ZC3VS2WNO5G6

#Pod不在节点的iptables规则,会拒绝请求
-A KUBE-XLB-FXIYY6OHUSNBITIX -m comment --comment "default/my-service 
has no local endpoints" -j KUBE-MARK-DROP

简单点说,现在的NodePort只有Pod所在节点能使用NodeIP+NodePort访问,其他没有Pod则不能访问,这样就可以减少LB的后端。比如200个节点,某Pod跑了5个副本(在不同的node),那么这个LB的后端就只有这个5个机器,就不会出现后端200个的情况,当然LB还必须要具备自动更新RS后端能力,因为Pod漂移会导致这个后端变更。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-03-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 运维小路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档