You add the office VPN's public address to the AKS API server allowlist, and kubectl works. A week later a node pool scale-up fails, a CI job cannot reach the cluster, and the portal shows an error that mentions nothing about IP ranges. Nobody changed the allowlist. The control you enabled is a public IP filter in front of the API server, and it has no idea who is calling, only which address the call came from. The VPN is one address among several that the cluster needs, and it is rarely the one that breaks first.

The allowlist matches an address, not a person

--api-server-authorized-ip-ranges takes CIDR blocks, not users or groups. When a developer's request leaves the VPN server for Azure, the source address at the API server is the VPN server's public egress. Every person on that VPN therefore shares one entry, and anyone off the VPN is refused before authentication even happens.

That also means the entry admits more people than you may intend. A contractor with VPN access, a personal laptop on the same concentrator, and a compromised account all arrive from the same address. Cluster authorization is unchanged, so role-based access control still decides what the caller may do, but the allowlist is not an identity control and should never be described as one.

What breaks first is usually not kubectl

The allowlist applies to the API server's public endpoint, so anything outside your listed addresses stops working at once. The obvious casualties are the second office without a VPN route, a CI runner in a hosted pipeline, and a laptop that forgot to connect. Those are easy to recognise because a human is waiting.

The less obvious case is automation that Azure or your own tooling drives. Some platform-initiated operations reach the API server from addresses that are not your VPN, and when one of them starts failing right after the list is tightened, the timing is the clue. Do not assume the list is complete because interactive access works; check what the feature requires for your region and subscriptions before you conclude the cluster is broken.

The failure signature helps. If the request never reaches authentication, it is the filter. If it authenticates and then gets a permission error, the filter did its job and the problem is role-based access control, which the allowlist never touches.

Build the whole list in one command

The update parameter replaces the entire list rather than adding an entry, so a command that carries only the VPN address silently drops everything else that was there. Read the current value first, keep it, and send the union:

az aks show -g rg-app -n aks-prod \
  --query apiServerAccessProfile.authorizedIpRanges -o tsv

az aks update -g rg-app -n aks-prod \
  --api-server-authorized-ip-ranges 203.0.113.10/32,198.51.100.0/24

Use a reserved public IP for the VPN server before you rely on this. A dynamic address changes on reconnect, and every change quietly locks the team out of the cluster until someone updates the list from a network that is still allowed. If you have two VPN egress points for redundancy, list both, because the filter has no concept of a preferred path.

Sequence the change so the first permitted attempt is also the test. Announce the new list, apply it, and connect from the VPN immediately; doing it in the other order leaves a window where nobody can reach the API server to fix a typo in a CIDR block.

What the allowlist never covered

It does not make the API server private. A private cluster uses a private endpoint and private DNS, and the authorized-ranges list is not the control that replaces it. It also does not change what an admitted caller can do, so a leaked admin kubeconfig still works from any permitted address. Treat the credential as the security boundary and the list as a network convenience.

It has nothing to do with workloads. Pods and Services keep running with the list enabled, and reaching an application over the VPN is a separate problem: a Service that only has a cluster IP still needs an internal load balancer, an ingress, or a port-forward before a laptop can open it. Mixing those two designs produces a change ticket that claims to restrict developers and actually restricts nothing about the applications.

Verify from both sides, then run one real operation

Test with a fresh client on the VPN and with a client outside it. The outside attempt should be refused at the API server, not at name resolution; if the name does not resolve, you are testing DNS and have learned nothing about the filter. Then run one operation that is not an interactive kubectl call, such as a node pool scale or an upgrade check, and confirm it completes rather than assuming it will.

Keep the previous list value recorded next to the change, and re-read the effective value after the update instead of trusting the command that was typed. The AKS authorized IP ranges documentation lists the supported parameters and the platform requirements that belong in the same list, which is the part most ticket descriptions leave out.

ບົດຄວາມທີ່ກ່ຽວຂ້ອງ