通过Ingress在Kubernetes集群之外提供HTTP / HTTPS服务

时间:2020-02-19 11:57:03

标签: nginx kubernetes kubernetes-ingress nginx-ingress

我的目的是通过Kubernetes入口路由不在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,则根本不会加载网站。它会捕获默认的Ingress。

如何正确地proxy_pass从Kubernetes入口到另一个在Kubernetes之外运行的服务的流量?因此它不会通过代理丢失任何东西。

很高兴对server-snippet进行探索,以了解Kubernetes Ingress配置与标准Nginx用法之间的区别。

如果使用不同的选项,则在访问路径/api时找不到用于proxy_pass到不同http的解决方案。

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

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

本地-工作人员

enter image description here

如果我点击manifest.json,它会显示“没有预览内容”。如果我使用wget下载该json,则在第一行中可以看到<!DOCTYPE html>。它是HTML文件下载。但是我可以确认这个本地版本可以正常运行多年。因此,此屏幕截图只是为了了解其工作时的外观。

通过入口-不起作用

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

enter image description here

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

enter image description here

如果我有意转到https://owncloud.example.com/login页:

enter image description here

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

enter image description here

如果我添加其他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"

enter image description here

总结

应用程序端无错误。因此,我想到的第一件事就是/logout行为。我收到412 HTTP代码,这意味着:Precondition Failed client error response code indicates that access to the target resource has been denied400错误的请求错误。

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

非常感谢

1 个答案:

答案 0 :(得分:1)

最后找到了可行的解决方案。

我刚刚更正了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,请删除sslsecureX-Forwarded-Prototls:

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

对于我来说,通过Kubernetes Ingress将一些本地Docker Compose和旧时尚服务路由到外部非常有用。

P.S。如果您是来解决Owncloud CSRF错误的,请不要忘记为@mWatney评论投票。