VPC環境で利用できます。
Ncloud Kubernetes Service(NKS)で ExternalDNSを使用して Kubernetesリソースと Global DNSサービスのレコードを同期できます。
使用前に確認
ExternalDNS活用のユースケースを行う前に、次のサポート範囲と準備事項をご確認ください。
| 項目 | サポート範囲 |
|---|---|
| 利用環境 | VPC |
| Kubernetes(NKS Add-on) | 1.36.2以上 |
| Kubernetes(Helm手動インストール) | 1.33以上 |
| ExternalDNS | 0.21.0 |
| サポートリソース | Service, Ingress, DNSEndpoint |
| サポートレコードタイプ | A, AAAA, CNAME, MX, TXT |
| 認証方式 | NKS Node IAM Roleまたは Sub Accountアクセスキー |
ExternalDNSが管理するレコードタイプと条件は、次の通りです。
| レコードタイプ | 管理条件 |
|---|---|
A, AAAA, CNAME |
基本管理対象 |
MX、直接定義した TXT |
Helm手動インストールで managedRecordTypesに追加した場合のみ管理(NKS Add-on未対応) |
所有権の確認用 TXT |
registry: txt 設定に応じて自動作成(管理対象タイプとは関係なし) |
次の項目を予め準備してください。
- Ncloud Kubernetes Serviceクラスタ
kubectlを使用できる kubeconfig- Helm 3(手動インストール時)
- Global DNSサービスに登録されたドメイン
- ドメイン照会、レコードの照会/作成/変更/削除、変更事項の適用権限
インストール中に使用する値は、次の通りです。
| 入力値 | 説明 | 例 |
|---|---|---|
<KUBE_CONTEXT> |
ExternalDNSをインストールする kubeconfig context | nks_kr_cluster_example |
<DNS_ZONE> |
Global DNSサービスに登録された管理対象ドメイン | example.com |
<DNS_BASE_URL> |
手動インストールに使用する環境別 Global DNS OpenAPIアドレス | https://globaldns.apigw.ntruss.com/dns/v1 |
<WEBHOOK_IMAGE_TAG> |
手動インストールに使用するウェブフックイメージの固定されたリリースタグ | v1.0.0 |
<TXT_OWNER_ID> |
手動インストールした ExternalDNSインスタンスを区分する固有値 | nks-cluster-a |
<INGRESS_CLASS> |
クラスタで使用する Ingress Class | alb |
<NODE_LABEL_KEY> |
Node IAM Roleが関連付けられているノードプールのラベルキー | ncloud.com/nks-nodepool |
<NODE_LABEL_VALUE> |
Node IAM Roleが関連付けられているノードプールのラベル値 | pool2 |
可能であれば、クラスタ別に別途の Global DNSドメインや委任したサブドメインを使用します。複数のクラスタが同じドメインを共有する必要がある場合はクラスタごとに固有の <TXT_OWNER_ID>を使用し、同じホスト名を重複管理しないよう構成します。NKS Add-onは、クラスタ UUIDを txtOwnerId デフォルト値として使用します。
以下のコマンドを実行して kubeconfig contextと Ingress Classを確認します。
kubectl --context "<KUBE_CONTEXT>" cluster-info
kubectl --context "<KUBE_CONTEXT>" get ingressclass
Global DNSのドメイン準備
ExternalDNSで管理するドメインを Global DNSサービスに登録します。
例えば、example.comを管理ドメインとして指定すると、app.example.comのようなサブホストのレコードを作成できます。
公開 DNSでレコードを照会するには、ドメイン登録機関に Global DNSのネームサーバ情報を設定する必要があります。
Kubernetesリソースに指定したホスト名が Global DNSの登録ドメインに含まれていない場合は DNSレコードを作成せずに警告ログを残します。
認証情報の準備
ウェブフックプロバイダは、NKS Node IAM Roleと Sub Accountアクセスキーをサポートします。2つの方式がすべて設定されている場合、Sub Accountアクセスキーを先に使用します。
NKS Node IAM Roleを使用する
NKS Node IAM Roleを使用する場合、長期アクセスキーを Kubernetes Secretに保存しなくても構いません。以下の順序に従って、ロールを準備します。
- ロール作成を参照して Serverタイプの Sub Accountロールを作成します。
- ロールに Global DNSドメインとレコード管理権限を追加します。
- ノードプールを作成する場合、当該ロールに Node IAM Roleを選択します。
- ExternalDNS Podが当該ノードプールに配置されるように、ノードラベルと taintを確認します。
Node IAM Role設定の詳細については、Node IAM Role 活用のユースケースをご参照ください。
Global DNSの全機能を許可するには NCP_GLOBAL_DNS_MANAGER マネージドポリシーを使用できます。最小権限のユーザー定義ポリシーを使用する場合、次のアクションを選択します。
| 権限区分 | 選択するアクション |
|---|---|
| 照会権限 | getDomainList, getRecordList |
| 変更権限 | createRecord, updateRecord, deleteRecord, applyRecordConfig |
Sub Accountは上記のアクションに必要な getDomainDetailと getRecordDetailを関連アクションとして自動追加します。自動的に追加された関連アクションの選択を解除しないでください。getDomainMonitor、downloadRecordList、createDomain、uploadZonefile、deleteDomain、changeDNSSECstatusは必要ありません。
詳細は Global DNS の権限管理をご参照ください。
Sub Accountアクセスキーを使用する
Sub Accountアクセスキーを使用する場合、ExternalDNS Podが実行される名前空間に認証情報が含まれた Secretを作成します。
NKS Add-onは kube-system 名前空間にインストールされます。既存のクラスタに Add-onをインストールする場合、以下のコマンドを実行して Secretを予め作成します。
kubectl --context "<KUBE_CONTEXT>" --namespace kube-system \
create secret generic ncloud-credentials \
--from-literal=access-key="<NCLOUD_ACCESS_KEY>" \
--from-literal=secret-key="<NCLOUD_SECRET_KEY>"
Add-on設定の credentials.secretNameに ncloud-credentialsを入力します。
クラスタ作成と同時に ExternalDNS Add-onをインストールする場合には、credentials.secretNameを先に入力できます。クラスタ作成が完了した後、kube-system 名前空間に Secretを作成し、以下のコマンドを実行して ExternalDNS Deploymentを再開してください。
kubectl --context "<KUBE_CONTEXT>" --namespace kube-system \
rollout restart deployment/external-dns
kubectl --context "<KUBE_CONTEXT>" --namespace kube-system \
rollout status deployment/external-dns --timeout=5m
Sub Accountアクセスキーを使用するには、Add-on設定の credentials.secretNameに Secret名を入力します。Node IAM Roleを使用するには、値を空にします。同じ名前の Secretでアクセスキーを変更した場合には、ExternalDNS Deploymentを再起動することで、変更された値が適用されます。
Helmで手動インストールする場合、以下のコマンドを実行して external-dns 名前空間と Secretを作成します。
kubectl --context "<KUBE_CONTEXT>" create namespace external-dns
kubectl --context "<KUBE_CONTEXT>" --namespace external-dns \
create secret generic ncloud-credentials \
--from-literal=access-key="<NCLOUD_ACCESS_KEY>" \
--from-literal=secret-key="<NCLOUD_SECRET_KEY>"
ExternalDNSのインストール
ExternalDNSは、NKS Add-onまたは Helmでインストールできます。
| インストール方式 | 値設定 | 管理方式 | 推奨状況 |
|---|---|---|---|
| NKS Add-on | NKSが一部の値を自動的に組み込み、ユーザーは Add-onが提供する設定項目のみ入力 | NKSで構成とバージョンを自動管理 | NKSでサポートする設定範囲で運用する場合 |
| Helm手動インストール | ExternalDNS Helmチャートの全体値をユーザーが直接設定 | インストール、アップグレード、削除をユーザーが直接管理 | Add-onで提供しない値を設定する必要がある場合 |
2つのインストール方式のうち、1つのみ選択します。同じクラスタに Add-onと Helmリリースを一緒にインストールすると、DNSレコードの所有権が競合することがあります。
NKS Add-onを利用したインストール
NKS Add-on機能で ExternalDNSを選択してインストールします。Add-onは ExternalDNSコンテナ、NAVERクラウドプラットフォーム用のウェブフックプロバイダ、DNSEndpoint CRD、サポートソースの service、ingress、crdに必要な RBACを一緒にインストールします。
Add-onはクラスタ UUIDと利用環境に応じた Global DNS OpenAPIアドレスなどの一部の値を自動的に組み込みます。ユーザーは Add-onが提供する設定項目のみ入力し、NKSが Add-onの構成とバージョンを自動的に管理します。Add-onが提供していない値を変更する必要がある場合、Helmを利用した手動インストールを行います。
主要 Add-on設定は次の通りです。
| 設定 | デフォルト値 | 説明 |
|---|---|---|
domainFilter |
空の値 | 管理する Global DNSドメイン。空の値の場合、使用中の認証情報で照会できる全ドメインが管理対象 |
sources |
service, ingress, crd |
DNSレコードを作成する Kubernetesリソースタイプ |
policy |
upsert-only |
レコード変更ポリシー。sync、upsert-only、create-onlyの中から選択 |
annotationFilter |
空の値 | 指定したアノテーション条件と一致するリソースのみ処理 |
labelFilter |
空の値 | 指定したラベル条件と一致するリソースのみ処理 |
txtPrefix |
_edns. |
所有権 TXTレコード名のプレフィックス |
txtSuffix |
空の値 | 所有権 TXTレコード名のサフィックス |
txtOwnerId |
クラスタ UUID | ExternalDNSインスタンスの所有者識別子 |
logLevel |
info |
ログレベル |
credentials.secretName |
空の値 | kube-system 名前空間の Sub Accountアクセスキー Secret の名前。Node IAM Role使用時に入力しない |
scheduling.nodeSelector |
空の値 | Node IAM Roleが接続されたノードプールを選択 |
scheduling.extraTolerations |
空の値 | 当該ノードプールの taint許可設定 |
設定時に次の事項をご参照ください。
- 運用環境では意図しないドメインが管理範囲に含まれないよう、管理するドメインを
domainFilterに指定することをお勧めします。 - Node IAM Roleを使用する場合、ロールが接続されたノードプールの
scheduling.nodeSelectorと必要なscheduling.extraTolerationsを入力します。 - Kubernetesリソースを削除する時、DNSレコードも一緒に削除するには、
policyをsyncとして設定します。デフォルト値upsert-onlyは、リソースを削除しても DNSレコードを維持します。 txtOwnerIdを入力しないと、クラスタ UUIDが使用されます。既存の ExternalDNSから移行する場合のみ、既存の所有者値を入力します。txtPrefixとtxtSuffixは、同時に設定できません。運用中に値を変更すると、既存の所有権 TXTレコードが残ることがあるため、インストール後には変更しないでください。- NKSが利用環境に適した Global DNS OpenAPIアドレスを自動的に設定するため、Add-onをインストールする時、
dnsBaseUrlを入力しなくても構いません。 - Add-onインストールステータスが正常に表示されたら、Service DNSレコード作成から行います。
Helmを利用した手動インストール
ExternalDNS Add-onを使用できない、またはユーザー定義設定を使用する必要がある場合、ExternalDNS公式 Helmチャートで手動インストールできます。手動インストールでは、インストール、値の変更、アップグレード、削除をユーザーが直接管理します。ExternalDNSコンテナと NAVERクラウドプラットフォーム用のウェブフックプロバイダは、1つの Podにリリースされます。
Node IAM Roleを使用する場合、以下のコマンドを実行して名前空間を作成します。
kubectl --context "<KUBE_CONTEXT>" create namespace external-dns
以下のコマンドを実行して ExternalDNS Helmストレージを追加します。
helm repo add external-dns https://kubernetes-sigs.github.io/external-dns/
helm repo update
手動インストールでは、利用環境に適した Global DNS OpenAPIアドレスを直接設定する必要があります。
| 利用環境 | <DNS_BASE_URL> |
|---|---|
| 個人/法人向け | https://globaldns.apigw.ntruss.com/dns/v1 |
| 公共官公庁向け | https://globaldns.apigw.gov-ntruss.com/dns/v1 |
| 金融 | https://globaldns.apigw.fin-ntruss.com/dns/v1 |
次の内容をコピーして external-dns-values.yaml ファイルで保存します。
<DNS_ZONE>、<DNS_BASE_URL>、<TXT_OWNER_ID>、<WEBHOOK_IMAGE_TAG>は、準備した値に変更します。
image:
tag: v0.21.0
sources:
- service
- ingress
- crd
registry: txt
policy: sync
logLevel: info
txtPrefix: "_edns."
txtOwnerId: "<TXT_OWNER_ID>"
domainFilters:
- "<DNS_ZONE>"
extraArgs:
- --webhook-provider-read-timeout=90s
terminationGracePeriodSeconds: 120
provider:
name: webhook
webhook:
image:
repository: nks.kr.ncr.ntruss.com/nks/external-dns-navercloud-webhook
tag: "<WEBHOOK_IMAGE_TAG>"
env:
- name: DOMAIN_FILTER
value: "<DNS_ZONE>"
- name: NCLOUD_DNS_BASE_URL
value: "<DNS_BASE_URL>"
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 3
periodSeconds: 5
- このユースケースでは、
sourcesをservice、ingress、crdに設定します。手動インストールでは、使用目的に応じてリソースタイプを追加・削除できます。 crdを使用する場合、ExternalDNS Helmチャートに含まれたDNSEndpointCRDをインストール対象から削除しないでください。
手動インストールで MX レコードと Kubernetesリソースから直接定義した TXT レコードを管理するには、external-dns-values.yamlに次の値を追加します。
managedRecordTypes:
- A
- AAAA
- CNAME
- MX
- TXT
txtPrefixは CNAMEレコードと所有権 TXTレコードの名前競合を防止します。txtOwnerIdは複数の ExternalDNSインスタンスが同じレコードを変更しないよう所有者を区分します。
Sub Accountアクセスキーを使用する場合、provider.webhook.envを次のように設定します。
env:
- name: DOMAIN_FILTER
value: "<DNS_ZONE>"
- name: NCLOUD_DNS_BASE_URL
value: "<DNS_BASE_URL>"
- name: NCLOUD_ACCESS_KEY
valueFrom:
secretKeyRef:
name: ncloud-credentials
key: access-key
- name: NCLOUD_SECRET_KEY
valueFrom:
secretKeyRef:
name: ncloud-credentials
key: secret-key
以下のコマンドを実行して ExternalDNSをインストールします。
helm upgrade --install external-dns external-dns/external-dns \
--kube-context "<KUBE_CONTEXT>" \
--namespace external-dns \
--version 1.21.1 \
--values external-dns-values.yaml
Helmチャートをインストールする時、DNSEndpoint CRDも一緒にインストールされます。--skip-crds オプションを使用しないでください。
以下のコマンドを実行して ExternalDNSと CRDのステータスを確認します。
kubectl --context "<KUBE_CONTEXT>" --namespace external-dns \
rollout status deployment/external-dns --timeout=5m
kubectl --context "<KUBE_CONTEXT>" --namespace external-dns get pod
kubectl --context "<KUBE_CONTEXT>" get crd dnsendpoints.externaldns.k8s.io
以下のコマンドを実行して ExternalDNSコンテナとウェブフックコンテナのログを確認します。
kubectl --context "<KUBE_CONTEXT>" --namespace external-dns \
logs deployment/external-dns --all-containers=true --tail=100
ウェブフックプロバイダが使用中の認証方式は、ログで次の値で確認できます。
provider=ServerRoleProvider: NKS Node IAM Roleを使用するprovider=EnvProvider: Sub Accountアクセスキーを使用する
Service DNSレコード作成
LoadBalancer タイプの Serviceに ExternalDNSアノテーションを追加すると、Serviceの外部アドレスを示す DNSレコードを作成できます。
ユースケースリソースは external-dns 名前空間に作成します。当該名前空間がない場合、以下のコマンドを実行して作成します。
kubectl --context "<KUBE_CONTEXT>" create namespace external-dns
次の内容をコピーして external-dns-service.yaml ファイルで保存します。<SERVICE_HOSTNAME>は <DNS_ZONE>のサブホスト名に変更します。
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns-nginx
namespace: external-dns
spec:
replicas: 1
selector:
matchLabels:
app: external-dns-nginx
template:
metadata:
labels:
app: external-dns-nginx
spec:
containers:
- name: nginx
image: nginx:1.27-alpine
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: external-dns-nginx
namespace: external-dns
annotations:
external-dns.alpha.kubernetes.io/hostname: "<SERVICE_HOSTNAME>"
external-dns.alpha.kubernetes.io/ttl: "300"
spec:
type: LoadBalancer
selector:
app: external-dns-nginx
ports:
- port: 80
targetPort: 80
以下のコマンドを実行して Deploymentと Serviceを作成し、外部アドレスの割り当てステータスを確認します。
kubectl --context "<KUBE_CONTEXT>" apply -f external-dns-service.yaml
kubectl --context "<KUBE_CONTEXT>" --namespace external-dns \
get service external-dns-nginx
次の同期が完了したら、Global DNSメニューで <SERVICE_HOSTNAME>のレコードと所有権 TXTレコードが作成されたか確認します。ExternalDNSは基本的に1分ごとに同期します。Load Balancer作成には数分以上かかることがあります。
Ingress DNSレコード作成
Ingress Controllerが Ingressに割り当てた外部アドレスと Ingressに指定したホスト名を利用して DNSレコードを作成できます。Ingress Controllerインストールと Ingress作成方法は ALB Ingress Controller 活用のユースケースをご参照ください。
次の内容をコピーして external-dns-ingress.yaml ファイルで保存します。<INGRESS_HOSTNAME>は <DNS_ZONE>のサブホスト名に変更します。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: external-dns-ingress
namespace: external-dns
annotations:
external-dns.alpha.kubernetes.io/ttl: "300"
spec:
ingressClassName: "<INGRESS_CLASS>"
rules:
- host: "<INGRESS_HOSTNAME>"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: external-dns-nginx
port:
number: 80
以下のコマンドを実行して Ingressを作成し、外部アドレスの割り当てステータスを確認します。
kubectl --context "<KUBE_CONTEXT>" apply -f external-dns-ingress.yaml
kubectl --context "<KUBE_CONTEXT>" --namespace external-dns \
get ingress external-dns-ingress
次の同期が完了したら、Global DNSメニューで <INGRESS_HOSTNAME>のレコードと所有権 TXTレコードが作成されたか確認します。
Ingress Controllerが IPアドレスを提供すると、A または AAAAレコードが作成されます。ホスト名を指定すると CNAME レコードが作成されます。
DNSEndpointで DNSレコード作成
DNSEndpointを使用すると、Serviceまたは Ingressと関係なく DNSレコードを直接定義できます。
次の内容をコピーして external-dns-crd.yaml ファイルで保存します。
<CRD_HOSTNAME>と <IP_ADDRESS>は、使用するホスト名と IPアドレスに変更します。
apiVersion: externaldns.k8s.io/v1alpha1
kind: DNSEndpoint
metadata:
name: external-dns-crd
namespace: external-dns
spec:
endpoints:
- dnsName: "<CRD_HOSTNAME>"
recordTTL: 300
recordType: A
targets:
- "<IP_ADDRESS>"
以下のコマンドを実行して DNSEndpointを作成し、作成有無を確認します。
kubectl --context "<KUBE_CONTEXT>" apply -f external-dns-crd.yaml
kubectl --context "<KUBE_CONTEXT>" --namespace external-dns \
get dnsendpoint external-dns-crd
次の同期が完了したら、Global DNSメニューで <CRD_HOSTNAME>の A レコードと所有権 TXTレコードが作成されたか確認します。
DNSレコード削除
このユースケースでは、policy: syncを使用するために Kubernetesリソースを削除すると、ExternalDNSが管理対象 DNSレコードと所有権 TXTレコードを削除します。
以下のコマンドを実行してユースケースリソースを削除します。
kubectl --context "<KUBE_CONTEXT>" delete -f external-dns-crd.yaml
kubectl --context "<KUBE_CONTEXT>" delete -f external-dns-ingress.yaml
kubectl --context "<KUBE_CONTEXT>" delete -f external-dns-service.yaml
次の同期が完了したら、Global DNSメニューで DNSレコードと所有権 TXTレコードが削除されたか確認します。
ExternalDNSをこれ以上使用しない場合、インストール方式に応じて削除します。
- NKS Add-on: NKSの Add-on管理画面で ExternalDNS Add-onを削除
- Helm手動インストール: 以下のコマンドを実行して Helmリリースを削除
helm uninstall external-dns \
--kube-context "<KUBE_CONTEXT>" \
--namespace external-dns
Helmリリースを削除しても DNSEndpoint CRDは削除されません。CRDがこれ以上必要でない場合、使用中の DNSEndpointがないか確認してから別途削除します。
Helm手動インストールで Sub Accountアクセスキーを使用した場合、当該 Secretを他のワークロードで使用していないか確認した後、以下のコマンドを実行して削除します。
kubectl --context "<KUBE_CONTEXT>" --namespace external-dns \
delete secret ncloud-credentials
Add-onで Sub Accountアクセスキーを使用した場合、当該 Secretを他のワークロードで使用していないか確認してから削除します。
Kubernetesリソースを削除する前に ExternalDNSを削除すると、DNSレコードを自動的にクリーンアップできません。policyを upsert-onlyに設定した場合にも DNSレコードが維持されるため、Global DNSサービスから直接削除する必要があります。
制限事項
ExternalDNSと NAVERクラウドプラットフォーム用のウェブフックプロバイダを使用する時、次の制限事項をご確認ください。
- Global DNSサービスに登録されていないドメインのホスト名はスキップします。
- Add-onで
domainFilterを設定、または Helm手動インストールでdomainFiltersとDOMAIN_FILTERを設定すると、指定したドメインのみ管理します。 - Global DNSでネームサーバに反映しなかった変更事項が残っている場合、ExternalDNSは当該ドメインのレコードを変更しません。[設定適用] > [リリース] ボタンを順に選択して変更事項を反映、または [変更事項キャンセル] ボタンを選択して戻すと次の同期から再処理されます。
- ウェブフックプロバイダが実行中の場合、Global DNSコンソールで同じドメインのレコードを直接変更しないでください。
SOAとNS基本レコードは管理しません。