What I did:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: root-ingress
namespace: kubernetes-dashboard
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /dashboard
pathType: Prefix
backend:
service:
name: kubernetes-dashboard
port:
number: 443
curl -k -v https://localhost response on localhost:
PS C:\Windows\system32> curl.exe -k -v https://localhost
* Trying [::1]:443...
* Connected to localhost (::1) port 443
* schannel: disabled automatic use of client certificate
* ALPN: curl offers http/1.1
* ALPN: server accepted http/1.1
* using HTTP/1.1
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/8.4.0
> Accept: */*
>
* schannel: remote party requests renegotiation
* schannel: renegotiating SSL/TLS connection
* schannel: SSL/TLS connection renegotiated
* schannel: remote party requests renegotiation
* schannel: renegotiating SSL/TLS connection
* schannel: SSL/TLS connection renegotiated
< HTTP/1.1 404 Not Found
< Date: Mon, 22 Jan 2024 20:20:40 GMT
< Content-Type: text/html
< Content-Length: 146
< Connection: keep-alive
< Strict-Transport-Security: max-age=15724800; includeSubDomains
<
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
* Connection #0 to host localhost left intact
PS C:\Windows\system32> curl.exe -k -v https://localhost/dashboard
* Trying [::1]:443...
* Connected to localhost (::1) port 443
* schannel: disabled automatic use of client certificate
* ALPN: curl offers http/1.1
* ALPN: server accepted http/1.1
* using HTTP/1.1
> GET /dashboard HTTP/1.1
> Host: localhost
> User-Agent: curl/8.4.0
> Accept: */*
>
* schannel: remote party requests renegotiation
* schannel: renegotiating SSL/TLS connection
* schannel: SSL/TLS connection renegotiated
* schannel: remote party requests renegotiation
* schannel: renegotiating SSL/TLS connection
* schannel: SSL/TLS connection renegotiated
< HTTP/1.1 400 Bad Request
< Date: Mon, 22 Jan 2024 20:23:04 GMT
< Transfer-Encoding: chunked
< Connection: keep-alive
< Strict-Transport-Security: max-age=15724800; includeSubDomains
<
Client sent an HTTP request to an HTTPS server.
* Connection #0 to host localhost left intact
Just use NodePort
apiVersion: v1
kind: Service
metadata:
name: kubernetes-dashboard-service
namespace: kubernetes-dashboard
spec:
selector:
k8s-app: kubernetes-dashboard
type: NodePort
ports:
- protocol: TCP
port: 8443
targetPort: 8443
nodePort: 31000
Dashboard will be available at https://localhost:31000
What you are sending looks like this
Browser ==HTTPS==> ingress ==HTTP==> k8s-dashboard
But expected is
Browser ==HTTPS==> ingress ==HTTPS==> k8s-dashboard
The issues it that k8s-dashboard
service expects HTTPS request, this is the reason why you get Client sent an HTTP request to an HTTPS server.
It was decrypted by ingress and later on forward by using plain HTTP
Instead of using ingress you can use NodePort (I gave it in Quick fix) or LoadBalancer. Idea is to work on ISO Layer 4(IP) instead of routing it using Layer 7(HTTP)
ssl-passthrough
from nginx-ingressTo make it work it needs two changes
kubectl edit
kubectl -n ingress-nginx edit deployment ingress-nginx-controller
You have to add - --enable-ssl-passthrough
(just one line) to the args
After change it should look like
...
containers:
- args:
- /nginx-ingress-controller
- --publish-service=$(POD_NAMESPACE)/ingress-nginx-controller
- --election-id=ingress-nginx-leader
- --controller-class=k8s.io/ingress-nginx
- --ingress-class=nginx
- --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
- --validating-webhook=:8443
- --validating-webhook-certificate=/usr/local/certificates/cert
- --validating-webhook-key=/usr/local/certificates/key
- --enable-ssl-passthrough
...
When route is created you can't specify path like /dashboard
because k8s dashboard doesn't know it's working in some subpath, so using rewrite
will not resolve it as links generated by dashboard will be wrong(I wrote more about it here)
So we need ingress route like this (with ssl-passthrough
and backend-protocol
)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: root-ingress
namespace: kubernetes-dashboard
annotations:
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kubernetes-dashboard
port:
number: 443
When you disable HTTPS in kubernetes dashboard your flow will look like this
Browser ==HTTPS==> ingress ==HTTP==> k8s-dashboard
It will perfectly match what you have right now and should work without issues
As I didn't try it I will leave this article how to do it.
There is also raw manifest but maybe a little old