通过 Ingress 在 Kubernetes 集群外部提供 HTTP/HTTPS 服务
Serving HTTP/HTTPS service which is outside of Kubernetes cluster through Ingress
我的目标是通过 Kubernetes Ingress 路由不在 Kubernetes 中的本地 HTTP 服务。
下面的配置有效,所以我可以从外部打开 http://owncloud.example.com
或 https://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/;
proxy_set_header Host $host;
}
location ~ ^/api(.*) {
proxy_pass http://192.168.250.100:8261/;
proxy_set_header Host $host;
}
spec:
tls:
- hosts:
- owncloud.example.com
secretName: owncloud-tls
rules:
- host: owncloud.example.com
问题是我在浏览器的 Javascript 控制台中看到一些与 "meta" 相关的奇怪错误。它们与深度 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 用法有何不同,那就太好了。
如果使用不同的选项,我无法找到 proxy_pass 访问路径 /api
时不同 http 的解决方案。
----------------更新----------------
我已经收集了所有问题以供比较。
本地 - 工作人员:
如果我点击 manifest.json
,它会显示 "Nothing to preview"。如果我使用 wget
下载 json,我可以在第一行看到 <!DOCTYPE html>
。已下载 HTML 个文件。但我可以确认这个本地版本多年来一直运行良好。所以这个截图只是为了了解它工作时的样子。
通过 Ingress - 不工作:
我登录成功了。未从用户体验中发现任何异常,但存在问题:
试图退出。我做不到。它抛出 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/;
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
行为。我得到 412
HTTP 代码,这意味着:Precondition Failed client error response code indicates that access to the target resource has been denied
和 400
错误请求错误。
是否有解决此问题的专业知识?
非常感谢
终于找到了可行的解决方案。
我刚刚更正了 location
和 proxy_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
、secure
、X-Forwarded-Proto
和 tls:
位
您可以添加更多 location
块,例如 ~ "^/api/(.*)"
以便它像正常的 Nginx 一样工作。
在我的例子中,通过 Kubernetes Ingress 将一些本地 Docker Compose 和老式服务路由到外部是很有用的。
P.S。如果您来这里是为了解决 Owncloud CSRF 错误,请不要忘记为@mWatney 评论投票。
我的目标是通过 Kubernetes Ingress 路由不在 Kubernetes 中的本地 HTTP 服务。
下面的配置有效,所以我可以从外部打开 http://owncloud.example.com
或 https://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/;
proxy_set_header Host $host;
}
location ~ ^/api(.*) {
proxy_pass http://192.168.250.100:8261/;
proxy_set_header Host $host;
}
spec:
tls:
- hosts:
- owncloud.example.com
secretName: owncloud-tls
rules:
- host: owncloud.example.com
问题是我在浏览器的 Javascript 控制台中看到一些与 "meta" 相关的奇怪错误。它们与深度 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 用法有何不同,那就太好了。
如果使用不同的选项,我无法找到 proxy_pass 访问路径 /api
时不同 http 的解决方案。
----------------更新----------------
我已经收集了所有问题以供比较。
本地 - 工作人员:
如果我点击 manifest.json
,它会显示 "Nothing to preview"。如果我使用 wget
下载 json,我可以在第一行看到 <!DOCTYPE html>
。已下载 HTML 个文件。但我可以确认这个本地版本多年来一直运行良好。所以这个截图只是为了了解它工作时的样子。
通过 Ingress - 不工作:
我登录成功了。未从用户体验中发现任何异常,但存在问题:
试图退出。我做不到。它抛出 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/;
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
行为。我得到 412
HTTP 代码,这意味着:Precondition Failed client error response code indicates that access to the target resource has been denied
和 400
错误请求错误。
是否有解决此问题的专业知识?
非常感谢
终于找到了可行的解决方案。
我刚刚更正了 location
和 proxy_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
、secure
、X-Forwarded-Proto
和tls:
位
您可以添加更多 location
块,例如 ~ "^/api/(.*)"
以便它像正常的 Nginx 一样工作。
在我的例子中,通过 Kubernetes Ingress 将一些本地 Docker Compose 和老式服务路由到外部是很有用的。
P.S。如果您来这里是为了解决 Owncloud CSRF 错误,请不要忘记为@mWatney 评论投票。