具有 externalTrafficPolicy=local 的 k8s loadbalancer 服务在 IPv4 上传递客户端 IP,在 IPv6 上隐藏它

具有 externalTrafficPolicy=local 的 k8s loadbalancer 服务在 IPv4 上传递客户端 IP,在 IPv6 上隐藏它

我无法让 kubernetes IPv6服务通过正确的源 IP 地址传递到 Pod。它在将流量传递到相同 Pod 的SingleStack LoadBalancer姊妹 IPv4 上工作正常。SingleStack LoadBalancer

该集群是一个裸机 v1.21.1 双栈集群,kubeadm使用 Calico v3.18 作为 cni 和 MetalLB 为配置的服务分配负载均衡器 IP type: LoadBalancer。然后配置 Calico 以通过 BGP 将负载均衡器 IP 通告给本地路由器。以一个包含两个服务(一个用于 IPv4,一个用于 IPv6)的单一nginx部署为例,如果我通过 IPv4 地址 curl IP,nginx 访问日志会在中打印正确的客户端 IP 192.168.2.0/24

192.168.2.128 - - [01/Jun/2021:19:32:37 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.1" "-"

但在 中从同一客户端卷曲 IPv6 地址2001:8b0:c8f:e8b0::/64,nginx 显示的客户端 IP 地址为fd5a:1111:1111::f31f

fd5a:1111:1111::f31f - - [01/Jun/2021:19:34:23 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.1" "-"

此地址来自集群的serviceSubnetfd5a:1111:1111::/112恰好是clusterIPIPv6 服务的地址。似乎某些东西实际上在这里执行一些 TCP 代理(ipvs?),但不清楚它为什么会这样表现。如果externalTrafficPolicy是的话,我会预料到这种情况Cluster- 事实上,如果我将服务从 更改LocalCluster,我会获得在 IPv4 上转发请求的集群节点的本地 IP 地址(如预期的那样),以及在 IPv6 上相同的 clusterIP 地址。externalTrafficPolicy在 IPv6 情况下似乎没有效果。

我是否忽略了一些显而易见的东西,或者这些服务应该以相同的方式运行?

测试清单:

---
apiVersion: v1
kind: Service
metadata:
  name: test-service-source-ip-v4
  namespace: default
  labels:
    k8s-app: test-service-source-ip
spec:
  selector:
    k8s-app: test-service-source-ip
  type: LoadBalancer
  ipFamilies:
    - IPv4
  ipFamilyPolicy: SingleStack
  loadBalancerIP: 192.168.254.11
  externalTrafficPolicy: "Local"
  ports:
    - name: http-tcp
      protocol: TCP
      port: 80
---
apiVersion: v1
kind: Service
metadata:
  name: test-service-source-ip-v6
  namespace: default
  labels:
    k8s-app: test-service-source-ip
spec:
  selector:
    k8s-app: test-service-source-ip
  type: LoadBalancer
  ipFamilies:
    - IPv6
  ipFamilyPolicy: SingleStack
  loadBalancerIP: 2001:8b0:c8f:e8b1:beef:f00d::11
  externalTrafficPolicy: "Local"
  ports:
    - name: http-tcp
      protocol: TCP
      port: 80

---
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: default
  name: test-service-source-ip
  labels:
    k8s-app: test-service-source-ip
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: test-service-source-ip
  template:
    metadata:
      labels:
        k8s-app: test-service-source-ip
    spec:
      containers:
        - name: test-service-source-ip
          image: nginx:1
          ports:
            - containerPort: 80
              protocol: TCP

答案1

事实证明,我ip-masq-agent运行的是旧版的 ,它被错误地配置为对集群内外的 IPv6 流量进行网络地址转换。我通过查看规则ip6tables并看到一堆MASQUERADE由 填充的规则来弄清楚了这一点ip-masq-agent

从集群中删除此部署并重新启动节点以删除ip6tables规则解决了该问题。

相关内容