{
  "$type": "site.standard.document",
  "canonicalUrl": "https://justingarrison.com/blog/2016-06-01-exposing-services-using-ingress-with-on-prem-kubernetes-clusters",
  "coverImage": {
    "$type": "blob",
    "ref": {
      "$link": "bafkreifgmy4p6loqmr7j2y6dfnjxll3zomn7aglwdkdfjb7xhxtcivs74a"
    },
    "mimeType": "image/png",
    "size": 213848
  },
  "description": "This article has not been updated for Kubernetes clusters that use RBAC for API authentication (versions 1.6+).",
  "path": "/blog/2016-06-01-exposing-services-using-ingress-with-on-prem-kubernetes-clusters",
  "publishedAt": "2016-06-01T00:00:00.000Z",
  "site": "at://did:plc:p7uix7mresfq4nfzxp3klgfa/site.standard.publication/3mmdn7mg2qm2d",
  "textContent": "NOTE: This article has not been updated for Kubernetes clusters that use RBAC for API authentication (versions 1.6+). I am leaving this article here for reference but you should be aware of the limitations of this guide.\n\nKubernetes is great and running and maintaining pods. It can schedule fast and has a great API. But getting access to your pods with on-prem installations has been a challenge. In the past people have solved this by manually mapping exposed service ports and essentially keeping a spreadsheet of port conflicts. Then they’d use the kube-proxy to make sure their traffic is routed to the right node and pod. But there’s a better way!\n\nI had been struggling with figuring out how to expose kubernetes services with the new ingress resource. I finally have failed enough times I think I can share what I’ve learned with others. The below steps assumes you have at least kubernetes 1.1 installed. It should work equally well with bare metal, VMs, or localkube/minikube.\n\nFirst create a deployment with\n\nThis creates a new deployment named microbot. Deployments are great because they’re versioned and can be used later for rolling upgrades. The deployment will create a ReplicaSet (or ReplicaController on 1.1) which will in turn create a pod from the image specified. All we need to do is tell it the image we want to run and what port that container is expecting traffic on.\n\nCheck out all the stuff that one command created for you. Notice the ReplicaSet (rs) has a version which makes future upgrades easier.\n\nIngress maps to stable service IPs (not pods) so you’ll want to create a service from your deployment. You can do that by “exposing” the deployment. We need to say what we want to expose (deployment) what port we want the service exposed on (port) and what port it should map to on the pod (target-port). Do that with\n\nOn bare metal or on-prem VMs you need to use type NodePort. This will expose your service on a high level port of all your nodes (default to 30000–32767). The port will be randomly selected and thanks to ingress pods will be managed so we don’t have to worry about port conflicts or additional ports.\n\nBefore we make an ingress controller and mapping lets make sure we can get to the service without it. First find the random port that the service was mapped to.\n\nThen find the node your pod was scheduled on\n\nNow check that your service is routing to your pod correctly with curl. You should see the sample output below.\n\nGreat! Remember you’re curling the service port and not the pod port. Only the service is exposed to the outside network. Now that our service and pod are working properly we can create our ingress controller. I’m using traefik but feel free to use nginx too.\n\nThis creates a Deployment (which creates a pod) using the official traefik image. The pod that is created is where the actual traefik load balancer runs.\n\nUse kubectl -o wide to get the node IP where your new ingress pod is running. I only have 1 node (running minikube) but yours will likely be different.\n\nNow that the pod has started (make sure it says “Running” in the status column) we need to make an ingress rule. This is the part that will say what hostname and path passes traffic to our service.\n\nHere’s an example for the microbot service.\n\nCreate the ingress object from the map above with the following command.\n\nThis takes anything that’s passed to the ingress pod with the “microbot” hostname on the root path (e.g. http://microbot/) and sends it to the microbot service on port 80 (the port our service is expecting traffic on).\n\nBecause our service is on NodePort the traefik pod will match the hostname + path and forward the traffic to 192.168.99.100:31649 automatically. We can verify the mapping with.\n\nThis command is telling curl to map the hostname “microbot” to it address 192.168.99.100 (like editing /etc/hosts) and then trying to get the URL http://microbot/. If you saw the output above then your ingress controller and mapping is working correctly. If not, read below for some more help.\n\nSo again just to recap. The bare minimum you need is\n\n- A pod accepting traffic on a port and path\n- A service exposed on NodePort sending traffic to the pod\n- An ingress pod watching for ingress rules\n- An ingress rule to map a hostname and path to a service\n\nTips and Troubleshooting\n\nIf you need to troubleshoot you should check the logs on the ingress pod or use describe on the ingress ReplicationController and ingress pod.\n\nIf you want to map ingress rules to services on different namespaces you need to add that to the ingress rules (not ingress pods). As an example, here’s a mapping for the kubernetes dashboard running in the kube-system namespace.\n\nMake sure you expose the kubernetes dashboard service on a NodePort first.\n\nService ports won’t conflict even if multiple services export port 80. They automatically get remapped to a high port (stated earlier) when exposed as a NodePort. It’s one of the key benefits to giving every pod and service an IP and using network subnets (usually via overlay networks) on each node in the cluster.\n\nIngress mappings are absolute paths after the given hostname. They also pass the trailing path on to the service so make sure your pod accepts traffic on that path.\n\nAn example is below. This would try to forward /ui to the kubernetes dashboard which is not a path the dashboard accepts traffic on so you won’t get what you expect.\n\nPath rewrite rules depend on the ingress pod support. Most load balancers have options via rule annotations. Deis router uses annotations for all load balancer options. Openshift uses HAproxy with custom configuration. Traefik has a StripPrefix option and nginx doesn’t have rewrite rule options yet.\n\nIngress mappings need to specify if they should recursively map to a service. For example if you have /foo and /bar mapping to service1 and service2 but you also want /foo/_ and /bar/_ to map to the services you need to say so explicitly.",
  "title": "Exposing Services using Ingress with Kubernetes <= 1.5"
}