router: How to configure router to serve routes from a flat file
Router has the ability to load routes from a JSON Lines file instead of the Content Store database. This guide describes the end-to-end process of configuring Router to serve routes from a file fetched from S3 in production.
It involves:
- Creating an S3 bucket via a local Terraform deployment
- Creating a Kubernetes service account that allows access to the S3 bucket
- Running a Kubernetes job to export routes from Content Store to the bucket
- Configuring Router's deployment to fetch the routes file from S3
- Setting the
ROUTER_ROUTES_FILEenv var to make Router load routes from the file
Prerequisites
-
GOVUK_ENVIRONMENTenvironment variable set to the environment name (e.g.export GOVUK_ENVIRONMENT=integration) - Assume the
fulladminrole in the AWS in the environment you're targeting:eval $(gds aws govuk-${GOVUK_ENVIRONMENT}-fulladmin -e --art 8h) - AWS and Kubernetes cluster access configured in your terminal (
aws eks update-kubeconfig --name govuk) - Terraform installed and logged in to Terraform Cloud (
terraform login)
Make sure you have assumed the role in your target environment before continuing.
Create Required AWS Infrastructure
Initialise and apply the provided Terraform infrastructure:
cd flat-file-infrastructure/terraform
terraform init -upgrade
terraform apply -var="govuk_environment=${GOVUK_ENVIRONMENT}"
This creates:
- S3 bucket:
govuk-router-routes-$GOVUK_ENVIRONMENT - IAM role:
router-routes-load-$GOVUK_ENVIRONMENT - Service account binding for
system:serviceaccount:apps:router-routes-load
Create Kubernetes service account
A service account is required for router to access the S3 bucket.
Fill in the AWS account ID and environment name in serviceaccount.yaml and apply it:
cd flat-file-infrastructure/kubernetes
# Get AWS account ID
export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
# Fill in environment name and account ID placeholders
sed -e "s/<environment>/${GOVUK_ENVIRONMENT}/g" \
-e "s/<aws-account-id>/${AWS_ACCOUNT_ID}/g" \
serviceaccount.yaml > my-serviceaccount.yaml
# Create service account in cluster
kubectl apply -f my-serviceaccount.yaml
Export Routes and Upload to S3
Routes are exported via a Kubernetes Job that runs the router in export mode and uploads the output to S3.
Fill in the environment name and current production router version:
# Set router version variable
# Replace the value with the current production router version
export ROUTER_VERSION="v183"
# Replace placeholder environment name and router version
sed -e "s/<environment>/${GOVUK_ENVIRONMENT}/g" \
-e "s/<router-version>/${ROUTER_VERSION}/g" \
export-job.yaml > my-job.yaml
Create the job:
kubectl apply -f my-job.yaml
Monitor the job:
# Check job status
kubectl get jobs -n apps router-route-export
# View logs from export step
kubectl logs -n apps job/router-route-export -c router
# View logs from upload step
kubectl logs -n apps job/router-route-export -c upload
Clean up the job after completion:
kubectl delete -f my-job.yaml
The exported routes file will be available at s3://govuk-router-routes-$GOVUK_ENVIRONMENT/routes.jsonl.
Configure Router to Load Routes from File
Update the Router app configuration in the corresponding environment's values file in govuk-helm-charts:
- name: router
...
# Add an initContainer which fetches the routes file from S3
initContainers:
- name: fetch-routes
image: 172025368201.dkr.ecr.eu-west-1.amazonaws.com/github/alphagov/govuk/govuk-toolbox-image:v6
# Fill in environment name here
command: ["sh", "-c", "HOME=/tmp aws s3 cp s3://govuk-router-routes-<!!environment!!>/routes.jsonl /tmp/routes.jsonl"]
volumeMounts:
- name: app-tmp
mountPath: /tmp
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
...
# Set ROUTER_ROUTES_FILE env var
extraEnv:
- name: ROUTER_ROUTES_FILE
value: /tmp/routes.jsonl
...
# Set service account
serviceAccount:
enabled: true
create: false
# Use the same service account you created earlier
name: router-routes-load
Reverting Back to Content Store
To revert back to loading routes from PostgreSQL:
- Revert changes made to govuk-helm-charts
- Remove Kubernetes service account with
kubectl delete -f my-serviceaccount.yaml - Empty S3 bucket:
aws s3 rm s3://govuk-router-routes-${GOVUK_ENVIRONMENT}/routes.jsonl - Perform a
terraform apply -destroy -var="govuk_environment=${GOVUK_ENVIRONMENT}"to remove AWS infrastructure