POST

In this brief article we’ll see how to setup a Kubernetes nginx ingress to redirect HTTP traffic from example.com to www.example.com.

Prerequisites here are a cluster with an nginx ingress controller and a route to the cluster. This relies on your domain routing example.com and www.example.com to your cluster, usually through some form of load-balancer. We’re not going to cover these aspect of the solution, just the ingress definition you need.

The solution is accomplished through the use of nginx annotations. There are a large number of annotations that you can apply to your ingress definition but the ones we’ll need to solve this specific problem are: -

  • from-to-www-redirect
  • configuration-snippet

The snippet is the clever aspect fo the solution. It allows you to add dynamic configuration to the ingress controller. We use it to detect the use of the non-www form of the URL and then simply issue a re-write that is pushed out (and back via your domain) to the www form.

The redirect is permanent with the user receiving a 308 status code as the redirect occurs, telling the recipient that a the resource has been permanently moved to the www form of the URI.

The snippet annotation looks like this: -

nginx.ingress.kubernetes.io/configuration-snippet: |
  if ($host = '' ) {
    rewrite ^ https://www.$request_uri permanent;
  }

You’ll notice that we’re defining the ingress using Ansible, our IaC tool of choice, which is responsible for defining the hostname in the variable w_hostname (a value of example.com in our case).

We need to handle both hostnames in our ingress (example.com and www.example.com) and we can do that with one ingress definition. The full Kubernetes Ingress, and associated Service definition now look like this: -

---
kind: Service
apiVersion: v1
metadata:
  name: website
  namespace: 
spec:
  selector:
    name: website
  ports:
  - name: http
    port: 80
    targetPort: 80
---
kind: Ingress
apiVersion: networking.k8s.io/v1beta1
metadata:
  name: website
  namespace: 
  annotations:
    ingress.kubernetes.io/rewrite-target: /
    kubernetes.io/ingress.class: "nginx"
    cert-manager.io/cluster-issuer: "letsencrypt-nginx-"
    nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      if ($host = '' ) {
        rewrite ^ https://www.$request_uri permanent;
      }
spec:
  tls:
  - hosts:
    - 
    - www.
    secretName: website-tls
  rules:
  - host: 
    http:
      paths:
      - path: /
        backend:
          serviceName: website
          servicePort: http
  - host: www.
    http:
      paths:
      - path: /
        backend:
          serviceName: website
          servicePort: http

When driven from Ansible the definitions rely on the variables w_namespace (to define the namespace), w_hostname and w_cert_issuer (used to define the certificate type).

We’ll explore certificate management in separate article.

Thanks to Benjamin Maynard’s blog for inspiration of this post

latest posts
by year
by category