🦔

ExternalDNSを使ってKubernetesからDNSレコードを登録する

2022/03/14に公開

ExternalDNSは公開されたIngressやServiceを見ていい感じにDNSレコードを登録してくれるやつです。

https://github.com/kubernetes-sigs/external-dns

たとえば、以下のようなIngressを公開することで、 myservice.foo.org のホスト名に対するAレコードを登録することができます。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-myservicea
spec:
  rules:
  - host: myservice.foo.org
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: myservicea
            port:
              number: 80
  ingressClassName: nginx

さまざまなクラウドプロバイダーに対応しているのでとても便利。

(v0.10.2時点で対応しているクラウドプロバイダー)

今回はIngressで公開したホスト名に対するDNSレコードをAWS Route53に登録していこうと思います。

external-dnsをデプロイする

今回はHelmを使ってexternal-dnsをクラスターにデプロイしていきます。

external-dnsリポジトリをHelmに追加

$ helm repo add external-dns https://kubernetes-sigs.github.io/external-dns/

chartをインストールする際の設定をvalues.yamlとして書き起こしています。

serviceAccount:
  create: true

sources:
  - ingress
policy: sync
registry: txt
txtOwnerId: rnakamine
env:
  - name: AWS_ACCESS_KEY_ID
    valueFrom:
      secretKeyRef:
        key: aws_access_key_id
        name: external-dns
  - name: AWS_SECRET_ACCESS_KEY
    valueFrom:
      secretKeyRef:
        key: aws_secret_access_key
        name: external-dns

設定の詳細は以下の通りです。

Parameter Description
serviceAccount.create 新しいサービスアカウントを作成する
sources 監視されるKubernetesリソース
policy DNSレコードがKubernetesとプロバイダー間でどのように同期されるか。sync, upsert-only
registry レジストリタイプ。txt, noop
txtOwnerId TXTレジストリの識別子
env external-dnsのコンテナの環境変数。SecretとConfigMapも使える。

今回はKuberenetes Clusterを別のクラウドプロバイダーで構築しているため、Route53へのアクセスは専用のIAM Userを作成して、そのCredencialsをSecretとして登録しています。(他に良い方法があれば....)

Route53を操作するIAM Policyは以下のように設定しています。

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

chartのインストール

上記で作成した values.yamlを指定しつつhelmコマンドでchartをインストールします。

$ helm upgrade --install external-dns external-dns/external-dns -f values.yaml --namespace external-dns

DNSレコードを追加する

Deployment, Serviceの作成

まずはIngressで公開するServiceとDeploymentを以下のように作成。今回はnginxのコンテナを使ってリクエストを受け付けるようにしました。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sample
  template:
    metadata:
      labels:
        app: sample
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80
              protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
  name: blog
spec:
  selector:
    app: blog
  ports:
    - name: http
      protocol: TCP
      port: 80

Ingressの作成

次にIngressを作成し、rnakamine.com というホスト名をRoute53に登録するようにします。今回はIngressコントローラーに NGINX Ingress Controller を使用しています。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: sample
spec:
  ingressClassName: nginx
  rules:
  - host: rnakamine.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: sample
            port:
              number: 80

これらをKubernetes上にapplyするとExternalDNSにより rnakamine.com のAレコードがRoute53に登録され、上記で作成したnginxのコンテナが入ったPodにアクセスすることができるようになります。

nginx

まとめ

ExternalDNSはを使うことでKubernetes上のServiceリソースやIngressリソースを監視しつつDNSレコードを動的に管理できるようになるのでかなり便利です。

Discussion