This is part 1 of a 4-part series on deploying an application to Azure Kubernetes. Here’s a full list of this series:
- k8spractice Overview
- k8spractice PostgreSQL Service Deployment
- k8spractice Services
- k8spractice Ingress Rules (this post)
Deploy Nginx Ingress Controller
To help with exposing our web services we need to setup an ingress controller. For k8spractice I’m using NGINX Ingress Controller. Here’s the command to apply the Ingress Controller to the cluster:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.43.0/deploy/static/provider/cloud/deploy.yaml
See the “Installation Guide” for the specific steps for other Kubernetes providers. Once the installationRun kubectl get all -n ingress-nginx
to verify that all resources deployed successfully.
The ingress-nginx-controller Service will list the External IP that the ingress controller has been configured by Kubernetes to listen to. Use this IP for the DNS entry for your k8spractice deployment. Also note that deploying an ingress controller will add an inbound rule in the Kubernetes cluster’s Network Security Group to allow TCP ports 80 and 443 to the External IP.
Deploy cert-manager
According to cert-manager’s documentation it is a “native Kubernetes certificate management controller.” This controller will handle the full lifecyle of k8spractice’s TLS certificate. Simply follow these instructions to install cert-manager on a Kubernetes cluster. Run kubectl get all -n cert-manager
to verify that all resources started successfully.
Configure A ClusterIssuer
According to cert-manager’s API documentation “ClusterIssuer represents a certificate issuing authority”. Basically, a ClusterIssuer can handle getting certificates from all resources that are deployed in the cluster regardless of namespace. If you are segregating “tenants” using namespaces, use “Issuer” instead. All configuration items are the same; except that the issuer is only accessible by resources within that namespace.
For the purpose of this exercise we will be using Let’s Encrypt’s “staging environment” to sign k8spractice’s TLS certificate. Here is a sample YAML configuration to deploy:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: le-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: <YOUR EMAIL HERE>
privateKeySecretRef:
name: <PRIVATE KEY SECRET NAME HERE>
solvers:
- selector: {}
http01:
ingress:
class: nginx
spec.acme.email
should contain the email address for Let’s Encrypt to send notification emails regarding the server’s certificate. spec.privateKeySecretRef.name
defines the name of the Kubernetes TLS secret to store the generated ACME account private key.
Create IngressRule for k8spractice
Now that we have a way to get a signed certificate, we can set the ingress rules to expose k8spractice to the world. Here is the full ingress rule configuration (which is also available in /k8s-files/ingress.yaml):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: practice-ingress
annotations:
cert-manager.io/cluster-issuer: le-staging
kubernetes.io/tls-acme: "true"
spec:
ingressClassName: nginx
defaultBackend:
service:
name: frontend
port:
name: frontendport
rules:
- host: k8spractice.homepluspower.info
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: backend
port:
name: backendport
tls:
- hosts:
- k8spractice.homepluspower.info
secretName: <TLS SECRET NAME>
The content of metadata.annotations
define that the practice-ingress Ingress resource should get its TLS cert from the “le-staging” ClusterIssuer resource defined earlier. spec.ingressClassName
specifies which ingress controller class to use–in this case “nginx”.
The service
nodes name
and port.name
should be set to the Service resource to route the request to. The following rule routes HTTP requests for paths with prefix /api
the backend
service on port 5000:
rules:
- host: k8spractice.homepluspower.info
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: backend
port:
name: backendport
If the value of pathType
is changed to “Exact” then the rule will only match on “/api” and not paths like “/api/auth/checksession” or “/api/nomenu”.
The defaultBackend
node specifies which service should any HTTP requests that doesn’t match any rules should be routed to. In the case of k8spractice the default service is Frontend; which will then allow React Router to handle all requested paths other than “/api”. Since path matching is done in the order defined the following will have the same effect as defaultBackend:
- path: /
pathType: Prefix
backend:
service:
name: frontend
port:
name: frontendport
At this point, k8spractice is fully operational. This series should give you an end-to-end walkthrough of deploying a web app in Kubernetes.