FQDN ネットワーク ポリシーを使用して Pod の下り(外向き)トラフィックを制御する


このページでは、完全修飾ドメイン名(FQDN)を使用して、Pod と Google Kubernetes Engine(GKE)クラスタ外のリソース間の下り(外向き)通信を制御する方法について説明します。FQDN の構成に使用するカスタム リソースは、FQDNNetworkPolicy リソースです。

始める前に

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

  • Google Kubernetes Engine API を有効にする。
  • Google Kubernetes Engine API の有効化
  • このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化する。すでに gcloud CLI をインストールしている場合は、gcloud components update を実行して最新のバージョンを取得する。

要件と制限事項

FQDNNetworkPolicy リソースには、次の要件と制限事項があります。

  • 次のいずれかのバージョンを実行している GKE クラスタが必要です。
    • 1.26.4-gke.500 以降
    • 1.27.1-gke.400 以降
  • クラスタで GKE Dataplane V2 を使用する必要があります。
  • GKE クラスタの DNS プロバイダの kube-dns または Cloud DNS を使用する必要があります。カスタム kube-dns や Core DNS のデプロイはサポートされていません。
  • Google Cloud CLI バージョン 462.0.0 以降。
  • Windows ノードプールはサポートされていません。
  • Cloud Service Mesh はサポートされていません。
  • アプリケーションに IP アドレスをハードコードしている場合は、FQDNNetworkPolicy ではなく、Kubernetes NetworkPolicyIPBlock フィールドを使用します。
  • resolv.conf の代替ネームサーバーなど、クラスタ以外の DNS ネームサーバーによって返された結果は、GKE データプレーンの許可リストへの登録に有効とみなされません。
  • FQDNNetworkPolicy が解決できる IPv4 および IPv6 の IP アドレスの最大数は 50 です。
  • ClusterIP または Headless Service へのトラフィックを FQDNNetworkPolicy の下り(外向き)宛先として許可することはできません。これは、GKE がネットワーク ポリシールールを評価する前に、Service の仮想 IP アドレス(VIP)をバックエンド Pod の IP アドレスに変換するためです。代わりに、Kubernetes ラベルベースの NetworkPolicy を使用してください。
  • ホスト名あたりの IP アドレスの割り当て上限は 100 です。
  • FQDN ネットワーク ポリシーでは、ノード間の透過的な暗号化はサポートされていません。

FQDN ネットワーク ポリシーを有効にする

FQDN ネットワーク ポリシーは、新規または既存のクラスタで有効にできます。

新しいクラスタで FQDN ネットワーク ポリシーを有効にする

--enable-fqdn-network-policy フラグを使用してクラスタを作成します。

gcloud container clusters create CLUSTER_NAME  \
    --enable-fqdn-network-policy

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

既存のクラスタで FQDN ネットワーク ポリシーを有効にする

  1. Autopilot クラスタと Standard クラスタの両方で、--enable-fqdn-network-policy フラグを使用してクラスタを更新します。

    gcloud container clusters update CLUSTER_NAME  \
        --enable-fqdn-network-policy
    

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

  2. Standard クラスタの場合のみ、GKE Dataplane V2 anetd DaemonSet を再起動します。

    kubectl rollout restart ds -n kube-system anetd
    

FQDNNetworkPolicy を作成する

  1. 次のマニフェストを fqdn-network-policy.yaml として保存します。

    apiVersion: networking.gke.io/v1alpha1
    kind: FQDNNetworkPolicy
    metadata:
      name: allow-out-fqdnnp
    spec:
      podSelector:
        matchLabels:
          app: curl-client
      egress:
      - matches:
        - pattern: "*.yourdomain.com"
        - name: "www.google.com"
        ports:
        - protocol: "TCP"
          port: 443
    

    このマニフェストには次のプロパティがあります。

    • name: www.google.com: 完全修飾ドメイン名。www.google.com に関連付けられたネームサーバーによって提供される IP アドレスは許可されます。namepattern のいずれか、または両方を指定する必要があります。
    • pattern: "*.yourdomain.com": このパターンに一致するネームサーバーによって提供される IP アドレスが許可されます。パターンキーには、^([a-zA-Z0-9*]([-a-zA-Z0-9_*]*[a-zA-Z0-9*])*\.?)*$ の正規表現を使用できます。一致条件は加算方式です。複数の pattern フィールドを使用できます。namepattern のいずれか、または両方を指定する必要があります。
    • protocol: "TCP"port: 443: プロトコルとポートを指定します。Pod がこのプロトコルとポートの組み合わせを使用して IP アドレスへの接続を確立しようとすると、名前解決は機能しますが、データプレーンはアウトバウンド接続をブロックします。このフィールドは省略可能です。
  2. ネットワーク ポリシーによってワークロードが選択されていることを確認します。

    kubectl describe fqdnnp
    

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

    Name:         allow-out-fqdnnp
    Labels:       <none>
    Annotations:  <none>
    API Version:  networking.gke.io/v1alpha1
    Kind:         FQDNNetworkPolicy
    Metadata:
    ...
    Spec:
      Egress:
        Matches:
          Pattern:  *.yourdomain.com
          Name:     www.google.com
        Ports:
          Port:      443
          Protocol:  TCP
      Pod Selector:
        Match Labels:
          App: curl-client
    Events:     <none>
    

FQDNNetworkPolicy を削除する

FQDNNetworkPolicy を削除するには、kubectl delete fqdnnp コマンドを使用します。

kubectl delete fqdnnp FQDN_POLICY_NAME

FQDN_POLICY_NAME は、FQDNNetworkPolicy の名前で置き換えます。

GKE はポリシーの適用からルールを削除しますが、既存の接続は conntrack 標準プロトコル ガイドラインに従って終了するまでアクティブなままです。

FQDN ネットワーク ポリシーの仕組み

FQDNNetworkPolicies は、選択した Pod がトラフィックを送信できるエンドポイントを制御する下り(外向き)専用のポリシーです。Kubernetes NetworkPolicy と同様に、ワークロードを選択する FQDNNetworkPolicy は、許可された下り(外向き)の宛先として指定されていないエンドポイントに暗黙の拒否ルールを作成します。FQDNNetworkPolicy と NetworkPolicy で説明されているように、FQDNNetworkPolicies は Kubernetes NetworkPolicies で使用できます。

FQDNNetworkPolicies は、IP アドレスとポートのレベルで適用されます。レイヤ 7 プロトコル情報(HTTP リクエストの Request-URI など)を使用して適用されることはありません。指定されたドメイン名は、GKE クラスタの DNS プロバイダが提供する DNS 情報を使用して IP アドレスに変換されます。

DNS リクエスト

ワークロードを選択するアクティブな FQDNNetworkPolicy は、ワークロードによる DNS リクエスト機能に影響しません。nslookupdig などのコマンドは、ポリシーの影響を受けずにどのドメインでも機能します。ただし、許可リストにないドメインのバックアップに使用する IP アドレスへの後続のリクエストは破棄されます。

たとえば、FQDNNetworkPolicywww.github.com への下り(外向き)を許可する場合、すべてのドメインの DNS リクエストは許可されますが、twitter.com をバッキングする IP アドレスに送信されたトラフィックは破棄されます。

TTL の有効期限

FQDNNetworkPolicy は、DNS レコードで指定された TTL を適用します。DNS レコードの TTL が経過した後に、Pod が期限切れの IP アドレスに接続しようとすると、新しい接続が拒否されます。継続時間が DNS レコードの TTL を超える長時間継続する接続ではトラフィックが中断することはありませんが、conntrack ではその接続がまだアクティブであると見なされます。

FQDNNetworkPolicy と NetworkPolicy

FQDNNetworkPolicyNetworkPolicy の両方が同じ Pod に適用される場合、Pod のラベルがポリシーで構成されているものと一致すると、いずれかのポリシーに一致する限り、下り(外向き)トラフィックが許可されます。IP アドレスまたはラベルセレクタを指定する下り(外向き)NetworkPolicies と、FQDNNetworkPolicies の間に階層はありません。

共有 IP アドレスのエンドポイント(ロードバランサ、CDN、VPN ゲートウェイなど)

多くのドメインにはドメインをサポートする専用の IP アドレスがなく、代わりに共有 IP アドレスを使用して公開されます。これは、アプリケーションがロードバランサまたは CDN によって提供される場合に特に頻繁に発生します。たとえば、Google Cloud APIs(compute.googleapis.comcontainer.googleapis.com など)には、API ごとに一意の IP アドレスが割り振られていません。代わりに、すべての API は共有範囲を使用して公開されます。

FQDNNetworkPolicies を構成するときは、許可されたドメインが専用 IP アドレスと共有 IP アドレスのどちらを使用しているかを考慮することが重要です。FQDNNetworkPolicies は IP アドレスとポートのレベルで適用されるため、同じ IP アドレスによって提供される複数のドメインを区別することはできません。共有 IP アドレスをバックエンドとするドメインへのアクセスを許可すると、Pod はその IP アドレスで提供される他のすべてのドメインと通信できるようになります。たとえば、compute.googleapis.com へのトラフィックを許可すると、Pod は他の Google Cloud APIs とも通信できるようになります。

CNAME 追跡

DNS レコードに CNAME を含むドメインが FQDNNetworkPolicy の FQDN オブジェクトに含まれている場合は、信頼性の高い FQDNNetworkPolicy の動作を実現するために、Pod から直接クエリできるすべてのドメイン名(エイリアスを含む)で FQDNNetworkPolicy を構成する必要があります。

Pod が example.com をクエリする場合は、example.com をルールに記述します。アップストリーム DNS サーバーからエイリアス チェーン(例: example.comexample.cdn.com1.2.3.4)が返された場合でも、FQDN ネットワーク ポリシーは引き続きトラフィックの通過を許可します。

既知の問題

このセクションでは、完全修飾ドメイン名(FQDN)の既知の問題をすべて示します。

protocol: ALL を指定するとポリシーが無視される

この既知の問題は、GKE バージョン 1.27.10-gke.1055000 以降と 1.28.3-gke.1055000 以降で修正されています。

ports セクションに protocol: ALL を指定する FQDNNetworkPolicy を作成しても、GKE はポリシーを適用しません。この問題は、ポリシーの解析に問題があることが原因で発生します。TCP または UDP を指定しても、この問題は発生しません。

回避策として、ports エントリに protocol を指定しない場合、デフォルトではルールがすべてのプロトコルと一致します。protocol: ALL を削除すると、解析の問題が回避され、GKE によって FQDNNetworkPolicy が適用されます。

GKE バージョン 1.27.10-gke.1055000 以降と 1.28.3-gke.1055000 以降では、protocol: ALL を含むポリシーが正しく解析され、適用されます。

NetworkPolicy ロギングでログが正しくないか、欠落する

この既知の問題は、GKE バージョン 1.27.10-gke.1055000 以降と 1.28.2-gke.1157000+ 以降で修正されています。

クラスタでネットワーク ポリシー ロギングと FQDN ネットワーク ポリシーを使用している場合、ログエントリが欠落したり、誤ったログエントリが記録される可能性のあるバグが存在します。

委任のないネットワーク ポリシー ロギングを使用すると、ワークロードを離れた DNS 接続のポリシーログに、トラフィックのドロップが誤って報告されます。トラフィック自体は(FQDNNetworkPolicy によって)許可されましたが、ログが正しくありませんでした。

委任のあるネットワーク ポリシー ロギングを使用する場合、ポリシーログはありません。トラフィック自体に影響はありません。

このバグは、GKE バージョン 1.27.10-gke.105500 以降と 1.28.2-gke.1157000 以降で修正されています。NetworkPolicy または FQDNNetworkPolicy によってトラフィックが選択された場合、DNS 接続が「ALLOWED」として正しくロギングされるようになりました。

次のステップ