我们在 1.7 中解决了这个问题,将无头服务更改为Type=NodePort
并设置externalTrafficPolicy=Local
。这会绕过服务的内部负载平衡,并且只有当 Kafka Pod 位于该节点上时,发往该节点端口上特定节点的流量才会起作用。
apiVersion: v1
kind: Service
metadata:
name: broker
spec:
externalTrafficPolicy: Local
ports:
- nodePort: 30000
port: 30000
protocol: TCP
targetPort: 9092
selector:
app: broker
type: NodePort
例如,我们有两个节点nodeA和nodeB,nodeB正在运行一个kafka pod。 NodeA:30000 将无法连接,但 NodeB:30000 将连接到在 NodeB 上运行的 kafka pod。
https://kubernetes.io/docs/tutorials/services/source-ip/#source-ip-for-services-with-typenodeport https://kubernetes.io/docs/tutorials/services/source-ip/#source-ip-for-services-with-typenodeport
请注意,这在 1.5 和 1.6 中也作为 beta 注释提供,可以在此处找到有关功能可用性的更多信息:https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip
另请注意,虽然这将 kafka pod 绑定到特定的外部网络身份,但它并不能保证您的存储卷将绑定到该网络身份。如果您在 StatefulSet 中使用 VolumeClaimTemplates,那么您的卷将与 pod 绑定,而 kafka 希望卷与网络身份绑定。
例如,如果 kafka-0 pod 重新启动并且 kafka-0 在 NodeC 而不是 NodeA 上出现,则 kafka-0 的 PVC(如果使用 VolumeClaimTemplates)具有用于 NodeA 的数据,并且在 kafka-0 上运行的代理开始拒绝请求它是节点A而不是节点C。
为了解决这个问题,我们期待本地持久卷,但现在我们的 kafka StatefulSet 有一个 PVC,数据存储在$NODENAME
在该 PVC 上将卷数据绑定到特定节点。
https://github.com/kubernetes/features/issues/121 https://github.com/kubernetes/features/issues/121
https://kubernetes.io/docs/concepts/storage/volumes/#local https://kubernetes.io/docs/concepts/storage/volumes/#local