You have probably heard of Kubernetes ingress
. What purpose does it serve? How to use it? Keep reading to find out.
Introduction
We have already seen how to point hostname to local WordPress. In addition, we have seen how HaProxy can serve as HTTP proxy. Now, we are going to point hostname to local WordPress using Kubernetes ingress. And we’ll use HaProxy as ingress controller. Jump straight to the demo if you prefer. Or keep reading if you want to understand the basic Kubernetes concepts we use here.
Kubernetes Services Limitations
When we want to expose some Kubernetes service (e.g. web app) to the outside world, we can configure it to be either of LoadBalancer
(on cloud) or NodePort (on-prem) type. Yet, Service API has several limitations:
- the need for manual configuration of external load balancer on-prem for NodePort services. This operational overhead might occur, for instance in the event of Kubernetes cluster node failures and their ip address changes.
- performance overhead when traffic reaches cluster ip service and kube proxy needs to route it to a different node.
- cloud costs for load balancers could bite if you have multiple external services.
- Service API operates at OSI level 4 (ip, port). Frequently, we want to operate at level 7, e.g. have path based routing.
Kubernetes ingresses and their controllers is another way to expose Kubernetes services. It addresses the above limitations.
Kubernetes Ingress Controller
In addition to the above limitations, we usually access services using some hostname (e.g. local.com
). And the requests directed to the service will usually through some api gateway. Api gateway may route the traffic to many backend services using provided hostnames or paths. The client of these services may not be even aware about the gateway. It just knows the path or host header it needs to provide to the (api gateway) host it accesses in order to consume the service. API gateway, in turn, needs to have routing rules defined in its configuration. Examples of such gateways are nginx
, haproxy
, etc… We have to deploy these third-party gateways to Kubernetes cluster. They are called Kubernetes ingress controllers. Routing rules are defined by Kubernetes ingress objects associated to ingress controllers.
Kubernetes Ingress
The routing rules of Ingress controllers are basically saying: “forward http requests sent on this path (e.g. /serviceA/doSmth
) to this backend service”. Or “forward http requests sent on with these host header (e.g. serviceA.com
) and this path (/serviceA/doSmth
) to this backend service”. For these purposes, Kubernetes Ingress object exists. It manages routing of external HTTP or HTTPS traffic to Kubernetes services. As there could be multiple api gateways installed for different purposes, these ingress objects need to have clear association to appropriate ingress controllers. This association is implemented by ingressclassess
Kubernetes objects. So each ingresclass
specifies the ingress controller it’s tied to. And to associate specific ingress with the controller, ingress needs to specify ingressclass
in its deployment manifest.
Kubernetes Ingress Use Cases
I’ll note 2 widely used use-cases Kubernetes Ingress supports:
- name-based virtual hosting
This case reminds me of shared hosting services different hosting providers offer when a single ip address might be associated with multiple hostnames (websites), e.g. using CNAME DNS records. In this case, Kubernetes ingress controller will be a an internet facing service, exposed via LoadBalancer service, for example. Requests coming to the ingress will be routed to the appropriate backend services (individual websites web servers) by matching host headers to the rules present in Kubernetes ingresses associated with the controller.
- path-based routing
Requests will be routed to backend services based on the URL paths. For example, requests to http://hostname/users
will be routed to users
microservice. Whereas, https://hostname/customers
will be routed to customers
microservice.
- combination of the host and path based routing.
Enough talking, let’s see all of this in action.
Demo
Demo Prerequisites
I assume you have Kubernetes
cluster. If you don’t, install on your machine minikube
, kubectl
and helm
.
Start Kubernetes
cluster using minikube start --profile custom
.
If you prefer, you can also repeat this demo on a managed Kubernetes cluster. Check out how easy it is to create Kubernetes Cluster on Linode. Get 100$ credit on Linode using this link. Linode is a cloud service provider recently purchased by Akamai. With this purchase, Akamai became a competitor in the cloud providers market.
Installation of HaProxy ingress controller
First, let’s install HaProxy ingress controller using helm
. We’ll just use official HaProxy docs and helm chart for that. Consider installing the chart to a dedicated namespace.
Let’s do a basic check that our ingress controller is working:
kubectl get svc -n hap
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mycontroller-kubernetes-ingress NodePort 10.96.227.38 <none> 80:30755/TCP,443:32615/TCP,1024:32212/TCP 22h
mycontroller-kubernetes-ingress-default-backend ClusterIP None <none> 8080/TCP
We see that mycontroller-kubernetes-ingress
service is of type NodePort
and it’s available at port 30755. Let’s access default backend service courteously provided to us by HaProxy chart:
$ minikube ip
192.168.58.2
$ curl http://192.168.58.2:30755/
default backend - 404
Ingress controller works.
Install WordPress helm chart
Next, we’ll install WordPress using helm chart to wp
namespace while customizing WordPress service type to ClusterIP
:
helm install wp bitnami/wordpress --set "service.type=ClusterIP" -n wp --create-namespace
I’m skipping helm repo add
and update
commands assuming you are already familiar with the flow. If you are not, you can see an example from a previous post when we installed Jenkins helm chart.
Expose WordPress
service using Kubernetes Ingress
Now, let’s point hostname wp.local.com
to WordPress service:
$ kubectl get svc -n wp
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-release-mariadb ClusterIP 10.111.48.139 <none> 3306/TCP 21h
my-release-wordpress ClusterIP 10.101.58.54 <none> 80/TCP,443/TCP 21h
For that purpose, we’ll create ingress object from the manifest below by running kubectl apply
on it.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-wp
namespace: wp
spec:
ingressClassName: haproxy
rules:
- host: wp.local.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: wp-wordpress
port:
number: 80
Pay attention to few important things:
- ingress is namespaced Kubernetes resource and has to be in the same namespace where the service it’s exposing is located. In our case it’s
wp-wordpress
:
kubectl get svc -n wp
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
wp-mariadb ClusterIP 10.111.166.90 <none> 3306/TCP 19h
wp-wordpress ClusterIP 10.98.171.120 <none> 80/TCP,443/TCP 19h
wp
prefix is derived from wp
helm release named we used during WordPress helm chart installation.
ingressClassName
is set tohaproxy
. This resource was installed when we installedhaproxy
ingress controller. Note, that it’s not namespaced object. That’s why we can reference it in any namespace.- Ingress rule is path based (
/
). It means that any request towp.local.com
hostname in the request header (or through DNSwp.local.com
name which points to Ingress controller public IP) will be routed to service namedwp-wordpress
on port 80.
Access WordPress through HaProxy ingress controller
As we are using minikube
, we can find the minikube
host using below command:
minikube ip -p custom
192.168.58.2
We see that ingress controller node port is 30755:
kubectl get svc -n hap
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mycontroller-kubernetes-ingress NodePort 10.96.227.38 <none> 80:30755/TCP,443:32615/TCP,1024:32212/TCP 22h
Let’s access our WordPress website using node ip and port and host header conforming to Ingress:
curl http://192.168.58.2:30755/ --header "Host: wp.local.com"
You should get a long html
file in response which you can save, open in the browser and see WordPress website delivered to us thanks to Ingress we defined.
You can, of course, simulate real-life website access scenarios using its hostname. For that you may add entry 192.168.58.2 wp.local.com
to /etc/hosts
. Then use curl command curl http://wp.local.com:30755
which will return the same result.
Summary
That’s it about Kubernetes ingress. It’s important to note also that Ingress API also supports routing HTTPS external traffic. In addition, ingress controllers usually load balance traffic across service endpoints (pods) thus eliminating performance penalty that exists with NodePort services when the chosen load-balanced clusterIP service endpoint runs on a different node. We’ll probably see relevant demos in the future.
You may find interesting below articles I wrote:
- Adding Google analytics to WordPress website
- Add Redis Cache to WordPress
- Point host name to WordPress in Docker
As always, feel free to share.
- Become a Certified Kubernetes Administrator (CKA)!
- Become a Certified Kubernetes Application Developer (CKAD)!
- BUNDLE KUBERNETES FUNDAMENTALS & CKA CERTIFICATION (COURSE & CERTIFICATION) FOR THE BEST DEAL! $499 ONLY!
Recommended Kubernetes
courses on Pluralsight:
- Configuring and Managing Kubernetes Networking, Services, and Ingress
- Managing Ingress Traffic Patterns for Kubernetes Services
Sign up using this link to get exclusive discounts like 50% off your first month or 15% off an annual subscription)
Recommended Kubernetes books on Amazon:
See more WordPress related posts here