Kubernetes Part 19: Use kubernetes ingress controller for sites outside kubernetes

 


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
---

Ingress
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
A service and an ingress entry will be created. The certificate manager will also have a ssl certificate generated automatically. 

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.

Comments

  1. 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.

    ReplyDelete
    Replies
    1. After 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)

      Delete
    2. I 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

Post a Comment