我无法让 kubernetes IPv6SingleStack
LoadBalancer
服务通过正确的源 IP 地址传递到 pod。SingleStack
LoadBalancer
它在将流量传递到相同 pod的姊妹 IPv4 上运行良好。
该集群是一个裸机 v1.21.1 双栈集群kubeadm
,使用 Calico v3.18 作为 cni 和 MetalLB 来为配置了type: LoadBalancer
. 然后将 Calico 配置为通过 BGP 向本地路由器宣布负载均衡器 IP。以具有两个服务(一个用于 IPv4,一个用于 IPv6)的单个nginx
部署为例,如果我通过 IPv4 地址卷曲 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" "-"
该地址来自集群的serviceSubnet
,fd5a:1111:1111::/112
并且恰好是clusterIP
IPv6 服务的地址。似乎有些东西实际上在这里做了一些 TCP 代理(ipvs?),但目前尚不清楚它为什么会这样。如果是的话,我希望这externalTrafficPolicy
是Cluster
- 事实上,如果我将服务从 更改Local
为Cluster
,我将获得在 IPv4 上转发请求的集群节点的本地 IP 地址(如预期的那样),以及在 IPv6 上相同的集群 IP 地址。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