Azure Firewall을 사용하여 AKS(Azure Kubernetes Service) 클러스터 보호
이 문서에서는 Azure Firewall을 사용하여 아웃바운드 및 인바운드 트래픽을 보호하여 AKS(Azure Kubernetes Service) 클러스터를 보호하는 방법을 보여줍니다.
배경
AKS(Azure Kubernetes Service)는 Azure에서 관리되는 Kubernetes 클러스터를 제공합니다. 자세한 내용은 Azure Container Service를 참조하세요.
AKS는 완전 관리형 솔루션이지만 클러스터와 외부 네트워크 간의 수신 및 송신 트래픽을 보호하는 기본 제공 솔루션을 제공하지 않습니다. Azure Firewall은 이에 대한 솔루션을 제공합니다.
AKS 클러스터는 가상 네트워크에 배포됩니다. 이 네트워크는 관리하거나(AKS에서 생성) 사용자 지정(사용자가 미리 구성)할 수 있습니다. 두 경우 모두 클러스터에는 해당 가상 네트워크 외부의 서비스에 대한 아웃바운드 종속성이 있습니다(서비스에 인바운드 종속성이 없음). 관리와 운영을 목적으로 AKS 클러스터의 노드는 특정 포트 및 이러한 아웃바운드 종속성을 설명하는 FQDN(정규화된 도메인 이름)에 액세스해야 합니다. 이는 Kubernetes API 서버와 통신하는 노드를 포함하되 이에 국한되지 않는 다양한 함수에 필요합니다. 핵심 Kubernetes 클러스터 구성 요소 및 노드 보안 업데이트를 다운로드 및 설치하거나 MCR(Microsoft Container Registry) 등에서 기본 시스템 컨테이너 이미지를 끌어옵니다. 이러한 아웃바운드 종속성은 FQDN으로 거의 완전히 정의되며 뒤에 고정 주소가 없습니다. 고정 주소가 없으면 네트워크 보안 그룹을 사용하여 AKS 클러스터의 아웃바운드 트래픽을 잠글 수 없습니다. 이러한 이유로 기본적으로 AKS 클러스터에는 무제한 아웃바운드(송신) 인터넷 액세스가 있습니다. 이러한 수준의 네트워크 액세스가 있으면 사용자가 실행하는 노드와 서비스는 필요할 때마다 외부 리소스에 액세스할 수 있습니다.
그러나 프로덕션 환경에서는 다른 취약성과 함께 데이터 반출을 방지하기 위해 Kubernetes 클러스터와의 통신을 보호해야 합니다. 들어오고 나가는 모든 네트워크 트래픽은 일련의 보안 규칙에 따라 모니터링 및 제어되어야 합니다. 이렇게 하려면 송신 트래픽을 제한해야 하지만, 정상 클러스터 유지 관리 작업을 유지하고 앞에서 언급한 아웃바운드 종속성을 충족하려면 제한된 수의 포트 및 주소에 계속 액세스할 수 있어야 합니다.
가장 간단한 솔루션은 도메인 이름을 기반으로 아웃바운드 트래픽을 제어할 수 있는 방화벽 디바이스를 사용합니다. 방화벽은 일반적으로 신뢰할 수 있는 네트워크와 신뢰할 수 없는 네트워크(예: 인터넷) 사이에 장벽을 설정합니다. 예를 들어 Azure Firewall은 대상의 FQDN을 기반으로 아웃바운드 HTTP 및 HTTPS 트래픽을 제한하여 세분화된 송신 트래픽 제어를 제공하지만 동시에 AKS 클러스터의 아웃바운드 종속성을 포함하는 FQDN에 대한 액세스를 제공할 수 있습니다(NSG에서 수행할 수 없는 작업). 마찬가지로, 공유 경계 네트워크에 배포된 Azure Firewall에서 위협 인텔리전스 기반 필터링을 사용하도록 설정하여 수신 트래픽을 제어하고 보안을 향상시킬 수 있습니다. 이러한 필터링은 경고를 제공하고 알려진 악성 IP 주소 및 도메인과 주고받는 트래픽을 거부할 수 있습니다.
샘플 환경에서 실제로 작동하는 방식에 대한 빠른 개요는 다음 비디오를 참조하세요.
비디오에 사용된 샘플 환경을 자동으로 구성하는 bash 스크립트 파일과 yaml 파일이 포함된 zip 파일은 Microsoft 다운로드 센터에서 다운로드할 수 있습니다. 이 파일은 수신 및 송신 트래픽을 모두 보호하도록 Azure Firewall 구성합니다. 다음 가이드는 사용자 지정 구성을 설정할 수 있도록 스크립트의 각 단계를 자세히 안내합니다.
다음 다이어그램은 스크립트 및 가이드가 구성하는 비디오의 샘플 환경을 보여줍니다.
스크립트와 다음 가이드 사이에는 한 가지 차이점이 있습니다. 스크립트는 관리 ID를 사용하지만 가이드에서는 서비스 주체를 사용합니다. 이를 통해 클러스터 리소스를 관리하고 만드는 ID를 만드는 두 가지 다른 방법을 보여줍니다.
Azure Firewall을 사용하여 송신 트래픽 제한
환경 변수를 통한 구성 설정
리소스 만들기에 사용할 환경 변수 집합을 정의합니다.
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개)을 사용하여 가상 네트워크를 만듭니다. 필요에 따라 내부 서비스를 수신하기 위해 하나를 만들 수도 있습니다.
모든 리소스를 저장할 리소스 그룹을 만듭니다.
# Create Resource Group
az group create --name $RG --location $LOC
AKS 클러스터 및 Azure 방화벽을 호스트하는 두 개의 서브넷이 있는 가상 네트워크를 만듭니다. 각각에는 고유한 서브넷이 있습니다. AKS 네트워크부터 시작해 보겠습니다.
# 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 cannot be changed)
az network vnet subnet create \
--resource-group $RG \
--vnet-name $VNET_NAME \
--name $FWSUBNET_NAME \
--address-prefix 10.42.2.0/24
UDR을 사용하여 Azure Firewall 만들기 및 설정
Azure Firewall 인바운드 및 아웃바운드 규칙을 구성해야 합니다. 방화벽의 주요 목적은 조직에서 AKS 클러스터에 대한 세분화된 수신 및 송신 트래픽 규칙을 구성할 수 있도록 하는 것입니다.
Important
클러스터나 애플리케이션이 동일하거나 소규모 대상 하위 집합으로 향하는 많은 수의 아웃바운드 연결을 생성하는 경우, 프런트 엔드 IP당 포트 수가 최대가 되지 않도록 더 많은 방화벽 프런트 엔드 IP가 필요할 수 있습니다. 여러 IP로 Azure Firewall을 만드는 방법에 대한 자세한 내용은 여기를 참조하세요.
Azure Firewall 프런트 엔드 주소로 사용되는 표준 SKU 공용 IP 리소스를 만듭니다.
az network public-ip create -g $RG -n $FWPUBLICIP_NAME -l $LOC --sku "Standard"
Azure Firewall을 만들려면 미리 보기 CLI 확장을 등록합니다.
# Install Azure Firewall preview CLI extension
az extension add --name azure-firewall
# Deploy Azure Firewall
az network firewall create -g $RG -n $FWNAME -l $LOC --enable-dns-proxy true
이제 이전에 만든 IP 주소를 방화벽 프런트 엔드에 할당할 수 있습니다.
참고 항목
Azure Firewall에 대한 공용 IP 주소를 설정하는 데 몇 분 정도 걸릴 수 있습니다. 네트워크 규칙에서 FQDN을 사용하려면 DNS 프록시를 사용하도록 설정해야 합니다. 사용하도록 설정되면 방화벽은 포트 53에서 수신 대기되며 앞서 지정한 DNS 서버로 DNS 요청을 전달합니다. 그러면 방화벽에서 FQDN을 자동으로 변환할 수 있습니다.
# Configure Firewall IP Config
az network firewall ip-config create -g $RG -f $FWNAME -n $FWIPCONFIG_NAME --public-ip-address $FWPUBLICIP_NAME --vnet-name $VNET_NAME
이전 명령이 성공한 경우 나중에 구성할 수 있도록 방화벽 프런트 엔드 IP 주소를 저장합니다.
# Capture Firewall IP Address for Later Use
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에 대한 UDR 만들기
Azure는 Azure 서브넷, 가상 네트워크 및 온-프레미스 네트워크 간에 트래픽을 자동으로 라우트합니다. Azure의 기본 라우팅 중 하나를 변경하려면 경로 테이블을 만듭니다.
지정된 서브넷과 연결할 빈 경로 테이블을 만듭니다. 경로 테이블은 앞서 만든 Azure Firewall로 다음 홉을 정의합니다. 각 서브넷에는 0 또는 하나의 경로 테이블이 연결될 수 있습니다.
# Create UDR and add a route for Azure Firewall
az network route-table create -g $RG -l $LOC --name $FWROUTE_TABLE_NAME
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에 대한 액세스를 허용합니다. 이러한 두 규칙은 모두 사용 중인 Azure 지역 CIDR(이 경우 미국 동부)로 향하는 트래픽만 허용합니다.
마지막으로 UDP를 통해 인터넷 시간 서버 FQDN(예: ntp.ubuntu.com
)에 포트 123을 여는 세 번째 네트워크 규칙을 추가합니다. 네트워크 규칙으로 FQDN을 추가하는 것은 Azure Firewall의 특정 기능 중 하나이며 사용자 고유의 옵션을 사용할 때 이를 조정해야 합니다.
네트워크 규칙을 설정한 후에는 필요한 모든 FQDN을 포함한 AzureKubernetesService
를 사용하는 애플리케이션 규칙도 추가하며 이 FQDN은 TCP 포트 443 및 포트 80을 통해 액세스할 수 있습니다. 또한 배포에 따라 더 많은 네트워크 및 애플리케이션 규칙을 구성해야 할 수도 있습니다. 자세한 내용은 AKS(Azure Kubernetes Service) 클러스터에 대한 아웃바운드 네트워크 및 FQDN 규칙을 참조하세요.
FW 네트워크 규칙 추가
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
FW 애플리케이션 규칙 추가
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에 경로 테이블 연결
클러스터를 방화벽과 연결하려면 클러스터의 서브넷에 대한 전용 서브넷이 앞서 만든 경로 테이블을 참조해야 합니다. 클러스터와 방화벽을 모두 보유하는 가상 네트워크에 대한 명령을 실행하여 클러스터의 서브넷에 대한 경로 테이블을 업데이트하면 연결을 수행할 수 있습니다.
# Associate route table with next hop to Firewall to the AKS subnet
az network vnet subnet update -g $RG --vnet-name $VNET_NAME --name $AKSSUBNET_NAME --route-table $FWROUTE_TABLE_NAME
아웃바운드 형식의 UDR을 사용하여 기존 네트워크에 AKS 배포
이제 AKS 클러스터는 기존 가상 네트워크로 배포될 수 있습니다. 아웃바운드 유형userDefinedRouting
도 사용합니다. 이 기능은 모든 아웃바운드 트래픽이 방화벽을 통과하고 다른 송신 경로가 존재하지 않도록 합니다(기본적으로 부하 분산 장치 아웃바운드 유형을 사용할 수 있음).
배포할 대상 서브넷은 환경 변수 $SUBNETID
로 정의됩니다. 이전 단계에서는 $SUBNETID
변수를 정의하지 않았습니다. 서브넷 ID의 값을 설정하려면 다음 명령을 사용할 수 있습니다.
SUBNETID=$(az network vnet subnet show -g $RG --vnet-name $VNET_NAME --name $AKSSUBNET_NAME --query id -o tsv)
서브넷에 이미 있는 UDR을 사용하도록 아웃바운드 유형을 정의합니다. 이 구성을 통해 AKS는 부하 분산 장치에 대한 설정 및 IP 프로비전을 건너뛸 수 있습니다.
Important
제한 사항을 포함한 아웃바운드 유형 UDR에 대한 자세한 내용은 송신 아웃바운드 유형 UDR을 참조하세요.
팁
프라이빗 클러스터 및 OS SKU 변경과 같은 추가 기능을 클러스터 배포에 추가할 수 있습니다.
API 서버 권한 있는 IP 범위에 대해 AKS 기능을 추가하여 API 서버 액세스를 방화벽의 공용 엔드포인트로만 제한할 수 있습니다. 권한 있는 IP 범위 기능은 다이어그램에서 선택 사항으로 표시됩니다. 권한 있는 IP 범위 기능을 사용하도록 설정하여 API 서버 액세스를 제한하는 경우 개발자 도구는 방화벽의 가상 네트워크에서 jumpbox를 사용하거나 모든 개발자 엔드포인트를 권한 있는 IP 범위에 추가해야 합니다.
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
참고 항목
kubenet
네트워크 플러그 인으로 자체 VNet 및 경로 테이블을 만들고 사용하려면 사용자가 할당한 관리 ID를 사용해야 합니다. 시스템이 할당한 관리 ID의 경우 클러스터를 만들기 전에는 ID를 가져올 수 없으므로 역할 할당 적용이 지연됩니다.
azure
네트워크 플러그 인을 사용하여 고유한 VNet 및 경로 테이블을 만들고 사용하기 위해 시스템 할당 및 사용자 할당 관리 ID가 모두 지원됩니다.
API 서버에 대한 개발자 액세스 사용
이전 단계에서 클러스터에 대해 권한 있는 IP 범위를 사용한 경우 여기에서 API 서버에 액세스하려면 권한 있는 IP 범위의 AKS 클러스터 목록에 개발자 도구 IP 주소를 추가해야 합니다. 또 다른 옵션은 Firewall의 가상 네트워크에서 별도의 서브넷 내에 필요한 도구를 사용하여 jumpbox를 구성하는 것입니다.
다음 명령을 사용하여 승인된 범위에 또 다른 IP 주소를 추가합니다.
# Retrieve your IP address
CURRENT_IP=$(dig @resolver1.opendns.com ANY myip.opendns.com +short)
# Add to AKS approved list
az aks update -g $RG -n $AKSNAME --api-server-authorized-ip-ranges $CURRENT_IP/32
az aks get-credentials 명령을 사용하여 새롭게 만든 Kubernetes 클러스터에 연결하도록 kubectl
을 구성합니다.
az aks get-credentials -g $RG -n $AKSNAME
Azure Firewall을 사용하여 수신 트래픽 제한
이제 이 클러스터에 서비스 공개 및 애플리케이션 배포를 시작할 수 있습니다. 이 예제에서는 공용 서비스를 제공하지만 내부 부하 분산 장치를 통해 내부 서비스를 제공하도록 선택할 수도 있습니다.
AKS 스토어 데모 빠른 시작 매니페스트를 검토하여 만들어질 모든 리소스를 확인합니다.
kubectl apply
명령을 사용하여 서비스를 배포합니다.kubectl apply -f https://raw.githubusercontent.com/Azure-Samples/aks-store-demo/main/aks-store-quickstart.yaml
Azure Firewall에 DNAT 규칙 추가
Important
Azure Firewall을 사용하여 송신 트래픽을 제한하고 UDR(사용자 정의 경로)을 만들어서 모든 송신 트래픽을 강제로 적용하는 경우에는 수신 트래픽을 올바르게 허용하도록 방화벽에서 적절한 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 주소를 지정해야 합니다. 다음을 실행하여 주소를 검색합니다.
kubectl get services
필요한 IP 주소는 다음과 유사하게 EXTERNAL-IP 열에 나열됩니다.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.41.0.1 <none> 443/TCP 10h
store-front LoadBalancer 10.41.185.82 203.0.113.254 80:32718/TCP 9m
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
다음을 실행하여 서비스 IP를 가져옵니다.
SERVICE_IP=$(kubectl get svc store-front -o jsonpath='{.status.loadBalancer.ingress[*].ip}')
다음을 실행하여 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가 203.0.113.32
였습니다.
이 페이지에서 제품을 보고 카트에 추가해서 주문할 수 있습니다.
리소스 정리
Azure 리소스를 정리하려면 AKS 리소스 그룹을 삭제합니다.
az group delete -g $RG
다음 단계
- Azure Kubernetes Service에 대한 자세한 내용은 AKS(Azure Kubernetes service)에 대한 Kubernetes 핵심 개념을 참조하세요.