EKS Fixed Responses

Sun Feb 06 2022

Overview

The AWS Load Balancer Controller can be used to manage Elastic Load Balancers (ELB) for an AWS Elastic Kubernetes Cluster (EKS). We can use the fixed-response and redirect features of ALBs to implement common tasks without additional pods or services. This is implemented through Kubernetes ingress resources. When combined with an ingress group we can have multiple services, redirects, and fixed responses from a single ALB.

Common Annotations

The documentation for the AWS load balancer controller has a variety of annotations that can be used to configure an AWS ELB.

We need to specify the ingress class to be configured by the controller:

kubernetes.io/ingress.class: alb

We can optionally add a group name and group order. All the ALB ingress resources with the same group name will share an ALB with the rule order specified:

alb.ingress.kubernetes.io/group.name: default
alb.ingress.kubernetes.io/group.order: '1'

Redirect

A redirect can be created on an ALB using the following. It will redirect old_url.mitchel.dev to the new hostname new_url.mitchel.dev.

You can configure redirects as either temporary (HTTP_302) or permanent (HTTP_301) based on your needs.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: redirect
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/group.name: default
    alb.ingress.kubernetes.io/group.order: '1'
    alb.ingress.kubernetes.io/actions.redirect-302: >-
      {
        "type": "redirect",
        "redirectConfig": {
          "host": "new_url.mitchel.dev",
          "statusCode": "HTTP_302"
        }
      }
spec:
  rules:
    - host: old_url.mitchel.dev
      http:
        paths:
          - path: /*
            pathType: ImplementationSpecific
            backend:
              service:
                name: redirect-302
                port:
                  name: use-annotation

Maintenance Page

A fixed response can be used to implement a catch-all maintenance page. The group.order can be swapped with the resource under maintenance to activate the page.

A 503 status code is used to prevent it from being cached by a CDN.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: maintenance
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/group.name: default
    alb.ingress.kubernetes.io/group.order: '2'
    alb.ingress.kubernetes.io/actions.response-503: >-
      {
        "type": "fixed-response",
        "fixedResponseConfig": {
          "contentType": "text/html",
          "statusCode": "503",
          "messageBody": "<!doctype html> <title>Site Maintenance</title> <style> body { text-align: center; padding: 150px; } h1 { font-size: 50px; } body { font: 20px Helvetica, sans-serif; color: #333; } article { display: block; text-align: left; width: 650px; margin: 0 auto; } a { color: #dc8100; text-decoration: none; } a:hover { color: #333; text-decoration: none; } </style> <article> <h1>We&rsquo;ll be back soon!</h1> <div> <p>Sorry for the inconvenience but we&rsquo;re performing some maintenance at the moment. If you need to you can always <a href='mailto:me@mitchel.dev'>contact us</a>, otherwise we&rsquo;ll be back online shortly!</p> <p>&mdash; The Team</p> </div> </article>"
        }
      }
spec:
  rules:
    - host: '*.mitchel.dev'
      http:
        paths:
          - path: /*
            pathType: ImplementationSpecific
            backend:
              service:
                name: response-503
                port:
                  name: use-annotation

Robots.txt

A robots.txt is used to communicate with web robots how the website should be processed or scanned. Most websites will have provisions for configuring and serving this file. However, for development clusters, it may be easier to have a high-priority rule that will return a default disallow all.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: robots
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/group.name: default
    alb.ingress.kubernetes.io/group.order: '3'
    alb.ingress.kubernetes.io/actions.robots-txt: >-
      {
        "type": "fixed-response",
        "fixedResponseConfig": {
          "contentType": "text/plain",
          "statusCode": "200",
          "messageBody": "User-Agent: *\nDisallow: /"
        }
      }
spec:
  rules:
    - http:
        paths:
          - path: /robots.txt
            pathType: ImplementationSpecific
            backend:
              service:
                name: robots-txt
                port:
                  name: use-annotation