从本地 Docker For Mac 中部署的服务访问本地 Kafka(包括 Kubernetes 扩展)

Posted

技术标签:

【中文标题】从本地 Docker For Mac 中部署的服务访问本地 Kafka(包括 Kubernetes 扩展)【英文标题】:Accessing Local Kafka from within Services deployed in Local Docker For Mac (incl. Kubernetes extension) 【发布时间】:2019-03-30 11:09:11 【问题描述】: 我在 OSX 本地工作。 我在本地模式下使用 Kafka 和 zookeeper。意思是我的 Kafka 安装中的 zookeeper。一个节点集群。 两者都在环回本地主机上工作

zookeeper.connect=localhost:2181

我的/etc/host 如下:
127.0.0.1         localhost MaatPro.local  
255.255.255.255   broadcasthost  
::1               localhost MaatPro.local  
fe80::1%lo0       localhost MaatPro.local
我的机器上设置了 docker for Mac,带有 Kubernetes 扩展。

我的场景

我有一个 dockerized 的 Akka-stream 微服务,它从外部数据库读取数据并将其写入 Kafka 主题。它用作引导服务器:

"localhost:9092"

问题

当我直接在我的机器上运行我的服务(例如命令行或从 Intellij 中)时,一切正常。当我在本地 Docker 或 Kubernetes 上运行它时,我收到以下错误:

(o.a.k.clients.NetworkClient) [Producer clientId=producer-1] Connection to node 0 could not be established. The broker may not be available.

使用 Kubernetes,我构建了以下 YAML 文件来部署我的 pod:

apiVersion: v1
kind: Pod
metadata:
  name: fetcher
spec:
  hostNetwork: true
  containers:
   - image: entellectextractorsfetchers:0.1.0-SNAPSHOT
     name: fetcher

我采取预防措施设置 hostNetwork: true

直接使用 Docker 守护程序我最初也尝试将网络设置为主机,但发现这不适用于 docker for mac。因此,我放弃了那条路线。我知道这与虚拟化有关。

1) docker 出现的虚拟化问题和我本地的 kubernetes 一样吗?基本上,主机网络是虚拟机而不是我的mac?

2) 我尝试更改我的代码并将以下地址添加为引导服务器:host.docker.internal 根据文档。但问题仍然存在。根本问题是我正在处理环回地址吗?我真的应该在我的网络地址上工作吗? host.docker.internal 指向哪个地址?我怎样才能使它与环回地址一起工作?如果我完全关闭,知道我需要实施什么才能使其正常工作吗?

非常感谢您对此提供的任何帮助。

【问题讨论】:

看看这对您的用例是否有意义。 rmoff.net/2018/08/02/kafka-listeners-explained。那就先试试不带 k8s 的 Kafka 非常感谢您的博文 【参考方案1】:

基于@cricket_007 指导Kafka Listeners - Explained 和我在这个问题上到处阅读的许多内容,包括官方 docker 文档I Want to connect from a container to a servicer on the host

我想出了以下解决方案。

我将以下内容添加到我的默认本地 kafka 配置(即 server.properties)

listeners=EXTERNAL://0.0.0.0:19092,INTERNAL://0.0.0.0:9092
listener.security.protocol.map=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
advertised.listeners=INTERNAL://127.0.0.1:9092,EXTERNAL://docker.for.mac.localhost:19092
inter.broker.listener.name=INTERNAL

实际上这里是外部,预计docker 网络。此配置仅适用于我的 OSX 机器,用于我的本地开发目的。我不希望连接到我的笔记本电脑的人使用我的本地 kafka,因此我可以使用 EXTERNAL://docker.for.mac.localhost:19092. 这是在 docker/kube 中向我的容器宣传的内容。在该网络中,可以访问 docker.for.mac.localhost。

请注意,这可能不适用于 Minikube。这是特定于 Docker For Mac 的。我在我的机器上运行的 kubernetes 是 docker for mac 自带的,而不是 minikube。

最后在我的代码中我在一个列表中同时使用了这两个

"localhost:9092, docker.for.mac.localhost:19092"

我使用 typeSafe 配置,因此在 prod 中,这会被 env 变量擦除。如果未指定 env 变量,则使用此变量。当我从 Intellij 运行我的微服务时,使用了 localhost:9092。那是因为在这种情况下,我和我机器中的 kafka/zookeeper 处于同一个网络中。但是,当我从 docker/kube 运行相同的微服务时,使用了 docker.for.mac.localhost:19092

回答我的附带问题

    是的。 Docker for Mac 使用 HyperKit 作为轻量级虚拟机,在其上运行 linux,并在其上运行 Docker Engine。 Docker for MAC Kubernetes 扩展基本上是关于在 docker 守护进程中将 kubernetes 集群服务/基础设施作为容器运行。 Docker for Mac vs. Docker Toolbox 。换句话说,宿主是 hyperkit 而不是 osx。但正如上面的文档所解释的,Docker for Mac 的实现就是让用户觉得 OSX 和 Docker 之间没有虚拟化。

    使用环回地址连接到主机是一个尚未解决的问题。我什至不确定它是否能完美运行,即使主机是 Linux。不确定,可能已经解决了。尽管如此,它需要通过声明容器或在 kube 的情况下的 pod 在主机网络上来运行图像。但是在 docker for mac 中,根据我的在线阅读,该功能将永远无法工作。因此,使用 docker.for.mac.localhosthost.docker.internal 的解决方案,Docker for Mac 确实设置为引用 mac 主机而不是 hyperkit主持人。

    host.docker.internaldocker.for.mac.localhost 是其中之一,此时较晚的推荐是 host.docker。内部的。话虽这么说,这个地址最初对我不起作用,因为我的 Kafka 设置不好。值得准备@criket_007 链接以了解http://rmoff.net/2018/08/02/kafka-listeners-explained。

【讨论】:

顺便说一句,advertised.listeners=INTERNAL://127.0.0.1:9092 实际上应该是该 pod/Kafka 容器的内部服务名称/IP。但是,如果您有多个代理,您只会注意到该配置的问题,因为它主要用于复制 我不完全明白你能解释一下吗。我的 Kafka 和 zookeeper 根本不在 kubernetes 中。它们在我的本地机器上,也就是在我机器的本地网络上。根据 docker/kube 进程,Docker/kubernetes 在我机器内的网络上。所以对我来说,Kafka/zookeeper 网络的外部网络是 docket/kube。因此,我不完全理解您的评论。你能澄清一下吗? 我的容器/pod 中有一个 akka-stream 微服务。该服务连接到我的 kubernetes 之外的 Kafka,尽管它在我的机器上。 哦,如果 Kafka 和 Zookeeper 不在 Kubernetes 上,那么我认为您根本不需要设置协议映射器。您需要的唯一侦听器是EXTERNAL://docker.for.mac.localhost:19092...无论如何,我的意思是,拥有127.0.0.1 的侦听器将使每个连接客户端仅连接到自身,而不是实际的外部服务器,这再次仅适用于多个代理(甚至当你有一台机器时) 明白。只是为了记录,对于响应的读者,我确实设置了该协议映射器,因为我必须从 intellij 中运行我的应用程序,当我使用调试启动我的开发时,并在我测试时从容器内运行推出前的整体行为。前者意味着我在我的本地机器网络上,而后者意味着我在 docker 网络上。因此,我需要两者都处于开发模式。【参考方案2】:

按照@MaatDeamon 方法,我只做了以下操作,它对我有用。

advertised.listeners=PLAINTEXT://:9092

在您的应用程序配置属性中

localhost:9092,host.docker.internal:9092

【讨论】:

以上是关于从本地 Docker For Mac 中部署的服务访问本地 Kafka(包括 Kubernetes 扩展)的主要内容,如果未能解决你的问题,请参考以下文章

IDEA快速实现Docker镜像部署运行(for mac M1)

Mac部署Docker

Mac部署k8s

Window for Docker深入浅出

Odoo安装之docker部署

如何部署 Docker Registry 服务