This repository contains Terraform configuration to deploy a private Azure Kubernetes Service (AKS) cluster with Cloud Shell VNet integration for secure access.
- Private AKS Cluster with API Server VNet Integration
- Custom VNet with multiple subnets for isolation
- Azure CNI Overlay networking
- Standard Load Balancer
- Private DNS zones (AKS API, Storage, Relay)
- User-assigned managed identity
- Cloud Shell infrastructure with VNet integration
- Azure Relay with private endpoint
- Storage account with Azure AD authentication (no shared keys)
- Private endpoints for all services
- Network Security Groups for Cloud Shell
This cluster can be configured for network isolation using one of two approaches:
- Limitation: Only works when VNet is managed by AKS
- Our configuration: Uses custom VNet, so this option is not available
- Sets
bootstrap_profile.artifact_source = "Cache" - AKS automatically creates and manages a private ACR
- Compatible: Works with custom VNet configurations like ours
- Requirements:
- Create Premium SKU ACR with private endpoint
- Configure ACR cache rule:
aks-managed-mcr→mcr.microsoft.com/*→aks-managed-repository/* - Set up private DNS zone for ACR (
privatelink.azurecr.io) - Grant AcrPull role to kubelet identity
- Configure
bootstrap_profilewithartifact_source = "Cache"andcontainer_registry_id - Set
outbound_type = "none"in network profile
For complete BYO ACR setup instructions, see: Network isolated AKS with BYO ACR
- Kubernetes Version: 1.32.9
- Network Plugin: Azure CNI Overlay
- Network Mode: Overlay
- Pod CIDR: 10.244.0.0/16
- Service CIDR: 10.0.0.0/16
- DNS Service IP: 10.0.0.10
- Private Cluster: Enabled with VNet Integration
- Outbound Type: loadBalancer (can be changed to "none" with BYO ACR for full network isolation)
- API Server Subnet: 10.1.2.0/24
- Node Subnet: 10.1.1.0/24
- Private FQDN: pvt-example-zjte58so.c5dd28a6-e22c-45f1-8bda-cced0f182bd4.private.westus3.azmk8s.io
This cluster is configured as a network isolated cluster, which means:
- No outbound internet access - The cluster has zero outbound connectivity (
outbound_type = "none") - AKS-managed ACR for bootstrapping - AKS creates and manages a private Azure Container Registry that caches all required images from Microsoft Artifact Registry (MAR)
- Private artifact source - All cluster components and images are pulled from the AKS-managed private ACR, eliminating dependency on public endpoints
- Data exfiltration protection - Prevents any data from leaving the cluster network without explicit configuration
This configuration is ideal for organizations with strict security and compliance requirements that need to eliminate risks of data exfiltration.
For more information, see: Network isolated AKS clusters
The deployment creates a single VNet (10.1.0.0/16) with the following subnets:
- aks-subnet (10.1.1.0/24) - AKS node pool
- api-server-subnet (10.1.2.0/24) - AKS API server VNet integration
- cloudshellsubnet (10.1.3.0/24) - Cloud Shell containers (delegated to Microsoft.ContainerInstance/containerGroups)
- relaysubnet (10.1.4.0/24) - Azure Relay private endpoint
- storagesubnet (10.1.5.0/24) - Storage account private endpoints
- Azure CLI logged in (
az login) - Terraform >= 1.11.4
- AzureRM Provider >= 4.54.0
- Subscription with appropriate permissions for:
- Creating managed identities
- Deploying AKS clusters
- Creating private endpoints
- Configuring Cloud Shell
- Navigate to the default directory and copy the example tfvars:
cd default
cp terraform.tfvars.example terraform.tfvars-
Edit
terraform.tfvarsto customize values (cluster name, storage account name, relay namespace name, etc.) -
Initialize and apply the Terraform configuration:
terraform init
terraform plan
terraform apply -auto-approve-
Activate Cloud Shell with VNet integration:
- Open Azure Portal
- Click on Cloud Shell icon
- Click Configure button
- Select the existing resources:
- Storage account:
csshellstorage<random> - File share:
acsshare - Relay namespace:
arn-cloudshell-westus3 - Network profile:
aci-networkProfile-westus3
- Storage account:
- Cloud Shell will deploy a container instance in the
cloudshellsubnet
-
Access the private cluster from Cloud Shell:
# Get cluster credentials
az aks get-credentials --resource-group rg-private-cluster --name private-cluster
# Verify connectivity
kubectl get nodes
kubectl cluster-infoThe deployment creates:
- Resource Group:
rg-private-cluster - Virtual Network:
vnet-private-cluster(10.1.0.0/16) - AKS Cluster:
private-cluster(Kubernetes 1.32) - System node pool: 1 node (Standard_DS2_v2)
- Storage Account: Azure AD authentication only (shared access keys disabled)
- File Share: 50 GB quota for Cloud Shell
- Azure Relay: Private endpoint connectivity for Cloud Shell
- Network Profile: Container network interface for Cloud Shell
To customize, modify variables in terraform.tfvars.
resource_group_name- The resource group namecluster_name- The AKS cluster namecloudshell_storage_account_name- Storage account for Cloud Shellcloudshell_relay_namespace_name- Azure Relay namespace for Cloud Shellcloudshell_container_subnet_id- Subnet ID for Cloud Shell containerskubeconfig- The cluster credentials (sensitive)
This cluster uses a custom VNet configuration, which means:
- AKS-managed ACR is not supported - Requires AKS-managed VNet
- BYO ACR required for network isolation - You must bring your own Premium SKU ACR
- Current configuration: Standard outbound connectivity via load balancer
To achieve full network isolation with this custom VNet setup:
- Create a Premium SKU Azure Container Registry
- Configure private endpoint for ACR in the VNet
- Set up ACR cache rule as documented in the BYO ACR guide
- Update the Terraform configuration with ACR resource ID
- Change
outbound_typeto "none"
See: Network isolated AKS with BYO ACR
The storage account is configured with:
- Azure AD authentication only (
shared_access_key_enabled = false) - Private endpoints only (
public_network_access_enabled = false) - Terraform provider setting:
storage_use_azuread = true(required in provider block)
Since this is a private cluster with API server VNet integration:
- Direct kubectl access requires network connectivity to the VNet
- Cloud Shell with VNet integration provides secure access from the same VNet
- Alternative: Use
az aks command invokefor one-off commands without VNet connectivity
The Terraform deployment creates all infrastructure components, but Cloud Shell requires one-time Portal activation:
- Infrastructure (Terraform) - VNet, subnets, storage, relay, network profile, DNS zones ✅
- Service Activation (Portal) - Click "Configure" to deploy the actual container instance
If you see connection timeouts or errors like:
Unable to connect to the server: dial tcp: lookup <fqdn> on 168.63.129.16:53: no such host
This is expected when accessing from outside the VNet. Use Cloud Shell with VNet integration or az aks command invoke.
If Terraform fails with "Key based authentication is not permitted":
- Ensure
storage_use_azuread = trueis set in the provider block - The subscription may have Azure Policy enforcing Azure AD authentication
To destroy all resources:
terraform destroy -auto-approve