Azure Kubernetes Service (AKS) で Azure Firewall を使用してネットワーク トラフィックを制限する

AKS クラスターのアウトバウンド ネットワークと FQDN の規則を使用して、AKS の Azure Firewall を使用してエグレス トラフィックを制御する方法について学習します。 この構成を簡略化するために、Azure Firewall には、AKS クラスターからの送信トラフィックを制限する Azure Kubernetes Service (AzureKubernetesService) 完全修飾ドメイン名 (FQDN) タグが用意されています。 この記事では、Azure Firewall を介して AKS クラスターのトラフィック規則を構成する方法を示します。

Note

FQDN タグには、「AKS クラスターのアウトバウンド ネットワークと FQDN の規則」に記載されているすべての FQDN が含まれており、自動的に更新されます。

運用環境のシナリオでは、SNAT ポート不足の問題を回避するために、Azure Firewall に "少なくとも 20 個のフロントエンド IP" を用意することをお勧めします。

次の情報は、デプロイのアーキテクチャの例を示しています。

ロック ダウンされたトポロジ

  • パブリック イングレスは、強制的にファイアウォール フィルターを経由します
    • AKS エージェント ノードは専用サブネットに分離されています
    • Azure Firewall は独自のサブネットにデプロイされています
    • DNAT 規則により、ファイアウォールのパブリック IP がロード バランサーフロントエンド IP に変換されます
  • 送信要求は、ユーザー定義ルート (UDR) を使用して、エージェント ノードから Azure Firewall 内部 IP に対して開始されます
    • AKS エージェント ノードからの要求は、AKS クラスターがデプロイされたサブネットに設定されている UDR に従います
    • Azure Firewall は、パブリック IP フロントエンドから仮想ネットワークを出ます
    • パブリック インターネットまたはその他の Azure サービスへのアクセスは、ファイアウォール フロントエンド IP アドレスを送信先と送信元として行われます。
    • AKS コントロール プレーンへのアクセスは、API サーバーの許可された IP 範囲 (ファイアウォールのパブリック フロントエンド IP アドレスを含みます) によって保護できます
  • 内部トラフィック

環境変数を構成する

リソースの作成に使用する一連の環境変数を定義します。

PREFIX="aks-egress"
RG="${PREFIX}-rg"
LOC="eastus"
PLUGIN=azure
AKSNAME="${PREFIX}"
VNET_NAME="${PREFIX}-vnet"
AKSSUBNET_NAME="aks-subnet"
# DO NOT CHANGE FWSUBNET_NAME - This is currently a requirement for Azure Firewall.
FWSUBNET_NAME="AzureFirewallSubnet"
FWNAME="${PREFIX}-fw"
FWPUBLICIP_NAME="${PREFIX}-fwpublicip"
FWIPCONFIG_NAME="${PREFIX}-fwconfig"
FWROUTE_TABLE_NAME="${PREFIX}-fwrt"
FWROUTE_NAME="${PREFIX}-fwrn"
FWROUTE_NAME_INTERNET="${PREFIX}-fwinternet"

複数のサブネットを含んだ仮想ネットワークを作成する

クラスター用とファイアウォール用の 2 つの異なるサブネットを持つ仮想ネットワークをプロビジョニングします。 必要に応じて、内部サービス イングレス用のものを作成できます。

空のネットワーク トポロジ

  1. az group create コマンドを使用して、リソース グループを作成します。

    az group create --name $RG --location $LOC
    
  2. az network vnet create および az network vnet subnet create コマンドを使用して、AKS クラスターと Azure Firewall をホストするための 2 つのサブネットを含む仮想ネットワークを作成します。

    # Dedicated virtual network with AKS subnet
    az network vnet create \
        --resource-group $RG \
        --name $VNET_NAME \
        --location $LOC \
        --address-prefixes 10.42.0.0/16 \
        --subnet-name $AKSSUBNET_NAME \
        --subnet-prefix 10.42.1.0/24
    
    # Dedicated subnet for Azure Firewall (Firewall name can't be changed)
    az network vnet subnet create \
        --resource-group $RG \
        --vnet-name $VNET_NAME \
        --name $FWSUBNET_NAME \
        --address-prefix 10.42.2.0/24
    

Azure Firewall を作成して設定する

Azure Firewall のインバウンドおよびアウトバウンド規則を構成する必要があります。 ファイアウォールの主な目的は、組織が AKS クラスターに対してきめ細かなイングレスおよびエグレス トラフィック規則を構成できるようにすることです。

重要

クラスターまたはアプリケーションにより、同じ送信先または送信先の小さいサブセットに対して多数の送信接続が作成される場合、フロントエンド IP あたりのポート数の上限に達するのを防ぐため、より多くのファイアウォール フロントエンド IP が必要になることがあります。

複数の IP を使用して Azure ファイアウォールを作成する方法の詳細については、Bicep を使用して複数のパブリック IP アドレスを含む Azure ファイアウォールを作成する方法に関する記事を参照してください。

ファイアウォールと UDR

  1. az network public-ip create コマンドを使用して、標準 SKU パブリック IP リソースを作成します。 このリソースは、Azure Firewall フロントエンド アドレスとして使用されます。

    az network public-ip create -g $RG -n $FWPUBLICIP_NAME -l $LOC --sku "Standard"
    
  2. Azure Firewall CLI 拡張機能を登録し、az extension add コマンドを使用して Azure Firewall を作成します。

    az extension add --name azure-firewall
    
  3. az network firewall create コマンドを使用し、--enable-dns-proxytrue に設定して、Azure ファイアウォールの作成と DNS プロキシの有効化を行います。

    az network firewall create -g $RG -n $FWNAME -l $LOC --enable-dns-proxy true
    

Azure Firewall へのパブリック IP アドレスの設定には数分かかる場合があります。 準備が完了したら、以前に作成した IP アドレスをファイアウォール フロントエンドに割り当てることができます。

注意

ネットワーク規則で FQDN を利用するには、DNS プロキシを有効にする必要があります。 DNS プロキシが有効になると、ファイアウォールによって、ポート 53 がリッスンされ、上記で指定された DNS サーバーに DNS 要求が転送されます。 これにより、ファイアウォールでは FQDN を自動的に変換できます。

  1. az network firewall ip-config create コマンドを使用して、Azure Firewall IP 構成を作成します。

    az network firewall ip-config create -g $RG -f $FWNAME -n $FWIPCONFIG_NAME --public-ip-address $FWPUBLICIP_NAME --vnet-name $VNET_NAME
    
  2. 前のコマンドが正常に完了したら、後で構成できるようにファイアウォールのフロントエンド IP アドレスを保存します。

    FWPUBLIC_IP=$(az network public-ip show -g $RG -n $FWPUBLICIP_NAME --query "ipAddress" -o tsv)
    FWPRIVATE_IP=$(az network firewall show -g $RG -n $FWNAME --query "ipConfigurations[0].privateIPAddress" -o tsv)
    

Note

承認済み IP アドレス範囲で AKS API サーバーへのセキュリティで保護されたアクセスを使用する場合は、承認された IP 範囲にファイアウォール パブリック IP を追加する必要があります。

Azure Firewall へのホップを含むルートを作成する

Azure では、Azure のサブネット、仮想ネットワーク、およびオンプレミスのネットワーク間のトラフィックが自動的にルーティングされます。 Azure の既定のルーティングを変更する場合は、ルート テーブルを作成できます。

重要

送信の種類の UDR (userDefinedRouting) には、ルート テーブルに 0.0.0.0/0 へのルートと、NVA のネクスト ホップ宛先が存在している必要があります。 ルート テーブルには、インターネットに対するデフォルトの 0.0.0.0/0 が既に存在します。 Azure でソース ネットワーク アドレス変換 (SNAT) に使用されるパブリック IP アドレスがない場合、このルートを追加するだけでは送信インターネット接続は提供されません。 AKS は、インターネットを指す 0.0.0.0/0 のルートが作成されておらず、ゲートウェイや NVA などを指すルートが作成されたことを検証します。送信の種類の UDR を使用する場合、loadbalancer の種類のサービスが構成されていない限り、受信要求用ロード バランサーのパブリック IP アドレスは作成されません。 送信の種類の UDR を設定した場合、送信要求用パブリック IP アドレスが AKS によって作成されることはありません。 詳細については、Azure Load Balancer のアウトバウンド規則に関するページを参照してください。

  1. az network route-table create コマンドを使用して、特定のサブネットに関連付ける空のルート テーブルを作成します。 ルート テーブルには、次のホップを以前の手順で作成した Azure Firewall と定義します。 各サブネットには、0 個または 1 個のルート テーブルを関連付けることができます。

    az network route-table create -g $RG -l $LOC --name $FWROUTE_TABLE_NAME
    
  2. az network route-table route create コマンドを使用して、サブネットのルート テーブルにルートを作成します。

    az network route-table route create -g $RG --name $FWROUTE_NAME --route-table-name $FWROUTE_TABLE_NAME --address-prefix 0.0.0.0/0 --next-hop-type VirtualAppliance --next-hop-ip-address $FWPRIVATE_IP
    
    az network route-table route create -g $RG --name $FWROUTE_NAME_INTERNET --route-table-name $FWROUTE_TABLE_NAME --address-prefix $FWPUBLIC_IP/32 --next-hop-type Internet
    

Azure の既定のシステム ルートをオーバーライドする方法や、サブネットのルート テーブルにさらにルートを追加する方法については、仮想ネットワークのルート テーブルに関するドキュメントを参照してください。

ファイアウォール規則を追加する

注意

kube-system または gatekeeper-system 名前空間の外部にあるアプリケーションが API サーバーと通信する必要がある場合は、fqdn-tag AzureKubernetesService に対するアプリケーション規則の追加に加えて、API サーバー IP 用のポート443 への TCP 通信を許可する追加のネットワーク規則が必要です。

このセクションでは、3 つのネットワーク規則と、ファイアウォールで構成するために使用できるアプリケーション規則について説明します。 デプロイに基づいてこれらの規則を調整することが必要な場合があります。

  • 最初のネットワーク規則では、TCP 経由でのポート 9000 へのアクセスを許可します。
  • 2 つ目のネットワーク規則では、UDP 経由でのポート 1194 と 123 へのアクセスを許可します。 21Vianet によって運営される Microsoft Azure にデプロイする場合は、「21Vianet によって運営される Microsoft Azure で必要なネットワーク規則」を参照してください。 どちらの規則でも、この記事の Azure リージョン CIDR (米国東部) 宛てのトラフィックのみが許可されます。
  • 3 つ目のネットワーク規則では、UDP 経由の ntp.ubuntu.com FQDN に対してポート 123 を開きます。 ネットワーク規則として FQDN を追加することは、Azure Firewall の固有の機能の 1 つであるため、独自のオプションを使用する場合はそれを調整する必要があります。
  • 4 番目と 5 番目のネットワーク規則により、GitHub Container Registry (ghcr.io) と Docker Hub (docker.io) からコンテナーをプルするためのアクセスが許可されます。
  1. az network firewall network-rule create コマンドを使用して、ネットワーク 規則を作成します。

    az network firewall network-rule create -g $RG -f $FWNAME --collection-name 'aksfwnr' -n 'apiudp' --protocols 'UDP' --source-addresses '*' --destination-addresses "AzureCloud.$LOC" --destination-ports 1194 --action allow --priority 100
    
    az network firewall network-rule create -g $RG -f $FWNAME --collection-name 'aksfwnr' -n 'apitcp' --protocols 'TCP' --source-addresses '*' --destination-addresses "AzureCloud.$LOC" --destination-ports 9000
    
    az network firewall network-rule create -g $RG -f $FWNAME --collection-name 'aksfwnr' -n 'time' --protocols 'UDP' --source-addresses '*' --destination-fqdns 'ntp.ubuntu.com' --destination-ports 123
    
    az network firewall network-rule create -g $RG -f $FWNAME --collection-name 'aksfwnr' -n 'ghcr' --protocols 'TCP' --source-addresses '*' --destination-fqdns ghcr.io pkg-containers.githubusercontent.com --destination-ports '443'
    
    az network firewall network-rule create -g $RG -f $FWNAME --collection-name 'aksfwnr' -n 'docker' --protocols 'TCP' --source-addresses '*' --destination-fqdns docker.io registry-1.docker.io production.cloudflare.docker.com --destination-ports '443'
    
  2. az network firewall application-rule create コマンドを使用して、アプリケーション規則を作成します。

    az network firewall application-rule create -g $RG -f $FWNAME --collection-name 'aksfwar' -n 'fqdn' --source-addresses '*' --protocols 'http=80' 'https=443' --fqdn-tags "AzureKubernetesService" --action allow --priority 100
    

Azure Firewall の詳細については、Azure Firewall のドキュメントを参照してください。

ルート テーブルを AKS に関連付ける

クラスターをファイアウォールに関連付けるには、クラスターのサブネットの専用サブネットから、以前の手順で作成したルート テーブルを参照する必要があります。 az network vnet subnet update コマンドを使用して、ルート テーブルを AKS に関連付けます。

az network vnet subnet update -g $RG --vnet-name $VNET_NAME --name $AKSSUBNET_NAME --route-table $FWROUTE_TABLE_NAME

アウトバウンド規則に従って AKS クラスターをデプロイする

これで、AKS クラスターを既存の仮想ネットワークにデプロイできます。 userDefinedRouting 送信の種類を使用します。これにより、すべての送信トラフィックが強制的にファイアウォールを経由し、他のエグレス パスが存在しないようになります。 loadBalancer 送信の種類を使用することもできます。

aks-deploy

デプロイ先のターゲット サブネットは、環境変数 $SUBNETID で定義します。 次のコマンドを使用して、サブネット ID の値を設定します。

SUBNETID=$(az network vnet subnet show -g $RG --vnet-name $VNET_NAME --name $AKSSUBNET_NAME --query id -o tsv)

サブネット上に既に存在する UDR を使用するように、送信の種類を定義します。 この構成により、AKS ではロード バランサーに対するセットアップと IP のプロビジョニングをスキップできるようになります。

ヒント

プライベート クラスターなどのさらなる機能をクラスターのデプロイに追加できます。

API サーバーの許可された IP 範囲に対して AKS 機能を追加して、API サーバーのアクセスをファイアウォールのパブリック エンドポイントのみに制限できます。 許可された IP 範囲の機能は、図ではオプションとして示されています。 許可された IP 範囲機能を有効にして API サーバーへのアクセスを制限する場合、開発者ツールでファイアウォールの仮想ネットワークからのジャンプボックスを使用するか、許可された IP 範囲にすべての開発者エンドポイントを追加する必要があります。


Note

独自の kubelet マネージド ID を指定しない場合、AKS はノード リソース グループにシステム割り当て kubelet ID を作成します。

ユーザー定義ルーティングの場合、システム割り当て ID でサポートされるのは CNI ネットワーク プラグインのみです。

az aks create コマンドを使用して、CNI ネットワーク プラグインでシステム割り当てマネージド ID を使用する AKS クラスターを作成します。

az aks create -g $RG -n $AKSNAME -l $LOC \
  --node-count 3 \
  --network-plugin azure \
  --outbound-type userDefinedRouting \
  --vnet-subnet-id $SUBNETID \
  --api-server-authorized-ip-ranges $FWPUBLIC_IP

開発者の API サーバーへのアクセスを有効にする

前の手順で、許可された IP 範囲をクラスターに使用した場合、それらから API サーバーにアクセスするために、許可された IP 範囲の AKS クラスター一覧に開発者ツールの IP アドレスを追加する必要があります。 ファイアウォールの仮想ネットワーク内の別のサブネット内に必要なツールを使用してジャンプボックスを構成することもできます。

  1. 次のコマンドを使用して IP アドレスを取得します。

    CURRENT_IP=$(dig @resolver1.opendns.com ANY myip.opendns.com +short)
    
  2. az aks update コマンドを使用して、許可された範囲に IP アドレスを追加します。

    az aks update -g $RG -n $AKSNAME --api-server-authorized-ip-ranges $CURRENT_IP/32
    
  3. az aks get-credentials コマンドを使用して、AKS クラスターに接続するように kubectl を構成します。

    az aks get-credentials -g $RG -n $AKSNAME
    

AKS にパブリック サービスをデプロイする

サービスの公開と、このクラスターへのアプリケーションのデプロイを始めることができます。 この例では、パブリック サービスを公開しますが、内部ロード バランサーを使用して内部サービスを公開することもできます。

パブリック サービスの DNAT

  1. AKS Store Demo のクイック スタート マニフェストを確認して、作成されるすべてのリソースを確認します。

  2. kubectl apply コマンドを使用して、サービスをデプロイします。

    kubectl apply -f https://raw.githubusercontent.com/Azure-Samples/aks-store-demo/main/aks-store-quickstart.yaml
    

Azure Firewall 経由の受信トラフィックを許可する

重要

Azure Firewall を使用してエグレス トラフィックを制限し、すべてのエグレス トラフィックに強制するUDR を作成する場合は、イグレス トラフィックを正しく許可するために、Azure Firewall に適切な DNAT 規則を作成するようにしてください。 UDR で Azure Firewall を使用すると、非対称ルーティングによってイングレス設定が機能しなくなります AKS サブネットにファイアウォールのプライベート IP アドレスに送信される既定のルートがあるのに、種類が loadBalancer であるイングレスまたは Kubernetes サービスのパブリック ロード バランサーを使用している場合、この問題が発生します。 この場合、ロード バランサーの受信トラフィックはパブリック IP アドレス経由で受信されますが、復路のパスはファイアウォールのプライベート IP アドレスを通過します。 ファイアウォールはステートフルであり、確立済みのセッションを認識しないため、返されるパケットは破棄されます。 Azure Firewall をイングレスまたはサービスのロード バランサーと統合する方法については、「Azure Firewall と Azure Standard Load Balancer を統合する」を参照してください。

受信接続を構成するには、DNAT 規則を Azure Firewall に記述する必要があります。 クラスターへの接続をテストするために、内部サービスによって公開されている内部 IP にルーティングされるように、ファイアウォール フロントエンド パブリック IP アドレスの規則を定義します。 宛先アドレスはカスタマイズできます。 変換されたアドレスは、内部ロード バランサーの IP アドレスである必要があります。 変換されたポートは、Kubernetes サービスの公開ポートである必要があります。 また、Kubernetes サービスによって作成されたロード バランサーに割り当てられた内部 IP アドレスを指定する必要があります。

  1. kubectl get services コマンドを使用して、ロード バランサーに割り当てられた内部 IP アドレスを取得します。

    kubectl get services
    

    次の出力例に示すように、IP アドレスが EXTERNAL-IP 列に表示されます。

    NAME              TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)              AGE
    kubernetes        ClusterIP      10.0.0.1       <none>        443/TCP              9m10s
    order-service     ClusterIP      10.0.104.144   <none>        3000/TCP             11s
    product-service   ClusterIP      10.0.237.60    <none>        3002/TCP             10s
    rabbitmq          ClusterIP      10.0.161.128   <none>        5672/TCP,15672/TCP   11s
    store-front       LoadBalancer   10.0.89.139    20.39.18.6    80:32271/TCP         10s
    
  2. kubectl get svc voting-app コマンドを使用して、サービス IP を取得します。

    SERVICE_IP=$(kubectl get svc store-front -o jsonpath='{.status.loadBalancer.ingress[*].ip}')
    
  3. az network firewall nat-rule create コマンドを使用して、NAT 規則を追加します。

    az network firewall nat-rule create --collection-name exampleset --destination-addresses $FWPUBLIC_IP --destination-ports 80 --firewall-name $FWNAME --name inboundrule --protocols Any --resource-group $RG --source-addresses '*' --translated-port 80 --action Dnat --priority 100 --translated-address $SERVICE_IP
    

接続の検証

ブラウザーで Azure Firewall フロントエンド IP アドレスに移動して、接続を検証します。

AKS ストア アプリが表示されます。 この例では、ファイアウォールのパブリック IP は 52.253.228.132 でした。

ローカル ブラウザーで開かれた、Azure Store Front アプリを示すスクリーンショット。

このページでは、製品を表示し、カートに追加して注文することができます。

リソースをクリーンアップする

Azure リソースをクリーンアップするには、az group delete コマンドを使用して AKS リソース グループを削除します。

az group delete -g $RG

次のステップ

この記事では、Azure Firewall を使用して送信トラフィックをセキュリティで保護する方法について説明しました。 必要に応じて、上記の手順を一般化して、送信の種類 userDefinedRoute に関するドキュメントに従い、好みのエグレス ソリューションにトラフィックを転送できます。