Skip to main content

Managing Network Security Groups

This guide shows how to create and attach an Azure Network Security Group (NSG) to your AKS cluster's virtual network subnet. NSGs let you control inbound and outbound traffic at the network layer — useful for blocking access to private IP ranges outside your cluster while preserving internal cluster communication and DNS resolution.

Overview

The setup involves:

  1. Identifying your AKS cluster's virtual network and subnet
  2. Creating a Network Security Group
  3. Adding rules in the correct priority order (allow exceptions first, then deny)
  4. Associating the NSG with the AKS subnet
  5. Verifying traffic flows as expected

Prerequisites

  • Access to the Azure subscription containing your AKS cluster
  • The cluster's resource group name and AKS cluster name
  • For CLI: Azure CLI installed and logged in (az login)
  • For Portal: Access to the Azure Portal
warning

NSG changes take effect immediately and can disrupt running workloads. Always test on a development cluster before applying to staging or production.

Only Apply to the AKS Subnet — Not the NIC

Each AKS cluster has an AKS-managed NSG (aks-agentpool-*-nsg) attached to the node NICs in the MC_* resource group. Do not modify that NSG. It is managed by AKS and changes will be overwritten or cause unpredictable behavior. This guide only covers creating and attaching a custom NSG to the AKS VNet subnet.


Rule Design Pattern: Block Private Network Egress

A common use case is blocking outbound traffic to RFC 1918 private IP ranges (other VNets, on-premises networks via peering/VPN) while keeping cluster-internal traffic working. The rule ordering is:

PriorityNameDirectionAccessPurpose
100+allow-dns-*OutboundAllowDNS resolution to specific resolvers
4000allow-selfOutboundAllowIntra-VNet traffic (node-to-node, node-to-pod)
4001block-rfc-1918OutboundDenyBlock all other private IP ranges

NSG rules are evaluated by priority (lowest number first). Allow exceptions must have lower priority numbers than the deny rule so critical traffic isn't blocked.

Priorities Are Suggestions

The priority numbers above are examples. Choose priorities that fit your overall NSG design. Azure NSG priorities range from 100 to 4096 — leave gaps between rules (e.g., increments of 10 or 100) so you have room to insert new rules later for other purposes without renumbering existing ones.

Critical — allow-self Must Precede the Deny Rule in Priority

The allow-self rule is required for cluster operations and must have a lower priority number than block-rfc-1918, and should be the highest-numbered (last-evaluated) allow rule that still needs to bypass that deny. This ensures intra-VNet traffic is allowed right before all other private IP traffic is denied. Without this rule, the RFC 1918 deny will block node-to-node communication, pod scheduling, service routing, DNS resolution within the cluster, and AKS control plane operations. Your cluster will stop functioning.

Here's what the completed ruleset looks like in the Azure Portal, with both custom and default rules visible:

NSG rules in Azure Portal showing the allow-then-deny pattern


Step 1: Find the AKS Virtual Network

  1. Navigate to the Azure Portal
  2. Go to Kubernetes services and select your AKS cluster
  3. In the left menu, click Properties
  4. Under Infrastructure resource group, note the resource group name
  5. Click Networking in the left menu — note the Virtual network and Subnet names

Step 2: Create the Network Security Group

  1. In the portal search bar, type Network security groups and select the service
  2. Click + Create
  3. Fill in:
    • Subscription: Select the subscription containing your AKS cluster
    • Resource group: Use the same resource group as your AKS cluster (not the MC_* infrastructure group)
    • Name: A generic name scoped to the cluster (e.g., <cluster-name>-nsg)
    • Region: Same region as your AKS cluster
  4. Click Review + create, then Create
Naming Convention

A subnet can only have one NSG associated with it, so the NSG will contain rules for multiple purposes over time. Name it after the cluster or environment it protects rather than a specific use case — for example, <cluster-name>-nsg or <environment>-subnet-nsg. Avoid naming it after a single rule set (e.g., block-private-egress) since it will grow to serve broader needs.

Step 3: Add Security Rules

Open your newly created NSG, then click Outbound security rules in the left menu. Add each rule by clicking + Add:

Rule 1: allow-dns-tcp

PriorityNameSourceSource PortsDestinationDest IP/CIDRDest PortsProtocolAction
100allow-dns-tcpAny*IP AddressesYour DNS server IPs53TCPAllow
tip

To find your cluster's DNS resolvers, inspect the resolv.conf on a running pod:

kubectl exec -it <pod-name> -- cat /etc/resolv.conf

Rule 2: allow-dns-udp

PriorityNameSourceSource PortsDestinationDest IP/CIDRDest PortsProtocolAction
110allow-dns-udpAny*IP AddressesYour DNS server IPs53UDPAllow

Rule 3: allow-self

Critical — Do Not Skip

This rule is required for cluster operations and must have a lower priority number than the deny rule, and should be the last allow rule that needs to bypass it. Without it, your cluster will stop functioning.

PriorityNameSourceSource PortsDestinationDest IP/CIDRDest PortsProtocolAction
4000allow-selfAny*VirtualNetwork*AnyAllow

Rule 4: block-rfc-1918

PriorityNameSourceSource PortsDestinationDest IP/CIDRDest PortsProtocolAction
4001block-rfc-1918Any*IP Addresses10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16*AnyDeny

After adding all rules, your outbound rules should look like this:

NSG rules in Azure Portal showing the allow-then-deny pattern

Step 4: Associate the NSG with the AKS Subnet

  1. In the portal, navigate to Virtual networks and select your AKS VNet
  2. Click Subnets in the left menu
  3. Click on your AKS subnet
  4. In the Network security group dropdown, select the NSG you created
  5. Click Save

If your cluster has multiple subnets (e.g., a secondary subnet for additional node pools), repeat this for each subnet that should be protected.


Verify the Configuration

Check NSG association

  1. Navigate to Virtual networks > your VNet > Subnets
  2. Click on your AKS subnet
  3. Confirm the Network security group field shows your NSG

Review rules

  1. Navigate to Network security groups and select your NSG
  2. Click Outbound security rules in the left menu
  3. Verify all four rules are present with the correct priorities, actions, and destinations
  4. Click Inbound security rules and confirm only the default rules exist (unless you added custom inbound rules)

Test from a pod

Start a debug pod with networking tools:

kubectl run debug --rm -it --restart=Never --image=nicolaka/netshoot -- bash

Verify DNS still works:

nslookup google.com

Verify internet egress still works:

curl -s --max-time 5 https://ifconfig.me

Verify private network access is blocked by scanning common ports against an IP in a peered VNet. All connections should time out:

for port in 22 23 53 80 443 8080 8443 3306 5432 6379; do
nc -zv -w 2 <private-ip-in-peered-vnet> $port 2>&1
done

Expected output when the NSG is working — every port times out:

nc: connect to <private-ip-in-peered-vnet> port 22 (tcp) timed out: Operation now in progress
nc: connect to <private-ip-in-peered-vnet> port 23 (tcp) timed out: Operation now in progress
nc: connect to <private-ip-in-peered-vnet> port 53 (tcp) timed out: Operation now in progress
nc: connect to <private-ip-in-peered-vnet> port 80 (tcp) timed out: Operation now in progress
nc: connect to <private-ip-in-peered-vnet> port 443 (tcp) timed out: Operation now in progress
nc: connect to <private-ip-in-peered-vnet> port 8080 (tcp) timed out: Operation now in progress
nc: connect to <private-ip-in-peered-vnet> port 8443 (tcp) timed out: Operation now in progress
nc: connect to <private-ip-in-peered-vnet> port 3306 (tcp) timed out: Operation now in progress
nc: connect to <private-ip-in-peered-vnet> port 5432 (tcp) timed out: Operation now in progress
nc: connect to <private-ip-in-peered-vnet> port 6379 (tcp) timed out: Operation now in progress
tip

If any port returns Connection succeeded or Connection refused instead of timing out, the NSG is not blocking that traffic. Check that the NSG is associated with the correct subnet and that no higher-priority allow rule is matching.


Adding More Allow Exceptions

To permit traffic to specific private IP destinations (e.g., a database in a peered VNet), add an allow rule with a priority lower than the deny rule's priority:

  1. Open your NSG in the Azure Portal
  2. Click Outbound security rules > + Add
  3. Fill in the rule fields (e.g., allow TCP 5432 to a database IP at priority 120)
  4. Click Add
tip

Keep a gap between priority numbers (e.g., 100, 110, 120) so you have room to insert new rules later without renumbering.


Removing the NSG

Disassociate from subnet

  1. Navigate to Virtual networks > your VNet > Subnets
  2. Click on the subnet
  3. Set Network security group to None
  4. Click Save

Delete the NSG

  1. Navigate to Network security groups
  2. Select your NSG
  3. Click Delete and confirm

Troubleshooting

Check effective security rules on a node

Find a node's NIC and inspect the effective rules (combines the custom NSG with the AKS-managed NSG on the node resource group):

# List NICs in the node resource group
az network nic list \
--resource-group <node-resource-group> \
--subscription <subscription> \
--query "[0].name" -o tsv

# View effective rules
az network nic list-effective-nsg \
--name <nic-name> \
--resource-group <node-resource-group> \
--subscription <subscription>

Common issues

IssueCauseSolution
Pods can't resolve DNSDNS allow rules missing or wrong IPsCheck resolv.conf in a pod and update DNS rule destinations
Node-to-node communication brokenallow-self rule missing or lower priority than denyEnsure allow-self priority is lower number than block-rfc-1918
Internet egress brokenNSG shouldn't affect internet — check if a deny-all outbound rule was addedReview rules with az network nsg rule list; default rules allow internet egress
Pods can still reach blocked IPsNSG not associated with subnet, or wrong subnetVerify association with az network vnet subnet show
AKS operations failing (upgrades, scaling)NSG blocking AKS control plane trafficAdd allow rules for AKS API server IPs or use the AzureCloud service tag

AKS-managed NSG vs. custom NSG

Your AKS cluster has two NSGs. Both are evaluated — traffic must be allowed by both to flow:

  1. AKS-managed NSG (aks-agentpool-*-nsg) in the node resource group (MC_*) — managed by AKS, do not modify
  2. Custom NSG (the one from this guide) on the VNet subnet — managed by you