首页 > 解决方案 > 通过 Ingress 提供 Kubernetes 集群外部的 HTTP/HTTPS 服务

问题描述

我的目标是通过 Kubernetes Ingress 路由不在 Kubernetes 中的本地 HTTP 服务。

以下配置有效,因此我可以打开http://owncloud.example.comhttps://owncloud.example.com从外部打开。

这是 Kubernetes 配置:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: owncloud
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
    ingress.kubernetes.io/ssl-redirect: "true" 
    ingress.kubernetes.io/secure-backends: "true"    
    ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/server-snippet:
      location ~ ^/(.*) {
        proxy_pass http://192.168.250.100:8260/$1;
        proxy_set_header Host $host;
      }
      location ~ ^/api(.*) {
        proxy_pass http://192.168.250.100:8261/$1;
        proxy_set_header Host $host;
      }
spec:
  tls:
  - hosts:
    - owncloud.example.com
    secretName: owncloud-tls

  rules:
  - host: owncloud.example.com

问题是我在浏览器的 Javascript 控制台中看到一些与“元”相关的奇怪错误。它们与深层 Javascript 代码有关。所以不幸的是,没有有用的日志。该网站在少数地方产生了奇怪的行为,而在本地运行良好。所以这似乎与 Kubernetes Ingress 有关。

以前我使用连接到外部的普通 Nginx,效果很好:

location / {
  proxy_pass http://192.168.250.100:8260/
}

如果我将完全相同的块添加到server-snippet,则网站根本不会加载。它捕获默认入口。

如何正确地proxy_pass从 Kubernetes Ingress 传输到在 Kubernetes 之外运行的另一个服务?所以它不会通过代理错过任何东西。

很高兴能够探索server-snippet了解 Kubernetes Ingress 配置与标准 Nginx 使用的不同之处。

如果使用不同的选项,我无法在访问 path 时找到 proxy_pass 到不同 http 的解决方案/api

- - - - - - - - - 更新 - - - - - - - - -

我收集了所有问题进行比较。

本地工作之一

在此处输入图像描述

如果我点击manifest.json,它会显示“Nothing to preview”。如果我wget用来下载那个 json,我可以<!DOCTYPE html>在第一行看到。这是下载的HTML文件。但我可以确认这个本地版本多年来一直运行良好。所以这个截图只是为了知道它工作时的样子。

通过入口 - 不工作

我登录成功。从用户体验中没有发现任何奇怪的东西,但存在问题:

在此处输入图像描述

试图注销。我做不到。它抛出 Owncloud 特定错误“访问禁止 CSRF 检查失败”,在控制台上我看到:

在此处输入图像描述

如果我故意访问https://owncloud.example.com/login页面:

在此处输入图像描述

如果我尝试访问此 Owncloud 上的文件,它也会失败并显示400

在此处输入图像描述

如果我添加额外的annotations

  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/server-snippet: |
      location ~ ^/?(.*) {
        proxy_pass http://192.168.250.100:8260/$1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
      }
    # Owncloud tuning
    nginx.ingress.kubernetes.io/proxy-body-size: "500000m"
    nginx.ingress.kubernetes.io/proxy-max-temp-file-size: "500000m"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "36000s"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "36000s"
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "36000s"
    nginx.ingress.kubernetes.io/proxy-buffering: "off"
    nginx.ingress.kubernetes.io/proxy-redirect-from: "off"
    nginx.ingress.kubernetes.io/connection-proxy-header: "keep-alive"

在此处输入图像描述

总结

应用程序端没有错误。所以我首先想到的是/logout行为。我得到412HTTP 代码,这意味着:Precondition Failed client error response code indicates that access to the target resource has been denied以及400错误的请求错误。

有什么专业知识可以解决这个问题吗?

非常感谢

标签: nginxkuberneteskubernetes-ingressnginx-ingress

解决方案


终于找到了一个可行的解决方案。

我刚刚纠正locationproxy_pass解决了根本原因。

因此,如果你有一些位于 Kubernetes 集群之外的本地 HTTP 服务,并且你想通过 Ingress 提供服务,你只需要这个:

kind: Ingress
apiVersion: extensions/v1beta1
metadata:
  name: owncloud
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
    ingress.kubernetes.io/ssl-redirect: "true"
    ingress.kubernetes.io/secure-backends: "true"
    ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/server-snippet: |
      location ~ "^/(.*)" {
        proxy_pass http://192.168.250.100:8260;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto https;

        # Owncloud tuning
        proxy_max_temp_file_size 0;
        client_max_body_size 500000m;
        proxy_read_timeout 36000s;
        proxy_send_timeout 36000s;
        proxy_connect_timeout 36000s;
        proxy_buffering off;
        proxy_redirect off;
        proxy_set_header Connection "Keep-Alive";
      }
    # Owncloud tuning
    nginx.ingress.kubernetes.io/proxy-max-temp-file-size: "0"
    nginx.ingress.kubernetes.io/proxy-body-size: "500000m"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "36000s"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "36000s"
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "36000s"
    nginx.ingress.kubernetes.io/proxy-buffering: "off"
    nginx.ingress.kubernetes.io/proxy-redirect-from: "off"
    nginx.ingress.kubernetes.io/connection-proxy-header: "keep-alive"
spec:
  rules:
  - host: owncloud.example.com
  tls:
  - hosts:
    - owncloud.example.com
    secretName: owncloud-example-tls
  • 如果您有其他服务,请删除 Owncloud 调整块

  • 如果不需要 HTTPS ,请删除ssl、和bitssecureX-Forwarded-Prototls:

您可以添加更多location块,例如~ "^/api/(.*)"使其像普通 Nginx 一样工作。

在我的例子中,通过 Kubernetes Ingress 将一些本地 Docker Compose 和老式服务路由到外部是很有用的。

PS 如果您来这里解决 Owncloud CSRF 错误,请不要忘记投票给@mWatney 评论。


推荐阅读