Kubernetes 上的多代理 Kafka 如何设置 KAFKA_ADVERTISED_HOST_NAME
Multi-broker Kafka on Kubernetes how to set KAFKA_ADVERTISED_HOST_NAME
我当前包含 3 个 Kafka 代理的 Kafka 部署文件如下所示:
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: kafka
spec:
selector:
matchLabels:
app: kafka
serviceName: kafka-headless
replicas: 3
updateStrategy:
type: RollingUpdate
podManagementPolicy: Parallel
template:
metadata:
labels:
app: kafka
spec:
containers:
- name: kafka-instance
image: wurstmeister/kafka
ports:
- containerPort: 9092
env:
- name: KAFKA_ADVERTISED_PORT
value: "9092"
- name: KAFKA_ADVERTISED_HOST_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: KAFKA_ZOOKEEPER_CONNECT
value: "zookeeper-0.zookeeper-headless.default.svc.cluster.local:2181,\
zookeeper-1.zookeeper-headless.default.svc.cluster.local:2181,\
zookeeper-2.zookeeper-headless.default.svc.cluster.local:2181"
- name: BROKER_ID_COMMAND
value: "hostname | awk -F '-' '{print }'"
- name: KAFKA_CREATE_TOPICS
value: hello:2:1
volumeMounts:
- name: data
mountPath: /var/lib/kafka/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 50Gi
这将创建 3 个 Kafka 代理作为有状态集,并使用 Kubedns 服务和 FQDN(完全限定域名)连接到 Zookeeper 集群,例如:
zookeeper-0.zookeeper-headless.default.svc.cluster.local:2181
代理 ID 是根据 pod 名称生成的:
- name: BROKER_ID_COMMAND
value: "hostname | awk -F '-' '{print }'"
结果:
kafka-0 = 0
kafka-1 = 1
kafka-2 = 2
但是,为了使用 Kafka 代理的 Kubedns 名称:
kafka-0.kafka-headless.default.svc.cluster.local:9092
kafka-1.kafka-headless.default.svc.cluster.local:9092
kafka-2.kafka-headless.default.svc.cluster.local:9092
我需要能够根据 pod 的名称将 KAFKA_ADVERTISED_HOST_NAME
变量设置为上述 FQDN 值。
目前我将变量设置为 pod 的名称:
- name: KAFKA_ADVERTISED_HOST_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
结果:
KAFKA_ADVERTISED_HOST_NAME=kafka-0
KAFKA_ADVERTISED_HOST_NAME=kafka-1
KAFKA_ADVERTISED_HOST_NAME=kafka-2
但不知何故我需要附加 DNS 名称的其余部分。
有什么方法可以直接设置 DNS 值吗?
类似的东西:
- name: KAFKA_ADVERTISED_HOST_NAME
valueFrom:
fieldRef:
fieldPath: kubedns.name
我设法通过 pod 定义中的命令字段解决了问题:
command:
- sh
- -c
- "export KAFKA_ADVERTISED_HOST_NAME=$(hostname).kafka-headless.default.svc.cluster.local &&
start-kafka.sh"
这会运行 shell 命令,该命令根据 hostname
值导出公布的主机名环境变量。
- name: MY_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: KAFKA_ZOOKEEPER_CONNECT
value: zook-zookeeper.zook.svc.cluster.local:2181
- name: KAFKA_PORT_NUMBER
value: "9092"
- name: KAFKA_LISTENERS
value: SASL_SSL://:$(KAFKA_PORT_NUMBER)
- name: KAFKA_ADVERTISED_LISTENERS
value: SASL_SSL://$(MY_POD_NAME).kafka-kafka-headless.kafka.svc.cluster.local:$(KAFKA_PORT_NUMBER)
以上配置将创建您的 FQDN。
当 Kafka 服务器启动时,您应该能够在 Kafka 日志中看到这些名称。
注意:Kubernetes 允许您使用语法 $(VARIABLE)
引用环境变量
以上的 None 对我有用;我在 Kubernetes 1.16 上的单个 pod 中设置了 wurstmeister/kafka:2.12-2.5.0
和 wurstmeister/zookeeper:3.4.6
(不要问); ClusterIp
顶部的服务将 9092 转发到 Kafka 容器。
这组环境变量有效:
- name: KAFKA_LISTENERS
value: "INSIDE://:9094,OUTSIDE://:9092"
- name: KAFKA_ADVERTISED_LISTENERS
value: "INSIDE://:9094,OUTSIDE://my-service.my-namespace.svc.cluster.local:9092"
- name: KAFKA_LISTENER_SECURITY_PROTOCOL_MAP
value: "INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT" # not production-ready!
- name: KAFKA_INTER_BROKER_LISTENER_NAME
value: INSIDE
- name: KAFKA_ZOOKEEPER_CONNECT
value: "localhost:2181" # since it's in the same pod
来源:wurstmeister/kafka doc, Kafka doc
内在的问题似乎是 Kafka 本身需要是一个 IP-ish 的东西来绑定到 并通过 与自己对话,而客户端需要一个 DNS-ish 名称从外部连接。由于某种原因,后一个不能包含 pod 名称。 (对我来说可能是一个单独的配置问题。)
我当前包含 3 个 Kafka 代理的 Kafka 部署文件如下所示:
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: kafka
spec:
selector:
matchLabels:
app: kafka
serviceName: kafka-headless
replicas: 3
updateStrategy:
type: RollingUpdate
podManagementPolicy: Parallel
template:
metadata:
labels:
app: kafka
spec:
containers:
- name: kafka-instance
image: wurstmeister/kafka
ports:
- containerPort: 9092
env:
- name: KAFKA_ADVERTISED_PORT
value: "9092"
- name: KAFKA_ADVERTISED_HOST_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: KAFKA_ZOOKEEPER_CONNECT
value: "zookeeper-0.zookeeper-headless.default.svc.cluster.local:2181,\
zookeeper-1.zookeeper-headless.default.svc.cluster.local:2181,\
zookeeper-2.zookeeper-headless.default.svc.cluster.local:2181"
- name: BROKER_ID_COMMAND
value: "hostname | awk -F '-' '{print }'"
- name: KAFKA_CREATE_TOPICS
value: hello:2:1
volumeMounts:
- name: data
mountPath: /var/lib/kafka/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 50Gi
这将创建 3 个 Kafka 代理作为有状态集,并使用 Kubedns 服务和 FQDN(完全限定域名)连接到 Zookeeper 集群,例如:
zookeeper-0.zookeeper-headless.default.svc.cluster.local:2181
代理 ID 是根据 pod 名称生成的:
- name: BROKER_ID_COMMAND
value: "hostname | awk -F '-' '{print }'"
结果:
kafka-0 = 0
kafka-1 = 1
kafka-2 = 2
但是,为了使用 Kafka 代理的 Kubedns 名称:
kafka-0.kafka-headless.default.svc.cluster.local:9092
kafka-1.kafka-headless.default.svc.cluster.local:9092
kafka-2.kafka-headless.default.svc.cluster.local:9092
我需要能够根据 pod 的名称将 KAFKA_ADVERTISED_HOST_NAME
变量设置为上述 FQDN 值。
目前我将变量设置为 pod 的名称:
- name: KAFKA_ADVERTISED_HOST_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
结果:
KAFKA_ADVERTISED_HOST_NAME=kafka-0
KAFKA_ADVERTISED_HOST_NAME=kafka-1
KAFKA_ADVERTISED_HOST_NAME=kafka-2
但不知何故我需要附加 DNS 名称的其余部分。
有什么方法可以直接设置 DNS 值吗?
类似的东西:
- name: KAFKA_ADVERTISED_HOST_NAME
valueFrom:
fieldRef:
fieldPath: kubedns.name
我设法通过 pod 定义中的命令字段解决了问题:
command:
- sh
- -c
- "export KAFKA_ADVERTISED_HOST_NAME=$(hostname).kafka-headless.default.svc.cluster.local &&
start-kafka.sh"
这会运行 shell 命令,该命令根据 hostname
值导出公布的主机名环境变量。
- name: MY_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: KAFKA_ZOOKEEPER_CONNECT
value: zook-zookeeper.zook.svc.cluster.local:2181
- name: KAFKA_PORT_NUMBER
value: "9092"
- name: KAFKA_LISTENERS
value: SASL_SSL://:$(KAFKA_PORT_NUMBER)
- name: KAFKA_ADVERTISED_LISTENERS
value: SASL_SSL://$(MY_POD_NAME).kafka-kafka-headless.kafka.svc.cluster.local:$(KAFKA_PORT_NUMBER)
以上配置将创建您的 FQDN。 当 Kafka 服务器启动时,您应该能够在 Kafka 日志中看到这些名称。
注意:Kubernetes 允许您使用语法 $(VARIABLE)
None 对我有用;我在 Kubernetes 1.16 上的单个 pod 中设置了 wurstmeister/kafka:2.12-2.5.0
和 wurstmeister/zookeeper:3.4.6
(不要问); ClusterIp
顶部的服务将 9092 转发到 Kafka 容器。
这组环境变量有效:
- name: KAFKA_LISTENERS
value: "INSIDE://:9094,OUTSIDE://:9092"
- name: KAFKA_ADVERTISED_LISTENERS
value: "INSIDE://:9094,OUTSIDE://my-service.my-namespace.svc.cluster.local:9092"
- name: KAFKA_LISTENER_SECURITY_PROTOCOL_MAP
value: "INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT" # not production-ready!
- name: KAFKA_INTER_BROKER_LISTENER_NAME
value: INSIDE
- name: KAFKA_ZOOKEEPER_CONNECT
value: "localhost:2181" # since it's in the same pod
来源:wurstmeister/kafka doc, Kafka doc
内在的问题似乎是 Kafka 本身需要是一个 IP-ish 的东西来绑定到 并通过 与自己对话,而客户端需要一个 DNS-ish 名称从外部连接。由于某种原因,后一个不能包含 pod 名称。 (对我来说可能是一个单独的配置问题。)