node.js - 在 GKE 上的 StatefulSet 中运行的 node.js API 上的 SSL

标签 node.js ssl kubernetes google-cloud-platform lets-encrypt

我有一个具有以下结构的应用程序:

  • 一个 R Shiny 应用程序,用作用户界面,它允许用户上传文件并将它们存储在 gcePersistentDisk 上。
  • 读取 gcePersistentDisk 上的这些文件的 node.js 服务器处理它们并为 Shiny 应用程序提供 API 以检索结果。

这在具有以下结构的 GKE 集群中运行:

  • 带有包含两个容器的 pod 的 StatefulSet,以允许客户端和服务器同时访问该卷。
  • StatefulSet 的 headless 服务。
  • 具有固定 IP 的 Ingress 指向域指向的位置。
  • 一个 NodePort 作为 Ingress 的后端,选择器指向 StatefulSet 的第 0 个 pod

至少这是我为完成这项工作所做的,我在 DevOps 或一般网络方面不太擅长。现在客户提出了第三方应用程序也将使用 node.js API 的请求,但它希望在 https 上这样做。

我的第一个尝试是使用 greenlock-express.js,然而,它需要一个面向公众的 IP,但服务器只能看到它的集群 IP。 我不知道这是否可以/应该改变,如果不能,我应该采取哪些其他方法?

谢谢!

YAML 的

apiVersion: v1
kind: Service
metadata:
  name: plo-set-service
  labels:
    app: plo
spec:
  clusterIP: None
  selector:
    app: plo
  ports:
  - name: web
    port: 80
    protocol: TCP
    targetPort: ploweb-port
  - name: api
    port: 3300
    protocol: TCP
    targetPort: ploapi-port
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: plo-set
spec:
  serviceName: plo-set-service
  replicas: 1
  selector:
    matchLabels:
      app: plo
  template:
    metadata:
      labels:
        app: plo
    spec:
      containers:
      - name: plo-server
        image: 
        readinessProbe:
          httpGet:
            path: /healthz
            port: 3300
          initialDelaySeconds: 15
          periodSeconds: 15
        ports:
        - name: ploapi-port
          containerPort: 3300
        volumeMounts:
        - mountPath: /data
          name: plo-volume
      - name: plo-client
        image: 
        ports:
        - name: ploweb-port
          containerPort: 80
        volumeMounts:
        - mountPath: /data
          name: plo-volume
  volumeClaimTemplates:
  - metadata:
      name: plo-volume
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 500Gi
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: plo-ingress
  annotations:
    kubernetes.io/ingress.global-static-ip-name: plo-ip
spec:
  backend:
    serviceName: plo-web
    servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: plo-web
spec:
  type: NodePort
  externalTrafficPolicy: Local
  selector:
    statefulset.kubernetes.io/pod-name: plo-set-0
  ports:
  - name: web
    port: 80
    protocol: TCP
    targetPort: 80

最佳答案

默认情况下,Nginx Ingress Controller 服务于端口 "HTTP/80""HTTPS/443",无论后端协议(protocol)和端口如何。

因此,在您的情况下,如果您只是开箱即用地使用 Nginx Ingress Controller,则无需更改任何内容即可为后端使用 HTTPS 协议(protocol)

例如,我有如下入口 Controller 服务,服务于端口 80443,这是在部署时创建的 Nginx Controller

$ kubectl get svc nginx-ingress-controller
NAME                       TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)                      AGE
nginx-ingress-controller   LoadBalancer   10.15.254.182   <external-ip-addr>   80:32594/TCP,443:31949/TCP   2d

此外,我还为监听 80 端口的 my-nginx 部署提供了服务

$ kubectl get svc my-nginx
NAME       TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
my-nginx   ClusterIP   10.15.252.11   <none>        80/TCP    30m

而且我已经部署了类似于你的简单入口资源

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-nginx-ingress
spec:
  backend:
    serviceName: my-nginx
    servicePort: 80

现在您可以通过 HTTP 或 HTTPS 调用您的服务,方法是从集群外部或集群内的 DNS/ClusterIP 请求 Nginx Controller LoadBalancer IP。

来自其他 pod 的

集群内的 HTTP 请求:

# curl -I http://nginx-ingress-controller
HTTP/1.1 200 OK
Server: nginx/1.15.9
...

HTTPS 请求:

# curl -Ik https://nginx-ingress-controller
HTTP/2 200 
server: nginx/1.15.9
...

希望对你有帮助

关于node.js - 在 GKE 上的 StatefulSet 中运行的 node.js API 上的 SSL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55935625/

相关文章:

ssl - 如何使用 OpenSSL 生成带有 SubjectAltName 的自签名证书?

ssl - Puppet 5 年后,证书什么时候到期?

kubernetes - 如何允许外部进程连接k8s的Pod?

kubernetes - Google Kubernetes Engine - 如何使用标准网络层将集群部署到区域数据中心?

node.js - axios没有检索cookie

javascript - 使用桥获取 PhantomJS 返回的状态码

ssl - 如何使用 Nginx 在 Centos 7 上安装 SSL 证书

node.js - Sailsjs "required"默认 JSON API 中的模型属性

javascript - 使用 VSCode 的 Node 调试器时是否可以黑盒 vendor 代码?

kubernetes - 访问Kubernetes负载均衡服务背后的客户端IP地址