Kubernetesでアプリケーションを運用していると、Service や Ingress に紐づくDNSレコードの管理が必要になります。このDNSレコードの作成・更新・削除を自動化できれば、運用の手間を大幅に削減できます。
本記事では、KubernetesリソースからAWS Route53のDNSレコードを自動的に作成・管理するための「external-dns」の使い方を解説します。
レコードの管理を自動化するには、Crossplaneなども選択肢に入りますが、これはクラウドベンダーごとにコンポジションというマッピングルールを作らないといけませんが、external-dnsを使うと、AWS Route53だけでなく様々なネームサーバーに統一的な方法で対応できるので、様々なネームサーバーに対応したいときにはかなり便利です。
前提条件
- Kubernetesクラスターがセットアップされていること
- 必要なコマンドツールがインストールされていること
- kubectl
- helm
- aws
- dig
external-dnsとAWS Route53について
external-dnsとは
external-dnsは、Kubernetesリソースを監視し、DNSレコードを自動的に更新するツールです。Service、Ingress、Gatewayなどのリソースを監視し、設定に基づいてDNSレコードを作成・更新・削除します。
AWS Route53とは
AWS Route53は、AWSが提供するマネージドDNSサービスです。高可用性と拡張性を備えており、複数のルーティングポリシーやヘルスチェックなどの機能を提供します。
セットアップ手順
1. AWS Route53 Hosted Zoneの作成
まず、AWSの認証情報を環境変数に設定します:
export AWS_ACCESS_KEY_ID=AKIAXXXXXXXXXXXXXXXX
export AWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
認証情報が正しく設定されているか確認します:
aws sts get-caller-identity
次に、AWS Route53でHosted Zoneを作成します:
aws route53 create-hosted-zone --name example-tutorial.com --caller-reference external-dns-tutorial
2. external-dnsのインストール
external-dnsのHelmチャートは、kubernetes-sigsが提供しているものがありますが、ここではBitnamiが提供しているものを使用します。こちらのほうがオプションが多く、AWS Route53の設定が簡単にできるためです。
helm install external-dns \
--set provider=aws \
--set aws.zoneType=public \
--set aws.credentials.accessKey="$AWS_ACCESS_KEY_ID" \
--set aws.credentials.secretKey="$AWS_SECRET_ACCESS_KEY" \
--set txtOwnerId=EXAMPLE-ZONE-ID123 \
--set "domainFilters[0]=example-tutorial.com" \
--set policy=sync \
--set "sources[0]=crd" \
--set crd.create=true \
--set crd.apiversion=externaldns.k8s.io/v1alpha1 \
--set crd.kind=DNSEndpoint \
oci://registry-1.docker.io/bitnamicharts/external-dns
インストールオプションの説明
オプション | 説明 |
---|---|
provider=aws |
AWS Route53を使用することを指定 |
aws.zoneType=public |
パブリックゾーンを使用することを指定 |
aws.credentials.accessKey |
AWSのアクセスキー |
aws.credentials.secretKey |
AWSのシークレットキー |
txtOwnerId |
TXTレコードのオーナーID |
domainFilters[0] |
監視対象のドメイン |
policy=sync |
DNSレコード同期ポリシー |
sources[0]=crd |
CRDを使用することを指定 |
crd.create=true |
CRDの作成を有効化 |
crd.apiversion |
CRDのAPIバージョン |
crd.kind |
CRDの種類 |
インストール後、external-dnsが正常に起動していることを確認します:
kubectl logs -l app.kubernetes.io/name=external-dns -f
次のようなログが表示されれば、正常に起動しています:
time="2024-11-06T05:12:29Z" level=info msg="Instantiating new Kubernetes client"
time="2024-11-06T05:12:29Z" level=info msg="Using inCluster-config based on serviceaccount-token"
time="2024-11-06T05:12:29Z" level=info msg="Created Kubernetes client https://10.43.0.1:443"
time="2024-11-06T05:12:31Z" level=info msg="Applying provider record filter for domains: [example-tutorial.com. .example-tutorial.com.]"
external-dnsにレコードを作らせてみる
external-dnsによって、KubernetesリソースからDNSレコードが作成されることを確認します。
external-dnsは、Service、Ingress、Gatewayなどのリソースを監視し、DNSレコードを作成します。今回はお試しなので、実体リソースが一切不要なCRDのDNSEndpointを使用します。
1. テストレコードの作成
CRDを使用してDNSレコードを作成してみましょう。次のマニフェストを作成します:
apiVersion: externaldns.k8s.io/v1alpha1
kind: DNSEndpoint
metadata:
name: test.example-tutorial.com
spec:
endpoints:
- dnsName: test.example-tutorial.com
recordTTL: 180
recordType: A
targets:
- 127.0.0.1
このマニフェストを適用します:
kubectl apply -f test.example-tutorial.com.yaml
2. DNSレコードの確認
DNSレコードが作成されたことを確認します。 @ns-1694.awsdns-19.co.uk
は、AWS Route53のネームサーバーのホスト名です。この部分は、前の手順で作成したHosted Zoneによって異なりますので、ご自身の環境に合わせてください。
まず、Aレコードを確認します:
dig @ns-1694.awsdns-19.co.uk +noall +answer -t A test.example-tutorial.com
正常に作成されていれば、次のような結果が表示されます:
test.example-tutorial.com. 180 IN A 127.0.0.1
3. TXTレコードの確認
また、TXTレコードも作成されていることを確認します:
dig @ns-1694.awsdns-19.co.uk +noall +answer -t TXT test.example-tutorial.com
結果:
test.example-tutorial.com. 300 IN TXT "heritage=external-dns,external-dns/owner=EXAMPLE-ZONE-ID123,external-dns/resource=crd/default/test.example-tutorial.com"
このTXTレコードは、external-dnsが管理のために作成したものです。この管理情報には、次の情報が含まれています:
-
heritage=external-dns
- このDNSレコードがexternal-dnsによって管理されていることを示す
-
external-dns/owner=EXAMPLE-ZONE-ID123
- 特定のexternal-dnsインスタンスを識別するためのownerID
- 複数インスタンス間の競合を防止
-
external-dns/resource=crd/default/test.example-tutorial.com
- DNSレコードの元となったKubernetesリソースの情報
- この例では
default
ネームスペースのtest.example-tutorial.com
CRDを参照
こうした管理情報はTXTレコードとして公開されてしまいますが、暗号化することも可能らしいです。このへんの機能は、試してみたらまた記事にしたいと思います。
掃除
レコードの削除
DNSレコードを削除するには、CRDリソースを削除します:
kubectl delete -f test.example-tutorial.com.yaml
しばらくすると、external-dnsがDNSレコードを削除します。external-dnsのログを確認してください。
time="2024-11-06T05:48:24Z" level=info msg="Desired change: DELETE a-test.example-tutorial.com TXT" profile=default zoneID=/hostedzone/Z08033563HFN15GSXJ766 zoneName=example-tutorial.com.
time="2024-11-06T05:48:24Z" level=info msg="Desired change: DELETE test.example-tutorial.com A" profile=default zoneID=/hostedzone/Z08033563HFN15GSXJ766 zoneName=example-tutorial.com.
time="2024-11-06T05:48:24Z" level=info msg="Desired change: DELETE test.example-tutorial.com TXT" profile=default zoneID=/hostedzone/Z08033563HFN15GSXJ766 zoneName=example-tutorial.com.
time="2024-11-06T05:48:24Z" level=info msg="3 record(s) were successfully updated" profile=default zoneID=/hostedzone/Z08033563HFN15GSXJ766 zoneName=example-tutorial.com.
DNSレコードが削除されたことを確認しておきます。
dig @ns-1694.awsdns-19.co.uk +noall +answer -t A test.example-tutorial.com
external-dnsの削除
Helmリリースを削除します:
helm uninstall external-dns
3. Hosted Zoneの削除
まず、Hosted Zoneの一覧を確認します:
aws route53 list-hosted-zones
確認したIDを使用してHosted Zoneを削除します:
aws route53 delete-hosted-zone --id Z08033563HFN15GSXJ766
まとめ
以上です!本記事では、external-dnsとAWS Route53を使用して、KubernetesリソースからDNSレコードを自動的に管理する方法を解説しました。
実践で使うには、他にもいろいろと考慮する事項があると思いますが、external-dnsの取っ掛かりとしてこのチュートリアルがお役に立てば嬉しいです!