はじめに
3-shakeのSreake事業部に所属する早川(@bells17)です。今回は、Kubernetesリソースと紐づくDNSレコードを自動で管理するツール「ExternalDNS」について解説します。
ExternalDNSを使用すると、Kubernetesのリソース状態に応じて外部DNSプロバイダのレコードを自動的に検出し、作成・更新・削除を行うことができます。
例えば、Gateway APIやIngressといったリソースを作成するとバックエンドで動作するコントローラーが紐づけるロードバランサーのIPの払い出しなどを行いますが、ExternalDNSは払い出されたIPアドレスやGateway API、Ingressといったリソースに設定されたドメインを読み取り、あらかじめ設定された外部DNSプロバイダにレコードを追加してくれます。
デフォルトで使用できる外部DNSプロバイダはこちらにまとめられています。また、Webhookを利用して独自のプロバイダを追加できるようになっています。
独自プロバイダについてはこちらに一覧があります。一覧には、例えばみなさんもご存知の「さくらのクラウド」などもあります。
ExternalDNSはKubernetesコミュニティのsig-networkによって管理されています。
ExternalDNSを導入する
ExternalDNSの導入について、今回はGKEでCloud DNSを利用するケースを参考に紹介します。あらかじめ下記を用意しておいてください:
- Workload Identity Federation for GKEを有効化したGKEクラスター
- ExternalDNSが利用するCloud DNSゾーン
Workload Identityの設定
ExternalDNSがCloud DNSのレコードを更新したりできるようにするため「Workload Identity」の設定を行います。
gcloud projects add-iam-policy-binding projects/<CLOUD_DNS_PROJECT_ID> ¥
--role=roles/dns.admin ¥
--member=principal://iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/<PROJECT_ID>.svc.id.goog/subject/ns/external-dns/sa/external-dns ¥
--condition=None下記については、自身の環境の値に置き換えてください:
- <CLOUD_DNS_PROJECT_ID>
- <PROJECT_NUMBER>
- <PROJECT_ID>
ExternalDNSのインストール
GKEクラスターに ExternalDNS をインストールします。「Workload Identityの設定」の項で参考にしたページでは手動でExternalDNSをインストールしていますが、ここでは「Helm Chart」を利用してインストールを行います。
下記のvalues.yamlを用意します:
provider:
name: google
domainFilters:
- example.com
extraArgs:
google-project: <CLOUD_DNS_PROJECT_ID>
google-zone-visibility: public
serviceAccount:
name: external-dns下記については、自身の環境の値に置き換えてください:
- <CLOUD_DNS_PROJECT_ID>
values.yamlを用意したら、下記のコマンドでExternalDNSをインストールします:
$ helm repo add external-dns https://kubernetes-sigs.github.io/external-dns/
$ helm repo update
$ helm upgrade --install external-dns external-dns/external-dns ¥
--create-namespace ¥
--namespace external-dns ¥
--version 1.20.0 ¥
--values values.yamlExternalDNSの動作確認
ExternalDNS をインストールしたので動作確認をしていきます。例として、下記のようなマニフェストをapplyします:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app
namespace: default
spec:
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-svc
port:
number: 80
---
apiVersion: v1
kind: Service
metadata:
name: app-svc
namespace: default
spec:
type: ClusterIP
selector:
app: app
ports:
- name: http
port: 80
targetPort: 80
---
apiVersion: v1
kind: Pod
metadata:
name: app-pod
namespace: default
labels:
app: app
spec:
containers:
- name: app
image: nginx
ports:
- containerPort: 80app.example.comのドメインが設定されたIngressリソースを作成しているので、apply後にしばらく待つと下記のようにロードバランサーが設定されており、IPアドレスが払い出されていることが分かります:
$ kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
app <none> app.example.com xxx.xxx.xxx.xxx 80 5mまた、Cloud DNSのレコード設定を確認してみると、下記のように、払い出されたIPアドレスに対してIngressリソースで設定したapp.example.comが関連付けられていることを確認できます。:
$ gcloud dns record-sets list --zone example-com --name app.example.com --type A
NAME TYPE TTL DATA
app.example.com. A 300 xxx.xxx.xxx.xxxこのように、ExternalDNSを使用するとIngressなどのリソースの状況に応じてDNSレコードを自動で設定できるようになります。これにより手動で DNSレコードを設定する手間が減り、運用業務の手間を減らすことができます。
ExternalDNSの仕組み
ExternalDNSは通常の定期ポーリングでのチェックとKubernetesのコントローラパターンに基づいて動作しています(コントローラーパターンでの動作は--eventsオプションを設定した場合に動作します)。コントローラパターンはIngressなどのリソース変更を監視しており、変更を検知した際にイベント駆動でDNSの変更をトライするというものです。
定期ポーリングやイベントを契機に、変更が必要なリソースの現在のDNSレコード設定を取得します。その内容と差分を計算し、実際に更新が必要なレコードを抽出して、必要に応じて更新する仕組みとなっています。
まとめ
ExternalDNSを使用すると、記事中で紹介したように簡単にリソースに対応するDNSレコードを管理することができて非常に便利です。
また、ExternalDNSは開発や管理もKubernetesのコミュニティ主導で行われており、メンテナンスについて信頼性が高いことから安心して利用できるツールかと思いますので、まだ利用したことがない方は積極的に利用してみてください。
