通过 AWS 上的 ELB 在 Kubernetes 上公开单个 Kafka 代理
Posted
技术标签:
【中文标题】通过 AWS 上的 ELB 在 Kubernetes 上公开单个 Kafka 代理【英文标题】:Expose individual Kafka brokers on Kubernetes through an ELB on AWS 【发布时间】:2018-07-10 01:18:23 【问题描述】:我在 AWS 上运行 KOPS Kubernetes 集群,试图让 kubernetes-kafka 示例与弹性负载均衡器一起工作。这是两个经纪人的外部服务部分:
kind: Service
apiVersion: v1
metadata:
name: outside-0
namespace: kafka
spec:
selector:
app: kafka
kafka-broker-id: "0"
ports:
- protocol: TCP
targetPort: 9094
port: 32400
nodePort: 32400
type: NodePort
---
kind: Service
apiVersion: v1
metadata:
name: outside-1
namespace: kafka
spec:
selector:
app: kafka
kafka-broker-id: "1"
ports:
- protocol: TCP
targetPort: 9094
port: 32401
nodePort: 32401
type: NodePort
这是我尝试通过 ELB 公开这些代理(实际 FQDN 替换为 my.copmany.com
)。
apiVersion: v1
kind: Service
metadata:
name: kafka-0
annotations:
dns.alpha.kubernetes.io/external: kafka-0.kafka.my.company.com
spec:
type: LoadBalancer
ports:
- port: 32400
name: outside
targetPort: 32400
selector:
app: outside-0
---
apiVersion: v1
kind: Service
metadata:
name: kafka-1
annotations:
dns.alpha.kubernetes.io/external: kafka-1.kafka.my.company.com
spec:
type: LoadBalancer
ports:
- port: 32401
name: outside
targetPort: 32401
selector:
app: outside-1
查看 AWS ELB 控制台显示 3 个实例中有 0 个可用于每个 Kafka ELB 代理,并使用 Kafka 命令行客户端超时生成到 kafka-1.kafka.my.company.com:9094
。 outside-0
NodePort 服务如何通过kafka-0
LoadBalancer 服务暴露?还是有其他方法可以考虑?
【问题讨论】:
也许这有助于***.com/q/41868161/741970 @DmitryMinkovsky - 谢谢你的链接,两个最重要的答案都有一些很好的元素,第一个通过ec2-host:port
公开它,第二个使用elb:port
。我的挑战是每个卡夫卡经纪人都需要拥有自己的“永久”网址,例如subdomain-on-company-domain:port
,例如kafka-1.kafka.my.company.com:9094
.
是的,我自己从来没有完全弄清楚。幸运的是,在我的情况下,我最终意识到我可以从内部发送数据,而不是向外部开放 Kafka。如果你明白这一点,请发布答案。
ELB DNS 对服务来说是永久的。如果您重新部署甚至删除部署,它不会改变。如果您删除该服务,它将被释放。如果您拥有自己的 DNS,例如 my.kafka.com,则可以将其别名为 ELB DNS
【参考方案1】:
Kakfa 非常注重需要直接访问作为主题领导者的服务器的客户端。为此,我做了以下工作:
1) 设置 configmap 以根据 pod 的序号值动态覆盖adverted.listeners 的值
POD_ID=$HOSTNAME##*-
kafka-server-start.sh server.properties \
--override advertised.listeners=INSIDE://`hostname -f`:9092,OUTSIDE://kafka-$POD_ID.kafka.my.company.com:9094 \
--override broker.id=$POD_ID \
--override listeners=INSIDE://:9092,OUTSIDE://:9094
2) 为每个 Kafka pod 创建一个 LoadBalancer 服务。更改选择器以匹配您的 kafka-pod-id。
apiVersion: v1
kind: Service
metadata:
name: kafka-0
annotations:
dns.alpha.kubernetes.io/external: kafka-0.kafka.my.company.com
spec:
externalTrafficPolicy: Local
type: LoadBalancer
ports:
- port: 9094
name: outside
targetPort: 9094
selector:
app: kafka
kafka-pod-id: "0"
---
apiVersion: v1
kind: Service
metadata:
name: kafka-1
annotations:
dns.alpha.kubernetes.io/external: kafka-1.kafka.my.company.com
spec:
externalTrafficPolicy: Local
type: LoadBalancer
ports:
- port: 9094
name: outside
targetPort: 9094
selector:
app: kafka
kafka-pod-id: "1"
【讨论】:
【参考方案2】:这些 Kubernetes 配置看起来正确。但是,如果 AWS 控制台显示“3 个实例中的 0 个可用”,这通常意味着您未通过 ELB 运行状况检查。如果没有可用于向其发送数据的健康后端实例,ELB 将丢弃任何流量,这将解释对 Kafka 的调用超时。
节点端口服务的简单 ELB 运行状况检查只是 SSH 以查看实例本身是否处于活动状态,因为该实例上的 kube-proxy 实际上会将流量转发到正确的实例。如果您只在 ELB 上运行一个侦听器,那么您实际上可以在运行状况检查中检查该端口。 (我经常为每个 ELB 运行一组 nodeport 侦听器,而不是为每个 nodeport 服务运行一个以节省资金。)
【讨论】:
【参考方案3】:根据文档 (Kuebrnetes Service Types):
LoadBalancer:使用云提供商的外部公开服务 负载均衡器。 NodePort 和 ClusterIP 服务,其外部 负载均衡器将路由,自动创建。
您不应该为 NodePort 和 LoadBalancer 类型定义单独的服务,而只能指定 LoadBalancer
并指定 nodePort
(请测试并尝试添加/删除一些选项,因为我没有可以测试的环境):
apiVersion: v1
kind: Service
metadata:
name: kafka-0
spec:
type: LoadBalancer
ports:
- port: 32400
name: kafka
nodePort: 32400
selector:
app: kafka
kafka-broker-id: "0"
---
apiVersion: v1
kind: Service
metadata:
name: kafka-1
spec:
type: LoadBalancer
ports:
- port: 32401
name: kafka
nodePort: 32401
selector:
app: kafka
kafka-broker-id: "1"
Kubernetes 集群应配置 AWS API 访问。 kubelet
、kube-apiserver
、kube-controller-manager/cloud-controller-manager
有云配置选项。
【讨论】:
【参考方案4】:目标端口设置不正确,必须使用容器端口,会自动分配一个NodePort。配置如下:
apiVersion: v1
kind: Service
metadata:
name: kafka-0
annotations:
dns.alpha.kubernetes.io/external: kafka-0.kafka.my.company.com
spec:
type: LoadBalancer
ports:
- port: 9094
name: outside
targetPort: 9094
selector:
app: outside-0
---
apiVersion: v1
kind: Service
metadata:
name: kafka-1
annotations:
dns.alpha.kubernetes.io/external: kafka-1.kafka.my.company.com
spec:
type: LoadBalancer
ports:
- port: 9094
name: outside
targetPort: 9094
selector:
app: outside-1
外部端口可以是任何你想要的,例如你可以使用9094,与容器的端口相同,并且它可以是所有服务的相同端口,因为你使用不同的ELB。只要确保选择器设置正确,这应该可以正常工作。
【讨论】:
以上是关于通过 AWS 上的 ELB 在 Kubernetes 上公开单个 Kafka 代理的主要内容,如果未能解决你的问题,请参考以下文章
AWS Elastic Beanstalk VPC - 从 ELB 到实例的 HTTPS
kubectl 等待 AWS EKS 上的服务公开 .status.loadBalancer.ingress 字段中报告的 Elastic Load Balancer (ELB) 地址