ExternalDNSを使用してDigitalOceanKubernetesからDNSレコードを自動的に管理する方法
著者は、 Write for DOnations プログラムの一環として、 Free and Open SourceFundを選択して寄付を受け取りました。
序章
ウェブアプリをKubernetesにデプロイする場合、通常は Services とIngressesを使用して、目的のドメインのクラスターを超えてアプリを公開します。 これには、入力だけでなく、プロバイダーでDNSレコードも手動で構成することが含まれます。これは、時間がかかり、エラーが発生しやすいプロセスになる可能性があります。 アプリケーションが複雑になるにつれて、これは障害になる可能性があります。 外部IPが変更された場合は、それに応じてDNSレコードを更新する必要があります。
これを克服するために、 Kubernetes sig-network team は、Kubernetesクラスター内から外部DNSレコードを自動的に管理する目的でExternalDNSを作成しました。 デプロイされると、ExternalDNSはバックグラウンドで動作し、追加の構成はほとんど必要ありません。 ServiceまたはIngressが作成または変更されるたびに、ExternalDNSはレコードをすぐに更新します。
このチュートリアルでは、Helmを介して DigitalOcean Kubernetes クラスターにExternalDNSをインストールし、DNSプロバイダーとしてDigitalOceanを使用するように構成します。 次に、Ingressを使用してサンプルWebアプリをデプロイし、ExternalDNSを使用してドメイン名を指定します。 最終的には、サービスとイングレスの両方に自動化されたDNSレコード管理システムが導入されます。
前提条件
- 接続が
kubectl
デフォルトとして構成されたDigitalOceanKubernetesクラスター。kubectl
を構成する方法の説明は、クラスターを作成するときのクラスターへの接続ステップの下に表示されます。 DigitalOceanでKubernetesクラスタを作成するには、 KubernetesQuickstartをお読みください。 - ローカルマシンにインストールされているHelm3パッケージマネージャー。 Helm 3 PackageManagerチュートリアルを使用してKubernetesクラスターにソフトウェアをインストールする方法のステップ1を完了します。
- IngressリソースでExternalDNSを使用するために、Helmを使用してクラスターにインストールされたNginxIngressController。 これを行うには、Helmを使用してDigitalOceanKubernetesでNginxIngressを設定する方法に従ってください。 手順2の手順に従って、
publishService
プロパティをtrue
に設定する必要があります。 - 読み取りおよび書き込み権限を持つDigitalOceanAPIキー(パーソナルアクセストークン)。 作成するには、パーソナルアクセストークンの作成方法にアクセスしてください。
- 完全に登録されたドメイン名。 このチュートリアルでは、全体を通して
echo.your_domain
を使用します。 Namecheap でドメイン名を購入するか、 Freenom で無料でドメイン名を取得するか、選択したドメイン登録事業者を使用できます。
ステップ1—Helmを使用したExternalDNSのインストール
このセクションでは、Helmを使用して外部DNSをクラスターにインストールし、DigitalOceanDNSサービスと連携するように構成します。
ExternalDNS Helmチャートのデフォルト設定の一部を上書きするには、インストール中にHelmに渡すvalues.yaml
ファイルを作成する必要があります。 前提条件でクラスターへのアクセスに使用するマシンで、次のコマンドを実行してファイルを作成します。
nano externaldns-values.yaml
次の行を追加します。
externaldns-values.yaml
provider: digitalocean digitalocean: apiToken: your_api_token interval: "1m" policy: sync # or upsert-only # domainFilters: [ 'your_domain' ]
最初のブロックでは、DNSサービスプロバイダーをDigitalOceanに設定します。 次に、次のブロックで、your_api_token
を置き換えてDigitalOceanAPIトークンを定義します。
次の行は、ExternalDNSがIngressesおよびServicesへの変更をポーリングする間隔を設定します。 これを低い値に設定すると、DNSへの変更をより速く伝播できます。デフォルト値は1分です。
policy
設定は、ExternalDNSがDNSレコードのみを挿入するか(upsert-only
)、必要に応じてそれらを作成および削除するか(sync
)を決定します。 幸い、バージョン0.3以降、ExternalDNSは、作成したドメインに関する情報を格納する付随する TXT レコードを作成することで所有権の概念をサポートし、アクションの範囲を作成したドメインのみに制限します。
domainFilters
パラメーターは、ExternalDNSが管理できるドメインを制限するために使用されます。 コメントを外して、文字列配列の形式でドメインを入力できますが、これは必須ではありません。
編集が終了したら、ファイルを保存して閉じます。
ExternalDNS Helmチャートは、Bitnamiチャートライブラリの一部です。 次のコマンドを実行して、Helmインストールに追加します。
helm repo add bitnami https://charts.bitnami.com/bitnami
次に、Helmのキャッシュを更新して、その内容をダウンロードします。
helm repo update
最後に、以下を実行して、ExternalDNSをクラスターにインストールします。
helm install external-dns bitnami/external-dns -f externaldns-values.yaml
出力は次のようになります。
OutputNAME: external-dns LAST DEPLOYED: ... NAMESPACE: default STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: ** Please be patient while the chart is being deployed ** To verify that external-dns has started, run: kubectl --namespace=default get pods -l "app.kubernetes.io/name=external-dns,app.kubernetes.io/instance=external-dns"
次のコマンドを実行して、ExternalDNSの作成を確認できます。
kubectl --namespace=default get pods -l "app.kubernetes.io/name=external-dns,app.kubernetes.io/instance=external-dns"
OutputNAME READY STATUS RESTARTS AGE external-dns-56c85ff66b-2vm88 1/1 Running 0 24s
KubernetesクラスターにExternalDNSをインストールしました。 次に、サンプルのWebアプリをデプロイし、Nginx Ingressを使用して公開し、ExternalDNSがドメイン名を適切なロードバランサーに自動的にポイントするようにします。
ステップ2—サンプルWebアプリのデプロイと公開
このセクションでは、Ingressを使用して公開するために、ダミーのWebアプリをクラスターにデプロイします。 次に、DNSレコードを自動的に構成するようにExternalDNSを設定します。 最終的に、ドメインのDNSレコードが入力のロードバランサーを指すようになります。
デプロイするダミーのWebアプリは、Hashicorpのhttp-echoです。 これは、指定したメッセージをエコーバックするメモリ内Webサーバーです。 Kubernetesマニフェストをecho.yaml
という名前のファイルに保存します。 それを作成し、編集のために開きます。
nano echo.yaml
次の行をファイルに追加します。
echo.yaml
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: echo-ingress annotations: kubernetes.io/ingress.class: nginx spec: rules: - host: "echo.your_domain" http: paths: - pathType: Prefix path: "/" backend: service: name: echo port: number: 80 --- apiVersion: v1 kind: Service metadata: name: echo spec: ports: - port: 80 targetPort: 5678 selector: app: echo --- apiVersion: apps/v1 kind: Deployment metadata: name: echo spec: selector: matchLabels: app: echo replicas: 3 template: metadata: labels: app: echo spec: containers: - name: echo image: hashicorp/http-echo args: - "-text=Echo!" ports: - containerPort: 5678
この構成では、デプロイメント、イングレス、およびサービスを定義します。 デプロイメントは、http-echo
アプリの3つのレプリカで構成され、カスタムメッセージ(Echo!
)が渡されます。 サービスは、ポート80
を介してデプロイメント内のポッドにアクセスできるように定義されています。 Ingressは、ドメインでサービスを公開するように構成されています。
echo.your_domain
をドメインに置き換えてから、ファイルを保存して閉じます。
これで、ドメインのDNSレコードを手動で構成する必要はありません。 設定をKubernetesに適用するとすぐに、ExternalDNSが自動的にこれを行います。
構成を適用するには、次のコマンドを実行します。
kubectl create -f echo.yaml
次の出力が表示されます。
Outputingress.extensions/echo-ingress created service/echo created deployment.apps/echo created
ExternalDNSが変更に気づき、適切なDNSレコードを作成するまで、少し待つ必要があります。 ヘルムチャートのinterval
設定は、DNSレコードの作成を待機する必要がある時間の長さを管理します。 externaldns-values.yaml
では、間隔の長さはデフォルトで1分に設定されています。
DigitalOceanコントロールパネルにアクセスして、AおよびTXTレコードを見つけることができます。
指定された時間間隔が経過するか、コントロールパネルでレコードを見つけたら、curl
を使用してドメインにアクセスします。
curl echo.your_domain
次の出力が表示されます。
OutputEcho!
このメッセージは、ExternalDNSを構成し、NginxIngressControllerのロードバランサーを指すために必要なDNSレコードを作成したことを確認します。 エラーメッセージが表示された場合は、しばらくお待ちください。 または、Echo!
を受け取るブラウザからドメインにアクセスしてみてください。
Ingressを使用してサンプルアプリをデプロイすることにより、ExternalDNSをテストしました。 DigitalOceanコントロールパネルで新しいDNSレコードを確認することもできます。 次のステップでは、ドメイン名でサービスを公開します。
ステップ3—(オプション)サービスを使用してアプリを公開する
このオプションのセクションでは、Ingressesの代わりにExternalDNSでサービスを使用します。 ExternalDNSを使用すると、さまざまなKubernetesリソースをDNSサーバーで利用できるようにすることができます。 サービスの使用は、この代替リソースの構成が変更されたIngressesと同様のプロセスです。
注:この手順を実行すると、作成したDNSレコードが削除されます。
echo.yaml
に含まれるサービスをカスタマイズするため、echo-ingress
は不要になります。 次のコマンドを使用して削除します。
kubectl delete ing echo-ingress
出力は次のようになります。
Outputingress.extensions/echo-ingress deleted
ExternalDNSは、前の手順で作成した既存のDNSレコードを削除します。 手順の残りの部分では、以前に使用したものと同じドメインを使用できます。
次に、echo.yaml
ファイルを開いて編集します。
nano echo.yaml
ファイルの内容を次の行に置き換えます。
echo.yaml
apiVersion: v1 kind: Service metadata: name: echo annotations: external-dns.alpha.kubernetes.io/hostname: echo.your_domain spec: type: LoadBalancer ports: - port: 80 targetPort: 5678 selector: app: echo --- apiVersion: apps/v1 kind: Deployment metadata: name: echo spec: selector: matchLabels: app: echo replicas: 3 template: metadata: labels: app: echo spec: containers: - name: echo image: hashicorp/http-echo args: - "-text=Echo!" ports: - containerPort: 5678
以前のセットアップのファイルからIngressを削除し、サービスタイプをLoadBalancer
に変更しました。 さらに、ExternalDNSのドメイン名を指定するアノテーションを追加しました。
次のコマンドを実行して、変更をクラスターに適用します。
kubectl apply -f echo.yaml
出力は次のようになります。
Output... service/echo configured deployment.apps/echo configured
次のコマンドを実行して、サービスのロードバランサーが使用可能になることを確認できます。
kubectl get svc echo -w
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE echo LoadBalancer 10.245.81.235 <pending> 80:31814/TCP 8s ...
前の手順と同様に、DNSレコードが作成されて伝達されるまでしばらく待つ必要があります。 それが完了したら、curl
指定したドメイン:
curl echo.your_domain
出力は前のステップと同じになります。
OutputEcho!
エラーが発生した場合は、もう少し待つか、別のドメインを試すことができます。 DNSレコードはクライアントシステムにキャッシュされるため、変更が実際に反映されるまでに長い時間がかかる場合があります。
この手順では、サービス(LoadBalancer
タイプ)を作成し、ExternalDNSを使用してドメイン名を指定しました。
結論
ExternalDNSはバックグラウンドでサイレントに動作し、摩擦のないエクスペリエンスを提供します。 Kubernetesクラスタは、ドメインに関する信頼できる唯一の情報源になりました。 DNSレコードを手動で更新する必要はもうありません。
ExternalDNSの真の力は、継続的デリバリーシステムからテスト環境を作成するときに明らかになります。 Kubernetesクラスタにこのようなシステムをセットアップする場合は、 DigitalOceanKubernetesでSpinnakerを使用してCDパイプラインをセットアップする方法にアクセスしてください。