---
title: "Quickstart: Create an Azure Kubernetes Fleet Manager and join member clusters using Terraform"
description: In this quickstart, you learn how to create an Azure Kubernetes Fleet Manager and join member clusters using Terraform.
ms.date: 12/16/2025
author: muhammadali
ms.author: alimuhammad
ms.service: azure-kubernetes-fleet-manager
ms.custom: template-quickstart, mode-other
ms.devlang: azurecli
ms.topic: quickstart
# Customer intent: As a cloud architect, I want to create an Azure Kubernetes Fleet Manager and join member clusters using Terraform, so that I can manage and orchestrate multiple Kubernetes clusters for improved scalability and application deployment.
---

# Quickstart: Create an Azure Kubernetes Fleet Manager using Terraform

**Applies to:** :heavy_check_mark: Fleet Manager :heavy_check_mark: Fleet Manager with hub cluster

Learn how to create an Azure Kubernetes Fleet Manager using Terraform.

## Before you begin

[!INCLUDE [free trial note](~/reusable-content/ce-skilling/azure/includes/quickstarts-free-trial-note.md)]

* Read the [conceptual overview of Fleet Manager](./concepts-fleet.md), which provides an explanation of fleets and member clusters referenced in this document.
* An Azure account with an active subscription. [Create an account for free](https://azure.microsoft.com/pricing/purchase-options/azure-account?cid=msft_learn).
* [Install and configure Terraform](/azure/developer/terraform/quickstart-configure).

> [!IMPORTANT]
> If you're using the 4.x AzureRM Terraform provider, you must [explicitly specify the Azure subscription ID](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/4.0-upgrade-guide#specifying-subscription-id-is-now-mandatory) to authenticate to Azure before running commands.
>
> One way to specify the Azure subscription ID without putting it in the `providers` block is to specify the subscription ID in an environment variable named `ARM_SUBSCRIPTION_ID`.
>
> For more information, see the [Azure provider reference documentation](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs#argument-reference).

## Create a Fleet Manager

You can create a Fleet Manager and later add your AKS and Arc-enabled clusters as member clusters.  If the Fleet Manager has a hub cluster, more features are enabled, such as [Kubernetes object propagation](./concepts-resource-placement.md) and [Managed Fleet Namespaces](./concepts-fleet-managed-namespace.md). For more information, see the [conceptual overview of Fleet Manager types](./concepts-choosing-fleet.md), which provides a comparison of different Fleet Manager configurations.

> [!NOTE]
> Once a Fleet Manager is created, it's possible to upgrade a Fleet Manager resource without a hub cluster to one with a hub cluster. For Fleet Manager resources with a hub cluster, once private or public is selected it can't be changed.

### [Fleet Manager without hub cluster](#tab/without-hub-cluster)

To create a Fleet Manager without a hub cluster, use the following steps.

1. Create a directory you can use to test the sample Terraform code and make it your current directory.

1. Create a file named `providers.tf` and insert the following code:
    [!code-terraform[master](~/terraform_samples/quickstart/101-aks-fleet-hubless/providers.tf)]

1. Create a file named `main.tf` and insert the following code:
    [!code-terraform[master](~/terraform_samples/quickstart/101-aks-fleet-hubless/main.tf)]

1. Create a file named `variables.tf` and insert the following code:
    [!code-terraform[master](~/terraform_samples/quickstart/101-aks-fleet-hubless/variables.tf)]

1. Create a file named `outputs.tf` and insert the following code:
    [!code-terraform[master](~/terraform_samples/quickstart/101-aks-fleet-hubless/outputs.tf)]

### [Fleet Manager with hub cluster](#tab/with-hub-cluster)

To use Fleet Manager for Kubernetes object propagation or Managed Fleet Namespaces in addition to cluster upgrades, you need to create the Fleet Manager with a hub cluster.

Fleet Manager hub clusters support both public and private modes for network access. For more information, see [Choose an Azure Kubernetes Fleet Manager option](./concepts-choosing-fleet.md#network-access-modes-for-hub-cluster).

1. Create a directory you can use to test the sample Terraform code and make it your current directory.

1. Create a file named `providers.tf` and insert the following code:

    ```terraform
    terraform {
     required_providers {
        azapi = {
          source  = "azure/azapi"
          version = "~> 2.0"
        }
        azurerm = {
          source  = "hashicorp/azurerm"
          version = "~> 4.0"
        }
        random = {
          source  = "hashicorp/random"
          version = "~> 3.1"
        }
      }
    }
    provider "azurerm" {
      features {}
    }
    provider "azapi" {
    }
    ```

1. Create a file named `variables.tf` insert the following code.

    ```terraform
    variable "location" {
      description = "The Azure region where resources will be created"
      type        = string
      default     = "Australia East"
    }
    
    variable "resource_group_name" {
      description = "The name of the resource group"
      type        = string
      default     = null
    }
    
    variable "fleet_name" {
      description = "The name of the Fleet"
      type        = string
      default     = null
    }
    
    variable "hub_cluster_vm_size" {
      description = "VM size for the Fleet hub cluster"
      type        = string
      default     = "Standard_D2s_v3"
    }
    ```

1. Create a file named `main.tf` and insert the following code:

    ```terraform
    # Generate random suffix for unique resource names
    resource "random_string" "suffix" {
      length  = 4
      special = false
      upper   = false
    }
    
    # Local values for resource naming
    locals {
      resource_group_name = coalesce(var.resource_group_name, "rg-fleet-example-${random_string.suffix.result}")
      fleet_name = coalesce(var.fleet_name, "fleet-example-${random_string.suffix.result}")
    }
    
    # Resource Group
    resource "azurerm_resource_group" "fleet_rg" {
      name     = local.resource_group_name
      location = var.location
    }
    ```

#### Public hub cluster

1. Create a file named `fleet.tf` and insert the following code:

    ```terraform
    resource "azapi_resource" "fleet_public" {
      type      = "Microsoft.ContainerService/fleets@2025-03-01"
      name      = "${local.fleet_name}-pub"
      location  = azurerm_resource_group.fleet_rg.location
      parent_id = azurerm_resource_group.fleet_rg.id
    
      body = {
        properties = {
          hubProfile = {
            agentProfile = {
              vmSize = var.hub_cluster_vm_size
            }
            apiServerAccessProfile = {
              enablePrivateCluster = false
              enableVnetIntegration = false
            }
            dnsPrefix = "${local.fleet_name}-pub"
          }
        }
      }
    
      identity {
        type = "SystemAssigned"
      }
    
      depends_on = [
        azurerm_resource_group.fleet_rg
      ]
    }
    ```

#### Private hub cluster

[!INCLUDE [private-fleet-prerequisites.md](./includes/private-fleet/private-fleet-prerequisites.md)]

1. Fetch Fleet Manager's service principal object ID:

    ```azurecli-interactive
    az ad sp list \
        --display-name "Azure Kubernetes Service - Fleet RP" \
        --query "[].{id:id}" \
        --output tsv
    ```
    
    ```output
    xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    ```

1. Create a file named `identity.tf` and insert the following code, updating the placeholder `principal_id` to match the output from the earlier service principal query:

    ```terraform
    ##
    # REQUIRED: Assign Network Contributor Role to "Azure Kubernetes Service - Fleet RP" to enable hub cluster updates
    ##
    resource "azurerm_role_assignment" "fleet_identity_01_network_contributor" {
      scope                = azurerm_subnet.hub-cluster-subnet.id
      role_definition_name = "Network Contributor"
      principal_id         = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
      principal_type       = "ServicePrincipal"
    
      depends_on = [azurerm_subnet.hub-cluster-subnet]
    }
    
    ##
    # REQUIRED: Create User Assigned Managed Identity for Fleet Manager
    ##
    resource "azurerm_user_assigned_identity" "fleet_user_assigned_identity" {
      location            = azurerm_resource_group.fleet_rg.location
      name                = "${local.fleet_name}-uai"
      resource_group_name = azurerm_resource_group.fleet_rg.name
    }
    
    # REQUIRED: Assign Managed Identity the Network Contributor Role scoped to Hub Cluster API Server Subnet
    resource "azurerm_role_assignment" "fleet_user_assign_id_api_subnet_network_contributor" {
      scope                = azurerm_subnet.fleet-hub-apiserver-subnet.id
      role_definition_name = "Network Contributor"
      principal_id         = azurerm_user_assigned_identity.fleet_user_assigned_identity.principal_id
      principal_type       = "ServicePrincipal"
    
      depends_on = [azurerm_subnet.fleet-hub-apiserver-subnet, azurerm_user_assigned_identity.fleet_user_assigned_identity]
    }
    
    # REQUIRED: Assign Managed Identity the Network Contributor Role scoped to Hub Cluster Subnet
    resource "azurerm_role_assignment" "fleet_user_assign_id_hub_subnet_network_contributor" {
      scope                = azurerm_subnet.hub-cluster-subnet.id
      role_definition_name = "Network Contributor"
      principal_id         = azurerm_user_assigned_identity.fleet_user_assigned_identity.principal_id
      principal_type       = "ServicePrincipal"
    
      depends_on = [azurerm_subnet.hub-cluster-subnet, azurerm_user_assigned_identity.fleet_user_assigned_identity]
    }
    ```

1. Create a file named `vnet.tf` and insert the following code. If you want to use an existing virtual network you can replace the contents of `vnet.tf` file with resource references only, ensuring you have the correct subnets and delegations in place.
    
    ```terraform
    resource "azurerm_virtual_network" "hub-vnet" {
      name                = "${local.fleet_name}-vnet"
      location            = azurerm_resource_group.fleet_rg.location
      resource_group_name = azurerm_resource_group.fleet_rg.name
      address_space       = ["10.224.0.0/12"]
    }
    
    resource "azurerm_subnet" "hub-cluster-subnet" {
      name                 = "fleet-hub-cluster-subnet"
      resource_group_name  = azurerm_resource_group.fleet_rg.name
      virtual_network_name = azurerm_virtual_network.hub-vnet.name
      address_prefixes     = ["10.224.0.0/15"]
      private_endpoint_network_policies = "Disabled"
      private_link_service_network_policies_enabled = true
    }
    
    resource "azurerm_subnet" "fleet-hub-apiserver-subnet" {
      name                 = "fleet-hub-apiserver-subnet"
      resource_group_name  = azurerm_resource_group.fleet_rg.name
      virtual_network_name = azurerm_virtual_network.hub-vnet.name
      address_prefixes     = ["10.226.0.0/15"]
      delegation {
        name = "aksApiServerSubnetDelegation"
        service_delegation {
          name    = "Microsoft.ContainerService/managedClusters"
        }
      }
    }
    ```

1. Create a file named `fleet.tf` and insert the following code:

    ```terraform   
    # Fleet Resource
    resource "azapi_resource" "fleet" {
      type      = "Microsoft.ContainerService/fleets@2025-03-01"
      name      = local.fleet_name
      location  = azurerm_resource_group.fleet_rg.location
      parent_id = azurerm_resource_group.fleet_rg.id
    
      body = {
        properties = {
          hubProfile = {
            agentProfile = {
              subnetId = azurerm_subnet.hub-cluster-subnet.id
              vmSize = var.hub_cluster_vm_size
            }
            apiServerAccessProfile = {
              enablePrivateCluster = true
              enableVnetIntegration = true
              subnetId = azurerm_subnet.fleet-hub-apiserver-subnet.id
            }
            dnsPrefix = local.fleet_name
          }
        }
      }
    
      identity {
        type = "UserAssigned"
        identity_ids = [azurerm_user_assigned_identity.fleet_user_assigned_identity.id]
      }
    
      depends_on = [
        azurerm_resource_group.fleet_rg,
        azurerm_role_assignment.fleet_identity_01_network_contributor, 
        azurerm_user_assigned_identity.fleet_user_assigned_identity, 
        azurerm_role_assignment.fleet_user_assign_id_api_subnet_network_contributor,
        azurerm_role_assignment.fleet_user_assign_id_hub_subnet_network_contributor
      ]
    }
    ```

---

#### Initialize Terraform

[!INCLUDE [terraform-init.md](~/azure-dev-docs-pr/articles/terraform/includes/terraform-init.md)]

#### Create a Terraform execution plan

[!INCLUDE [terraform-plan.md](~/azure-dev-docs-pr/articles/terraform/includes/terraform-plan.md)]

#### Apply a Terraform execution plan

[!INCLUDE [terraform-apply-plan.md](~/azure-dev-docs-pr/articles/terraform/includes/terraform-apply-plan.md)]

#### Verify the results

Verify results using either Azure CLI or Azure PowerShell.

### [Azure CLI](#tab/azure-cli)

1. Get the Azure resource group name.

    ```console
    resource_group_name=$(terraform output -raw resource_group_name)
    ```

1. Get the Fleet Manager name.

    ```console
    batch_name=$(terraform output -raw fleet_name)
    ```

1. Run [az fleet show](/cli/azure/fleet#az-fleet-show) to view the Azure Kubernetes Fleet Manager.

    ```azurecli
    az fleet show --resource-group $resource_group_name --name $fleet_name
    ```

### [Azure PowerShell](#tab/azure-powershell)

1. Get the Azure resource group name.

    ```powershell
    $resource_group_name=$(terraform output -raw resource_group_name)
    ```

1. Get the Fleet Manager name.

    ```powershell
    $batch_name=$(terraform output -raw fleet_name)
    ```

1. Run [Get-AzFleet](/powershell/module/az.fleet/get-azfleet) to view the Azure Kubernetes Fleet Manager.

    ```azurepowershell
    Get-AzFleet -ResourceGroupName $resource_group_name -Name $fleet_name
    ```
---
    
#### Clean up resources

[!INCLUDE [terraform-plan-destroy.md](~/azure-dev-docs-pr/articles/terraform/includes/terraform-plan-destroy.md)]

## Next steps

* [Access Fleet Manager hub cluster Kubernetes API](./access-fleet-hub-cluster-kubernetes-api.md).
* [Deploy cluster-scoped resources across multiple clusters](./quickstart-resource-propagation.md).
* [Deploy namespace-scoped resources across multiple clusters](./quickstart-namespace-scoped-resource-propagation.md).
* [Create and configure Managed Fleet Namespaces](./howto-managed-namespaces.md).
* [How-to: Upgrade multiple clusters using Azure Kubernetes Fleet Manager update runs](./update-orchestration.md).