在 Kubernetes 上使用 Nginx SSL 代理运行 Meteor 应用程序

Posted

技术标签:

【中文标题】在 Kubernetes 上使用 Nginx SSL 代理运行 Meteor 应用程序【英文标题】:Running Meteor app with Nginx SSL proxy on Kubernetes 【发布时间】:2016-05-21 05:33:31 【问题描述】:

我在 Google Cloud 上使用 Kubernetes 部署了一个 Meteor 应用,并配置了 nginx 作为 SSL 终止。一切正常。

但是,如果两个不同的客户端连接到两个不同的 SSL 容器,则更新不会显示在各自的应用程序上长达 10 秒,这使得 Websockets 似乎无法正常工作,但轮询正在进行影响。我已经确认所有客户端都与 Websockets 连接,但由于更新不会立即传播,可能 Nginx 未配置为与 Meteor 应用程序正确通信。

这是我的 SSL/Nginx 服务:

apiVersion: v1 kind: Service metadata: name: frontend-ssl labels: name: frontend-ssl spec: ports: - name: http port: 80 targetPort: 80 - name: https port: 443 targetPort: 443 selector: name: frontend-ssl type: LoadBalancer loadBalancerIP: 123.456.123.456 sessionAffinity: ClientIP

这是 Meteor 服务:

apiVersion: v1 kind: Service metadata: name: frontend labels: name: frontend spec: ports: - port: 3000 targetPort: 3000 selector: name: flow-frontend type: LoadBalancer loadBalancerIP: 123.456.123.456 sessionAffinity: ClientIP

对于 SSL 终止,我使用的是 Kubernetes 建议的 SSL 设置,它带有 Websockets 添加 https://github.com/markoshust/nginx-ssl-proxy

【问题讨论】:

您将 123.456.123.456 指向两个服务(或者这是一个错字)?我不熟悉流星,但你的问题有可能不是流星问题。您应该至少有 2 个 pod(最好由 2 个 RC 管理)和 2 个服务,一个用于 nginx,一个用于您的应用程序。只有 nginx 服务需要是 Type=Loadbalacer。 要缩小未知范围,您可以使用节点选择器 (github.com/kubernetes/kubernetes/blob/release-1.1/docs/…) 强制 Pod 登陆同一节点。您还可以在配置中使用 proxy_pass http://svcName.svcNamespace.svc.cluster.local:svcPort 之类的内容将 nginx 实例直接指向服务(假设您有集群 DNS 工作并且可以使用例如 nslookup 解析您的服务名称)。让我知道这是怎么回事。 Nginx 和 Meteor 都有独立的 rcs 和 pod。我认为只有 nginx 需要 Type=LoadBalancer,但是我不认为在流星端有它会影响任何东西。它们确实存在于同一个 IP 上,但这只是使两者都公开可用,每个都在自己的端口上。 在回应您的第二条评论时,我不希望 pod 登陆相同的实例,因为这违背了运行 kubernetes 的目的。我想潜在地在位于 100 个不同实例的 100 个 pod 上运行我的流星应用程序。我实际上使用proxy_pass http://target_service:port 将请求从 nginx 路由到流星。 仅供参考,我确实从我的流星服务中删除了 type=LoadBalancer。然而,事情是一样的。 【参考方案1】:

在您的 NginX 配置中,您是否确保每次都使用 ip_hash 标志将 websockets 定向到同一服务器?您还需要确保转发 websocket 升级标头:

upstream meteorapp
     ip_hash;
     server   hostname:port

server 
    # your server stuff here
    # 
    location / 
        proxy_pass                  http://meteorapp;
        proxy_set_header            Host $host;
        proxy_set_header            X-Real-IP $remote_addr;
        proxy_http_version          1.1;
        proxy_set_header            Upgrade $http_upgrade;
        proxy_set_header            Connection "upgrade";

        proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header            X-Forwarded-Proto http;
        proxy_redirect              http:// $scheme://;
    

【讨论】:

Arg no... 单线,pfft。让我测试一下。非常感谢! 不行。添加ip_hash 行似乎没有效果。 升级头呢? 看来我已经有了这些设置。这是我的 nginx 配置。 github.com/markoshust/nginx-ssl-proxy/tree/master/nginx 抱歉不确定。我会尝试评论以下内容: ssl_session_tickets off; ssl_stapling 开启; ssl_stapling_verify 开启;解析器 8.8.8.8 8.8.4.4 有效=300s; resolver_timeout 5s;哪些正在外面打电话,可能会减慢速度?【参考方案2】:

运行应用最简单的方法是使用基于 Nginx 的入口控制器而不是 Nginx 服务。

在我看来,部署入口控制器最简单的方法是使用 helm: https://docs.helm.sh/using_helm/#installing-helm https://kubeapps.com/charts/stable/nginx-ingress

但如果您不想在堆栈中添加其他工具,您可以使用官方安装指南:https://github.com/kubernetes/ingress-nginx/tree/master/deploy。

可在此处找到支持 Web 套接字的入口对象配置示例:https://github.com/nginxinc/kubernetes-ingress/tree/master/examples/websocket

【讨论】:

这可能是正确的。由于一些原因,我离开了 Kubernetes,但这里的 Nginx 肯定有问题。

以上是关于在 Kubernetes 上使用 Nginx SSL 代理运行 Meteor 应用程序的主要内容,如果未能解决你的问题,请参考以下文章

使用 nginx 反向代理在 Kubernetes 中公开服务

如何在Kubernetes 上部署安装PHP + Nginx 多容器应用

Kubernetes Ingress Nginx 加载资源 404

使用 nginx 入口控制器的 minikube Kubernetes 集群上没有入口地址

使用 Google Cloud Kubernetes TCP 负载均衡器的 Nginx 状态码 499

Kubernetes NGINX 入口控制器未获取 TLS 证书