Skip to main content

Route53 Record Set

The Route53RecordSet resource allows you to create and manage DNS records (resource record sets) in AWS Route53 using native Kubernetes resources.

Overview

Route53 Record Sets define how traffic is routed to resources (servers, load balancers, etc.). It supports all standard DNS record types and advanced routing policies.

Use Cases:

  • Simple DNS records (A, AAAA, CNAME, TXT, MX)
  • Alias records for AWS resources (ELB, CloudFront, S3)
  • Weight-based, latency-based, or geolocation-based routing
  • Automatic failover with health checks
  • Declarative DNS management via GitOps

Supported Record Types

  • A - IPv4 address
  • AAAA - IPv6 address
  • CNAME - Canonical name
  • MX - Mail exchange
  • TXT - Text record
  • PTR - Pointer record
  • SRV - Service locator
  • SPF - Sender Policy Framework
  • NS - Name server
  • SOA - Start of authority
  • CAA - Certification Authority Authorization
  • NAPTR - Name Authority Pointer

Basic Examples

Simple A Record

Example:

apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: Route53RecordSet
metadata:
name: www-record
spec:
providerRef:
name: aws-provider
hostedZoneID: Z1234567890ABC
name: www.example.com
type: A
ttl: 300
resourceRecords:
- 192.0.2.1
- 192.0.2.2

CNAME Record

Example:

apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: Route53RecordSet
metadata:
name: blog-cname
spec:
providerRef:
name: aws-provider
hostedZoneID: Z1234567890ABC
name: blog.example.com
type: CNAME
ttl: 300
resourceRecords:
- www.example.com

Alias Record (Load Balancer)

Example:

apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: Route53RecordSet
metadata:
name: api-alias
spec:
providerRef:
name: aws-provider
hostedZoneID: Z1234567890ABC
name: api.example.com
type: A
aliasTarget:
hostedZoneID: Z215JYRZR1TBD5 # ELB hosted zone
dnsName: my-lb-123.us-east-1.elb.amazonaws.com
evaluateTargetHealth: true

Spec Fields

FieldTypeRequiredDescription
providerRefProviderReferenceYesReference to AWSProvider
hostedZoneIDstringYesHosted zone ID
namestringYesFull DNS name (FQDN)
typestringYesRecord type (A, AAAA, CNAME, etc.)
ttl*int64ConditionalTTL in seconds (required for non-alias)
resourceRecords[]stringConditionalRecord values (required for non-alias)
aliasTarget*AliasTargetConditionalTarget for alias records
setIdentifierstringConditionalIdentifier for routing policies
weight*int64NoWeight (0-255) for weighted routing
regionstringNoRegion for latency-based routing
geoLocation*GeoLocationNoLocation for geolocation routing
failoverstringNoPRIMARY or SECONDARY
multiValueAnswerboolNoEnable multivalue answer
healthCheckIDstringNoHealth check ID
deletionPolicystringNoDelete or Retain (default: Delete)

Routing Policies

1. Simple Routing (Default)

A single record with one or more values:

apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: Route53RecordSet
metadata:
name: simple-a-record
spec:
providerRef:
name: aws-provider
hostedZoneID: Z1234567890ABC
name: app.example.com
type: A
ttl: 300
resourceRecords:
- 192.0.2.1
- 192.0.2.2
- 192.0.2.3

2. Weighted Routing

Distributes traffic based on weights:

---
# 70% of traffic
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: Route53RecordSet
metadata:
name: app-server-1
spec:
providerRef:
name: aws-provider
hostedZoneID: Z1234567890ABC
name: app.example.com
type: A
ttl: 60
resourceRecords:
- 192.0.2.10
setIdentifier: "server-1"
weight: 70

---
# 30% of traffic
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: Route53RecordSet
metadata:
name: app-server-2
spec:
providerRef:
name: aws-provider
hostedZoneID: Z1234567890ABC
name: app.example.com
type: A
ttl: 60
resourceRecords:
- 192.0.2.20
setIdentifier: "server-2"
weight: 30

3. Latency-Based Routing

Routes to region with lowest latency:

---
# US East
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: Route53RecordSet
metadata:
name: global-us-east
spec:
providerRef:
name: aws-provider
hostedZoneID: Z1234567890ABC
name: global.example.com
type: A
ttl: 60
resourceRecords:
- 192.0.2.10
setIdentifier: "us-east-1"
region: us-east-1

---
# EU West
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: Route53RecordSet
metadata:
name: global-eu-west
spec:
providerRef:
name: aws-provider
hostedZoneID: Z1234567890ABC
name: global.example.com
type: A
ttl: 60
resourceRecords:
- 192.0.2.20
setIdentifier: "eu-west-1"
region: eu-west-1

4. Geolocation Routing

Routes based on user location:

---
# US users
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: Route53RecordSet
metadata:
name: geo-us
spec:
providerRef:
name: aws-provider
hostedZoneID: Z1234567890ABC
name: geo.example.com
type: A
ttl: 300
resourceRecords:
- 192.0.2.10
setIdentifier: "us-users"
geoLocation:
countryCode: US

---
# European users
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: Route53RecordSet
metadata:
name: geo-eu
spec:
providerRef:
name: aws-provider
hostedZoneID: Z1234567890ABC
name: geo.example.com
type: A
ttl: 300
resourceRecords:
- 192.0.2.20
setIdentifier: "eu-users"
geoLocation:
continentCode: EU

---
# Default (rest of the world)
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: Route53RecordSet
metadata:
name: geo-default
spec:
providerRef:
name: aws-provider
hostedZoneID: Z1234567890ABC
name: geo.example.com
type: A
ttl: 300
resourceRecords:
- 192.0.2.30
setIdentifier: "default-location"
geoLocation:
continentCode: "*"

5. Failover Routing

Active/passive configuration:

---
# Primary
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: Route53RecordSet
metadata:
name: failover-primary
spec:
providerRef:
name: aws-provider
hostedZoneID: Z1234567890ABC
name: app.example.com
type: A
ttl: 60
resourceRecords:
- 192.0.2.10
setIdentifier: "primary"
failover: PRIMARY
healthCheckID: abc123-health-check

---
# Secondary (backup)
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: Route53RecordSet
metadata:
name: failover-secondary
spec:
providerRef:
name: aws-provider
hostedZoneID: Z1234567890ABC
name: app.example.com
type: A
ttl: 60
resourceRecords:
- 192.0.2.20
setIdentifier: "secondary"
failover: SECONDARY

6. Multivalue Answer Routing

Returns multiple values with health checks:

apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: Route53RecordSet
metadata:
name: multivalue-1
spec:
providerRef:
name: aws-provider
hostedZoneID: Z1234567890ABC
name: multi.example.com
type: A
ttl: 60
resourceRecords:
- 192.0.2.10
setIdentifier: "server-1"
multiValueAnswer: true
healthCheckID: health-check-1

Special Records

MX (Mail Exchange)

Example:

apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: Route53RecordSet
metadata:
name: mx-record
spec:
providerRef:
name: aws-provider
hostedZoneID: Z1234567890ABC
name: example.com
type: MX
ttl: 3600
resourceRecords:
- 10 mail1.example.com
- 20 mail2.example.com
- 30 mail3.example.com

TXT (SPF, DKIM, DMARC)

Example:

---
# SPF Record
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: Route53RecordSet
metadata:
name: spf-record
spec:
providerRef:
name: aws-provider
hostedZoneID: Z1234567890ABC
name: example.com
type: TXT
ttl: 300
resourceRecords:
- '"v=spf1 include:_spf.google.com ~all"'

---
# DMARC Record
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: Route53RecordSet
metadata:
name: dmarc-record
spec:
providerRef:
name: aws-provider
hostedZoneID: Z1234567890ABC
name: _dmarc.example.com
type: TXT
ttl: 300
resourceRecords:
- '"v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com"'

SRV (Service Records)

Example:

apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: Route53RecordSet
metadata:
name: srv-record
spec:
providerRef:
name: aws-provider
hostedZoneID: Z1234567890ABC
name: _service._tcp.example.com
type: SRV
ttl: 300
resourceRecords:
- 10 60 5060 sipserver.example.com

Alias Records for AWS Resources

Application Load Balancer (ALB)

Example:

apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: Route53RecordSet
metadata:
name: alb-alias
spec:
providerRef:
name: aws-provider
hostedZoneID: Z1234567890ABC
name: app.example.com
type: A
aliasTarget:
hostedZoneID: Z35SXDOTRQ7X7K # ALB hosted zone (us-east-1)
dnsName: my-alb-123.us-east-1.elb.amazonaws.com
evaluateTargetHealth: true

CloudFront Distribution

Example:

apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: Route53RecordSet
metadata:
name: cloudfront-alias
spec:
providerRef:
name: aws-provider
hostedZoneID: Z1234567890ABC
name: cdn.example.com
type: A
aliasTarget:
hostedZoneID: Z2FDTNDATAQYW2 # CloudFront hosted zone
dnsName: d123abc.cloudfront.net
evaluateTargetHealth: false

S3 Website Endpoint

Example:

apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: Route53RecordSet
metadata:
name: s3-website-alias
spec:
providerRef:
name: aws-provider
hostedZoneID: Z1234567890ABC
name: static.example.com
type: A
aliasTarget:
hostedZoneID: Z3AQBSTGFYJSTF # S3 website hosted zone (us-east-1)
dnsName: mybucket.s3-website-us-east-1.amazonaws.com
evaluateTargetHealth: false

Operations

Create Record

Command:

kubectl apply -f recordset.yaml

Check Status

Command:

# List records
kubectl get route53recordset
kubectl get r53rs # shortname

# Details
kubectl describe route53recordset www-record

# View change status
kubectl get route53recordset www-record -o jsonpath='{.status.changeStatus}'

Update Record

Example:

spec:
ttl: 600 # Update TTL
resourceRecords:
- 192.0.2.100 # New IP

Command:

kubectl apply -f recordset.yaml

Delete Record

Command:

kubectl delete route53recordset www-record

Troubleshooting

Record Not Ready

Solutions:

  1. Check hosted zone exists
  2. Check IAM permissions
  3. Validate record type and values
  4. Check controller logs

Validation Error

Problem: Alias target and resource records cannot coexist

Solution: Use only one:

# Either aliasTarget
spec:
aliasTarget:
hostedZoneID: Z123
dnsName: lb.example.com

# OR resourceRecords + ttl
spec:
ttl: 300
resourceRecords:
- 192.0.2.1

Change Status PENDING

Normal: DNS changes can take up to 60 seconds to propagate

Check:

kubectl get route53recordset my-record -w

IAM Permissions

Example:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets",
"route53:GetChange",
"route53:ListResourceRecordSets"
],
"Resource": [
"arn:aws:route53:::hostedzone/*",
"arn:aws:route53:::change/*"
]
},
{
"Effect": "Allow",
"Action": [
"route53:GetHostedZone",
"route53:ListHostedZones"
],
"Resource": "*"
}
]
}

Best Practices

Best Practices
  • Set appropriate TTL — Development: 60-300s, Production: 300-3600s, reduce before changes
  • Use alias records for AWS resources — Free, faster resolution for ALB/CloudFront/S3
  • Implement health checks — Enable failover routing for high availability
  • Document record purposes — Clear naming conventions and descriptions
  • Use routing policies wisely — Simple for basic, weighted for A/B, failover for DR

AWS Resource Hosted Zone IDs

ELB/ALB by Region

  • us-east-1: Z35SXDOTRQ7X7K
  • us-west-2: Z1H1FL5HABSF5
  • eu-west-1: Z32O12XQLNTSW2

CloudFront

  • Global: Z2FDTNDATAQYW2

S3 Website by Region

  • us-east-1: Z3AQBSTGFYJSTF
  • us-west-2: Z3BJ6K6RIION7M

Complete list in AWS documentation

References