Need help on exposing services

I have a running setup of Rancher with the following configurations:

  • Rancher host runs on a public IP machine (say 11.22.33.44 for example);
  • I have 8 nodes on my 10.1.1.0/24 network (not accessible from the internet);

My goal is to provide a web service with load balancing using Rancher and I have a few questions:

  • Is it risky to serve Rancher’s web interface publicly?
  • How could I serve this web app using a single public IP?

Here are the steps I tried:

1 - Deploy a workload called “web-app” with a scalable deployment of 8 pods using the “rancher/hello-world” image with port mapping as follows:

  • Port Name: http
  • Publish the container port: 80
  • Protocol: TCP
  • As a: NodePort
  • On listening port: Random
    2 - Add Ingress on Load Balancing called “hello” on the same namespace using “Automatically generate a .xip.io hostname” (otherwise I couldn’t manage it to work). Rule as follows:
  • Path: /
  • Target: web-app
  • Port: 80
    3 - Finally, when it starts, it becomes available at hello.gabriel-milan.10.1.1.14.xip.io/, which is not accessible from the Internet.

How could I provide this service publicly?

1 Like

Hi, Gabriel. I responded to your question yesterday on Stack Overflow. If you have more questions, let’s continue the discussion there.

1 Like

Hey @adrian.goins,

I saw your answer on Stack Overflow. One thing I’m not clear about yet:

I’ve installed Rancher and RKE2 locally on my machine using RancherD, purely for learning purposes. I want to know how I can make xip hostnames accessible from the internet. You mentioned something about giving a node a public IP first and it should automatically generate xip.io hostnames that work over the internet, correct?

Right now I’m only able to generate xip hostnames that work on my local network, not working of the web.

Is it possible to give an already create RKE2 node a public IP after it was created? How would I got about that?

Also, how would to port mapping look like on a home network?

Do I have to map it to, say, my home’s public IP?

Here is an example:

My router’s public IP is 16.43.236.65

My server’s IP on the local network is 192.168.0.155

Do I have to map my router’s IP like so:

16.43.236.65:80 -> 192.168.0.155:80

16.43.236.65:443 -> 192.168.0.155:443

and then set the public IP for my node to 16.43.236.65 ?

Before you get to Kubernetes, you need to deal with the networking of the node. If you have a public IP on your router, then the router is doing NAT from a public network to a private network, such as 192.168.0.0/24. Whatever address your node got from the DHCP server is private.

If you want the node to have a public IP, its network interface needs to sit next to, not behind, the router. Unless you have an ISP who gave you an ethernet handoff and a block of addresses, that may not be possible. Usually an ISP that gives you a block of public addresses will give you a /30 for the external and a larger block that is routed to your side of the /30. For example, the external interface might be 1.2.3.2/30 connecting to 1.2.3.1/30 on the ISP’s side. They would then route 4.5.6.0/24 to 1.2.3.2, and then your router can do whatever it wants with the address space, including assign it to internal hosts and then handle firewalling traffic to those addresses.

Instead, you probably have a single IP on the outside of your router and that’s it. In that case you can either do port-forwarding or map a “DMZ address” on the router (actual functionality varies from router to router). I would not recommend the DMZ solution - you don’t want to forward every packet on every port to your internal host. Instead, I’d do as you describe - set up :80 and :443 on the router to forward to your internal host.

On the host itself, you’ll have an ingress controller listening on :80 and :443 that will handle the traffic. Then in DNS you’d create A records that use the public IP on your router.

You don’t need to tell Kubernetes the external IP on the outside of the router. Kubernetes doesn’t care. All you need to do is make sure that packets from the outside are forwarded by your router to the host on the correct port. Once Kubernetes receives the packet, it’ll do the rest.

1 Like

Really appreciate the response @adrian.goins thank you!

Posting this here in case someone else comes across the same issues I had and needs help.

With everything on bare metal-metal in a traditional home network using a router, I wanted to expose apps on the web with only limited points of entry into the cluster (ports 80 and 443 for http and https traffic respectively), without opening any more ports than necessary and keeping workloads and services safe behind ClusterIP networking (no need to expose ports for workloads and services with NodePort).

None of my nodes have a public IP, only my router does.

Ingress was the answer, as it can route traffic based on different hostnames all the while using the same IP address.

Because the nodes in my cluster were all inside a private home network, there were no straightforward instructions on how to do this.

Additionally, I wanted to use xip.io to generate free URLs for testing purposes that worked over the WWW, but the Automatically generate a .xip.io hostname option when adding ingress through the Rancher UI would only work on my local network, not the web.

I banged my head on this for days.

But I finally figured it out and it’s easy as pie.

First, we need to go into the router’s settings and do some port forwarding.

Say your router’s public IP is 16.43.236.65 and you have a node on your cluster whose internal private IP on the home network is 192.168.0.155

In your router’s settings, forward all port 80 and 443 traffic to ports 80 and 443 of one of your nodes so that it essentially looks like something like this:

16.43.236.65:80192.168.0.155:80

16.43.236.65:443192.168.0.155:443

Once that is done, go back to Rancher and click on Add Ingress under Load Balancing, unfortunately Automatically generate a .xip.io hostname will still use your node’s private IP in your home network and only work locally.

Instead, you can just select Specify a hostname to use and use your public IP with xip.io like so:

16.43.236.65.xip.io

Now configure the rest of your ingress, I just leave everything at their defaults for now, I use Service instead of Workload for Target Backend.

Now, when navigating to 16.43.236.65.xip.io on your browser, you should be able to access the service you selected in the Ingress you added over the web.

If you want to add other services using xip.io you can, just add subdomains, for example:

another-service.16.43.236.65.xip.io
yet-another-service.16.43.236.65.xip.io

It might look like magic but the way it works is by hostname, so you can literally have any domain name point to the same public IP, Ingress will know where to forward the traffic and which service/workload to use based on the hostname, which I find brilliant.

Lastly, if you want to use an actual domain name: in the DNS settings from your domain name provider set an A Record that points to your Router’s public IP. Using our current example that would be 16.43.236.65.

On Rancher add an Ingress and specify that same domain name.

Same concept. Hopes this helps!