Last updated: 8 Sep 2026
JobRequest Architecture
System Components
- govuk-job-request-operator:
This includes:
- Custom Resource Defitinitions
(CRDs)
for JobRequest (short name
jr) and JobRequestReview (short namejrr) resources - Kubernetes Operator which is responsible for reconcilling the JobRequest and JobRequestReview resources
- Kubernetes Mutating Admission Policy which is responsible for validating, and adding the AWS ARN of the requesting user into annotations on the JobRequest and JobRequestReview during admission
- Garbage collection to clean up JobRequest and JobRequestReview resoureces more than 30 days old
- Custom Resource Defitinitions
(CRDs)
for JobRequest (short name
- OPA Gatekeeper policies responsible for validating API requests to create/update JobRequest and JobRequestReview resources, and providing useful error messages to the end user if the request is denied.
- govuk-cli: A command line interface with a jobrequest subcommand which is the primary interface developers are expected to use to create and review JobRequests. This also does validation prior to making create requests to the Kubernetes API to give the most friendly error messages possible.
Expected usage
The following describes the intended happy path from creation of a JobRequest to Job completion.
- User A uses
govuk-clito create a JobRequest, it prints out the CLI command which can be used to review the JobRequest, and waits to show the logs from the Job that will be created later. - User A sends User B the printed out CLI command to run in order to review the request.
- User B runs the CLI command, reads and reviews the command intended to run, chooses to approve or reject it, then
govuk-clicreates a JobRequestReview. - Review outcome: a. If user B rejects the JobRequest, assuming user A is still following the logs, user A sees a message telling them the request was rejected. This flow ends here. b. If user B approves the JobRequest then continue this process
- The JobRequest operator changes the Status of the JobRequest to approved.
- The JobRequest operator reads the pod spec it needs to create from the target resource specified in the JobRequest
- The JobRequest operator creates a Kubernetes Job from the pod spec retrieved in the previous step, overriding the command to be the one approved in the JobRequest
- The JobRequest operator updates the Status of the JobRequest to include the name of the Job that was created
- The govuk-cli command that was run in step 1. sees the Job has been created, informs user A, and starts printing out the logs of the Job as they are produced.
- The JobRequest operator watches the status of the Job and updates the JobRequest status to include the current state of the Job.
- When the status of the Job reaches a terminal state, the govuk-cli stops following the logs and informs User A the Job has completed.
Sequence Diagram for an Approved JobRequest
sequenceDiagram
actor Requester
actor Reviewer
participant k8sAPI as Kubernetes API
participant Operator
Requester->>k8sAPI: `govuk-cli create jobrequest... --follow`
k8sAPI->>Operator: Job Request Created
Requester->>Reviewer: Please review my request
Reviewer->>k8sAPI: `govuk-cli jobrequest review...` Approved
k8sAPI->>Operator: JobRequestReview Created
Operator->>k8sAPI: Create Job
k8sAPI->>Requester: Logs
k8sAPI->>Requester: More Logs
k8sAPI->>Requester: Job Complete
Sequence Diagram for a Rejected JobRequest
sequenceDiagram
actor Requester
actor Reviewer
participant k8sAPI as Kubernetes API
participant Operator
Requester->>k8sAPI: `govuk-cli create jobrequest... --follow`
k8sAPI->>Operator: JobRequest Created
Requester->>Reviewer: Please review my request
Reviewer->>k8sAPI: `govuk-cli jobrequest review...` Rejected
k8sAPI->>Operator: Rejected JobRequestReview Created
Operator->>k8sAPI: Update JobRequest to Rejected
k8sAPI->>Requester: JobRequest Rejected
Garbage Collection
Any time a JobRequest or JobRequestReview resource is presented for reconcilliation, if it has lived longer than the TTL duration (which is set for 720 hours (30 days)), it will be deleted.
The Kubernetes Controller Runtime
configuration
includes a SyncPeriod, any resources managed by the controller runtime will be
presented to the operator every time the SyncPeriod has elapsed.
The SyncPeriod in the is configurable in the
govuk-job-request-operator
by setting the --resource-ttl flag.
Architecture Diagrams
JobRequest state diagram
stateDiagram
state "''" as NoState
[*] --> NoState
NoState --> Malformed
NoState --> Pending
Pending --> Rejected
Pending --> Approved
Approved --> Started
Approved --> Malformed
Started --> Complete
Started --> Failed
Started --> Malformed
Malformed --> [*]
Complete --> [*]
Failed --> [*]
JobRequestReview state diagram
stateDiagram
[*] --> Approved
[*] --> Rejected
Approved --> JobRequestNotFound
Approved --> JobRequestMalformed
Approved --> Conflict
Rejected --> JobRequestNotFound
Rejected --> JobRequestMalformed
Rejected --> Conflict
Approved --> [*]
Rejected --> [*]
JobRequestNotFound --> [*]
JobRequestMalformed --> [*]
Conflict --> [*]
Creating a JobRequest Flowchart
flowchart TD
RequesterA@{ shape: person }
RequesterB@{ shape: person }
govuk-cli
RequesterA--govuk-cli jobrequest create ...-->govuk-cli
govuk-cli--Create JobRequest-->k8sAPI
RequesterB--Create JobRequest-->k8sAPI
subgraph k8s[Kubernetes]
direction TD
k8sAPI[Kubernetes API]
MutatingAdmissionPolicy
gatekeeper[OPA Gatekeeper]
govuk-job-request-operator[Operator JobRequest controller]
etcd[(Etcd)]
k8sAPI-- Create JobRequest -->MutatingAdmissionPolicy
MutatingAdmissionPolicy--Create JobRequest-->gatekeeper
gatekeeper--Create JobRequest-->etcd
etcd--Created JobRequest-->govuk-job-request-operator
govuk-job-request-operator-->validateJobRequest{Validate}
validateJobRequest--valid\n\nSet JobRequest Pending-->k8sAPI
validateJobRequest--invalid\n\nSet JobRequest Malformed-->k8sAPI
end
Reviewing a JobRequest Flowchart
flowchart TD
RequesterA@{ shape: person }
RequesterB@{ shape: person }
govuk-cli
RequesterA--govuk-cli jobrequest review ...-->govuk-cli
govuk-cli--Create JobRequestReview-->k8sAPI
RequesterB--Create JobRequestReview-->k8sAPI
subgraph k8s[Kubernetes]
direction TD
k8sAPI[Kubernetes API]
MutatingAdmissionPolicy
gatekeeper[OPA Gatekeeper]
govuk-job-request-operator[Operator JobRequestReview controller]
etcd[(Etcd)]
k8sAPI-- Create JobRequestReview -->MutatingAdmissionPolicy
MutatingAdmissionPolicy-- Create JobRequestReview -->gatekeeper
gatekeeper-- Create JobRequestReview -->etcd
etcd-- Created JobRequestReview -->govuk-job-request-operator
govuk-job-request-operator-->validateJobRequestReview{Validate}
validateJobRequestReview-- invalid\n\nSet JobRequestReview Malformed -->k8sAPI
validateJobRequestReview-- valid -->jobRequestFound{JobRequest Exists?}
jobRequestFound-- found\n\nSet state of JobRequestReview to Approved/Rejected\n\nSet state of JobRequest to Approved/Rejected -->k8sAPI
jobRequestFound-- not-found\n\nSet state of JobRequestReview toJobRequestNotFound -->k8sAPI
end
After a JobRequest has been Approved Flowchart
flowchart TD
subgraph k8s[Kubernetes]
direction TD
k8sAPI[Kubernetes API]
MutatingAdmissionPolicy
gatekeeper[OPA Gatekeeper]
govuk-job-request-operator[Operator JobRequest controller]
etcd[(Etcd)]
etcd-- 1. JobRequest Updated -->govuk-job-request-operator
govuk-job-request-operator<-- 2. Get Pod/Deployment -->k8sAPI
govuk-job-request-operator-- 3. Create Job -->k8sAPI
k8sAPI-- 3. Create Job -->etcd
govuk-job-request-operator-- 4. Watch Job -->k8sAPI
etcd-- 5. Job State Change --> govuk-job-request-operator
govuk-job-request-operator-- 5. Update JobRequest with Job State -->k8sAPI
k8sAPI-- 5. Update JobRequest -->MutatingAdmissionPolicy
MutatingAdmissionPolicy-- 5. Update JobRequest -->gatekeeper
gatekeeper-- 5. Update JobRequest -->etcd
end