Amazon EKSのコミュニティアドオンにexternal-dnsが追加されたのでインストールしてみた
コミュニティアドオンに以下が追加されました。
- kube-state-metrics
- cert-manager
- prometheus-node-exporter
- external-dns
コミュニティアドオンについては、以下をご確認ください。
2025年1月時点で metrics-server のみだったのが前述のアドオンが追加された形です。
今回はExternalDNSをインストールしてみます。
前提
- EKS Auto Modeを有効化した環境
- AWSリソースはTerraformを使って定義
ExternalDNSをインストールする
EKS Moduleのcluster_addons
でExternalDNSを定義しています。
Service Accountは、ExternalDNSのデフォルトのものを利用します。
EKS Pod Identityを使って、PodにIAMアクセス許可を付与しています。
後半部分は、ExternalDNSがRoute53にレコードを登録するためのIAMロールの定義です。
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 20.34.0"
cluster_compute_config = {
enabled = true
node_pools = ["general-purpose"]
}
# 省略
cluster_addons = {
# ExternalDNSアドオン
external-dns = {
most_recent = true
pod_identity_association = {
role_arn = aws_iam_role.external_dns.arn
# デフォルトのSA名
# https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/community-addons.html
service_account = "external-dns"
}
}
}
# 省略
}
### ExternalDNS用IAM Role
resource "aws_iam_role" "external_dns" {
name = "${var.prefix}-external-dns"
assume_role_policy = data.aws_iam_policy_document.eks_pod_assume_role.json
tags = local.tags
}
data "aws_iam_policy_document" "eks_pod_assume_role" {
statement {
actions = [
"sts:AssumeRole",
"sts:TagSession"
]
effect = "Allow"
principals {
type = "Service"
identifiers = ["pods.eks.amazonaws.com"]
}
}
}
resource "aws_iam_policy" "external_dns_policy" {
name = "${var.prefix}-external-dns-policy"
description = "Policy for External DNS to manage Route 53 records"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"route53:ChangeResourceRecordSets"
]
Resource = [
"arn:aws:route53:::hostedzone/<Route53ホステッドゾーンID>"
]
},
{
Effect = "Allow"
Action = [
"route53:ListHostedZones",
"route53:ListResourceRecordSets",
"route53:ListTagsForResource"
]
Resource = [
"*"
]
}
]
})
}
resource "aws_iam_role_policy_attachment" "external_dns" {
role = aws_iam_role.external_dns.name
policy_arn = aws_iam_policy.external_dns_policy.arn
}
Terraformを実行してリソースを作成します。
terraform init
terraform plan
terraform apply
コンソールからもExternalDNSアドオンがインストールされていることを確認できます。
デプロイされたリソースの確認
Deploymentsを確認してみます。
kubectl describe deployments external-dns
Name: external-dns
Namespace: external-dns
CreationTimestamp: Tue, 08 Apr 2025 18:14:17 +0900
Labels: app.kubernetes.io/instance=external-dns
app.kubernetes.io/managed-by=Helm
app.kubernetes.io/name=external-dns
app.kubernetes.io/version=0.15.1
helm.sh/chart=external-dns-1.15.2
Annotations: deployment.kubernetes.io/revision: 1
Selector: app.kubernetes.io/instance=external-dns,app.kubernetes.io/name=external-dns
Replicas: 1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType: Recreate
MinReadySeconds: 0
Pod Template:
Labels: app.kubernetes.io/instance=external-dns
app.kubernetes.io/name=external-dns
Annotations: eks.amazonaws.com/timestamp: 2025-04-08 09:14:17.245356898 +0000 UTC m=+1137.669895953
Service Account: external-dns
Containers:
external-dns:
Image: 1234567890.dkr.ecr.us-east-2.amazonaws.com/eks/external-dns:v0.16.1-eksbuild.2
Port: 7979/TCP
Host Port: 0/TCP
Args:
--log-level=info
--log-format=text
--interval=1m
--source=service
--source=ingress
--policy=sync
--registry=txt
--txt-owner-id=gitlab
--provider=aws
Limits:
memory: 64Mi
Requests:
cpu: 10m
memory: 32Mi
Liveness: http-get http://:http/healthz delay=10s timeout=5s period=10s #success=1 #failure=2
Readiness: http-get http://:http/healthz delay=5s timeout=5s period=10s #success=1 #failure=6
Environment:
AWS_DEFAULT_REGION: us-east-2
Mounts: <none>
Volumes: <none>
Priority Class Name: system-cluster-critical
Node-Selectors: <none>
Tolerations: CriticalAddonsOnly op=Exists
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: external-dns-6d86bb649c (1/1 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 17m deployment-controller Scaled up replica set external-dns-6d86bb649c to 1
Helmでデプロイする際には、以下のようにprovider
やAWS_DEFAULT_REGION
を指定する必要がありました。
provider:
name: aws
env:
- name: AWS_DEFAULT_REGION
value: us-east-1 # change to region where EKS is installed
アドオンでデプロイしてみたところ、こちらの設定は自動的に設定されました。
AWS_DEFAULT_REGION
はClusterをデプロイしたリージョンで設定されました。
動作確認
以下の手順を参考にレコードを登録できる確認します。
テスト用のマニフェストを作成します。
Route53レコードは、アノテーションexternal-dns.alpha.kubernetes.io/hostname
に対応する名前で登録されます。
nginx.example.com
部分は、自身のホスト名に置き換えてください。
apiVersion: v1
kind: Service
metadata:
name: nginx
annotations:
external-dns.alpha.kubernetes.io/hostname: nginx.example.com
spec:
type: LoadBalancer
ports:
- port: 80
name: http
targetPort: 80
selector:
app: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx
name: nginx
ports:
- containerPort: 80
name: http
default
ネームスペースにリソースを作成します。
kubectl create --filename nginx.yaml --namespace default
AWS CLIで登録状況を確認するため、以下のコマンドでゾーンIDを確認します。
aws route53 list-hosted-zones
ゾーンIDとホスト名を設定して、レコードの登録状況を確認するコマンドを実行します。
aws route53 list-resource-record-sets --output json --hosted-zone-id <ゾーンID> \
--query "ResourceRecordSets[?Name == 'nginx.example.com.']|[?Type == 'A']"
以下のようにレコードが作成されていることを確認できました。
[
{
"Name": "nginx.example.com",
"Type": "A",
"AliasTarget": {
"HostedZoneId": "<ゾーンID>",
"DNSName": "k8s-default-nginx-1234567890.elb.us-east-2.amazonaws.com.",
"EvaluateTargetHealth": true
}å
}
]
おわりに
インストール作業が楽になるため、コミュニティアドオンの拡張はありがたいですね。
以前Helmを使って、ExternlDNSをインストールしました。
比較すると手順が簡単になったことが分かりやすいと思います。ご興味があればご確認ください。
以上、AWS事業本部の佐藤(@chari7311)でした。