Limitare il traffico di rete con Firewall di Azure nel servizio Azure Kubernetes

Informazioni su come usare le regole di rete in uscita e FQDN per i cluster del servizio Azure Kubernetes per controllare il traffico in uscita usando Firewall di Azure nel servizio Azure Kubernetes. Per semplificare questa configurazione, Firewall di Azure fornisce un tag nome di dominio completo (FQDN) del servizio Azure Kubernetes (AzureKubernetesService) che limita il traffico in uscita dal cluster del servizio Azure Kubernetes. Questo articolo illustra come configurare le regole di traffico del cluster del servizio Azure Kubernetes tramite firewall di Azure.

Nota

Il tag FQDN contiene tutti i nomi di dominio completi elencati nelle regole di rete in uscita e FQDN per i cluster del servizio Azure Kubernetes e viene aggiornato automaticamente.

Per gli scenari di produzione, è consigliabile avere almeno 20 indirizzi IP front-end nel Firewall di Azure per evitare problemi di esaurimento delle porte SNAT.

Le informazioni seguenti forniscono un'architettura di esempio della distribuzione:

Topologia bloccata

  • L’ingresso pubblico viene forzato a passare attraverso i filtri del firewall
    • I nodi dell'agente del servizio Azure Kubernetes sono isolati in una subnet dedicata
    • Il Firewall di Azure viene distribuito nella propria subnet
    • Una regola DNAT converte l'IP pubblico del firewall nell'indirizzo IP front-end del servizio di bilanciamento del carico
  • Le richieste in uscita iniziano dai nodi agente all'indirizzo IP interno del Firewall di Azure usando una route definita dall'utente (UDR)
    • Le richieste provenienti dai nodi agente del servizio Azure Kubernetes seguono una route definita dall'utente che è stata inserita nella subnet in cui è stato distribuito il cluster del servizio Azure Kubernetes
    • Uscite di Firewall di Azure dalla rete virtuale da un front-end IP pubblico
    • L'accesso alla rete Internet pubblica o ad altri servizi di Azure viene trasmesso da e verso l'indirizzo IP front-end del firewall
    • L'accesso al piano di controllo del servizio Azure Kubernetes può essere protetto da intervalli IP autorizzati del server API, incluso l'indirizzo IP front-end pubblico del firewall
  • Traffico interno

Configurare le variabili di ambiente

Definire un set di variabili di ambiente da usare durante la creazione di risorse.

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"

Creare una rete virtuale con più subnet

Effettuare il provisioning di una rete virtuale con due subnet separate: una per il cluster e una per il firewall. Facoltativamente, è possibile crearne una per l'ingresso del servizio interno.

Topologia di rete vuota

  1. Creare un gruppo di risorse usando il comando az group create.

    az group create --name $RG --location $LOC
    
  2. Creare una rete virtuale con due subnet per ospitare il cluster del servizio Azure Kubernetes e firewall di Azure usando i comandi az network vnet create e az network vnet subnet create.

    # 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
    

Creare e configurare un firewall di Azure

È necessario configurare le regole in ingresso e in uscita di Firewall di Azure. Il firewall viene usato principalmente per consentire alle organizzazioni di configurare regole granulari di traffico in ingresso e in uscita all'interno e all'esterno del cluster del servizio Azure Kubernetes.

Importante

Se il cluster o l'applicazione crea un numero elevato di connessioni in uscita dirette allo stesso subset di destinazioni o a un piccolo subset di destinazioni, potrebbe essere necessario un numero maggiore di indirizzi IP front-end del firewall per evitare il numero massimo di porte per IP front-end.

Per altre informazioni su come creare un firewall di Azure con più indirizzi IP, vedere Creare un firewall di Azure con più indirizzi IP pubblici usando Bicep.

Firewall e route definita dall'utente

  1. Creare una risorsa IP pubblico SKU standard usando il comando az network public-ip create. Questa risorsa verrà usata come indirizzo front-end di Firewall di Azure.

    az network public-ip create -g $RG -n $FWPUBLICIP_NAME -l $LOC --sku "Standard"
    
  2. Registrare l'estensione dell'interfaccia della riga di comando di Firewall di Azure per creare un firewall di Azure usando il comando az extension add.

    az extension add --name azure-firewall
    
  3. Creare un firewall di Azure e abilitare il proxy DNS usando il comando az network firewall create e impostando il --enable-dns-proxy su true.

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

La configurazione dell'indirizzo IP pubblico per Firewall di Azure può richiedere alcuni minuti. Una volta pronto, l'indirizzo IP creato in precedenza può essere assegnato al front-end del firewall.

Nota

Per sfruttare il nome di dominio completo nelle regole di rete, è necessario abilitare il proxy DNS. Quando il proxy DNS è abilitato, il firewall è in ascolto sulla porta 53 e inoltra le richieste DNS al server DNS specificato in precedenza. In questo modo il firewall può convertire automaticamente il nome di dominio completo.

  1. Creare una configurazione IP di Firewall di Azure usando il comando az network firewall ip-config create.

    az network firewall ip-config create -g $RG -f $FWNAME -n $FWIPCONFIG_NAME --public-ip-address $FWPUBLICIP_NAME --vnet-name $VNET_NAME
    
  2. Al termine del comando precedente, salvare l'indirizzo IP front-end del firewall per la configurazione in un secondo momento.

    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)
    

Nota

Se si usa l'accesso sicuro al server API del servizio Azure Kubernetes con intervalli di indirizzi IP autorizzati, è necessario aggiungere l'indirizzo IP pubblico del firewall all'intervallo IP autorizzato.

Creare una route con un hop in Firewall di Azure

Azure effettua il routing automatico del traffico tra subnet di Azure, reti virtuali e reti locali. Se si vuole modificare un routing predefinito di Azure, è possibile creare una tabella di route.

Importante

Il tipo in uscita di route definita dall'utente (userDefinedRouting) richiede una route per 0.0.0.0/0 e una destinazione hop successiva dell'appliance virtuale di rete nella tabella di route. La tabella di route ha già un valore predefinito 0.0.0.0/0 su Internet. Senza un indirizzo IP pubblico per Azure da usare per SNAT (Source Network Address Translation), l'aggiunta di questa route non fornirà connettività Internet in uscita. Il servizio Azure Kubernetes convalida che non si crei una route 0.0.0.0/0 diretta a Internet, ma a un gateway, un'appliance virtuale di rete e così via. Quando si usa un tipo di UDR in uscita, non viene creato un indirizzo IP pubblico del servizio di bilanciamento del carico per richieste in ingresso a meno che non si configuri un servizio di tipo bilanciamento del carico. Il servizio Azure Kubernetes non crea mai un indirizzo IP pubblico per le richieste in uscita se si imposta un tipo di route definita dall'utente in uscita. Per altre informazioni, vedere Regole in uscita per Azure Load Balancer.

  1. Creare una tabella di route vuota da associare a una determinata subnet usando il comando az network route-table create. Firewall di Azure creato in precedenza verrà impostato come hop successivo nella tabella di route. A ogni subnet può essere associata una o nessuna tabella di route.

    az network route-table create -g $RG -l $LOC --name $FWROUTE_TABLE_NAME
    
  2. Creare route nella tabella di route per le subnet usando il comando 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
    

Per informazioni su come eseguire l'override delle route di sistema predefinite di Azure o aggiungere altre route alla tabella di route di una subnet, vedere la documentazione della tabella di route di rete virtuale.

Aggiungere regole di firewall

Nota

Per le applicazioni esterne agli spazi dei nomi kube-system o gatekeeper-system che devono comunicare con il server API, è necessaria una regola di rete aggiuntiva per consentire la comunicazione TCP alla porta 443 per l'IP del server API oltre all'aggiunta della regola dell'applicazione per AzureKubernetesService fqdn-tag.

Questa sezione illustra tre regole di rete e una regola dell'applicazione che è possibile usare per configurare nel firewall. Potrebbe essere necessario adattare queste regole in base alla distribuzione.

  • La prima regola di rete consente l'accesso alla porta 9000 tramite TCP.
  • La seconda regola di rete consente l'accesso alla porta 1194 e 123 tramite UDP. Se si esegue la distribuzione in Microsoft Azure gestito da 21Vianet, vedere le regole di rete necessarie per Azure gestito da 21Vianet. Entrambe queste regole consentiranno solo il traffico destinato al CIDR dell'area di Azure in questo articolo, ovvero Stati Uniti orientali.
  • La terza regola di rete apre la porta 123 al nome di dominio completo FQDN ntp.ubuntu.com tramite UDP. L'aggiunta di un nome di dominio completo come regola di rete è una delle funzionalità specifiche di Firewall di Azure, quindi è necessario adattarla quando si usano le proprie opzioni.
  • La quarta e la quinta regola di rete consentono l'accesso ai contenitori di pull dal Registro Contenitori GitHub (ghcr.io) e dall'hub Docker (docker.io).
  1. Creare le regole di rete usando il comando 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. Creare la regola dell'applicazione usando il comando 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
    

Per altre informazioni su Firewall di Azure, vedere la documentazione di Firewall di Azure.

Associare la tabella di route al servizio Azure Kubernetes

Per associare il cluster al firewall, la subnet dedicata per la subnet del cluster deve fare riferimento alla tabella di route creata in precedenza. Usare il comando az network vnet subnet update per associare la tabella di route al servizio Azure Kubernetes.

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

Distribuire un cluster del servizio Azure Kubernetes che segue le regole in uscita

È ora possibile distribuire un cluster del servizio Azure Kubernetes nella rete virtuale esistente. Si userà il tipo in uscitauserDefinedRouting, che garantisce che qualsiasi traffico in uscita venga forzato attraverso il firewall e non esistano altri percorsi in uscita. È anche possibile usare il tipo in uscita loadBalancer.

aks-deploy

Per definire la subnet di destinazione in cui eseguire la distribuzione, si usa la variabile di ambiente $SUBNETID. Impostare il valore per l'ID subnet usando il comando seguente:

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

Si definirà il tipo in uscita per usare la route definita dall'utente già esistente nella subnet. Questa configurazione consentirà al servizio Azure Kubernetes di ignorare l'installazione e il provisioning IP per il servizio di bilanciamento del carico.

Suggerimento

È possibile aggiungere funzionalità aggiuntive alla distribuzione del cluster, ad esempio cluster privati.

È possibile aggiungere la funzionalità servizio Azure Kubernetes per intervalli IP autorizzati del server API per limitare l'accesso del server API solo all'endpoint pubblico del firewall. La funzionalità degli intervalli IP autorizzati è indicata nel diagramma come facoltativo. Quando si abilita la funzionalità degli intervalli IP autorizzati per limitare l'accesso al server API, gli strumenti di sviluppo devono usare un JumpBox dalla rete virtuale del firewall, oppure è necessario aggiungere tutti gli endpoint sviluppatore all'intervallo di indirizzi IP autorizzati.


Nota

Il servizio Azure Kubelet creerà un'identità kubelet assegnata dal sistema nel gruppo di risorse del nodo se non si specifica la propria identità gestita kubelet.

Per il routing definito dall'utente, l'identità assegnata dal sistema supporta solo il plug-in di rete CNI.

Creare un cluster del servizio Azure Kubernetes usando un'identità gestita assegnata dal sistema con il plug-in di rete CNI usando il comando az aks create.

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

Consentire agli sviluppatori di accedere al server API

Se nel passaggio precedente sono stati usati intervalli IP autorizzati per il cluster, è necessario aggiungere gli indirizzi IP degli strumenti di sviluppo all'elenco di cluster del servizio Azure Kubernetes degli intervalli IP approvati in modo da accedere al server API da questa posizione. È anche possibile configurare un jumpbox con gli strumenti necessari all'interno di una subnet separata nella rete virtuale del firewall.

  1. Recuperare l'indirizzo IP usando il comando seguente:

    CURRENT_IP=$(dig @resolver1.opendns.com ANY myip.opendns.com +short)
    
  2. Aggiungere l'indirizzo IP agli intervalli approvati usando il comando az aks update.

    az aks update -g $RG -n $AKSNAME --api-server-authorized-ip-ranges $CURRENT_IP/32
    
  3. Configurare kubectl per connettersi al cluster del servizio Azure Kubernetes usando il comando az aks get-credentials.

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

Distribuire un servizio pubblico nel servizio Azure Kubernetes

È ora possibile iniziare a esporre i servizi e distribuire applicazioni in questo cluster. In questo esempio verrà esposto un servizio pubblico, ma è anche possibile esporre un servizio interno usando un servizio di bilanciamento del carico interno.

DNAT del servizio pubblico

  1. Esaminare il manifesto di avvio rapido della demo dello Store del servizio Azure Kubernetes per visualizzare tutte le risorse che verranno create.

  2. Distribuire il servizio usando il comando kubectl apply.

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

Consentire il traffico in ingresso tramite Firewall di Azure

Importante

Quando si usa Firewall di Azure per limitare il traffico in uscita e creare una route definita dall'utente per forzare tutto il traffico in uscita, assicurarsi di creare una regola DNAT appropriata in Firewall di Azure per consentire correttamente il traffico in ingresso. L'uso del servizio Firewall di Azure con una route definita dall'utente interrompe la configurazione in ingresso a causa del routing asimmetrico. Questo problema si verifica se la subnet del servizio Azure Kubernetes ha una route predefinita verso l'indirizzo IP privato del firewall, ma si sta usando un servizio di bilanciamento del carico pubblico in ingresso o del servizio Kubernetes di tipo loadBalancer. In questo caso, il traffico del servizio di bilanciamento del carico in ingresso viene ricevuto tramite l'indirizzo IP pubblico, ma il percorso di ritorno passa attraverso l'indirizzo IP privato del firewall. Poiché il firewall è con stato, elimina il pacchetto di ritorno perché il firewall non è a conoscenza del fatto che è stata stabilita una sessione. Per informazioni su come integrare Firewall di Azure con il servizio di bilanciamento del carico in ingresso o del servizio, vedere Integrare Firewall di Azure con Azure Load Balancer Standard.

Per configurare la connettività in ingresso, è necessario scrivere una regola DNAT in Firewall di Azure. Per testare la connettività al cluster, viene definita una regola per l'indirizzo IP pubblico del front-end del firewall da indirizzare all'IP interno esposto dal servizio interno. L'indirizzo di destinazione può essere personalizzato. L'indirizzo convertito deve essere l'indirizzo IP del bilanciamento del carico interno. La porta convertita deve essere la porta esposta per il servizio Kubernetes. È anche necessario specificare l'indirizzo IP interno assegnato al servizio di bilanciamento del carico creato dal servizio Kubernetes.

  1. Ottenere l'indirizzo IP interno assegnato al servizio di bilanciamento del carico usando il comando kubectl get services.

    kubectl get services
    

    L'indirizzo IP verrà elencato nella colonna EXTERNAL-IP, come illustrato nell'output di esempio seguente:

    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. Ottenere l'indirizzo IP del servizio usando il comando kubectl get svc voting-app.

    SERVICE_IP=$(kubectl get svc store-front -o jsonpath='{.status.loadBalancer.ingress[*].ip}')
    
  3. Aggiungere la regola NAT usando il comando az network firewall nat-rule create.

    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
    

Convalidare la connettività

In un browser accedere all'indirizzo IP front-end di Firewall di Azure per convalidare la connettività.

Verrà visualizzata l'app dello Store del servizio Azure Kubernetes. In questo esempio, l'indirizzo IP pubblico del firewall era 52.253.228.132.

Screenshot che mostra l'app front di Azure Store aperta in un browser locale.

In questa pagina è possibile visualizzare i prodotti, aggiungerli al carrello e quindi effettuare un ordine.

Pulire le risorse

Per pulire le risorse di Azure, eliminare il gruppo di risorse del servizio Azure Kubernetes usando il comando az group delete.

az group delete -g $RG

Passaggi successivi

In questo articolo si è appreso come proteggere il traffico in uscita usando Firewall di Azure. Se necessario, è possibile generalizzare i passaggi precedenti per inoltrare il traffico alla soluzione di uscita preferita seguendo la documentazione userDefinedRoute di tipo in uscita .