GKE 向け Cloud DNS を使用する

このドキュメントでは、Google Kubernetes Engine(GKE)クラスタの DNS プロバイダとして Cloud DNS を設定して使用する方法について説明します。

Cloud DNS は、Kubernetes Service の DNS レコードを自動的に管理します。デフォルトでは、これらのレコードにはクラスタ内(クラスタ スコープ)からのみアクセスできます。

Compute Engine VM など、クラスタの外部からヘッドレス サービスを解決する必要がある場合は、VPC スコープまたは追加の VPC スコープのいずれかを有効にする必要があります。

このドキュメントは、デベロッパー、管理者、アーキテクトなどの GKE ユーザーを対象としています。 Google Cloudの一般的なロールとタスクの例の詳細については、一般的な GKE Enterprise ユーザーのロールとタスクをご覧ください。

このドキュメントを最大限に活用するには、次のことを理解しておく必要があります。

クラスタの外部から ClusterIP または NodePort Service にアクセスできるようにするには、LoadBalancer または他の方法で Service を公開し、その外部 IP アドレスを Cloud DNS に登録する必要があります。

DNS プロバイダとして kube-dns を使用する方法についての詳細は、サービス ディスカバリと DNS をご覧ください。

カスタム バージョンの kube-dns またはカスタム DNS プロバイダを使用する方法については、カスタム kube-dns Deployment の設定をご覧ください。

料金

Cloud DNS が GKE Standard クラスタの DNS プロバイダである場合、GKE クラスタ内の Pod からの DNS クエリは、Cloud DNS の料金に応じて課金されます。

GKE によって管理される VPC スコープ DNS ゾーンに対するクエリは、標準の Cloud DNS 料金に応じて課金されます。

制限事項

次の制限が適用されます。

  • VPC スコープは Autopilot クラスタではサポートされていません。クラスタ スコープのみがサポートされています。GKE Autopilot クラスタで実行されているヘッドレス Service の名前を解決する必要がある場合は、追加の VPC スコープを使用する必要があります。
  • 追加の VPC スコープの GKE Autopilot クラスタは、クラスタの作成時にのみ有効にできます。既存の GKE Autopilot クラスタで追加の VPC スコープを有効または無効にすることはできません。
  • 共有 VPC ネットワークのサービス プロジェクトで追加の VPC スコープのクラスタを作成することはできません。
  • GKE 向け Cloud DNS は、IL4 コンプライアンス レジームの Assured Workload では使用できません。このような規制対象の環境では、kube-dns が強制されます。
  • マネージド プライベート DNS ゾーンに対する手動変更はサポートされておらず、Cloud DNS コントローラによって上書きされます。これらのゾーンの DNS レコードに対する変更は、コントローラを再起動すると保持されません。
  • GKE 向け Cloud DNS をクラスタで一度有効にすると、kube-dns はそのクラスタで動作し続けます。kube-dns Deployment とオートスケーラーをゼロにスケーリングすることで、kube-dns を無効にできます。
  • --cluster-dns-scope フラグでスコープを設定した後で、クラスタの DNS スコープを変更することはできません。DNS スコープを変更する必要がある場合は、別の DNS スコープでクラスタを再作成する必要があります。
  • CloudDNS リソースの制限が適用されます。特に、VPC ネットワークにバインドできるレスポンス ポリシー ゾーンは一度に 1 つだけです。VPC スコープと追加の VPC スコープの場合、クラスタの VPC ネットワークにバインドされた命名規則に従わないレスポンス ポリシー ゾーンがすでに存在すると、クラスタの作成は失敗します。
  • カスタム スタブドメインとアップストリーム DNS サーバー構成は、Pod とノードの DNS 構成に適用されます。ホスト ネットワーキングを使用する Pod またはホスト上で直接実行されるプロセスも、スタブドメインとアップストリーム ネームサーバー構成を使用します。この動作は Standard でのみサポートされています。
  • kube-dns Configmap で構成されたカスタム スタブドメインとアップストリーム ネームサーバーは、クラスタ スコープ DNS の Cloud DNS に自動的に適用されます。VPC スコープ DNS は kube-dns ConfigMap を無視するので、これらの構成を Cloud DNS で直接適用する必要があります。この動作は Standard でのみサポートされています。
  • kube-dns から VPC スコープへの移行は、中断が発生する操作です。kube-dns から VPC スコープに切り替えるとき、またはその逆を行うときに、クラスタを再作成します。
  • VPC スコープの場合、Service のセカンダリ IP アドレス範囲はそのサブネットワーク内の他のクラスタと共有しないでください。
  • VPC スコープの場合、PTR レコードに関連付けられたレスポンス ポリシーが VPC ネットワークに接続されます。クラスタ ネットワークにバインドされた他のレスポンス ポリシーがある場合、Kubernetes Service IP アドレスの PTR レコードの解決は失敗します。
  • 許可された割り当てを超える数の Pod を使用してヘッドレス Service を作成しようとすると、Cloud DNS は Service のレコードセットやレコードを作成しません。
  • DNS ラベルの最大文字数は 63 文字ですが、サービス名とポート名は 62 文字に制限されます。これは、GKE が DNS レコードにアンダースコアの接頭辞を追加するためです。

始める前に

作業を始める前に、次のタスクが完了していることを確認してください。

  • Google Kubernetes Engine API を有効にする。
  • Google Kubernetes Engine API の有効化
  • このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化する。gcloud CLI をインストール済みの場合は、gcloud components update コマンドを実行して最新のバージョンを取得します。以前のバージョンの gcloud CLI では、このドキュメントのコマンドを実行できない場合があります。
  • プロジェクトで Cloud DNS API を有効にする。

    Cloud DNS API を有効にする

  • クラスタ スコープで Cloud DNS を使用するには、次のいずれかのバージョンが必要です。

    • Standard の場合: GKE バージョン 1.24.7-gke.800、1.25.3-gke.700 以降。
    • Autopilot の場合: GKE バージョン 1.25.9-gke.400、1.26.4-gke.500 以降。
    • Google Cloud CLI バージョン 411.0.0 以降。
  • 追加の VPC スコープで Cloud DNS を使用するには、次のいずれかのバージョンが必要です。

    • GKE バージョン 1.28.3-gke.1430000 以降
    • Google Cloud CLI バージョン 503.0.0 以降。

クラスタ スコープ DNS を有効にする

クラスタ スコープ DNS では、GKE クラスタで動作しているノードのみがサービス名を解決でき、サービス名はクラスタ間で競合しません。この動作は GKE クラスタの kube-dns と同じです。つまり、ダウンタイムやアプリケーションへの変更なしで kube-dns から Cloud DNS クラスタ スコープにクラスタを移行できます。

次の図は、Cloud DNS により GKE クラスタの限定公開 DNS ゾーンが作成される仕組みを示しています。クラスタの DNS レコードを解決できるのは、クラスタ内のノードで動作しているプロセスと Pod のみです。これは、DNS スコープにはノードのみが含まれているためです。

GKE クラスタ内の Service を解決するさまざまなノード上の Pod
図: クラスタ スコープ DNS

新しいクラスタでクラスタ スコープを有効にする

バージョン 1.25.9-gke.400、1.26.4-gke.500 以降の新しい Autopilot クラスタは、デフォルトで Cloud DNS クラスタ スコープになります。次のセクションでは、新しい Standard クラスタでクラスタ スコープを有効にする方法について説明します。

クラスタ スコープを有効にして Standard クラスタを作成する

gcloud CLI または Google Cloud コンソールを使用して、Cloud DNS クラスタ スコープを有効にした GKE Standard クラスタを作成できます。

gcloud

--cluster-dns フラグを使用してクラスタを作成します。

gcloud container clusters create CLUSTER_NAME \
    --cluster-dns=clouddns \
    --cluster-dns-scope=cluster \
    --location=COMPUTE_LOCATION

次のように置き換えます。

cluster がデフォルト値であるため、コマンドでは --cluster-dns-scope=cluster フラグは省略可能です。

コンソール

  1. Google Cloud コンソールで、[Kubernetes クラスタの作成] ページに移動します。

    [Kubernetes クラスタの作成] に移動

  2. ナビゲーション パネルの [クラスタ] の下の [ネットワーキング] をクリックします。

  3. [DNS プロバイダ] セクションで、[Cloud DNS] をクリックします。

  4. [クラスタのスコープ] を選択します。

  5. 必要に応じてクラスタを構成します。

  6. [作成] をクリックします。

既存のクラスタでクラスタ スコープを有効にする

既存の Autopilot クラスタを kube-dns から Cloud DNS クラスタ スコープに移行することはできません。Cloud DNS クラスタ スコープを有効にするには、GKE バージョン 1.25.9-gke.400、1.26.4-gke.500 以降で Autopilot クラスタを再作成します。

既存の Standard クラスタを kube-dns から Cloud DNS クラスタ スコープに移行するには、gcloud CLI またはGoogle Cloud コンソールを使用します。

既存のクラスタを kube-dns から Cloud DNS に移行する場合は、変更を有効にするためにノードを再作成する必要があります。各ノードプールで Cloud DNS を DNS プロバイダとして個別に有効にして、クラスタ間の通信を中断することなく、アプリケーションを実行しているクラスタを移行します。一部のノードプールで kube-dns が使用され、一部のノードプールで Cloud DNS が使用されているため、ノードのサブセットは常に稼働しています。

gcloud

  1. 既存のクラスタを更新します。

    gcloud container clusters update CLUSTER_NAME \
        --cluster-dns=clouddns \
        --cluster-dns-scope=cluster \
        --location=COMPUTE_LOCATION
    

    次のように置き換えます。

    cluster がデフォルト値であるため、コマンドでは --cluster-dns-scope=cluster フラグは省略可能です。

    レスポンスは次の例のようになります。

    All the node-pools in the cluster need to be re-created by the user to start using Cloud DNS for DNS lookups. It is highly recommended to complete this step
    shortly after enabling Cloud DNS.
    Do you want to continue (Y/n)?
    

    確認後、Cloud DNS コントローラは GKE コントロール プレーンで動作するようになりますが、ノードプールをアップグレードするか、クラスタに新しいノードプールを追加するまで、Pod は DNS 解決に Cloud DNS を使用しません。

  2. Cloud DNS を使用するようにクラスタ内のノードプールをアップグレードします。

    gcloud container clusters upgrade CLUSTER_NAME \
        --node-pool=POOL_NAME \
        --location=COMPUTE_LOCATION
    

    次のように置き換えます。

    • CLUSTER_NAME: クラスタの名前。
    • POOL_NAME: アップグレードするノードプールの名前。

    ノードプールとコントロール プレーンが同じバージョンを実行している場合は、コントロール プレーンの手動アップグレードに従ってコントロール プレーンをアップグレードしてから、ノードプールをアップグレードしてください。

    レスポンスを確認し、クラスタ内のノードプールごとにこのコマンドを繰り返します。クラスタにノードプールが 1 つしかない場合は、--node-pool フラグを省略します。

コンソール

  1. Google Cloud コンソールで [Google Kubernetes Engine] ページに移動します。

    Google Kubernetes Engine に移動

  2. 変更するクラスタの名前をクリックします。

  3. [ネットワーキング] の [DNS プロバイダ] フィールドで、 [DNS プロバイダを編集] をクリックします。

  4. [Cloud DNS] をクリックします。

  5. [クラスタのスコープ] をクリックします。

  6. [変更を保存] をクリックします。

追加の VPC スコープを有効にする

このセクションでは、Cloud DNS クラスタ スコープのアドオンとして、追加の VPC スコープを有効または無効にする手順について説明します。

新しいクラスタで追加の VPC スコープを有効にする

新しい GKE クラスタで追加の VPC スコープ DNS を有効にするには、gcloud CLI または Google Cloud コンソールを使用します。

追加の VPC スコープを使用して Autopilot クラスタを作成する

gcloud container clusters create-auto CLUSTER_NAME \
    --additive-vpc-scope-dns-domain=UNIQUE_CLUSTER_DOMAIN

次のように置き換えます。

  • CLUSTER_NAME: クラスタの名前。
  • UNIQUE_CLUSTER_DOMAIN: ドメインの名前。GKE はこの値を確認しないため、この名前は VPC 内で必ず一意になるようにしてください。この値は、設定後は変更できません。.local で終わるドメインは使用しないでください。DNS の解決に失敗する可能性があります。

追加の VPC スコープを使用して Standard クラスタを作成する

gcloud container clusters create CLUSTER_NAME \
    --cluster-dns=clouddns \
    --cluster-dns-scope=cluster \
    --additive-vpc-scope-dns-domain=UNIQUE_CLUSTER_DOMAIN

cluster がデフォルト値であるため、--cluster-dns-scope=cluster フラグは省略可能です。

次のように置き換えます。

  • CLUSTER_NAME: クラスタの名前。
  • UNIQUE_CLUSTER_DOMAIN: ドメインの名前。GKE はこの値を確認しないため、この名前は VPC 内で必ず一意になるようにしてください。この値は、設定後は変更できません。.local で終わるドメインは使用しないでください。DNS の解決に失敗する可能性があります。

既存の Standard クラスタで追加の VPC スコープを有効にする

既存の Autopilot クラスタで追加の VPC スコープを有効にすることはできません。

既存の Standard クラスタで追加の VPC スコープを有効にするには、次のコマンドを実行します。

gcloud container clusters update CLUSTER_NAME \
    --additive-vpc-scope-dns-domain=UNIQUE_CLUSTER_DOMAIN \
    --location=COMPUTE_LOCATION

次のように置き換えます。

  • CLUSTER_NAME: クラスタの名前。
  • UNIQUE_CLUSTER_DOMAIN: ドメインの名前。GKE はこの値を確認しないため、この名前は VPC 内で必ず一意になるようにしてください。この値は、設定後は変更できません。.local で終わるドメインは使用しないでください。DNS の解決に失敗する可能性があります。
  • COMPUTE_LOCATION: クラスタの Compute Engine のロケーション

VPC スコープ DNS を有効にする

VPC スコープ DNS では、クラスタの DNS 名を VPC 内全体で解決できます。VPC 内のすべてのクライアントが、クラスタ DNS レコードを解決できます。

VPC スコープ DNS を使用すると、次のようなユースケースが可能になります。

  • 同じ VPC 内の GKE 以外のクライアントのヘッドレス サービス ディスカバリ。
  • オンプレミスまたはサードパーティのクラウド クライアントからの GKE Service の解決。詳細については、インバウンド サーバー ポリシーをご覧ください。
  • クライアントがカスタム クラスタの DNS ドメインを使用して通信するクラスタを決定できる Service の解決。

次の図では、2 つの GKE クラスタが同じ VPC 内の VPC スコープ DNS を使用しています。どちらのクラスタにも、デフォルトの .cluster.local ドメインではなく、.cluster1.cluster2 というカスタム DNS ドメインがあります。VM は backend.default.svc.cluster1 を解決して、ヘッドレス バックエンド サービスと通信します。Cloud DNS は、ヘッドレス Service を Service の個々の Pod IP に解決し、VM が Pod IP アドレスと直接通信します。

GKE クラスタの外部からヘッドレス Service に解決するクライアント
図: VPC スコープ DNS

また、Cloud Interconnect または Cloud VPN 経由で VPC に接続するときに、他のネットワークからこのタイプの解決を行うこともできます。DNS サーバー ポリシーを使用すると、VPC に接続されているネットワークのクライアントから Cloud DNS で名前を解決できます。クラスタが VPC スコープ DNS を使用している場合、これには GKE Service が含まれます。

既存のクラスタで VPC スコープを有効にする

VPC スコープへの移行は Standard でのみサポートされており、Autopilot ではサポートされていません。

既存の Standard クラスタを kube-dns から Cloud DNS VPC スコープに移行するには、gcloud CLI または Google Cloud コンソールを使用します。

VPC スコープに移行する場合は、変更を有効にするためにノードを再作成する必要があります。

gcloud

  1. 既存のクラスタを更新します。

    gcloud container clusters update CLUSTER_NAME \
        --cluster-dns=clouddns \
        --cluster-dns-scope=vpc \
        --cluster-dns-domain=CUSTOM_DOMAIN \
        --location=COMPUTE_LOCATION
    

    次のように置き換えます。

    • CLUSTER_NAME: クラスタの名前。
    • COMPUTE_LOCATION: クラスタの Compute Engine のロケーション
    • CUSTOM_DOMAIN: ドメインの名前。GKE はこの値を確認しないため、この名前は VPC 内で必ず一意になるようにしてください。この値は、設定後は変更できません。.local で終わるドメインは使用しないでください。DNS の解決に失敗する可能性があります。

    レスポンスは次の例のようになります。

    All the node-pools in the cluster need to be re-created by the user to start using Cloud DNS for DNS lookups. It is highly recommended to complete this step
    shortly after enabling Cloud DNS.
    Do you want to continue (Y/n)?
    

    確認後、Cloud DNS コントローラは GKE コントロール プレーンで動作するようになります。ノードプールをアップグレードするか、クラスタに新しいノードプールを追加するまで、Pod は DNS 解決に Cloud DNS を使用しません。

  2. Cloud DNS を使用するようにクラスタ内のノードプールをアップグレードします。

    gcloud container clusters upgrade CLUSTER_NAME \
        --node-pool=POOL_NAME
    

    次のように置き換えます。

    • CLUSTER_NAME: クラスタの名前。
    • POOL_NAME: アップグレードするノードプールの名前。

    ノードプールとコントロール プレーンが同じバージョンを実行している場合は、コントロール プレーンの手動アップグレードに従ってコントロール プレーンをアップグレードしてから、ノードプールをアップグレードしてください。

    レスポンスを確認し、クラスタ内のノードプールごとにこのコマンドを繰り返します。クラスタにノードプールが 1 つしかない場合は、--node-pool フラグを省略します。

コンソール

  1. Google Cloud コンソールで [Google Kubernetes Engine] ページに移動します。

    Google Kubernetes Engine に移動

  2. 変更するクラスタの名前をクリックします。

  3. [ネットワーキング] の [DNS プロバイダ] フィールドで、 [DNS プロバイダを編集] をクリックします。

  4. [Cloud DNS] をクリックします。

  5. [VPC スコープ] をクリックします。

  6. [保存] をクリックします。

Cloud DNS を確認する

GKE 用 Cloud DNS がクラスタで正しく動作していることを確認します。

  1. ノード上の Pod に接続し、cat /etc/resolv.conf コマンドを実行して、ノードが Cloud DNS を使用していることを確認します。

    kubectl exec -it POD_NAME -- cat /etc/resolv.conf | grep nameserver
    

    POD_NAME は、Pod の名前で置き換えます。

    クラスタモードに基づいて、出力は次のようになります。

    GKE Autopilot クラスタ

    nameserver 169.254.20.10
    

    GKE Autopilot では NodeLocal DNSCache がデフォルトで有効になっているため、Pod は NodeLocal DNSCache を使用します。

    ローカル キャッシュに検索対象名のエントリがない場合、NodeLocal DNSCache はリクエストを Cloud DNS に転送します。

    GKE Standard クラスタ

    nameserver 169.254.169.254
    

    この Pod の例では、nameserver として 169.254.169.254 を使用しています。これは、Cloud DNS データプレーンがポート 53 でリクエストをリッスンするメタデータ サーバーの IP アドレスです。ノードは kube-dns Service アドレスを DNS 解決に使用しなくなり、すべての DNS 解決がローカルノードで行われます。

    出力が 10.x.y.10 のような IP アドレスの場合、Pod は kube-dns を使用します。Pod がまだ kube-dns を使用している理由については、トラブルシューティングのセクションをご覧ください。

    出力が 169.254.20.10 の場合、クラスタで NodeLocal DNSCache が有効になっており、Pod は NodeLocal DNSCache を使用しています。

  2. サンプル アプリケーションをクラスタにデプロイします。

    kubectl run dns-test --image us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0
    
  3. サンプル アプリケーションを Service で公開します。

    kubectl expose pod dns-test --name dns-test-svc --port 8080
    
  4. Service が正常にデプロイされたことを確認します。

    kubectl get svc dns-test-svc
    

    出力は次のようになります。

    NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
    dns-test-svc   ClusterIP   10.47.255.11    <none>        8080/TCP   6m10s
    

    CLUSTER-IP 列の値は、クラスタの仮想 IP アドレスです。この例の仮想 IP アドレスは 10.47.255.11 です。

  5. Service 名がクラスタの限定公開 DNS ゾーンにレコードとして作成されていることを確認します。

    gcloud dns record-sets list \
        --zone=PRIVATE_DNS_ZONE \
        --name=dns-test-svc.default.svc.DOMAIN_NAME.
    

    次のように置き換えます。

    • PRIVATE_DNS_ZONE: GKE によって作成されたマネージド DNS ゾーンの名前。ゾーン名は、 Google Cloud コンソールの Cloud DNS ゾーンページで確認するか、命名規則をご覧ください。
    • DOMAIN_NAME: 追加の VPC スコープなしでクラスタ スコープを使用する場合は cluster.local、または VPC スコープまたは追加の VPC スコープを有効にしたときに構成したカスタム ドメイン。

    出力は次のようになります。

    NAME: dns-test-svc.default.svc.cluster.local.
    TYPE: A
    TTL: 30
    DATA: 10.47.255.11
    

Standard クラスタで Cloud DNS を無効にする

Cloud DNS がデフォルトで有効になっている状態で作成された Autopilot クラスタでは、Cloud DNS を無効にすることはできません。

Standard で VPC スコープを無効にすることはできません。DNS プロバイダとして kube-dns を使用してクラスタを再作成する必要があります。

Standard クラスタでクラスタ スコープを無効にして kube-dns に戻すには、gcloud CLI またはGoogle Cloud コンソールを使用します。

gcloud

kube-dns を使用するようにクラスタを更新します。

gcloud container clusters update CLUSTER_NAME \
    --cluster-dns=kube-dns \
    --location=COMPUTE_LOCATION

次のように置き換えます。

コンソール

  1. Google Cloud コンソールで [Google Kubernetes Engine] ページに移動します。

    Google Kubernetes Engine に移動

  2. 変更するクラスタの名前をクリックします。

  3. [ネットワーキング] の [DNS プロバイダ] フィールドで、 [DNS プロバイダを編集] をクリックします。

  4. [Kube-dns] をクリックします。

  5. [変更を保存] をクリックします。

Cloud DNS を無効にした後、ノードが解決に kube-dns を使用できるようにするには、ノードプールを再作成する必要があります。以前に kube-dns をゼロノードにスケーリングした場合は、ノードが DNS 解決に使用できるようにする前に、kube-dns をスケールアップする必要があります。ノードプールを再作成しない場合、ノードが再作成されるまで /etc/resolv.conf ファイルが更新されないため、既存のノードの Pod は DNS 解決に Cloud DNS を引き続き使用します。

追加の VPC スコープを無効にする

クラスタに対して追加の VPC スコープを無効にすると、VPC ネットワークに接続されているプライベート ゾーンの DNS レコードのみが削除されます。GKE クラスタのプライベート DNS ゾーン内のレコードは、ヘッドレス Service がクラスタから削除されるまで、GKE 向け Cloud DNS によって管理されます。

追加の VPC スコープを無効にするには、次のコマンドを実行します。

gcloud container clusters update CLUSTER_NAME \
    --disable-additive-vpc-scope

CLUSTER_NAME は、クラスタの名前に置き換えます。

この設定により、Cloud DNS クラスタ スコープが有効なクラスタが維持され、クラスタ内から DNS 解決を行うことができます。

クリーンアップ

このドキュメントの演習を完了したら、次の手順でリソースを削除し、アカウントで不要な請求が発生しないようにします。

  1. 次のコマンドで Service を削除します。

    kubectl delete service dns-test-svc
    
  2. Pod を削除します。

    kubectl delete Pod dns-test
    
  3. クラスタを削除することもできます。

トラブルシューティング

Cloud DNS のトラブルシューティングについては、次のページをご覧ください。

次のステップ