k8spractice Ingress Rules

This is part 1 of a 4-part series on deploying an application to Azure Kubernetes. Here’s a full list of this series:

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.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.