You have probably heard of
Kubernetes ingress. What purpose does it serve? How to use it? Keep reading to find out.
- Kubernetes Services Limitations
- Kubernetes Ingress Controller
- Kubernetes Ingress
- Kubernetes Ingress Use Cases
- Demo Prerequisites
- Installation of HaProxy ingress controller
- Install WordPress helm chart
- Expose WordPress service using Kubernetes Ingress
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
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.
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
- combination of the host and path based routing.
Enough talking, let’s see all of this in action.
I assume you have
Kubernetes cluster. If you don’t, install on your machine
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
helm install wp bitnami/wordpress --set "service.type=ClusterIP" -n wp --create-namespace
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.
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
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.
ingressClassNameis set to
haproxy. This resource was installed when we installed
haproxyingress 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 to
wp.local.comhostname in the request header (or through DNS
wp.local.comname which points to Ingress controller public IP) will be routed to service named
wp-wordpresson 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.
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!
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