Amazon EKSのコミュニティアドオンにexternal-dnsが追加されたのでインストールしてみた

Amazon EKSのコミュニティアドオンにexternal-dnsが追加されたのでインストールしてみた

Clock Icon2025.04.08

コミュニティアドオンに以下が追加されました。

  • kube-state-metrics
  • cert-manager
  • prometheus-node-exporter
  • external-dns

コミュニティアドオンについては、以下をご確認ください。

https://dev.classmethod.jp/articles/eks-community-addon/

2025年1月時点で metrics-server のみだったのが前述のアドオンが追加された形です。

https://aws.amazon.com/jp/about-aws/whats-new/2025/03/amazon-eks-new-catalog-community-add-ons/

今回はExternalDNSをインストールしてみます。

前提

  • EKS Auto Modeを有効化した環境
  • AWSリソースはTerraformを使って定義

ExternalDNSをインストールする

EKS Moduleのcluster_addonsでExternalDNSを定義しています。

Service Accountは、ExternalDNSのデフォルトのものを利用します。

EKS Pod Identityを使って、PodにIAMアクセス許可を付与しています。

後半部分は、ExternalDNSがRoute53にレコードを登録するためのIAMロールの定義です。

main.tf
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アドオンがインストールされていることを確認できます。

vscode-drop-1744107483615-u99d8rof1tm.png

デプロイされたリソースの確認

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でデプロイする際には、以下のようにproviderAWS_DEFAULT_REGIONを指定する必要がありました。

values.yaml
provider:
  name: aws
env:
  - name: AWS_DEFAULT_REGION
    value: us-east-1 # change to region where EKS is installed

アドオンでデプロイしてみたところ、こちらの設定は自動的に設定されました。

AWS_DEFAULT_REGIONはClusterをデプロイしたリージョンで設定されました。

動作確認

以下の手順を参考にレコードを登録できる確認します。

Verify ExternalDNS works (Service example) - Setting up ExternalDNS for Services on AWS - external-dns

テスト用のマニフェストを作成します。

Route53レコードは、アノテーションexternal-dns.alpha.kubernetes.io/hostnameに対応する名前で登録されます。

nginx.example.com部分は、自身のホスト名に置き換えてください。

nginx.yaml
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をインストールしました。

比較すると手順が簡単になったことが分かりやすいと思います。ご興味があればご確認ください。

https://dev.classmethod.jp/articles/eks-gitlab-alb-external-dns/

以上、AWS事業本部の佐藤(@chari7311)でした。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.