Kubernetes pod 将 coredns 中的外部 kafka 主机名解析为 pod 内的主机别名

use*_*777 7 apache-kafka docker kubernetes kube-dns coredns

我有 Spring Boot 应用程序,application.property我们在其中指定了以下属性。kafka 安装在带有自签名证书的远程机器上(在 kubernete 集群之外)。

camel.component.kafka.configuration.brokers=kafka-worker1.abc.com:9092,kafka-worker2.abc.com:9092,kafka-worker3.abc.com:9092
Run Code Online (Sandbox Code Playgroud)

在应用程序启动时,它会尝试寻找 kafka 代理。现在,如果我将主机别名添加到部署中,它将像下面一样正常工作

  hostAliases:
  - ip: 10.76.XX.XX
    hostnames:
    - kafka-worker1.abc.com
  - ip: 10.76.XX.XX
    hostnames:
    - kafka-worker2.abc.com
  - ip: 10.76.XX.XX
    hostnames:
    - kafka-worker3.abc.com
Run Code Online (Sandbox Code Playgroud)

它会正常工作,但我不希望这是拥有主机别名的不好做法,如果 IP 更改,我们可能需要重新启动 pod。我们希望主机名解析发生在 coredns 上,或者在不将 ip 添加到 pod 的主机文件的情况下进行解析。

如何实现这一目标。遵循此无法从 kubernetes pod服务端点内部连接到外部数据库,如下所示为 kafka-worker2 和 kafka-worker3 使用各自的 IP 创建

    kind: Service
    apiVersion: v1
    metadata:
     name: kafka-worker1
    spec:
     clusterIP: None
     ports:
     - port: 9092
       targetPort: 9092
     externalIPs:
       - 10.76.XX.XX
Run Code Online (Sandbox Code Playgroud)

并将其添加到属性文件中

camel.component.kafka.configuration.brokers=kafka-worker1.default:9092,kafka-worker2.default:9092,kafka-worker3.default:9092
Run Code Online (Sandbox Code Playgroud)

仍然收到同样的警告

2020-05-13T11:57:12.004+0000 Etc/UTC docker-desktop WARN  [main] org.apache.kafka.clients.ClientUtils(:74) - Couldn't resolve server hal18-coworker2.default:9092 from bootstrap.servers as DNS resolution failed for kafka-worker1.default
2020-05-13T11:57:12.318+0000 Etc/UTC docker-desktop WARN  [main] org.apache.kafka.clients.ClientUtils(:74) - Couldn't resolve server hal18-coworker1.default:9092 from bootstrap.servers as DNS resolution failed for kafka-worker2.default
2020-05-13T11:57:12.567+0000 Etc/UTC docker-desktop WARN  [main] org.apache.kafka.clients.ClientUtils(:74) - Couldn't resolve server hal18-coworker3.default:9092 from bootstrap.servers as DNS resolution failed for kafka-worker3.default
Run Code Online (Sandbox Code Playgroud)

更新部分

使用“没有选择器的服务”如下仍然得到同样的错误

2020-05-18T14:47:10.865+0000 Etc/UTC docker-desktop WARN  [Camel (SMP-Proactive-Camel) thread #1 - KafkaConsumer[recommendations-topic]] org.apache.kafka.clients.NetworkClient(:750) - [Consumer clientId=consumer-hal-tr69-streaming-1, groupId=hal-tr69-streaming] Connection to node -1 (kafka-worker.default.svc.cluster.local/10.100.153.152:9092) could not be established. Broker may not be available.
2020-05-18T14:47:12.271+0000 Etc/UTC docker-desktop WARN  [Camel (SMP-Proactive-Camel) thread #1 - KafkaConsumer[recommendations-topic]] org.apache.kafka.clients.NetworkClient(:750) - [Consumer clientId=consumer-hal-tr69-streaming-1, groupId=hal-tr69-streaming] Connection to node -1 (kafka-worker.default.svc.cluster.local/10.100.153.152:9092) could not be established. Broker may not be available.
2020-05-18T14:47:14.191+0000 Etc/UTC docker-desktop WARN  [Camel (SMP-Proactive-Camel) thread #1 - KafkaConsumer[recommendations-topic]] org.apache.kafka.clients.NetworkClient(:750) - [Consumer clientId=consumer-hal-tr69-streaming-1, groupId=hal-tr69-streaming] Connection to node -1 (kafka-worker.default.svc.cluster.local/10.100.153.152:9092) could not be established. Broker may not be available.
Run Code Online (Sandbox Code Playgroud)

服务和端点 yaml

apiVersion: v1
kind: Service
metadata:
 name: kafka-worker
spec:
 type: ClusterIP
 ports:
 - port: 9092
   targetPort: 9092
---
apiVersion: v1
kind: Endpoints
metadata:
 name: kafka-worker
subsets:
 - addresses:
   - ip: 10.76.XX.XX # kafka worker 1
   - ip: 10.76.XX.XX # kafka worker 2
   - ip: 10.76.XX.XX # kafka worker 3
   ports:
   - port: 9092
     name: kafka-worker

kubectl.exe get svc,ep
NAME                                         TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
service/ingress-nginx-controller             LoadBalancer   10.99.101.185    localhost     80:31247/TCP,443:31340/TCP   11d
service/ingress-nginx-controller-admission   ClusterIP      10.103.212.117   <none>        443/TCP                      11d
service/kafka-worker                         ClusterIP      10.100.153.152   <none>        9092/TCP                     97s
service/kubernetes                           ClusterIP      10.96.0.1        <none>        443/TCP                      17d

NAME                                           ENDPOINTS                                            AGE
endpoints/ingress-nginx-controller             10.1.0.XX:80,10.1.0.XX:443                           11d
endpoints/ingress-nginx-controller-admission   10.1.0.xx:8443                                       11d
endpoints/kafka-worker                         10.76.xx.xx:9092,10.76.xx.xx:9092,10.76.xx.xx:9092   97s
endpoints/kubernetes                           192.168.XX.XX:6443                                   17d
Run Code Online (Sandbox Code Playgroud)

gar*_*ium 6

感谢您提出问题并展示您解决问题的努力。

添加hostAliases不是一个好的做法是正确的,因为在您的 kafka 主机 IP 更改的事件中,您必须将新 IP 应用到部署中,它会触发 pod 重新加载。

我不确定externalIPs如何作为解决方案适合这里,因为:

在服务端口上使用外部 IP(作为目标 IP)进入集群的流量将被路由到服务端点之一。externalIP 不受 Kubernetes 管理,由集群管理员负责。

但是,如果我想当然地认为 externalIP 解决方案正在起作用,那么即使您访问服务的方式也不正确!

DNS 解析失败,因为您的域名错误,camel.component.kafka.configuration.brokers=kafka-worker1.default:9092将其更改为这camel.component.kafka.configuration.brokers=kafka-worker1.default.svc.cluster.local:9092可能会解决问题。注意:如果您的 k8s 集群的域与默认域不同,则替换cluster.local为您的 k8s 集群域。

检查 DNS 调试REF

我能想到的解决方案有两种:

第一个没有选择器和手动端点创建的服务:

(示例代码)端点的名称用于附加到服务。因此对服务和端点使用相同的名称kafka-worker

apiVersion: v1
kind: Service
metadata:
 name: kafka-worker
spec:
 type: ClusterIP
 ports:
 - port: 9092
   targetPort: 9092
---
apiVersion: v1
kind: Endpoints
metadata:
 name: kafka-worker
subsets:
 - addresses:
   - ip: 10.76.XX.XX # kafka worker 1
   - ip: 10.76.XX.XX # kafka worker 2
   - ip: 10.76.XX.XX # kafka worker 3
   ports:
   - port: 9092
     name: kafka-worker
Run Code Online (Sandbox Code Playgroud)

访问这个的方法是 camel.component.kafka.configuration.brokers=kafka-worker.default.svc.cluster.local:9092

注意: - 您可以向端点 ip 添加更多信息,例如 nodeName、hostName 签出此api ref - 这种方法的优点是 k8s 将为您平衡 kafka 工作人员的负载

第二个外部名称

对于这种方法,您需要已经定义了单个域名,如何做到这一点超出了本答案的范围,但例如kafka-worker.abc.com 是您的域名,现在您有责任将所有 3 个 kafka 工作节点 IP 附加到一个(也许)循环方式到您的 DNS 服务器。注意:这种负载平衡(通过 DNS)并不总是首选,因为 DNS 服务器没有执行健康检查来确保哪些节点是活动的,哪些是死的

这种方法不能保证,可能需要根据您的系统网络进行额外的调整来解析域名。也就是说,运行该节点的 coredns/kube-dns 的节点应该能够解析,kafka-worker.abc.com否则当 k8s 返回 CNAME 时,您的应用程序将无法解析它!

下面是一个例子:

kind: Service
metadata:
  name: kafka-worker
spec:
  type: ExternalName
  externalName: kafka-worker.abc.com
Run Code Online (Sandbox Code Playgroud)

更新:按照您在问题中的更新。查看第一个错误,您似乎创建了 3 个生成 3 个 DNS 的服务

kafka-worker3.default.svc.cluster.local
kafka-worker2.default.svc.cluster.local
kafka-worker1.default.svc.cluster.local
Run Code Online (Sandbox Code Playgroud)

我建议,如果你可以请检查我的示例代码!您不需要创建 3 个服务,只需创建一个附加到端点的服务,该端点具有 3 个代理的 3 个 IP。

对于您的第二个错误: hostname不是域名,主机名通常是机器的名称(请检查差异)。为简单起见,我建议在端点对象中仅使用 IP。