Google 容器操作系统上的 MQTT 连接失败

fri*_*ian 8 node.js mqtt docker google-container-os mqtt-vernemq

对于我的设置,我正在与 AWS 中托管的第三方 MQTT VerneMQ 代理合作。我已获得用户名/密码凭据,可以使用特定的 clientId 通过安全 MQTT(端口 8883)进行连接。我的目标(尽管与当前的问题无关)仅仅是订阅一个主题并将流量从该主题重定向到 Google PubSub。

我编写了一个简单的 NodeJS 程序来建立上述连接,并且在本地运行时效果非常好ts-node

const client = connect(`mqtts://${process.env.MQTT_HOST}`, {
    port: parseInt(process.env.MQTT_PORT, 10),
    clientId: process.env.MQTT_CLIENT_ID,
    username: process.env.MQTT_USERNAME,
    password: process.env.MQTT_PASSWORD,
    rejectUnauthorized: false,
});

client.on('error', handleError);

client.on('connect', (p) => {
    console.log('connect', JSON.stringify(p));
    client.subscribe({ [mqttTopic]: { qos: 0 } });
});
client.on('message', (topic, msg) => onMessageReceived(msg));
Run Code Online (Sandbox Code Playgroud)

然后我继续对其进行 Dockerize

FROM node:lts-alpine
RUN apk update
WORKDIR /app
COPY . .
RUN npm i
EXPOSE 8883
CMD ["npm", "start"]
Run Code Online (Sandbox Code Playgroud)

并且通过 本地运行得非常好docker run

当我使用“将容器映像部署到此虚拟机实例”选项(使用容器优化的操作系统映像)将映像加载到 Google 的计算引擎时,问题就开始了。当我检查日志时,代码试图使用连接数据包进行连接,但总是会立即关闭。

我认为这可能是我如何进行部署的问题,因此为了验证,我启动了一个标准的 Debian VM,在安装 Docker 并运行我的映像后,就像我在本地所做的那样,它工作得很好!所以这并不是说 Docker 发生了远程故障。

我认为也许通过 Compute Engine 进行部署很奇怪,但当我只需要单个映像时,它比建立 Kubernetes 集群更简单。考虑到我的问题,我继续花时间在 GKE 中解决所有问题。日志报告的消息与通过 Compute Engine 部署映像时报告的消息完全相同。这是 YAML:

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: test-mqtt
  labels:
    app: test-mqtt
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test-mqtt
  serviceName: test-mqtt-service
  template:
    metadata:
      labels:
        app: test-mqtt
    spec:
      containers:
        - name: mqtt
          image: us-central1-docker.pkg.dev/{GCP_PROJECT}/docker/test-mqtt
          ports:
            - name: mqtt-ssl
              containerPort: 8883
---
apiVersion: v1
kind: Service
metadata:
  name: test-mqtt-service
  labels:
    app: test-mqtt
spec:
  ports:
    - name: mqtt-ssl
      port: 8883
  selector:
    app: test-mqtt
  type: LoadBalancer
Run Code Online (Sandbox Code Playgroud)

毕竟,我确信这是一个端口问题,所以我检查并仔细检查了 vNIC 和内部的防火墙(正如 Google 所建议的那样- 这没有改变任何东西)。我可以通过端口进行访问,通过端口运行应用程序,但当我向世界开放所有端口时,它仍然失败。为了三重检查端口,我继续更改代码以访问https://test.mosquitto.org,并验证我仍然可以使用端口 8883 访问他们的服务器。所以它不可能是端口。

我得出的结论是,操作系统(它在 Debian 中通过手动部署工作)和代理(它在 Mosquitto 测试代理中工作)的某种组合使这不起作用,但我觉得我已经用尽了所有可能性。

我还可以检查什么才能使这项工作正常进行?我觉得这一定是我所缺少的简单的东西,但我花了几天时间在这上面却无济于事。