Kube Endpoints and Reverse-Proxying Non-Kube Services

For a while now, I’ve been using my hybrid-cloud K3s nodes to reverse proxy into a few services that are not running in my Kubernetes cluster. Originally, I planned on proxying the traffic I wanted in NGINX at the edge, but then it would be nearly impossible to pass through to Traefik without a lot of manual work and effort. I ended up doing it in a reasonably hacky way, but ultimately decided to move away from that approach due to maintenance and re-deployability concerns. Everything I needed to learn to get it working was found on a blog post from Eleven Labs, and I extended that information to get it working on Trafik running on Kubernetes. Functional, but definitely hacky.

Over the 2021-2022 holidays, I stumbled into a very interesting StackOverflow post. TL;DR: They recommended creating an Endpoint Object and just pointing the addresses to an external IP.

Well…that’s kind of a neat idea. Let’s see if we can get that approach working! First, let’s look over how the network traffic should be flowing.

Network flow

From the public internet, this is effectively how traffic makes it way from the user over the public internet to the service running on a VM host in my homelab.

WikiJS Screenshot

Migrating over wiki.danmanners.com

Okay, so if I wanted to update things from A to B, it should probably look something like this:

Original Code

[http]
    [http.middlewares]
        [http.middlewares.http-https-redirectscheme.redirectScheme]
            scheme = "https"
            permanent = true
    [http.services]
    [http.services.wikijs]
        [http.services.wikijs.loadBalancer]
            [[http.services.wikijs.loadBalancer.servers]]
                url = "http://10.45.0.32:80/"

The original code to reference can be found here, here, and here.

New Code

---
apiVersion: v1
kind: Service
metadata:
  name: wikijs
  namespace: kube-system
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  clusterIP: None
  type: ClusterIP
---
apiVersion: v1
kind: Endpoints
metadata:
  name: wikijs
  namespace: kube-system
subsets:
- addresses:
  - ip: 10.45.0.32
  ports:
  - name: http
    port: 80
    protocol: TCP
---
apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:
  name: wikijs
  namespace: kube-system
  labels:
    app.kubernetes.io/instance: traefik
spec:
  weighted:
    services:
      - name: wikijs
        passHostHeader: true
        port: 80
        scheme: http

The full code for my homelab with Traefik can be viewed here

Does it work?

Short answer: Yes!

WikiJS Screenshot

Longer answer: It definitely works, and latency from my house, over the internet, and back seems to be pretty consistently under 12ms. Not bad at all, especially considering how many hops there are!

Are there other possible challenges or issues I’m not aware of today? Absolutely. Is there perhaps an even better way to do things? Very well may be! Does this work quite easily, AND allow me to easily manage everything through GitOps? Yes, absolutely.

Questions? Thoughts?

Feel free to ping me at daniel.a.manners@gmail.com. If something I wrote isn’t clear, feel free to ask me a question or tell me to update it!