AKS(Azure Kubernetes Service)에서 Azure Firewall을 사용하여 네트워크 트래픽 제한

AKS 클러스터에 대한 아웃바운드 네트워크 및 FQDN 규칙을 통해 AKS에서 Azure Firewall을 사용하여 송신 트래픽을 제어하는 방법을 알아봅니다. 이 구성을 간소화하기 위해 Azure Firewall은 AKS 클러스터에서 아웃바운드 트래픽을 제한하는 Azure Kubernetes Service(AzureKubernetesService) FQDN(정규화된 도메인 이름) 태그를 제공합니다. 이 문서는 Azure Firewall을 통해 AKS 클러스터 트래픽 규칙을 구성하는 방법을 보여 줍니다.

참고 항목

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 컨트롤 플레인에 대한 액세스는 방화벽 공용 프런트 엔드 IP 주소를 포함하는 API 서버 승인 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개)을 사용하여 가상 네트워크를 프로비전합니다. 필요에 따라 내부 서비스를 수신하기 위해 하나를 만들 수 있습니다.

빈 네트워크 토폴로지

  1. az group create 명령을 사용하여 리소스 그룹을 만듭니다.

    az group create --name $RG --location $LOC
    
  2. az network vnet createaz network vnet subnet create 명령을 사용하여 AKS 클러스터와 Azure 방화벽을 호스트하는 두 개의 서브넷이 있는 가상 네트워크를 만듭니다.

    # 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 클러스터에 대한 세분화된 수신 및 송신 트래픽 규칙을 구성할 수 있도록 하는 것입니다.

Important

클러스터나 애플리케이션이 동일하거나 소규모 대상 하위 집합으로 향하는 많은 수의 아웃바운드 연결을 생성하는 경우, 프런트 엔드 IP당 포트 수가 최대가 되지 않도록 더 많은 방화벽 프런트 엔드 IP가 필요할 수 있습니다.

여러 IP가 포함된 Azure Firewall을 만드는 방법에 대한 자세한 내용은 Bicep을 사용하여 여러 공용 IP 주소가 포함된 Azure Firewall 만들기를 참조하세요.

방화벽 및 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 명령을 사용하여 Azure Firewall을 만들고 --enable-dns-proxytrue로 설정하여 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)
    

참고 항목

권한 있는 IP 주소 범위가 있는 AKS API 서버에 대한 보안 액세스를 사용하는 경우 방화벽 공용 IP를 권한 있는 IP 범위에 추가해야 합니다.

홉을 사용하여 Azure Firewall 경로 만들기

Azure는 Azure 서브넷, 가상 네트워크 및 온-프레미스 네트워크 간에 트래픽을 자동으로 라우트합니다. Azure의 기본 라우팅 중 하나를 변경하려는 경우 경로 테이블을 만들 수 있습니다.

Important

아웃바운드 형식의 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을 설정한 경우 AKS는 아웃바운드 요청의 공용 IP 주소를 만들지 않습니다. 자세한 내용은 Azure Load Balancer에 대한 아웃바운드 규칙을 참조하세요.

  1. az network route-table create 명령을 사용하여 지정된 서브넷과 연결할 빈 경로 테이블을 만듭니다. 경로 테이블은 위에서 만든 Azure Firewall로 다음 홉을 정의합니다. 각 서브넷에는 0 또는 하나의 경로 테이블이 연결될 수 있습니다.

    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의 기본 시스템 경로를 재정의하거나 서브넷의 경로 테이블에 추가 경로를 추가하는 방법에 대한 자세한 내용은 가상 네트워크 경로 테이블 설명서를 참조하세요.

방화벽 규칙 추가

참고 항목

API 서버와 통신해야 하는 kube-system 또는 gatekeeper-system 네임스페이스 외부의 애플리케이션의 경우 fqdn 태그 AzureKubernetesService에 대한 애플리케이션 규칙을 추가하는 것 외에도 API 서버 IP에 대한 포트 443에 대한 TCP 통신을 허용하는 추가 네트워크 규칙이 필요합니다.

이 섹션에서는 방화벽에서 구성하는 데 사용할 수 있는 세 가지 네트워크 규칙과 애플리케이션 규칙을 다룹니다. 배포에 따라 이러한 규칙을 조정해야 할 수도 있습니다.

  • 첫 번째 네트워크 규칙은 TCP를 통해 포트 9000에 대한 액세스를 허용합니다.
  • 두 번째 네트워크 규칙은 UDP를 통해 포트 1194 및 123에 대한 액세스를 허용합니다. 21Vianet에서 운영하는 Microsoft Azure에 배포하는 경우 21Vianet 필수 네트워크 규칙에서 운영하는 Azure를 참조하세요. 이러한 두 규칙은 이 문서의 Azure 지역 CIDR(미국 동부)로 향하는 트래픽만 허용합니다.
  • 세 번째 네트워크 규칙은 UDP를 통해 ntp.ubuntu.com FQDN에 포트 123을 엽니다. 네트워크 규칙으로 FQDN을 추가하는 것은 Azure Firewall의 특정 기능 중 하나이므로 사용자 고유의 옵션을 사용할 때 이를 조정해야 합니다.
  • 네 번째 및 다섯 번째 네트워크 규칙을 사용하면 GitHub Container Registry(ghcr.io) 및 Docker 허브(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 서버 액세스를 제한하는 경우 개발자 도구는 방화벽의 가상 네트워크에서 jumpbox를 사용하거나 모든 개발자 엔드포인트를 권한 있는 IP 범위에 추가해야 합니다.


참고 항목

사용자 고유의 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 주소를 추가해야 합니다. 방화벽의 가상 네트워크에서 별도의 서브넷 내에 필요한 도구를 사용하여 jumpbox를 구성할 수도 있습니다.

  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 스토어 데모 빠른 시작 매니페스트를 검토하여 만들어질 모든 리소스를 확인합니다.

  2. kubectl apply 명령을 사용하여 서비스를 배포합니다.

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

Azure Firewall을 통한 인바운드 트래픽 허용

Important

Azure Firewall을 사용하여 송신 트래픽을 제한하고 UDR을 만들어서 모든 송신 트래픽을 강제로 적용하는 경우에는 수신 트래픽을 올바르게 허용하도록 Azure Firewall에서 적절한 DNAT 규칙을 만들어야 합니다. UDR과 함께 Azure Firewall을 사용하면 비대칭 라우팅으로 인해 수신 설정이 손상됩니다. AKS 서브넷에 방화벽의 개인 IP 주소로 이동하는 기본 경로가 있지만 공용 부하 분산 장치(수신 또는 loadBalancer 형식의 Kubernetes 서비스)를 사용하는 경우 문제가 발생할 수 있습니다. 이 경우 들어오는 부하 분산 장치 트래픽은 해당 공용 IP 주소를 통해 수신되지만 반환 경로는 방화벽의 개인 IP 주소를 거칩니다. 방화벽은 상태를 저장하고 방화벽이 설정된 세션을 인식하지 못하므로 반환 패킷을 삭제합니다. Azure Firewall을 수신 또는 서비스 부하 분산 장치와 통합하는 방법을 알아보려면 Azure Firewall을 Azure 표준 Load Balancer와 통합을 참조하세요.

인바운드 연결을 구성하려면 Azure Firewall에 DNAT 규칙을 작성해야 합니다. 클러스터에 대한 연결을 테스트하기 위해 내부 서비스에서 노출되는 내부 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 설명서에 따라 위의 단계를 일반화하여 선호하는 송신 솔루션으로 트래픽을 전달할 수 있습니다.