From 002a40cea1ca5f5795792512533c5737e644a77f Mon Sep 17 00:00:00 2001 From: asudbring Date: Wed, 5 Aug 2026 17:10:54 +0100 Subject: [PATCH 1/6] Add 101-aks-automatic-custom-network quickstart sample Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../101-aks-automatic-custom-network/main.tf | 100 ++++++++++++++++++ .../outputs.tf | 23 ++++ .../providers.tf | 17 +++ .../readme.md | 41 +++++++ .../variables.tf | 53 ++++++++++ 5 files changed, 234 insertions(+) create mode 100644 quickstart/101-aks-automatic-custom-network/main.tf create mode 100644 quickstart/101-aks-automatic-custom-network/outputs.tf create mode 100644 quickstart/101-aks-automatic-custom-network/providers.tf create mode 100644 quickstart/101-aks-automatic-custom-network/readme.md create mode 100644 quickstart/101-aks-automatic-custom-network/variables.tf diff --git a/quickstart/101-aks-automatic-custom-network/main.tf b/quickstart/101-aks-automatic-custom-network/main.tf new file mode 100644 index 000000000..c8d3db86c --- /dev/null +++ b/quickstart/101-aks-automatic-custom-network/main.tf @@ -0,0 +1,100 @@ +# Create a random name for the resource group using random_pet +resource "random_pet" "rg_name" { + prefix = var.resource_group_name_prefix +} + +# Create a resource group using the generated random name +resource "azurerm_resource_group" "rg" { + location = var.resource_group_location + name = random_pet.rg_name.id +} + +# Create the custom virtual network that hosts the cluster +resource "azurerm_virtual_network" "vnet" { + name = var.virtual_network_name + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name + address_space = var.virtual_network_address_space +} + +# Create the subnet delegated to AKS for API Server VNet Integration +resource "azurerm_subnet" "api_server" { + name = "apiServerSubnet" + resource_group_name = azurerm_resource_group.rg.name + virtual_network_name = azurerm_virtual_network.vnet.name + address_prefixes = var.api_server_subnet_address_prefixes + + delegation { + name = "aks-delegation" + + service_delegation { + name = "Microsoft.ContainerService/managedClusters" + actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"] + } + } +} + +# Create the subnet that hosts the user node pools +resource "azurerm_subnet" "user_nodes" { + name = "userNodeSubnet" + resource_group_name = azurerm_resource_group.rg.name + virtual_network_name = azurerm_virtual_network.vnet.name + address_prefixes = var.user_node_subnet_address_prefixes +} + +# Create the subnet that hosts the managed system node pool +resource "azurerm_subnet" "system_nodes" { + name = "managedSystemNodeSubnet" + resource_group_name = azurerm_resource_group.rg.name + virtual_network_name = azurerm_virtual_network.vnet.name + address_prefixes = var.system_node_subnet_address_prefixes + + lifecycle { + # AKS adds its own managed cluster delegation to this subnet after the + # cluster is created. + ignore_changes = [delegation] + } +} + +# Create the user-assigned managed identity used by the cluster +resource "azurerm_user_assigned_identity" "aks" { + name = var.identity_name + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name +} + +# Grant the cluster identity Network Contributor on the virtual network +resource "azurerm_role_assignment" "network_contributor" { + scope = azurerm_virtual_network.vnet.id + role_definition_name = "Network Contributor" + principal_id = azurerm_user_assigned_identity.aks.principal_id + principal_type = "ServicePrincipal" +} + +# Create a random name for the AKS Automatic cluster +resource "random_pet" "cluster_name" { + prefix = var.cluster_name_prefix +} + +# Create the AKS Automatic cluster in the custom virtual network +resource "azurerm_kubernetes_automatic_cluster" "aks_automatic" { + name = random_pet.cluster_name.id + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name + + identity { + type = "UserAssigned" + identity_ids = [azurerm_user_assigned_identity.aks.id] + } + + api_server_access { + subnet_id = azurerm_subnet.api_server.id + } + + hosted_system { + node_subnet_id = azurerm_subnet.user_nodes.id + system_node_subnet_id = azurerm_subnet.system_nodes.id + } + + depends_on = [azurerm_role_assignment.network_contributor] +} diff --git a/quickstart/101-aks-automatic-custom-network/outputs.tf b/quickstart/101-aks-automatic-custom-network/outputs.tf new file mode 100644 index 000000000..b735efa72 --- /dev/null +++ b/quickstart/101-aks-automatic-custom-network/outputs.tf @@ -0,0 +1,23 @@ +output "resource_group_name" { + value = azurerm_resource_group.rg.name +} + +output "cluster_name" { + value = azurerm_kubernetes_automatic_cluster.aks_automatic.name +} + +output "cluster_id" { + value = azurerm_kubernetes_automatic_cluster.aks_automatic.id +} + +output "node_resource_group_id" { + value = azurerm_kubernetes_automatic_cluster.aks_automatic.node_resource_group_id +} + +output "virtual_network_name" { + value = azurerm_virtual_network.vnet.name +} + +output "fully_qualified_domain_name" { + value = azurerm_kubernetes_automatic_cluster.aks_automatic.fully_qualified_domain_name +} diff --git a/quickstart/101-aks-automatic-custom-network/providers.tf b/quickstart/101-aks-automatic-custom-network/providers.tf new file mode 100644 index 000000000..9e76a7ea8 --- /dev/null +++ b/quickstart/101-aks-automatic-custom-network/providers.tf @@ -0,0 +1,17 @@ +terraform { + required_version = ">= 1.0" + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~>5.0" + } + random = { + source = "hashicorp/random" + version = "~>3.0" + } + } +} + +provider "azurerm" { + features {} +} diff --git a/quickstart/101-aks-automatic-custom-network/readme.md b/quickstart/101-aks-automatic-custom-network/readme.md new file mode 100644 index 000000000..e69a08954 --- /dev/null +++ b/quickstart/101-aks-automatic-custom-network/readme.md @@ -0,0 +1,41 @@ +# Azure Kubernetes Service (AKS) Automatic cluster in a custom virtual network (AzureRM provider) + +This template deploys an AKS Automatic cluster into a custom virtual network, in a resource group with a random name beginning with "rg-". + +The virtual network contains a subnet delegated to the cluster API server, a subnet for the user node pools, and a subnet for the managed system node pool. The cluster uses a user-assigned managed identity that's granted the Network Contributor role on the virtual network, which is required when you bring your own network. + +The cluster is created with the AzureRM provider's [`azurerm_kubernetes_automatic_cluster`](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/kubernetes_automatic_cluster) resource, which is the recommended way to declare an AKS Automatic cluster. This resource requires AzureRM provider `5.0` or later. + +For an equivalent sample that declares the same cluster with the AzAPI provider, see [101-aks-automatic-custom-network-azapi](../101-aks-automatic-custom-network-azapi/). For a private cluster in a custom virtual network, see [101-aks-automatic-private-custom-network](../101-aks-automatic-private-custom-network/). + +## Terraform resource types + +- [random_pet](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) +- [azurerm_resource_group](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group) +- [azurerm_virtual_network](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_network) +- [azurerm_subnet](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet) +- [azurerm_user_assigned_identity](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/user_assigned_identity) +- [azurerm_role_assignment](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) +- [azurerm_kubernetes_automatic_cluster](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/kubernetes_automatic_cluster) + +## Variables + +| Name | Description | Default | +|-|-|-| +| `resource_group_name_prefix` | Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription. | rg | +| `resource_group_location` | Location of the resource group. | eastus | +| `cluster_name_prefix` | Prefix of the AKS Automatic cluster name that's combined with a random ID so the name is unique in your Azure subscription. | aks-automatic | +| `virtual_network_name` | Name of the custom virtual network that hosts the cluster. | aks-automatic-vnet | +| `identity_name` | Name of the user-assigned managed identity that the cluster uses. | aks-automatic-identity | +| `virtual_network_address_space` | Address space of the custom virtual network. | ["172.19.0.0/16"] | +| `api_server_subnet_address_prefixes` | Address prefixes of the subnet delegated to the cluster API server. | ["172.19.0.0/28"] | +| `user_node_subnet_address_prefixes` | Address prefixes of the subnet that hosts the user node pools. | ["172.19.1.0/24"] | +| `system_node_subnet_address_prefixes` | Address prefixes of the subnet that hosts the managed system node pool. | ["172.19.0.64/26"] | + +## Example + +```console +terraform init -upgrade +terraform plan -out main.tfplan +terraform apply main.tfplan +``` diff --git a/quickstart/101-aks-automatic-custom-network/variables.tf b/quickstart/101-aks-automatic-custom-network/variables.tf new file mode 100644 index 000000000..7e26e3864 --- /dev/null +++ b/quickstart/101-aks-automatic-custom-network/variables.tf @@ -0,0 +1,53 @@ +variable "resource_group_location" { + type = string + default = "eastus" + description = "Location of the resource group." +} + +variable "resource_group_name_prefix" { + type = string + default = "rg" + description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription." +} + +variable "cluster_name_prefix" { + type = string + default = "aks-automatic" + description = "Prefix of the AKS Automatic cluster name that's combined with a random ID so the name is unique in your Azure subscription." +} + +variable "virtual_network_name" { + type = string + default = "aks-automatic-vnet" + description = "Name of the custom virtual network that hosts the cluster." +} + +variable "identity_name" { + type = string + default = "aks-automatic-identity" + description = "Name of the user-assigned managed identity that the cluster uses." +} + +variable "virtual_network_address_space" { + type = list(string) + default = ["172.19.0.0/16"] + description = "Address space of the custom virtual network." +} + +variable "api_server_subnet_address_prefixes" { + type = list(string) + default = ["172.19.0.0/28"] + description = "Address prefixes of the subnet delegated to the cluster API server." +} + +variable "user_node_subnet_address_prefixes" { + type = list(string) + default = ["172.19.1.0/24"] + description = "Address prefixes of the subnet that hosts the user node pools." +} + +variable "system_node_subnet_address_prefixes" { + type = list(string) + default = ["172.19.0.64/26"] + description = "Address prefixes of the subnet that hosts the managed system node pool." +} From 8a5bcc94835948dbbb914182105284d2b7ef5b57 Mon Sep 17 00:00:00 2001 From: asudbring Date: Wed, 5 Aug 2026 17:10:54 +0100 Subject: [PATCH 2/6] Add 101-aks-automatic-custom-network-azapi quickstart sample Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../main.tf | 113 ++++++++++++++++++ .../outputs.tf | 19 +++ .../providers.tf | 24 ++++ .../readme.md | 42 +++++++ .../variables.tf | 64 ++++++++++ 5 files changed, 262 insertions(+) create mode 100644 quickstart/101-aks-automatic-custom-network-azapi/main.tf create mode 100644 quickstart/101-aks-automatic-custom-network-azapi/outputs.tf create mode 100644 quickstart/101-aks-automatic-custom-network-azapi/providers.tf create mode 100644 quickstart/101-aks-automatic-custom-network-azapi/readme.md create mode 100644 quickstart/101-aks-automatic-custom-network-azapi/variables.tf diff --git a/quickstart/101-aks-automatic-custom-network-azapi/main.tf b/quickstart/101-aks-automatic-custom-network-azapi/main.tf new file mode 100644 index 000000000..555fe590a --- /dev/null +++ b/quickstart/101-aks-automatic-custom-network-azapi/main.tf @@ -0,0 +1,113 @@ +# Create a random name for the resource group using random_pet +resource "random_pet" "rg_name" { + prefix = var.resource_group_name_prefix +} + +# Create a resource group using the generated random name +resource "azurerm_resource_group" "rg" { + location = var.resource_group_location + name = random_pet.rg_name.id +} + +# Create the custom virtual network that hosts the cluster +resource "azurerm_virtual_network" "vnet" { + name = var.virtual_network_name + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name + address_space = var.virtual_network_address_space +} + +# Create the subnet delegated to AKS for API Server VNet Integration +resource "azurerm_subnet" "api_server" { + name = "apiServerSubnet" + resource_group_name = azurerm_resource_group.rg.name + virtual_network_name = azurerm_virtual_network.vnet.name + address_prefixes = var.api_server_subnet_address_prefixes + + delegation { + name = "aks-delegation" + + service_delegation { + name = "Microsoft.ContainerService/managedClusters" + actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"] + } + } +} + +# Create the subnet that hosts the user node pools +resource "azurerm_subnet" "user_nodes" { + name = "userNodeSubnet" + resource_group_name = azurerm_resource_group.rg.name + virtual_network_name = azurerm_virtual_network.vnet.name + address_prefixes = var.user_node_subnet_address_prefixes +} + +# Create the subnet that hosts the managed system node pool +resource "azurerm_subnet" "system_nodes" { + name = "managedSystemNodeSubnet" + resource_group_name = azurerm_resource_group.rg.name + virtual_network_name = azurerm_virtual_network.vnet.name + address_prefixes = var.system_node_subnet_address_prefixes + + lifecycle { + # AKS adds its own managed cluster delegation to this subnet after the + # cluster is created. + ignore_changes = [delegation] + } +} + +# Create the user-assigned managed identity used by the cluster +resource "azurerm_user_assigned_identity" "aks" { + name = var.identity_name + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name +} + +# Grant the cluster identity Network Contributor on the virtual network +resource "azurerm_role_assignment" "network_contributor" { + scope = azurerm_virtual_network.vnet.id + role_definition_name = "Network Contributor" + principal_id = azurerm_user_assigned_identity.aks.principal_id + principal_type = "ServicePrincipal" +} + +# Create a random name for the AKS Automatic cluster +resource "random_pet" "cluster_name" { + prefix = var.cluster_name_prefix +} + +# Create the AKS Automatic cluster in the custom virtual network. +# The AzAPI provider gives you direct control over the managed cluster API +# payload, including properties that the AzureRM provider doesn't expose yet. +resource "azapi_resource" "aks_automatic" { + type = "Microsoft.ContainerService/managedClusters@2026-04-01" + name = random_pet.cluster_name.id + parent_id = azurerm_resource_group.rg.id + location = azurerm_resource_group.rg.location + + identity { + type = "UserAssigned" + identity_ids = [azurerm_user_assigned_identity.aks.id] + } + + body = { + sku = { + name = var.cluster_sku_name + } + + properties = { + apiServerAccessProfile = { + subnetId = azurerm_subnet.api_server.id + } + + hostedSystemProfile = { + nodeSubnetID = azurerm_subnet.user_nodes.id + systemNodeSubnetID = azurerm_subnet.system_nodes.id + } + } + } + + response_export_values = ["properties.nodeResourceGroup", "properties.fqdn"] + + depends_on = [azurerm_role_assignment.network_contributor] +} diff --git a/quickstart/101-aks-automatic-custom-network-azapi/outputs.tf b/quickstart/101-aks-automatic-custom-network-azapi/outputs.tf new file mode 100644 index 000000000..69c2038c3 --- /dev/null +++ b/quickstart/101-aks-automatic-custom-network-azapi/outputs.tf @@ -0,0 +1,19 @@ +output "resource_group_name" { + value = azurerm_resource_group.rg.name +} + +output "cluster_name" { + value = azapi_resource.aks_automatic.name +} + +output "cluster_id" { + value = azapi_resource.aks_automatic.id +} + +output "node_resource_group" { + value = azapi_resource.aks_automatic.output.properties.nodeResourceGroup +} + +output "virtual_network_name" { + value = azurerm_virtual_network.vnet.name +} diff --git a/quickstart/101-aks-automatic-custom-network-azapi/providers.tf b/quickstart/101-aks-automatic-custom-network-azapi/providers.tf new file mode 100644 index 000000000..172c6cb0b --- /dev/null +++ b/quickstart/101-aks-automatic-custom-network-azapi/providers.tf @@ -0,0 +1,24 @@ +terraform { + required_version = ">= 1.0" + required_providers { + azapi = { + source = "Azure/azapi" + version = "~>2.0" + } + azurerm = { + source = "hashicorp/azurerm" + version = "~>4.0" + } + random = { + source = "hashicorp/random" + version = "~>3.0" + } + } +} + +provider "azurerm" { + features {} +} + +provider "azapi" { +} diff --git a/quickstart/101-aks-automatic-custom-network-azapi/readme.md b/quickstart/101-aks-automatic-custom-network-azapi/readme.md new file mode 100644 index 000000000..23281bdd2 --- /dev/null +++ b/quickstart/101-aks-automatic-custom-network-azapi/readme.md @@ -0,0 +1,42 @@ +# Azure Kubernetes Service (AKS) Automatic cluster in a custom virtual network (AzAPI provider) + +This template deploys an AKS Automatic cluster into a custom virtual network, in a resource group with a random name beginning with "rg-". + +The virtual network contains a subnet delegated to the cluster API server, a subnet for the user node pools, and a subnet for the managed system node pool. The cluster uses a user-assigned managed identity that's granted the Network Contributor role on the virtual network, which is required when you bring your own network. + +The cluster is declared with the AzAPI provider's [`azapi_resource`](https://registry.terraform.io/providers/Azure/azapi/latest/docs/resources/resource) against the `Microsoft.ContainerService/managedClusters` API. Use this pattern when you need direct control over the managed cluster API payload, or when you need an API version or property that the AzureRM provider doesn't expose yet. + +For the equivalent sample that uses the AzureRM provider's `azurerm_kubernetes_automatic_cluster` resource, see [101-aks-automatic-custom-network](../101-aks-automatic-custom-network/). For a private cluster in a custom virtual network, see [101-aks-automatic-private-custom-network-azapi](../101-aks-automatic-private-custom-network-azapi/). + +## Terraform resource types + +- [random_pet](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) +- [azurerm_resource_group](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group) +- [azurerm_virtual_network](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_network) +- [azurerm_subnet](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet) +- [azurerm_user_assigned_identity](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/user_assigned_identity) +- [azurerm_role_assignment](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) +- [azapi_resource](https://registry.terraform.io/providers/Azure/azapi/latest/docs/resources/resource) + +## Variables + +| Name | Description | Default | Validation | +|-|-|-|-| +| `resource_group_name_prefix` | Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription. | rg | | +| `resource_group_location` | Location of the resource group. | eastus | | +| `cluster_name_prefix` | Prefix of the AKS Automatic cluster name that's combined with a random ID so the name is unique in your Azure subscription. | aks-automatic | | +| `cluster_sku_name` | The managed cluster SKU name. Use `Automatic` for an AKS Automatic cluster. | Automatic | Must be `Automatic` or `Base`. | +| `virtual_network_name` | Name of the custom virtual network that hosts the cluster. | aks-automatic-vnet | | +| `identity_name` | Name of the user-assigned managed identity that the cluster uses. | aks-automatic-identity | | +| `virtual_network_address_space` | Address space of the custom virtual network. | ["172.19.0.0/16"] | | +| `api_server_subnet_address_prefixes` | Address prefixes of the subnet delegated to the cluster API server. | ["172.19.0.0/28"] | | +| `user_node_subnet_address_prefixes` | Address prefixes of the subnet that hosts the user node pools. | ["172.19.1.0/24"] | | +| `system_node_subnet_address_prefixes` | Address prefixes of the subnet that hosts the managed system node pool. | ["172.19.0.64/26"] | | + +## Example + +```console +terraform init -upgrade +terraform plan -out main.tfplan +terraform apply main.tfplan +``` diff --git a/quickstart/101-aks-automatic-custom-network-azapi/variables.tf b/quickstart/101-aks-automatic-custom-network-azapi/variables.tf new file mode 100644 index 000000000..9f19678d3 --- /dev/null +++ b/quickstart/101-aks-automatic-custom-network-azapi/variables.tf @@ -0,0 +1,64 @@ +variable "resource_group_location" { + type = string + default = "eastus" + description = "Location of the resource group." +} + +variable "resource_group_name_prefix" { + type = string + default = "rg" + description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription." +} + +variable "cluster_name_prefix" { + type = string + default = "aks-automatic" + description = "Prefix of the AKS Automatic cluster name that's combined with a random ID so the name is unique in your Azure subscription." +} + +variable "cluster_sku_name" { + type = string + default = "Automatic" + description = "The managed cluster SKU name. Use 'Automatic' for an AKS Automatic cluster." + + validation { + condition = contains(["Automatic", "Base"], var.cluster_sku_name) + error_message = "The cluster_sku_name value must be either 'Automatic' or 'Base'." + } +} + +variable "virtual_network_name" { + type = string + default = "aks-automatic-vnet" + description = "Name of the custom virtual network that hosts the cluster." +} + +variable "identity_name" { + type = string + default = "aks-automatic-identity" + description = "Name of the user-assigned managed identity that the cluster uses." +} + +variable "virtual_network_address_space" { + type = list(string) + default = ["172.19.0.0/16"] + description = "Address space of the custom virtual network." +} + +variable "api_server_subnet_address_prefixes" { + type = list(string) + default = ["172.19.0.0/28"] + description = "Address prefixes of the subnet delegated to the cluster API server." +} + +variable "user_node_subnet_address_prefixes" { + type = list(string) + default = ["172.19.1.0/24"] + description = "Address prefixes of the subnet that hosts the user node pools." +} + +variable "system_node_subnet_address_prefixes" { + type = list(string) + default = ["172.19.0.64/26"] + description = "Address prefixes of the subnet that hosts the managed system node pool." +} From 65c106ec8062dc6bb956834bfdab9c7f0f1cbbb1 Mon Sep 17 00:00:00 2001 From: asudbring Date: Wed, 5 Aug 2026 17:10:55 +0100 Subject: [PATCH 3/6] Add 101-aks-automatic-private-custom-network quickstart sample Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../main.tf | 106 ++++++++++++++++++ .../outputs.tf | 23 ++++ .../providers.tf | 17 +++ .../readme.md | 42 +++++++ .../variables.tf | 59 ++++++++++ 5 files changed, 247 insertions(+) create mode 100644 quickstart/101-aks-automatic-private-custom-network/main.tf create mode 100644 quickstart/101-aks-automatic-private-custom-network/outputs.tf create mode 100644 quickstart/101-aks-automatic-private-custom-network/providers.tf create mode 100644 quickstart/101-aks-automatic-private-custom-network/readme.md create mode 100644 quickstart/101-aks-automatic-private-custom-network/variables.tf diff --git a/quickstart/101-aks-automatic-private-custom-network/main.tf b/quickstart/101-aks-automatic-private-custom-network/main.tf new file mode 100644 index 000000000..4d2be1fd2 --- /dev/null +++ b/quickstart/101-aks-automatic-private-custom-network/main.tf @@ -0,0 +1,106 @@ +# Create a random name for the resource group using random_pet +resource "random_pet" "rg_name" { + prefix = var.resource_group_name_prefix +} + +# Create a resource group using the generated random name +resource "azurerm_resource_group" "rg" { + location = var.resource_group_location + name = random_pet.rg_name.id +} + +# Create the custom virtual network that hosts the cluster +resource "azurerm_virtual_network" "vnet" { + name = var.virtual_network_name + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name + address_space = var.virtual_network_address_space +} + +# Create the subnet delegated to AKS for API Server VNet Integration +resource "azurerm_subnet" "api_server" { + name = "apiServerSubnet" + resource_group_name = azurerm_resource_group.rg.name + virtual_network_name = azurerm_virtual_network.vnet.name + address_prefixes = var.api_server_subnet_address_prefixes + + delegation { + name = "aks-delegation" + + service_delegation { + name = "Microsoft.ContainerService/managedClusters" + actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"] + } + } +} + +# Create the subnet that hosts the user node pools +resource "azurerm_subnet" "user_nodes" { + name = "userNodeSubnet" + resource_group_name = azurerm_resource_group.rg.name + virtual_network_name = azurerm_virtual_network.vnet.name + address_prefixes = var.user_node_subnet_address_prefixes +} + +# Create the subnet that hosts the managed system node pool +resource "azurerm_subnet" "system_nodes" { + name = "managedSystemNodeSubnet" + resource_group_name = azurerm_resource_group.rg.name + virtual_network_name = azurerm_virtual_network.vnet.name + address_prefixes = var.system_node_subnet_address_prefixes + + lifecycle { + # AKS adds its own managed cluster delegation to this subnet after the + # cluster is created. + ignore_changes = [delegation] + } +} + +# Create the user-assigned managed identity used by the cluster +resource "azurerm_user_assigned_identity" "aks" { + name = var.identity_name + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name +} + +# Grant the cluster identity Network Contributor on the virtual network +resource "azurerm_role_assignment" "network_contributor" { + scope = azurerm_virtual_network.vnet.id + role_definition_name = "Network Contributor" + principal_id = azurerm_user_assigned_identity.aks.principal_id + principal_type = "ServicePrincipal" +} + +# Create a random name for the AKS Automatic cluster +resource "random_pet" "cluster_name" { + prefix = var.cluster_name_prefix +} + +# Create the private AKS Automatic cluster in the custom virtual network +resource "azurerm_kubernetes_automatic_cluster" "aks_automatic" { + name = random_pet.cluster_name.id + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name + + identity { + type = "UserAssigned" + identity_ids = [azurerm_user_assigned_identity.aks.id] + } + + api_server_access { + subnet_id = azurerm_subnet.api_server.id + } + + hosted_system { + node_subnet_id = azurerm_subnet.user_nodes.id + system_node_subnet_id = azurerm_subnet.system_nodes.id + } + + # The private_cluster block makes the cluster API server private, so it's + # only reachable from inside the virtual network. + private_cluster { + public_fully_qualified_domain_name_enabled = var.public_fully_qualified_domain_name_enabled + } + + depends_on = [azurerm_role_assignment.network_contributor] +} diff --git a/quickstart/101-aks-automatic-private-custom-network/outputs.tf b/quickstart/101-aks-automatic-private-custom-network/outputs.tf new file mode 100644 index 000000000..56b82dc53 --- /dev/null +++ b/quickstart/101-aks-automatic-private-custom-network/outputs.tf @@ -0,0 +1,23 @@ +output "resource_group_name" { + value = azurerm_resource_group.rg.name +} + +output "cluster_name" { + value = azurerm_kubernetes_automatic_cluster.aks_automatic.name +} + +output "cluster_id" { + value = azurerm_kubernetes_automatic_cluster.aks_automatic.id +} + +output "node_resource_group_id" { + value = azurerm_kubernetes_automatic_cluster.aks_automatic.node_resource_group_id +} + +output "virtual_network_name" { + value = azurerm_virtual_network.vnet.name +} + +output "private_fully_qualified_domain_name" { + value = azurerm_kubernetes_automatic_cluster.aks_automatic.private_fully_qualified_domain_name +} diff --git a/quickstart/101-aks-automatic-private-custom-network/providers.tf b/quickstart/101-aks-automatic-private-custom-network/providers.tf new file mode 100644 index 000000000..9e76a7ea8 --- /dev/null +++ b/quickstart/101-aks-automatic-private-custom-network/providers.tf @@ -0,0 +1,17 @@ +terraform { + required_version = ">= 1.0" + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~>5.0" + } + random = { + source = "hashicorp/random" + version = "~>3.0" + } + } +} + +provider "azurerm" { + features {} +} diff --git a/quickstart/101-aks-automatic-private-custom-network/readme.md b/quickstart/101-aks-automatic-private-custom-network/readme.md new file mode 100644 index 000000000..2d98d96d5 --- /dev/null +++ b/quickstart/101-aks-automatic-private-custom-network/readme.md @@ -0,0 +1,42 @@ +# Private Azure Kubernetes Service (AKS) Automatic cluster in a custom virtual network (AzureRM provider) + +This template deploys a private AKS Automatic cluster into a custom virtual network, in a resource group with a random name beginning with "rg-". + +The virtual network contains a subnet delegated to the cluster API server, a subnet for the user node pools, and a subnet for the managed system node pool. The cluster uses a user-assigned managed identity that's granted the Network Contributor role on the virtual network, which is required when you bring your own network. Because the cluster is private, its API server is only reachable from inside the virtual network. + +The cluster is created with the AzureRM provider's [`azurerm_kubernetes_automatic_cluster`](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/kubernetes_automatic_cluster) resource, which is the recommended way to declare an AKS Automatic cluster. This resource requires AzureRM provider `5.0` or later. + +For an equivalent sample that declares the same cluster with the AzAPI provider, see [101-aks-automatic-private-custom-network-azapi](../101-aks-automatic-private-custom-network-azapi/). For a public cluster in a custom virtual network, see [101-aks-automatic-custom-network](../101-aks-automatic-custom-network/). + +## Terraform resource types + +- [random_pet](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) +- [azurerm_resource_group](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group) +- [azurerm_virtual_network](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_network) +- [azurerm_subnet](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet) +- [azurerm_user_assigned_identity](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/user_assigned_identity) +- [azurerm_role_assignment](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) +- [azurerm_kubernetes_automatic_cluster](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/kubernetes_automatic_cluster) + +## Variables + +| Name | Description | Default | +|-|-|-| +| `resource_group_name_prefix` | Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription. | rg | +| `resource_group_location` | Location of the resource group. | eastus | +| `cluster_name_prefix` | Prefix of the AKS Automatic cluster name that's combined with a random ID so the name is unique in your Azure subscription. | aks-automatic | +| `public_fully_qualified_domain_name_enabled` | Whether to provision a public FQDN for the private cluster. | false | +| `virtual_network_name` | Name of the custom virtual network that hosts the cluster. | aks-automatic-vnet | +| `identity_name` | Name of the user-assigned managed identity that the cluster uses. | aks-automatic-identity | +| `virtual_network_address_space` | Address space of the custom virtual network. | ["172.19.0.0/16"] | +| `api_server_subnet_address_prefixes` | Address prefixes of the subnet delegated to the cluster API server. | ["172.19.0.0/28"] | +| `user_node_subnet_address_prefixes` | Address prefixes of the subnet that hosts the user node pools. | ["172.19.1.0/24"] | +| `system_node_subnet_address_prefixes` | Address prefixes of the subnet that hosts the managed system node pool. | ["172.19.0.64/26"] | + +## Example + +```console +terraform init -upgrade +terraform plan -out main.tfplan +terraform apply main.tfplan +``` diff --git a/quickstart/101-aks-automatic-private-custom-network/variables.tf b/quickstart/101-aks-automatic-private-custom-network/variables.tf new file mode 100644 index 000000000..03443159f --- /dev/null +++ b/quickstart/101-aks-automatic-private-custom-network/variables.tf @@ -0,0 +1,59 @@ +variable "resource_group_location" { + type = string + default = "eastus" + description = "Location of the resource group." +} + +variable "resource_group_name_prefix" { + type = string + default = "rg" + description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription." +} + +variable "cluster_name_prefix" { + type = string + default = "aks-automatic" + description = "Prefix of the AKS Automatic cluster name that's combined with a random ID so the name is unique in your Azure subscription." +} + +variable "public_fully_qualified_domain_name_enabled" { + type = bool + default = false + description = "Whether to provision a public FQDN for the private cluster." +} + +variable "virtual_network_name" { + type = string + default = "aks-automatic-vnet" + description = "Name of the custom virtual network that hosts the cluster." +} + +variable "identity_name" { + type = string + default = "aks-automatic-identity" + description = "Name of the user-assigned managed identity that the cluster uses." +} + +variable "virtual_network_address_space" { + type = list(string) + default = ["172.19.0.0/16"] + description = "Address space of the custom virtual network." +} + +variable "api_server_subnet_address_prefixes" { + type = list(string) + default = ["172.19.0.0/28"] + description = "Address prefixes of the subnet delegated to the cluster API server." +} + +variable "user_node_subnet_address_prefixes" { + type = list(string) + default = ["172.19.1.0/24"] + description = "Address prefixes of the subnet that hosts the user node pools." +} + +variable "system_node_subnet_address_prefixes" { + type = list(string) + default = ["172.19.0.64/26"] + description = "Address prefixes of the subnet that hosts the managed system node pool." +} From 1a1ebaf200beeb9e1698cd1bc6686a3ebdbde564 Mon Sep 17 00:00:00 2001 From: asudbring Date: Wed, 5 Aug 2026 17:10:55 +0100 Subject: [PATCH 4/6] Add 101-aks-automatic-private-custom-network-azapi quickstart sample Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../main.tf | 121 ++++++++++++++++++ .../outputs.tf | 23 ++++ .../providers.tf | 24 ++++ .../readme.md | 42 ++++++ .../variables.tf | 64 +++++++++ 5 files changed, 274 insertions(+) create mode 100644 quickstart/101-aks-automatic-private-custom-network-azapi/main.tf create mode 100644 quickstart/101-aks-automatic-private-custom-network-azapi/outputs.tf create mode 100644 quickstart/101-aks-automatic-private-custom-network-azapi/providers.tf create mode 100644 quickstart/101-aks-automatic-private-custom-network-azapi/readme.md create mode 100644 quickstart/101-aks-automatic-private-custom-network-azapi/variables.tf diff --git a/quickstart/101-aks-automatic-private-custom-network-azapi/main.tf b/quickstart/101-aks-automatic-private-custom-network-azapi/main.tf new file mode 100644 index 000000000..d7e1dd887 --- /dev/null +++ b/quickstart/101-aks-automatic-private-custom-network-azapi/main.tf @@ -0,0 +1,121 @@ +# Create a random name for the resource group using random_pet +resource "random_pet" "rg_name" { + prefix = var.resource_group_name_prefix +} + +# Create a resource group using the generated random name +resource "azurerm_resource_group" "rg" { + location = var.resource_group_location + name = random_pet.rg_name.id +} + +# Create the custom virtual network that hosts the cluster +resource "azurerm_virtual_network" "vnet" { + name = var.virtual_network_name + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name + address_space = var.virtual_network_address_space +} + +# Create the subnet delegated to AKS for API Server VNet Integration +resource "azurerm_subnet" "api_server" { + name = "apiServerSubnet" + resource_group_name = azurerm_resource_group.rg.name + virtual_network_name = azurerm_virtual_network.vnet.name + address_prefixes = var.api_server_subnet_address_prefixes + + delegation { + name = "aks-delegation" + + service_delegation { + name = "Microsoft.ContainerService/managedClusters" + actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"] + } + } +} + +# Create the subnet that hosts the user node pools +resource "azurerm_subnet" "user_nodes" { + name = "userNodeSubnet" + resource_group_name = azurerm_resource_group.rg.name + virtual_network_name = azurerm_virtual_network.vnet.name + address_prefixes = var.user_node_subnet_address_prefixes +} + +# Create the subnet that hosts the managed system node pool +resource "azurerm_subnet" "system_nodes" { + name = "managedSystemNodeSubnet" + resource_group_name = azurerm_resource_group.rg.name + virtual_network_name = azurerm_virtual_network.vnet.name + address_prefixes = var.system_node_subnet_address_prefixes + + lifecycle { + # AKS adds its own managed cluster delegation to this subnet after the + # cluster is created. + ignore_changes = [delegation] + } +} + +# Create the user-assigned managed identity used by the cluster +resource "azurerm_user_assigned_identity" "aks" { + name = var.identity_name + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name +} + +# Grant the cluster identity Network Contributor on the virtual network +resource "azurerm_role_assignment" "network_contributor" { + scope = azurerm_virtual_network.vnet.id + role_definition_name = "Network Contributor" + principal_id = azurerm_user_assigned_identity.aks.principal_id + principal_type = "ServicePrincipal" +} + +# Create a random name for the AKS Automatic cluster +resource "random_pet" "cluster_name" { + prefix = var.cluster_name_prefix +} + +# Create the private AKS Automatic cluster in the custom virtual network. +# The AzAPI provider gives you direct control over the managed cluster API +# payload, including properties that the AzureRM provider doesn't expose yet. +resource "azapi_resource" "aks_automatic" { + type = "Microsoft.ContainerService/managedClusters@2026-04-01" + name = random_pet.cluster_name.id + parent_id = azurerm_resource_group.rg.id + location = azurerm_resource_group.rg.location + + identity { + type = "UserAssigned" + identity_ids = [azurerm_user_assigned_identity.aks.id] + } + + body = { + sku = { + name = var.cluster_sku_name + } + + properties = { + apiServerAccessProfile = { + # A private cluster API server is only reachable from inside the + # virtual network. + enablePrivateCluster = true + subnetId = azurerm_subnet.api_server.id + } + + hostedSystemProfile = { + nodeSubnetID = azurerm_subnet.user_nodes.id + systemNodeSubnetID = azurerm_subnet.system_nodes.id + } + } + } + + response_export_values = ["properties.nodeResourceGroup", "properties.privateFQDN"] + + timeouts { + create = "2h" + delete = "2h" + } + + depends_on = [azurerm_role_assignment.network_contributor] +} diff --git a/quickstart/101-aks-automatic-private-custom-network-azapi/outputs.tf b/quickstart/101-aks-automatic-private-custom-network-azapi/outputs.tf new file mode 100644 index 000000000..fce5003c5 --- /dev/null +++ b/quickstart/101-aks-automatic-private-custom-network-azapi/outputs.tf @@ -0,0 +1,23 @@ +output "resource_group_name" { + value = azurerm_resource_group.rg.name +} + +output "cluster_name" { + value = azapi_resource.aks_automatic.name +} + +output "cluster_id" { + value = azapi_resource.aks_automatic.id +} + +output "node_resource_group" { + value = azapi_resource.aks_automatic.output.properties.nodeResourceGroup +} + +output "virtual_network_name" { + value = azurerm_virtual_network.vnet.name +} + +output "private_fully_qualified_domain_name" { + value = azapi_resource.aks_automatic.output.properties.privateFQDN +} diff --git a/quickstart/101-aks-automatic-private-custom-network-azapi/providers.tf b/quickstart/101-aks-automatic-private-custom-network-azapi/providers.tf new file mode 100644 index 000000000..172c6cb0b --- /dev/null +++ b/quickstart/101-aks-automatic-private-custom-network-azapi/providers.tf @@ -0,0 +1,24 @@ +terraform { + required_version = ">= 1.0" + required_providers { + azapi = { + source = "Azure/azapi" + version = "~>2.0" + } + azurerm = { + source = "hashicorp/azurerm" + version = "~>4.0" + } + random = { + source = "hashicorp/random" + version = "~>3.0" + } + } +} + +provider "azurerm" { + features {} +} + +provider "azapi" { +} diff --git a/quickstart/101-aks-automatic-private-custom-network-azapi/readme.md b/quickstart/101-aks-automatic-private-custom-network-azapi/readme.md new file mode 100644 index 000000000..555a6106f --- /dev/null +++ b/quickstart/101-aks-automatic-private-custom-network-azapi/readme.md @@ -0,0 +1,42 @@ +# Private Azure Kubernetes Service (AKS) Automatic cluster in a custom virtual network (AzAPI provider) + +This template deploys a private AKS Automatic cluster into a custom virtual network, in a resource group with a random name beginning with "rg-". + +The virtual network contains a subnet delegated to the cluster API server, a subnet for the user node pools, and a subnet for the managed system node pool. The cluster uses a user-assigned managed identity that's granted the Network Contributor role on the virtual network, which is required when you bring your own network. Because the cluster is private, its API server is only reachable from inside the virtual network. + +The cluster is declared with the AzAPI provider's [`azapi_resource`](https://registry.terraform.io/providers/Azure/azapi/latest/docs/resources/resource) against the `Microsoft.ContainerService/managedClusters` API. Use this pattern when you need direct control over the managed cluster API payload, or when you need an API version or property that the AzureRM provider doesn't expose yet. + +For the equivalent sample that uses the AzureRM provider's `azurerm_kubernetes_automatic_cluster` resource, see [101-aks-automatic-private-custom-network](../101-aks-automatic-private-custom-network/). For a public cluster in a custom virtual network, see [101-aks-automatic-custom-network-azapi](../101-aks-automatic-custom-network-azapi/). + +## Terraform resource types + +- [random_pet](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) +- [azurerm_resource_group](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group) +- [azurerm_virtual_network](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_network) +- [azurerm_subnet](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet) +- [azurerm_user_assigned_identity](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/user_assigned_identity) +- [azurerm_role_assignment](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment) +- [azapi_resource](https://registry.terraform.io/providers/Azure/azapi/latest/docs/resources/resource) + +## Variables + +| Name | Description | Default | Validation | +|-|-|-|-| +| `resource_group_name_prefix` | Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription. | rg | | +| `resource_group_location` | Location of the resource group. | eastus | | +| `cluster_name_prefix` | Prefix of the AKS Automatic cluster name that's combined with a random ID so the name is unique in your Azure subscription. | aks-automatic | | +| `cluster_sku_name` | The managed cluster SKU name. Use `Automatic` for an AKS Automatic cluster. | Automatic | Must be `Automatic` or `Base`. | +| `virtual_network_name` | Name of the custom virtual network that hosts the cluster. | aks-automatic-vnet | | +| `identity_name` | Name of the user-assigned managed identity that the cluster uses. | aks-automatic-identity | | +| `virtual_network_address_space` | Address space of the custom virtual network. | ["172.19.0.0/16"] | | +| `api_server_subnet_address_prefixes` | Address prefixes of the subnet delegated to the cluster API server. | ["172.19.0.0/28"] | | +| `user_node_subnet_address_prefixes` | Address prefixes of the subnet that hosts the user node pools. | ["172.19.1.0/24"] | | +| `system_node_subnet_address_prefixes` | Address prefixes of the subnet that hosts the managed system node pool. | ["172.19.0.64/26"] | | + +## Example + +```console +terraform init -upgrade +terraform plan -out main.tfplan +terraform apply main.tfplan +``` diff --git a/quickstart/101-aks-automatic-private-custom-network-azapi/variables.tf b/quickstart/101-aks-automatic-private-custom-network-azapi/variables.tf new file mode 100644 index 000000000..9f19678d3 --- /dev/null +++ b/quickstart/101-aks-automatic-private-custom-network-azapi/variables.tf @@ -0,0 +1,64 @@ +variable "resource_group_location" { + type = string + default = "eastus" + description = "Location of the resource group." +} + +variable "resource_group_name_prefix" { + type = string + default = "rg" + description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription." +} + +variable "cluster_name_prefix" { + type = string + default = "aks-automatic" + description = "Prefix of the AKS Automatic cluster name that's combined with a random ID so the name is unique in your Azure subscription." +} + +variable "cluster_sku_name" { + type = string + default = "Automatic" + description = "The managed cluster SKU name. Use 'Automatic' for an AKS Automatic cluster." + + validation { + condition = contains(["Automatic", "Base"], var.cluster_sku_name) + error_message = "The cluster_sku_name value must be either 'Automatic' or 'Base'." + } +} + +variable "virtual_network_name" { + type = string + default = "aks-automatic-vnet" + description = "Name of the custom virtual network that hosts the cluster." +} + +variable "identity_name" { + type = string + default = "aks-automatic-identity" + description = "Name of the user-assigned managed identity that the cluster uses." +} + +variable "virtual_network_address_space" { + type = list(string) + default = ["172.19.0.0/16"] + description = "Address space of the custom virtual network." +} + +variable "api_server_subnet_address_prefixes" { + type = list(string) + default = ["172.19.0.0/28"] + description = "Address prefixes of the subnet delegated to the cluster API server." +} + +variable "user_node_subnet_address_prefixes" { + type = list(string) + default = ["172.19.1.0/24"] + description = "Address prefixes of the subnet that hosts the user node pools." +} + +variable "system_node_subnet_address_prefixes" { + type = list(string) + default = ["172.19.0.64/26"] + description = "Address prefixes of the subnet that hosts the managed system node pool." +} From d24368bf217d051d99e92df472368a805c6fd2bb Mon Sep 17 00:00:00 2001 From: asudbring Date: Wed, 5 Aug 2026 22:40:17 +0100 Subject: [PATCH 5/6] Address review feedback on AKS Automatic custom network samples Default to the validated westus2 region, hard-code the Automatic SKU in the AzAPI variants, clarify private cluster reachability, and document BYO-network guardrails. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../main.tf | 2 +- .../readme.md | 20 +++++++++++++--- .../variables.tf | 13 +---------- .../readme.md | 16 ++++++++++++- .../variables.tf | 2 +- .../main.tf | 8 ++++--- .../readme.md | 23 +++++++++++++++---- .../variables.tf | 13 +---------- .../main.tf | 6 +++-- .../readme.md | 19 +++++++++++++-- .../variables.tf | 2 +- 11 files changed, 82 insertions(+), 42 deletions(-) diff --git a/quickstart/101-aks-automatic-custom-network-azapi/main.tf b/quickstart/101-aks-automatic-custom-network-azapi/main.tf index 555fe590a..31170c3ce 100644 --- a/quickstart/101-aks-automatic-custom-network-azapi/main.tf +++ b/quickstart/101-aks-automatic-custom-network-azapi/main.tf @@ -92,7 +92,7 @@ resource "azapi_resource" "aks_automatic" { body = { sku = { - name = var.cluster_sku_name + name = "Automatic" } properties = { diff --git a/quickstart/101-aks-automatic-custom-network-azapi/readme.md b/quickstart/101-aks-automatic-custom-network-azapi/readme.md index 23281bdd2..4b1a00700 100644 --- a/quickstart/101-aks-automatic-custom-network-azapi/readme.md +++ b/quickstart/101-aks-automatic-custom-network-azapi/readme.md @@ -4,7 +4,7 @@ This template deploys an AKS Automatic cluster into a custom virtual network, in The virtual network contains a subnet delegated to the cluster API server, a subnet for the user node pools, and a subnet for the managed system node pool. The cluster uses a user-assigned managed identity that's granted the Network Contributor role on the virtual network, which is required when you bring your own network. -The cluster is declared with the AzAPI provider's [`azapi_resource`](https://registry.terraform.io/providers/Azure/azapi/latest/docs/resources/resource) against the `Microsoft.ContainerService/managedClusters` API. Use this pattern when you need direct control over the managed cluster API payload, or when you need an API version or property that the AzureRM provider doesn't expose yet. +The cluster is declared with the AzAPI provider's [`azapi_resource`](https://registry.terraform.io/providers/Azure/azapi/latest/docs/resources/resource) against the `Microsoft.ContainerService/managedClusters` API. Use this pattern when you need direct control over the managed cluster API payload, or when you need an API version or property that the AzureRM provider doesn't expose yet. The cluster SKU is hard-coded to `Automatic`. For the equivalent sample that uses the AzureRM provider's `azurerm_kubernetes_automatic_cluster` resource, see [101-aks-automatic-custom-network](../101-aks-automatic-custom-network/). For a private cluster in a custom virtual network, see [101-aks-automatic-private-custom-network-azapi](../101-aks-automatic-private-custom-network-azapi/). @@ -23,9 +23,8 @@ For the equivalent sample that uses the AzureRM provider's `azurerm_kubernetes_a | Name | Description | Default | Validation | |-|-|-|-| | `resource_group_name_prefix` | Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription. | rg | | -| `resource_group_location` | Location of the resource group. | eastus | | +| `resource_group_location` | Location of the resource group. | westus2 | | | `cluster_name_prefix` | Prefix of the AKS Automatic cluster name that's combined with a random ID so the name is unique in your Azure subscription. | aks-automatic | | -| `cluster_sku_name` | The managed cluster SKU name. Use `Automatic` for an AKS Automatic cluster. | Automatic | Must be `Automatic` or `Base`. | | `virtual_network_name` | Name of the custom virtual network that hosts the cluster. | aks-automatic-vnet | | | `identity_name` | Name of the user-assigned managed identity that the cluster uses. | aks-automatic-identity | | | `virtual_network_address_space` | Address space of the custom virtual network. | ["172.19.0.0/16"] | | @@ -33,6 +32,19 @@ For the equivalent sample that uses the AzureRM provider's `azurerm_kubernetes_a | `user_node_subnet_address_prefixes` | Address prefixes of the subnet that hosts the user node pools. | ["172.19.1.0/24"] | | | `system_node_subnet_address_prefixes` | Address prefixes of the subnet that hosts the managed system node pool. | ["172.19.0.64/26"] | | + +> [!NOTE] +> The default location is `westus2` because that's the region these samples were validated in. At the time of testing, `eastus` returned `AKSCapacityHeavyUsage` for API Server VNet Integration. Set `resource_group_location` to deploy elsewhere. + +## Network guardrails + +This sample creates its own virtual network, so the defaults are safe as written. Read these before pointing the variables at an existing network: + +- **Subnet containment and non-overlap.** Every subnet prefix must sit inside `virtual_network_address_space` and must not overlap another subnet in the same virtual network. The defaults carve `172.19.0.0/28`, `172.19.0.64/26`, and `172.19.1.0/24` out of `172.19.0.0/16`. +- **Subnet sizing.** The API server subnet must be at least a `/28`, and AKS reserves at least nine addresses in it. Size the node subnets for the pod and node scale you expect, because a subnet that runs out of addresses blocks scaling. +- **Role assignment blast radius.** The cluster identity is granted **Network Contributor** on the whole virtual network, which is what Node Autoprovisioning needs. If you retarget this sample at a shared virtual network, that grant reaches every subnet and resource in it. Scope it more tightly, or keep the cluster in a dedicated network. +- **Delegation drift is hidden.** The managed system node subnet sets `ignore_changes = [delegation]` because AKS adds its own managed cluster delegation after the cluster is created. That keeps plans clean, but it also means Terraform won't report if the delegation is later changed or removed outside Terraform. + ## Example ```console @@ -40,3 +52,5 @@ terraform init -upgrade terraform plan -out main.tfplan terraform apply main.tfplan ``` + + diff --git a/quickstart/101-aks-automatic-custom-network-azapi/variables.tf b/quickstart/101-aks-automatic-custom-network-azapi/variables.tf index 9f19678d3..8fe2b1ef4 100644 --- a/quickstart/101-aks-automatic-custom-network-azapi/variables.tf +++ b/quickstart/101-aks-automatic-custom-network-azapi/variables.tf @@ -1,6 +1,6 @@ variable "resource_group_location" { type = string - default = "eastus" + default = "westus2" description = "Location of the resource group." } @@ -16,17 +16,6 @@ variable "cluster_name_prefix" { description = "Prefix of the AKS Automatic cluster name that's combined with a random ID so the name is unique in your Azure subscription." } -variable "cluster_sku_name" { - type = string - default = "Automatic" - description = "The managed cluster SKU name. Use 'Automatic' for an AKS Automatic cluster." - - validation { - condition = contains(["Automatic", "Base"], var.cluster_sku_name) - error_message = "The cluster_sku_name value must be either 'Automatic' or 'Base'." - } -} - variable "virtual_network_name" { type = string default = "aks-automatic-vnet" diff --git a/quickstart/101-aks-automatic-custom-network/readme.md b/quickstart/101-aks-automatic-custom-network/readme.md index e69a08954..94634d8f2 100644 --- a/quickstart/101-aks-automatic-custom-network/readme.md +++ b/quickstart/101-aks-automatic-custom-network/readme.md @@ -23,7 +23,7 @@ For an equivalent sample that declares the same cluster with the AzAPI provider, | Name | Description | Default | |-|-|-| | `resource_group_name_prefix` | Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription. | rg | -| `resource_group_location` | Location of the resource group. | eastus | +| `resource_group_location` | Location of the resource group. | westus2 | | `cluster_name_prefix` | Prefix of the AKS Automatic cluster name that's combined with a random ID so the name is unique in your Azure subscription. | aks-automatic | | `virtual_network_name` | Name of the custom virtual network that hosts the cluster. | aks-automatic-vnet | | `identity_name` | Name of the user-assigned managed identity that the cluster uses. | aks-automatic-identity | @@ -32,6 +32,19 @@ For an equivalent sample that declares the same cluster with the AzAPI provider, | `user_node_subnet_address_prefixes` | Address prefixes of the subnet that hosts the user node pools. | ["172.19.1.0/24"] | | `system_node_subnet_address_prefixes` | Address prefixes of the subnet that hosts the managed system node pool. | ["172.19.0.64/26"] | + +> [!NOTE] +> The default location is `westus2` because that's the region these samples were validated in. At the time of testing, `eastus` returned `AKSCapacityHeavyUsage` for API Server VNet Integration. Set `resource_group_location` to deploy elsewhere. + +## Network guardrails + +This sample creates its own virtual network, so the defaults are safe as written. Read these before pointing the variables at an existing network: + +- **Subnet containment and non-overlap.** Every subnet prefix must sit inside `virtual_network_address_space` and must not overlap another subnet in the same virtual network. The defaults carve `172.19.0.0/28`, `172.19.0.64/26`, and `172.19.1.0/24` out of `172.19.0.0/16`. +- **Subnet sizing.** The API server subnet must be at least a `/28`, and AKS reserves at least nine addresses in it. Size the node subnets for the pod and node scale you expect, because a subnet that runs out of addresses blocks scaling. +- **Role assignment blast radius.** The cluster identity is granted **Network Contributor** on the whole virtual network, which is what Node Autoprovisioning needs. If you retarget this sample at a shared virtual network, that grant reaches every subnet and resource in it. Scope it more tightly, or keep the cluster in a dedicated network. +- **Delegation drift is hidden.** The managed system node subnet sets `ignore_changes = [delegation]` because AKS adds its own managed cluster delegation after the cluster is created. That keeps plans clean, but it also means Terraform won't report if the delegation is later changed or removed outside Terraform. + ## Example ```console @@ -39,3 +52,4 @@ terraform init -upgrade terraform plan -out main.tfplan terraform apply main.tfplan ``` + diff --git a/quickstart/101-aks-automatic-custom-network/variables.tf b/quickstart/101-aks-automatic-custom-network/variables.tf index 7e26e3864..8fe2b1ef4 100644 --- a/quickstart/101-aks-automatic-custom-network/variables.tf +++ b/quickstart/101-aks-automatic-custom-network/variables.tf @@ -1,6 +1,6 @@ variable "resource_group_location" { type = string - default = "eastus" + default = "westus2" description = "Location of the resource group." } diff --git a/quickstart/101-aks-automatic-private-custom-network-azapi/main.tf b/quickstart/101-aks-automatic-private-custom-network-azapi/main.tf index d7e1dd887..9fd84d1c6 100644 --- a/quickstart/101-aks-automatic-private-custom-network-azapi/main.tf +++ b/quickstart/101-aks-automatic-private-custom-network-azapi/main.tf @@ -92,13 +92,15 @@ resource "azapi_resource" "aks_automatic" { body = { sku = { - name = var.cluster_sku_name + name = "Automatic" } properties = { apiServerAccessProfile = { - # A private cluster API server is only reachable from inside the - # virtual network. + # A private cluster API server is assigned a private IP address in the + # virtual network. Reaching it requires private connectivity and DNS + # resolution of the private FQDN, which peering, a VPN, or ExpressRoute + # can provide from outside this virtual network. enablePrivateCluster = true subnetId = azurerm_subnet.api_server.id } diff --git a/quickstart/101-aks-automatic-private-custom-network-azapi/readme.md b/quickstart/101-aks-automatic-private-custom-network-azapi/readme.md index 555a6106f..b9fd77a54 100644 --- a/quickstart/101-aks-automatic-private-custom-network-azapi/readme.md +++ b/quickstart/101-aks-automatic-private-custom-network-azapi/readme.md @@ -2,9 +2,9 @@ This template deploys a private AKS Automatic cluster into a custom virtual network, in a resource group with a random name beginning with "rg-". -The virtual network contains a subnet delegated to the cluster API server, a subnet for the user node pools, and a subnet for the managed system node pool. The cluster uses a user-assigned managed identity that's granted the Network Contributor role on the virtual network, which is required when you bring your own network. Because the cluster is private, its API server is only reachable from inside the virtual network. +The virtual network contains a subnet delegated to the cluster API server, a subnet for the user node pools, and a subnet for the managed system node pool. The cluster uses a user-assigned managed identity that's granted the Network Contributor role on the virtual network, which is required when you bring your own network. Because the cluster is private, the API server endpoint is assigned a private IP address in the virtual network instead of a public one. Reaching it requires private network connectivity to that virtual network and DNS resolution of the private FQDN, so access isn't limited to clients inside the virtual network itself: virtual network peering, a VPN gateway, or Azure ExpressRoute can all provide a path from outside it. Enabling a public FQDN changes only how the cluster is named in DNS. It doesn't make the private endpoint routable from the internet. -The cluster is declared with the AzAPI provider's [`azapi_resource`](https://registry.terraform.io/providers/Azure/azapi/latest/docs/resources/resource) against the `Microsoft.ContainerService/managedClusters` API. Use this pattern when you need direct control over the managed cluster API payload, or when you need an API version or property that the AzureRM provider doesn't expose yet. +The cluster is declared with the AzAPI provider's [`azapi_resource`](https://registry.terraform.io/providers/Azure/azapi/latest/docs/resources/resource) against the `Microsoft.ContainerService/managedClusters` API. Use this pattern when you need direct control over the managed cluster API payload, or when you need an API version or property that the AzureRM provider doesn't expose yet. The cluster SKU is hard-coded to `Automatic`. For the equivalent sample that uses the AzureRM provider's `azurerm_kubernetes_automatic_cluster` resource, see [101-aks-automatic-private-custom-network](../101-aks-automatic-private-custom-network/). For a public cluster in a custom virtual network, see [101-aks-automatic-custom-network-azapi](../101-aks-automatic-custom-network-azapi/). @@ -23,9 +23,8 @@ For the equivalent sample that uses the AzureRM provider's `azurerm_kubernetes_a | Name | Description | Default | Validation | |-|-|-|-| | `resource_group_name_prefix` | Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription. | rg | | -| `resource_group_location` | Location of the resource group. | eastus | | +| `resource_group_location` | Location of the resource group. | westus2 | | | `cluster_name_prefix` | Prefix of the AKS Automatic cluster name that's combined with a random ID so the name is unique in your Azure subscription. | aks-automatic | | -| `cluster_sku_name` | The managed cluster SKU name. Use `Automatic` for an AKS Automatic cluster. | Automatic | Must be `Automatic` or `Base`. | | `virtual_network_name` | Name of the custom virtual network that hosts the cluster. | aks-automatic-vnet | | | `identity_name` | Name of the user-assigned managed identity that the cluster uses. | aks-automatic-identity | | | `virtual_network_address_space` | Address space of the custom virtual network. | ["172.19.0.0/16"] | | @@ -33,6 +32,19 @@ For the equivalent sample that uses the AzureRM provider's `azurerm_kubernetes_a | `user_node_subnet_address_prefixes` | Address prefixes of the subnet that hosts the user node pools. | ["172.19.1.0/24"] | | | `system_node_subnet_address_prefixes` | Address prefixes of the subnet that hosts the managed system node pool. | ["172.19.0.64/26"] | | + +> [!NOTE] +> The default location is `westus2` because that's the region these samples were validated in. At the time of testing, `eastus` returned `AKSCapacityHeavyUsage` for API Server VNet Integration. Set `resource_group_location` to deploy elsewhere. + +## Network guardrails + +This sample creates its own virtual network, so the defaults are safe as written. Read these before pointing the variables at an existing network: + +- **Subnet containment and non-overlap.** Every subnet prefix must sit inside `virtual_network_address_space` and must not overlap another subnet in the same virtual network. The defaults carve `172.19.0.0/28`, `172.19.0.64/26`, and `172.19.1.0/24` out of `172.19.0.0/16`. +- **Subnet sizing.** The API server subnet must be at least a `/28`, and AKS reserves at least nine addresses in it. Size the node subnets for the pod and node scale you expect, because a subnet that runs out of addresses blocks scaling. +- **Role assignment blast radius.** The cluster identity is granted **Network Contributor** on the whole virtual network, which is what Node Autoprovisioning needs. If you retarget this sample at a shared virtual network, that grant reaches every subnet and resource in it. Scope it more tightly, or keep the cluster in a dedicated network. +- **Delegation drift is hidden.** The managed system node subnet sets `ignore_changes = [delegation]` because AKS adds its own managed cluster delegation after the cluster is created. That keeps plans clean, but it also means Terraform won't report if the delegation is later changed or removed outside Terraform. + ## Example ```console @@ -40,3 +52,6 @@ terraform init -upgrade terraform plan -out main.tfplan terraform apply main.tfplan ``` + + + diff --git a/quickstart/101-aks-automatic-private-custom-network-azapi/variables.tf b/quickstart/101-aks-automatic-private-custom-network-azapi/variables.tf index 9f19678d3..8fe2b1ef4 100644 --- a/quickstart/101-aks-automatic-private-custom-network-azapi/variables.tf +++ b/quickstart/101-aks-automatic-private-custom-network-azapi/variables.tf @@ -1,6 +1,6 @@ variable "resource_group_location" { type = string - default = "eastus" + default = "westus2" description = "Location of the resource group." } @@ -16,17 +16,6 @@ variable "cluster_name_prefix" { description = "Prefix of the AKS Automatic cluster name that's combined with a random ID so the name is unique in your Azure subscription." } -variable "cluster_sku_name" { - type = string - default = "Automatic" - description = "The managed cluster SKU name. Use 'Automatic' for an AKS Automatic cluster." - - validation { - condition = contains(["Automatic", "Base"], var.cluster_sku_name) - error_message = "The cluster_sku_name value must be either 'Automatic' or 'Base'." - } -} - variable "virtual_network_name" { type = string default = "aks-automatic-vnet" diff --git a/quickstart/101-aks-automatic-private-custom-network/main.tf b/quickstart/101-aks-automatic-private-custom-network/main.tf index 4d2be1fd2..a80e65589 100644 --- a/quickstart/101-aks-automatic-private-custom-network/main.tf +++ b/quickstart/101-aks-automatic-private-custom-network/main.tf @@ -96,8 +96,10 @@ resource "azurerm_kubernetes_automatic_cluster" "aks_automatic" { system_node_subnet_id = azurerm_subnet.system_nodes.id } - # The private_cluster block makes the cluster API server private, so it's - # only reachable from inside the virtual network. + # The private_cluster block gives the API server a private IP address in the + # virtual network. Reaching it requires private connectivity and DNS + # resolution of the private FQDN, which peering, a VPN, or ExpressRoute can + # provide from outside this virtual network. private_cluster { public_fully_qualified_domain_name_enabled = var.public_fully_qualified_domain_name_enabled } diff --git a/quickstart/101-aks-automatic-private-custom-network/readme.md b/quickstart/101-aks-automatic-private-custom-network/readme.md index 2d98d96d5..8db07309a 100644 --- a/quickstart/101-aks-automatic-private-custom-network/readme.md +++ b/quickstart/101-aks-automatic-private-custom-network/readme.md @@ -2,7 +2,7 @@ This template deploys a private AKS Automatic cluster into a custom virtual network, in a resource group with a random name beginning with "rg-". -The virtual network contains a subnet delegated to the cluster API server, a subnet for the user node pools, and a subnet for the managed system node pool. The cluster uses a user-assigned managed identity that's granted the Network Contributor role on the virtual network, which is required when you bring your own network. Because the cluster is private, its API server is only reachable from inside the virtual network. +The virtual network contains a subnet delegated to the cluster API server, a subnet for the user node pools, and a subnet for the managed system node pool. The cluster uses a user-assigned managed identity that's granted the Network Contributor role on the virtual network, which is required when you bring your own network. Because the cluster is private, the API server endpoint is assigned a private IP address in the virtual network instead of a public one. Reaching it requires private network connectivity to that virtual network and DNS resolution of the private FQDN, so access isn't limited to clients inside the virtual network itself: virtual network peering, a VPN gateway, or Azure ExpressRoute can all provide a path from outside it. Enabling a public FQDN changes only how the cluster is named in DNS. It doesn't make the private endpoint routable from the internet. The cluster is created with the AzureRM provider's [`azurerm_kubernetes_automatic_cluster`](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/kubernetes_automatic_cluster) resource, which is the recommended way to declare an AKS Automatic cluster. This resource requires AzureRM provider `5.0` or later. @@ -23,7 +23,7 @@ For an equivalent sample that declares the same cluster with the AzAPI provider, | Name | Description | Default | |-|-|-| | `resource_group_name_prefix` | Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription. | rg | -| `resource_group_location` | Location of the resource group. | eastus | +| `resource_group_location` | Location of the resource group. | westus2 | | `cluster_name_prefix` | Prefix of the AKS Automatic cluster name that's combined with a random ID so the name is unique in your Azure subscription. | aks-automatic | | `public_fully_qualified_domain_name_enabled` | Whether to provision a public FQDN for the private cluster. | false | | `virtual_network_name` | Name of the custom virtual network that hosts the cluster. | aks-automatic-vnet | @@ -33,6 +33,19 @@ For an equivalent sample that declares the same cluster with the AzAPI provider, | `user_node_subnet_address_prefixes` | Address prefixes of the subnet that hosts the user node pools. | ["172.19.1.0/24"] | | `system_node_subnet_address_prefixes` | Address prefixes of the subnet that hosts the managed system node pool. | ["172.19.0.64/26"] | + +> [!NOTE] +> The default location is `westus2` because that's the region these samples were validated in. At the time of testing, `eastus` returned `AKSCapacityHeavyUsage` for API Server VNet Integration. Set `resource_group_location` to deploy elsewhere. + +## Network guardrails + +This sample creates its own virtual network, so the defaults are safe as written. Read these before pointing the variables at an existing network: + +- **Subnet containment and non-overlap.** Every subnet prefix must sit inside `virtual_network_address_space` and must not overlap another subnet in the same virtual network. The defaults carve `172.19.0.0/28`, `172.19.0.64/26`, and `172.19.1.0/24` out of `172.19.0.0/16`. +- **Subnet sizing.** The API server subnet must be at least a `/28`, and AKS reserves at least nine addresses in it. Size the node subnets for the pod and node scale you expect, because a subnet that runs out of addresses blocks scaling. +- **Role assignment blast radius.** The cluster identity is granted **Network Contributor** on the whole virtual network, which is what Node Autoprovisioning needs. If you retarget this sample at a shared virtual network, that grant reaches every subnet and resource in it. Scope it more tightly, or keep the cluster in a dedicated network. +- **Delegation drift is hidden.** The managed system node subnet sets `ignore_changes = [delegation]` because AKS adds its own managed cluster delegation after the cluster is created. That keeps plans clean, but it also means Terraform won't report if the delegation is later changed or removed outside Terraform. + ## Example ```console @@ -40,3 +53,5 @@ terraform init -upgrade terraform plan -out main.tfplan terraform apply main.tfplan ``` + + diff --git a/quickstart/101-aks-automatic-private-custom-network/variables.tf b/quickstart/101-aks-automatic-private-custom-network/variables.tf index 03443159f..28e4a7d0a 100644 --- a/quickstart/101-aks-automatic-private-custom-network/variables.tf +++ b/quickstart/101-aks-automatic-private-custom-network/variables.tf @@ -1,6 +1,6 @@ variable "resource_group_location" { type = string - default = "eastus" + default = "westus2" description = "Location of the resource group." } From 011a1690696847326d9de108fdab91fdcc94fee4 Mon Sep 17 00:00:00 2001 From: asudbring Date: Thu, 6 Aug 2026 16:16:27 +0100 Subject: [PATCH 6/6] Pin azurerm consistently, correct provider version, drop region notes Set the azurerm pin to ~>5.0 in the AzAPI samples to match the provider-native ones, correct the minimum provider version to v4.81, and remove the tested-region notes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../101-aks-automatic-custom-network-azapi/providers.tf | 2 +- quickstart/101-aks-automatic-custom-network-azapi/readme.md | 4 +--- quickstart/101-aks-automatic-custom-network/readme.md | 6 ++---- .../providers.tf | 2 +- .../readme.md | 4 +--- .../101-aks-automatic-private-custom-network/readme.md | 6 ++---- 6 files changed, 8 insertions(+), 16 deletions(-) diff --git a/quickstart/101-aks-automatic-custom-network-azapi/providers.tf b/quickstart/101-aks-automatic-custom-network-azapi/providers.tf index 172c6cb0b..2c375b07c 100644 --- a/quickstart/101-aks-automatic-custom-network-azapi/providers.tf +++ b/quickstart/101-aks-automatic-custom-network-azapi/providers.tf @@ -7,7 +7,7 @@ terraform { } azurerm = { source = "hashicorp/azurerm" - version = "~>4.0" + version = "~>5.0" } random = { source = "hashicorp/random" diff --git a/quickstart/101-aks-automatic-custom-network-azapi/readme.md b/quickstart/101-aks-automatic-custom-network-azapi/readme.md index 4b1a00700..c3b100f9f 100644 --- a/quickstart/101-aks-automatic-custom-network-azapi/readme.md +++ b/quickstart/101-aks-automatic-custom-network-azapi/readme.md @@ -33,9 +33,6 @@ For the equivalent sample that uses the AzureRM provider's `azurerm_kubernetes_a | `system_node_subnet_address_prefixes` | Address prefixes of the subnet that hosts the managed system node pool. | ["172.19.0.64/26"] | | -> [!NOTE] -> The default location is `westus2` because that's the region these samples were validated in. At the time of testing, `eastus` returned `AKSCapacityHeavyUsage` for API Server VNet Integration. Set `resource_group_location` to deploy elsewhere. - ## Network guardrails This sample creates its own virtual network, so the defaults are safe as written. Read these before pointing the variables at an existing network: @@ -54,3 +51,4 @@ terraform apply main.tfplan ``` + diff --git a/quickstart/101-aks-automatic-custom-network/readme.md b/quickstart/101-aks-automatic-custom-network/readme.md index 94634d8f2..ba812b094 100644 --- a/quickstart/101-aks-automatic-custom-network/readme.md +++ b/quickstart/101-aks-automatic-custom-network/readme.md @@ -4,7 +4,7 @@ This template deploys an AKS Automatic cluster into a custom virtual network, in The virtual network contains a subnet delegated to the cluster API server, a subnet for the user node pools, and a subnet for the managed system node pool. The cluster uses a user-assigned managed identity that's granted the Network Contributor role on the virtual network, which is required when you bring your own network. -The cluster is created with the AzureRM provider's [`azurerm_kubernetes_automatic_cluster`](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/kubernetes_automatic_cluster) resource, which is the recommended way to declare an AKS Automatic cluster. This resource requires AzureRM provider `5.0` or later. +The cluster is created with the AzureRM provider's [`azurerm_kubernetes_automatic_cluster`](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/kubernetes_automatic_cluster) resource, which is the recommended way to declare an AKS Automatic cluster. This resource requires AzureRM provider `v4.81` or later. For an equivalent sample that declares the same cluster with the AzAPI provider, see [101-aks-automatic-custom-network-azapi](../101-aks-automatic-custom-network-azapi/). For a private cluster in a custom virtual network, see [101-aks-automatic-private-custom-network](../101-aks-automatic-private-custom-network/). @@ -33,9 +33,6 @@ For an equivalent sample that declares the same cluster with the AzAPI provider, | `system_node_subnet_address_prefixes` | Address prefixes of the subnet that hosts the managed system node pool. | ["172.19.0.64/26"] | -> [!NOTE] -> The default location is `westus2` because that's the region these samples were validated in. At the time of testing, `eastus` returned `AKSCapacityHeavyUsage` for API Server VNet Integration. Set `resource_group_location` to deploy elsewhere. - ## Network guardrails This sample creates its own virtual network, so the defaults are safe as written. Read these before pointing the variables at an existing network: @@ -53,3 +50,4 @@ terraform plan -out main.tfplan terraform apply main.tfplan ``` + diff --git a/quickstart/101-aks-automatic-private-custom-network-azapi/providers.tf b/quickstart/101-aks-automatic-private-custom-network-azapi/providers.tf index 172c6cb0b..2c375b07c 100644 --- a/quickstart/101-aks-automatic-private-custom-network-azapi/providers.tf +++ b/quickstart/101-aks-automatic-private-custom-network-azapi/providers.tf @@ -7,7 +7,7 @@ terraform { } azurerm = { source = "hashicorp/azurerm" - version = "~>4.0" + version = "~>5.0" } random = { source = "hashicorp/random" diff --git a/quickstart/101-aks-automatic-private-custom-network-azapi/readme.md b/quickstart/101-aks-automatic-private-custom-network-azapi/readme.md index b9fd77a54..d30690194 100644 --- a/quickstart/101-aks-automatic-private-custom-network-azapi/readme.md +++ b/quickstart/101-aks-automatic-private-custom-network-azapi/readme.md @@ -33,9 +33,6 @@ For the equivalent sample that uses the AzureRM provider's `azurerm_kubernetes_a | `system_node_subnet_address_prefixes` | Address prefixes of the subnet that hosts the managed system node pool. | ["172.19.0.64/26"] | | -> [!NOTE] -> The default location is `westus2` because that's the region these samples were validated in. At the time of testing, `eastus` returned `AKSCapacityHeavyUsage` for API Server VNet Integration. Set `resource_group_location` to deploy elsewhere. - ## Network guardrails This sample creates its own virtual network, so the defaults are safe as written. Read these before pointing the variables at an existing network: @@ -55,3 +52,4 @@ terraform apply main.tfplan + diff --git a/quickstart/101-aks-automatic-private-custom-network/readme.md b/quickstart/101-aks-automatic-private-custom-network/readme.md index 8db07309a..40462a6cc 100644 --- a/quickstart/101-aks-automatic-private-custom-network/readme.md +++ b/quickstart/101-aks-automatic-private-custom-network/readme.md @@ -4,7 +4,7 @@ This template deploys a private AKS Automatic cluster into a custom virtual netw The virtual network contains a subnet delegated to the cluster API server, a subnet for the user node pools, and a subnet for the managed system node pool. The cluster uses a user-assigned managed identity that's granted the Network Contributor role on the virtual network, which is required when you bring your own network. Because the cluster is private, the API server endpoint is assigned a private IP address in the virtual network instead of a public one. Reaching it requires private network connectivity to that virtual network and DNS resolution of the private FQDN, so access isn't limited to clients inside the virtual network itself: virtual network peering, a VPN gateway, or Azure ExpressRoute can all provide a path from outside it. Enabling a public FQDN changes only how the cluster is named in DNS. It doesn't make the private endpoint routable from the internet. -The cluster is created with the AzureRM provider's [`azurerm_kubernetes_automatic_cluster`](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/kubernetes_automatic_cluster) resource, which is the recommended way to declare an AKS Automatic cluster. This resource requires AzureRM provider `5.0` or later. +The cluster is created with the AzureRM provider's [`azurerm_kubernetes_automatic_cluster`](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/kubernetes_automatic_cluster) resource, which is the recommended way to declare an AKS Automatic cluster. This resource requires AzureRM provider `v4.81` or later. For an equivalent sample that declares the same cluster with the AzAPI provider, see [101-aks-automatic-private-custom-network-azapi](../101-aks-automatic-private-custom-network-azapi/). For a public cluster in a custom virtual network, see [101-aks-automatic-custom-network](../101-aks-automatic-custom-network/). @@ -34,9 +34,6 @@ For an equivalent sample that declares the same cluster with the AzAPI provider, | `system_node_subnet_address_prefixes` | Address prefixes of the subnet that hosts the managed system node pool. | ["172.19.0.64/26"] | -> [!NOTE] -> The default location is `westus2` because that's the region these samples were validated in. At the time of testing, `eastus` returned `AKSCapacityHeavyUsage` for API Server VNet Integration. Set `resource_group_location` to deploy elsewhere. - ## Network guardrails This sample creates its own virtual network, so the defaults are safe as written. Read these before pointing the variables at an existing network: @@ -55,3 +52,4 @@ terraform apply main.tfplan ``` +