External DNS for K8s
External DNS is a great tool for automating DNS entries for service exposed externally via Ingress, Service or Gateway API resource. It supports most common DNS providers, and in this example my domain is configured in AWS Route53 and will be using Envoy Gateway to expose my application externally.
Configure External DNS
There are 2 parts to installing and configuring external DNS. In this example, I will demonstrate configuring EKS cluster to manage domains configured on Route53
- Create IAM policy and Pod Identity association
- Install External-DNS by passing necessary values
IAM policy and pod identity
Step 1. Create IAM policy with necessary permissions. Note that this policy is open to manage all zones, ideally restrict policy to respective ZoneID.
IAM policy external_dns_iam_policy allowing DNS updates.
{
"Version" : "2012-10-17",
"Statement" : [
{
"Effect" : "Allow",
"Action" : [
"route53:ChangeResourceRecordSets"
],
"Resource" : [
"arn:aws:route53:::hostedzone/*"
]
},
{
"Effect" : "Allow",
"Action" : [
"route53:ListHostedZones",
"route53:ListResourceRecordSets"
],
"Resource" : [
"*"
]
}
]
}
external-dns-controller
with Pod Identity trust policy.
Trust policy for Pod Identity service
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "pods.eks.amazonaws.com"
},
"Action": [
"sts:TagSession",
"sts:AssumeRole"
]
}
]
}
external_dns_iam_policy
to IAM role external-dns-controller
Step 4. Create Pod Identity association for Namespace external-dns
, ServiceAccount external-dns-controller
to the role created.
Step 5. Install External DNS using Helm charts with custom values.yaml
.
serviceAccount:
name: external-dns-controller
sources:
- ingress
- gateway-httproute
domainFilters:
- vettom.online
txtOwnerId: "eks-demo-cluster"
- serviceAccount : Specify service account mentioned while creating Pod Identity association
- sources: : Supports Ingress, httproute(gateway API) or service.
- domainFilters : List of domains ext-dns will manage entries for.
- txtOwnerId : Unique string allows you to distinguish between multiple instances of ExternalDNS managing DNS records.
helm install external-dns external-dns -n external-dns \
--create-namespace --repo https://kubernetes-sigs.github.io/external-dns \
--version 1.15.0 -f ./values.yaml
Step 6. Deploy application with Httproute
and validate. Sample application can be found at aws-eks-terraform/EKS-Cluster-generic/Sample-app repo
Terraform code for IAM
Below terraform code will create IAM role with POD ID trust, create POD ID association, and attaches policy allowing DNS modification.
Pod ID trust policy
data "aws_iam_policy_document" "podidentity" {
statement {
effect = "Allow"
principals {
type = "Service"
identifiers = ["pods.eks.amazonaws.com"]
}
actions = [
"sts:AssumeRole",
"sts:TagSession"
]
}
}
# Create IAM role with trust policy
resource "aws_iam_role" "externaldns_iam_role" {
name = "external-dns-controller"
assume_role_policy = data.aws_iam_policy_document.podidentity.json
}
# Associate Identity allowing serviceAccount external-dns-controller in NS external-dns
resource "aws_eks_pod_identity_association" "externaldns" {
cluster_name = module.eks.cluster_name
namespace = "external-dns"
service_account = "external-dns-controller"
role_arn = aws_iam_role.externaldns_iam_role.arn
}
# IAM policy to allow Route53 zone updates
resource "aws_iam_policy" "external_dns_iam_policy" {
name = "ExternalDNSControllerIAMPolicy"
policy = jsonencode(
{
"Version" : "2012-10-17",
"Statement" : [
{
"Effect" : "Allow",
"Action" : [
"route53:ChangeResourceRecordSets"
],
"Resource" : [
"arn:aws:route53:::hostedzone/*"
]
},
{
"Effect" : "Allow",
"Action" : [
"route53:ListHostedZones",
"route53:ListResourceRecordSets"
],
"Resource" : [
"*"
]
}
]
}
)
}
# Attach policy to IAM role.
resource "aws_iam_role_policy_attachment" "externaldns_policy_attachement" {
role = aws_iam_role.externaldns_iam_role.name
policy_arn = aws_iam_policy.external_dns_iam_policy.arn
}