My aim is to route local HTTP service that is not in Kubernetes through Kubernetes Ingress.
The configuration below works so I'm able to open http://owncloud.example.com
or https://owncloud.example.com
from outside.
Here is Kubernetes configuration:
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
The issue is that I see some strange errors in browser's Javascript console related to "meta". They are related with deep Javascript code. So unfortunately, there is no useful log. The website produces weird behaviour at few places while locally it works fine. So it seems this is something to do with Kubernetes Ingress.
Previously I used plain Nginx connected to outside and this worked great:
location / {
proxy_pass http://192.168.250.100:8260/
}
If I add exactly the same block to server-snippet
, website doesn't load at all. It catches default Ingress.
How to properly proxy_pass
traffic from Kubernetes Ingress to another service which is running outside of Kubernetes? So it doesn't miss something through proxy.
Would be nice to have exploration on server-snippet
to understand how Kubernetes Ingress configuration is different from standard Nginx usage.
If using different options, I was not able to find a solution to proxy_pass to different http when accessing path /api
.
----------------- Updates -----------------
I have collected all issues for comparison.
Locally - working one:
If I click on manifest.json
, it shows "Nothing to preview". If I use wget
to download that json, I can see <!DOCTYPE html>
in this first line. It's HTML file downloaded. But I can confirm this local version is working perfectly for years. So this screenshot is just to know how it looks when it works.
Through Ingress - not working:
I logged in successfully. Didn't spot anything weird from user experience, but issue exists:
Tried to log out. I'm not able to do it. It throws Owncloud specific error "Access forbidden CSRF check failed" and on the console I see this:
If I go to https://owncloud.example.com/login page on purpose:
If I try to access files on this Owncloud, it also fails with 400
:
If I add additional 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"
Summarise
No errors on application side. So first thing that comes to my mind is /logout
behaviour. I get 412
HTTP code which means: Precondition Failed client error response code indicates that access to the target resource has been denied
and 400
bad request error.
Any expertise to catch this issue?
Many thanks
Finally found a working solution.
I just corrected location
and proxy_pass
to solve the root cause.
So if you have some local HTTP service which is outside of Kubernetes cluster and you want to serve this through Ingress, you just need this:
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
Remove Owncloud tuning block if you have another service
Remove ssl
, secure
, X-Forwarded-Proto
and tls:
bits if you don't need HTTPS
You can add more location
blocks such as ~ "^/api/(.*)"
so it works as normal Nginx.
In my case it was useful to route some local Docker Compose and old fashion services to outside through Kubernetes Ingress.
P.S. Don't forget to vote for @mWatney comment if you came here to solve Owncloud CSRF error.