In this blog I would like to explain how you can use your nginx ingress controller on your kubernetes cluster for a site outside your kubernetes cluster. I was wondering if this was possible, and it's not that difficult to configure. Before we continue I strongly recommend to read part 5 & part 6 first (if you haven't done already) since this part is a follow up on these to chapters.
What's the goal ? In this example I have a Synology NAS with a management portal on port 5000 (http) and 5001 (https), which is the default portal configuration for the management of a Synology NAS. This is just an example I am going to use, but you can basically use every ip and port you want. The requirement is that your kubernetes hosts should be able to access the website and corresponding port.
In this example my Synology NAS has IP 192.168.0.225, and for it's management portal I login to https://192.168.0.225:5001. and we would like use the ingress-nginx, so we can access it on https://nas.mydomain.com, with an automatically generated ssl certificate.
To achieve this we need to configure the following items in kubernetes. A namespace, a service and a ingress entry, and we need a (public) dns record for nas.mydomain.com pointing the CNAME of your ingress controller. (for more detailed information about the ingress controller see part 5)
The first thing we need to do is to create a (public) CNAME dns entry for the website, pointing to the dns name of the ingress controller. For the example the should be something like:
DNS CNAME record
nas.mydomain.com CNAME ingress-nginx.mydomain.com TTL 3600
Change the red values into your own equivalent
Namespace
Second we need to create a namespace in kubernetes with the following yaml entry. Please make sure that the service and ingress entry use this namespace.
apiVersion: v1
kind: Namespace
metadata:
name: nas # create namespace nas
---
Service
Next we create a service. What is relevant is the ports of the webserver you want to connect to. (In our example this is 5000 and 5001), is that the type should be "ExternalName" and the ExternalName entry should the ip of website (which is in our example 192.168.0.225). This this could also be a dns entry. Just keep in mind should NOT be the same name of the dns entry that will point to the ingress controller.
kind: Service
apiVersion: v1
metadata:
name: nas-service-v4
namespace: nas
spec:
ipFamilies:
- IPv4
ports:
- name: nas-5000
protocol: TCP
port: 5000
- name: nas-5001
protocol: TCP
port: 5001
spec:
type: ExternalName
externalName: 192.168.0.225 # ip of external website of dns name of the external website
---
The next part is to create an ingress entry. Since in our example port 5001 of the synology nas is using HTTPS, we should configure the backend protocal as HTTPS. If we would use port 5000, we should remark it or change it HTTP. The tls part will generate a Let's Encrypt certificate for nas.mydomain.com
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nas-ingress
namespace: nas
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" # Remark this entry if you only have a HTTP port connection to external webserver
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
rules:
- host: nas.mydomain.com
http:
paths:
- path: /
pathType: Prefix # pathType no longer has a default value in v1; "Exact", "Prefix", or "ImplementationSpecific" must be specified
backend:
service:
name: nas-service-v4 # make sure this is same service name as in the service yaml
port:
number: 5001
tls: # < placing a host in the TLS config will indicate a cert should be created
- hosts:
- nas.mydomain.com
secretName: nas.mydomain.com-tls # < cert-manager will store the created certificate in this secret.
You now can combine the entries and save them to a yaml files (for example external-nas.yaml) . You can find the complete example script here, so you can change it to own settings. You can apply the yaml to your kubernetes cluster via the following command.
kubectl apply -f external-nas.yaml
If everything went ok. Open a browser and goto https://nas.mydomain.com (example) and you should see something like this:
We now can access the Synology nas portal via the ingress-nginx controller with a ssl certificate.
I hope you found this blog useful. I you have any questions do not hesitate to leave a comment below.
I tried something based on this (without introducing the ssl cert) on my k3s/Traefik installation to add an Ingress for an IOT device and it didn't work - Traefik didn't seem to recognize the service I had added. Then I found this issue (https://github.com/traefik/traefik/issues/1816) which indicates an Endpoint definition needs to be added (which unfortunately requires a numerical IP and not a hostname). It is also says this isn't Traefik specific and any Ingress would require the same. I did get my goal to work but thought this article might need an update - I'd love to understand why this article didn't work for me as is.
ReplyDeleteAfter even more digging it appears that Endpoints are being replaced with EndpointSlices (an explanation why is at https://www.linkedin.com/pulse/kubernetes-concept-endpoints-vs-endpointslices-mbong-ekwoge/) and that EndpointSlices now do support FDQNs as an improvement over numerical IPs (See https://github.com/vmware-tanzu/cross-cluster-connectivity/issues/96)
DeleteI am using this solution in combination with a ingress-nginx controller in stead of traefik. I can confirm that it doesn't require an endpoint (just checked) for it to work. Did you have a look at the ingress annotation setting ? In my case I should be "nginx", but in your case it should be "traefik". You can also try if you can get to work with an ingress-nginx on k3s. See https://blog.thenets.org/how-to-create-a-k3s-cluster-with-nginx-ingress-controller/. Nginx has always been easier to configure than traefik. At least in my personal experience.
Delete