为什么在我的 GKE 节点被抢占后我会失去与 MongoDB 的连接?

Why am I losing my connection to my MongoDB after my GKE node gets preempted?

我是 运行 GKE 集群中的一个 Mongo、Express、Node、React 应用程序,该集群设置了抢占式 VM(为了省钱)。我正在使用 mongoose 连接到我的 Mongo 数据库,该数据库托管在 Mongo Cloud Atlas 上。当 Pod 首次启动时,一切正常。但是,当我的节点被抢占时,我失去了与 mongoDB 实例的连接。然后我必须进入并手动将部署缩小到 0 个副本,然后再将其放大并恢复与 mongoDB 的连接。下面是我收到的错误以及我的 mongo 连接的代码。这只是使用可抢占实例的预期效果吗?有没有办法处理它,比如在抢占后自动扩展部署?我是 运行 GKE 自动驾驶集群,没有遇到任何问题,但对我来说有点贵。谢谢

mongoose
    .connect(process.env.MONGODB_URL, {
        useNewUrlParser: true,
        useUnifiedTopology: true,
        useFindAndModify: false,
    })
    .then(() => console.log('mongoDB connected...'));
(node: 24) UnhandledPromiseRejectionWarning: Error: querySrv ECONNREFUSED _mongodb._tcp.clusterx.xxxxx.azure.mongodb.net at QueryReqWrap.onresolve (dns.js:203)

可以在 Compute Engine -> Instance groups -> Restart/Replace VMS 中重现 VM 抢占,然后选择选项:替换。 VM 重新启动后,容器也将重新创建,但不幸的是,如前所述,存在网络问题。

我的解决方案是通过 /health URL 向 Kubernetes Pods/Deployment 添加 liveness 和 readiness 探测器,检查 MongoDB 是否可用以及 returns 状态代码500如果没有。有关如何在 Kubernetes 中定义活跃度和就绪度探测的详细信息,请参见 here。 Kubernetes 将重启 pods 不活跃的。之后创建的pods不会有网络问题。

我项目中的 yaml 规范块如下所示:

spec:
  containers:
  - env:
    - name: MONGO_URL
      value: "$MONGO_URL"
    - name: NODE_ENV
      value: "$NODE_ENV"
    image: gcr.io/$GCP_PROJECT/$APP_NAME:$APP_VERSION
    imagePullPolicy: IfNotPresent
    name: my-container
    # the readiness probe details
    readinessProbe:
      httpGet: # make an HTTP request
        port: 3200 # port to use
        path: /health # endpoint to hit
        scheme: HTTP # or HTTPS
      initialDelaySeconds: 5 # how long to wait before checking
      periodSeconds: 5 # how long to wait between checks
      successThreshold: 1 # how many successes to hit before accepting
      failureThreshold: 1 # how many failures to accept before failing
      timeoutSeconds: 3 # how long to wait for a response
    # the livenessProbe probe details
    livenessProbe:
      httpGet: # make an HTTP request
        port: 3200 # port to use
        path: /health # endpoint to hit
        scheme: HTTP # or HTTPS
      initialDelaySeconds: 15 # how long to wait before checking
      periodSeconds: 5 # how long to wait between checks
      successThreshold: 1 # how many successes to hit before accepting
      failureThreshold: 2 # how many failures to accept before failing
      timeoutSeconds: 3 # how long to wait for a response