【问题标题】:How to set up express.js with SSL inside K8s deployment如何在 K8s 部署中使用 SSL 设置 express.js
【发布时间】:2020-11-19 04:10:39
【问题描述】:

我正在尝试让 https 在 express.js 上为 K8s 部署中的节点工作,但我不知道如何。

快递应用应该是这样工作的:

  1. 当您访问/healthz 端点时,返回200httphttps 请求)
  2. 将任何其他http 流量重定向到https

我面临的问题是应用程序正在侦听两个不同的端口(@98​​7654328@ 和 8443),但 K8s Ingress 仅指向单个端口 - 我正在考虑使用 Nginx 解决这个问题作为反向代理,但是,我如何将两个容器“链接”在一起?

这是我的app.ts

import express from "express"
import { createServer as httpServer } from "http"
import { createServer as httpsServer } from "https"
import { readFileSync } from "fs"

const app = express()

const options = {
  key: readFileSync(`${__dirname}/cert/[company].key`),
  cert: readFileSync(`${__dirname}/cert/[company].crt`),
}

app.use("/healthz", (req, res) => {
  res.status(200).send("healthy")
})
app.use("*", (req, res) => {
  if (!req.secure) {
    return res.redirect(["https://", req.get("Host"), req.baseUrl].join(""));
  }
})
app.get("/", (req, res) => {
  res.status(200).send("Hello from Express!")
})

httpServer(app).listen(8080)
httpsServer(options, app).listen(8443)

这是Dockerfile

FROM node:14.4.0-alpine
...
EXPOSE 8080 8443
CMD [ "yarn", "start" ]

这是Ingress.yaml

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
...
spec:
  tls:
    - secretName: [secret-name]
  rules:
    - host: [company]
      http:
        paths:
          - backend:
              serviceName: [service-name]
              servicePort: 8080

您能否指出正确的方向,如何解决/解决这个问题?

【问题讨论】:

  • 您可以在 express 应用程序内部将所有 http 请求重定向到 https。

标签: node.js express kubernetes https


【解决方案1】:

回答

在 Kubernetes 上,您的 Node.js 服务器不需要处理 TLS。规范的方法是将 Ingress 用于TLS termination。这是因为您的 Node.js 服务器可以位于 ClusterIP 服务之后,并且只能通过 Ingress Controller 服务从集群外部访问。

假设您的 TLS 密钥有效,并且您的 Ingress Controller 设置正确(例如 nginx),那么您链接的 YAML 应该可以工作。

确保 Ingress 后端中定义的 Service 是 ClusterIP 类型,因为它只需要被 Ingress Controller Pod 访问。

您需要更新 Node.js 服务器,以便在单个端口(例如 8080)上为所有端点提供 HTTP。

如果您希望/healthz 允许 HTTP 流量,那么您需要创建第二个不带 TLS 的 Ingress 资源:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
...
spec:
  rules:
  - http:
      paths:
      - path: /healthz
        pathType: Prefix
        backend:
          serviceName: [service]
          servicePort: 8080

更多信息

关于您关于将 nginx 入口控制器与您的 Node.js 应用程序“链接”的问题 - 入口控制器将指向在入口资源的 backend 字段中指定的 ClusterIP 服务。

为简单起见,请记住将 Ingress 资源部署在与它们指向的服务相同的命名空间中。否则,您必须在 Ingress 资源的命名空间中创建一个 ExternalName 类型的服务,该服务指向另一个命名空间中的服务。见here

您的 Ingress Controller 可以位于任何 Namespace 中,前提是它被配置为监视所有 Namespace 的 Ingress 资源。

【讨论】:

  • 感谢您的回答,因为它让我更清楚了!我已经修改了代码,它确实可以工作,但是现在我遇到了另一个问题:当我在https 上使用curl 访问应用程序时,我正确地得到了200,但是当我尝试从另一个node 应用程序,然后我得到request to https://localhost:8080 failed, reason: unable to verify the first certificate另外,我提到的两个容器只是以某种方式将node.jsnginx 一起使用。
  • 如果其他 Node 应用程序正在使用 localhost,那么它必须与它试图命中的容器位于同一个 Pod 中。否则,如果它在一个单独的 Pod 中,它可以使用它试图命中的容器的 ClusterIP Service 的 A 记录。另一方面,如果您有一个需要访问 Ingress 服务的集群外节点应用程序,您需要确保该应用程序具有根证书,请查看此答案:stackoverflow.com/questions/31673587/…
  • 我已经更新了我的答案,以解决您在上述评论中所做的 nginx-node.js 链接说明。 TY
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-23
  • 1970-01-01
  • 2021-12-13
  • 1970-01-01
  • 2020-01-28
相关资源
最近更新 更多