Azure Arc Guide
Extend Azure management to hybrid and multi-cloud with Azure Arc: servers, Kubernetes, SQL, governance with Azure Policy, and GitOps.
Prerequisites
- Basic understanding of Azure Resource Manager and Azure Policy
- Familiarity with Kubernetes concepts (for Arc-enabled K8s)
Introduction to Azure Arc
Azure Arc extends Azure management and governance to resources running outside of Azure, including on-premises servers, edge devices, Kubernetes clusters in any cloud, and SQL Server instances in your data center. By projecting these resources into Azure Resource Manager, Arc enables you to manage hybrid and multi-cloud infrastructure using the same Azure tools, policies, and security controls you use for native Azure resources.
Without Azure Arc, managing a hybrid environment requires separate tooling for each platform: Azure portal for cloud resources, System Center for on-premises Windows servers, separate Kubernetes management for each cluster, and custom scripts for compliance across environments. Arc unifies this into a single control plane. You can apply Azure Policy to an on-premises Linux server, deploy applications to a Kubernetes cluster running in AWS, monitor a SQL Server instance in your data center with Azure Monitor, and manage all of these from the Azure portal.
This guide covers the four pillars of Azure Arc: Arc-enabled servers (Windows and Linux machines), Arc-enabled Kubernetes (any CNCF-conformant cluster), Arc-enabled data services (SQL Managed Instance and PostgreSQL), and Arc-enabled application services. You will learn how to onboard resources, apply governance policies, deploy applications with GitOps, and extend Azure services to any infrastructure.
Azure Arc Pricing
Azure Arc control plane functionality is free for all resource types. This includes onboarding servers, Kubernetes clusters, and SQL Server instances, viewing them in the Azure portal, and applying Azure Policy for auditing. Some features built on top of Arc have additional charges: Microsoft Defender for Servers ($15/server/month), Azure Monitor agent data ingestion (per GB), Azure Automanage ($6/server/month), and Arc-enabled data services (per vCore-hour). GitOps configuration for Kubernetes is free.
Arc-Enabled Servers
Arc-enabled servers let you manage Windows and Linux machines running on-premises, in other clouds (AWS, GCP), or at the edge as if they were native Azure VMs. Once connected, servers appear in the Azure portal alongside your Azure VMs, and you can apply Azure Policy, install VM extensions, use Azure Monitor, enable Microsoft Defender for Cloud, and run Azure Update Management.
Onboarding a Single Server
# Download and install the Azure Connected Machine agent
# Linux (one-line install)
wget https://aka.ms/azcmagent -O install_linux_azcmagent.sh
sudo bash install_linux_azcmagent.sh
# Connect the machine to Azure
azcmagent connect \
--resource-group rg-arc-servers \
--location eastus \
--tenant-id <tenant-id> \
--subscription-id <subscription-id> \
--resource-name "web-server-dc1" \
--tags "Environment=Production,Role=WebServer,DataCenter=DC1"
# Verify the connection
azcmagent show
# Windows (PowerShell)
# Invoke-WebRequest -Uri https://aka.ms/AzureConnectedMachineAgent -OutFile AzureConnectedMachineAgent.msi
# Start-Process msiexec.exe -ArgumentList '/i AzureConnectedMachineAgent.msi /quiet' -Wait
# & "$env:ProgramW6432\AzureConnectedMachineAgent\azcmagent.exe" connect --resource-group rg-arc-servers --location eastus --tenant-id <tenant-id>Onboarding at Scale
# Generate a service principal for automated onboarding
az ad sp create-for-rbac \
--name arc-onboarding-sp \
--role "Azure Connected Machine Onboarding" \
--scopes /subscriptions/<subscription-id>/resourceGroups/rg-arc-servers
# Create an onboarding script for Linux (runs unattended)
cat > onboard-arc.sh << 'SCRIPT'
#!/bin/bash
export SUBSCRIPTION_ID="<subscription-id>"
export RESOURCE_GROUP="rg-arc-servers"
export TENANT_ID="<tenant-id>"
export LOCATION="eastus"
export AUTH_TYPE="principal"
export CLIENT_ID="<sp-client-id>"
export CLIENT_SECRET="<sp-client-secret>"
# Install the agent
wget https://aka.ms/azcmagent -O install_linux_azcmagent.sh
sudo bash install_linux_azcmagent.sh
# Connect with service principal
sudo azcmagent connect \
--service-principal-id "$CLIENT_ID" \
--service-principal-secret "$CLIENT_SECRET" \
--resource-group "$RESOURCE_GROUP" \
--tenant-id "$TENANT_ID" \
--location "$LOCATION" \
--subscription-id "$SUBSCRIPTION_ID" \
--resource-name "$(hostname)" \
--tags "Onboarded=automated,Environment=production"
SCRIPT
chmod +x onboard-arc.sh
# Run on each server (via SSH, Ansible, or configuration management tool)
# ansible all -i inventory -m script -a "onboard-arc.sh"
# List all Arc-enabled servers
az connectedmachine list \
--resource-group rg-arc-servers \
--query '[].{Name: name, Status: status, OS: osName, Location: location, Agent: agentVersion}' \
--output tableNetwork Requirements
The Connected Machine agent requires outbound HTTPS (port 443) connectivity to several Azure endpoints. If your servers are behind a firewall, allow traffic to *.his.arc.azure.com, *.guestconfiguration.azure.com,management.azure.com, login.microsoftonline.com, andpackages.microsoft.com. For environments with strict egress controls, use an Azure Arc private link scope to route traffic through a private endpoint instead of public endpoints.
Governance with Azure Policy
One of Arc's most powerful features is extending Azure Policy to non-Azure resources. Azure Policy evaluates resources against rules and can audit non-compliance, enforce configurations, or automatically remediate deviations. For Arc-enabled servers, this includes Guest Configuration policies that evaluate settings inside the operating system.
# Assign a policy to audit servers without the Log Analytics agent
az policy assignment create \
--name audit-log-analytics-agent \
--display-name "Audit Arc servers without Log Analytics agent" \
--policy "/providers/Microsoft.Authorization/policyDefinitions/d26f7642-7545-4e18-9b75-8c9bbdee3a9a" \
--scope "/subscriptions/<subscription-id>/resourceGroups/rg-arc-servers" \
--mi-system-assigned \
--location eastus
# Assign a Guest Configuration policy (audit SSH settings on Linux)
az policy assignment create \
--name audit-ssh-config \
--display-name "Audit SSH configuration on Linux Arc servers" \
--policy "/providers/Microsoft.Authorization/policyDefinitions/a8f3e6a6-dcd2-434c-b0f7-6f309ce913b4" \
--scope "/subscriptions/<subscription-id>/resourceGroups/rg-arc-servers"
# Install the Azure Monitor agent on all Arc servers via policy
az policy assignment create \
--name deploy-ama-linux \
--display-name "Deploy Azure Monitor Agent on Linux Arc servers" \
--policy "/providers/Microsoft.Authorization/policyDefinitions/845857af-0333-4c5d-bbbc-6076697da122" \
--scope "/subscriptions/<subscription-id>/resourceGroups/rg-arc-servers" \
--mi-system-assigned \
--location eastus \
--params '{"effect": {"value": "DeployIfNotExists"}}'
# View compliance status
az policy state list \
--resource-group rg-arc-servers \
--query '[].{Resource: resourceId, Policy: policyDefinitionName, Compliance: complianceState}' \
--output tableArc-Enabled Kubernetes
Arc-enabled Kubernetes connects any CNCF-conformant Kubernetes cluster to Azure, whether it runs on-premises, at the edge, or in another cloud (EKS, GKE, Rancher, OpenShift). Once connected, you can manage the cluster from the Azure portal, apply Azure Policy for Kubernetes, deploy applications using GitOps, enable Container Insights for monitoring, and install Azure Arc extensions for additional capabilities.
# Install the Azure CLI connectedk8s extension
az extension add --name connectedk8s
# Connect a Kubernetes cluster to Azure Arc
az connectedk8s connect \
--name onprem-cluster \
--resource-group rg-arc-kubernetes \
--location eastus \
--tags "Environment=Production,Platform=Rancher,DataCenter=DC1"
# Verify the connection
az connectedk8s show \
--name onprem-cluster \
--resource-group rg-arc-kubernetes \
--query '{Name: name, Status: connectivityStatus, Distribution: distribution, K8sVersion: kubernetesVersion, Nodes: totalNodeCount}' \
--output table
# Enable Azure Monitor Container Insights
az k8s-extension create \
--name azuremonitor-containers \
--cluster-name onprem-cluster \
--resource-group rg-arc-kubernetes \
--cluster-type connectedClusters \
--extension-type Microsoft.AzureMonitor.Containers \
--configuration-settings "logAnalyticsWorkspaceResourceID=/subscriptions/<sub>/resourceGroups/rg-monitoring/providers/Microsoft.OperationalInsights/workspaces/log-analytics"
# Enable Microsoft Defender for Kubernetes
az k8s-extension create \
--name microsoft.azuredefender.kubernetes \
--cluster-name onprem-cluster \
--resource-group rg-arc-kubernetes \
--cluster-type connectedClusters \
--extension-type microsoft.azuredefender.kubernetes
# List connected clusters
az connectedk8s list \
--resource-group rg-arc-kubernetes \
--query '[].{Name: name, Status: connectivityStatus, Version: kubernetesVersion, Nodes: totalNodeCount}' \
--output tableGitOps with Flux
Azure Arc uses Flux v2 for GitOps-based application deployment to Kubernetes clusters. GitOps is a practice where the desired state of your Kubernetes resources is stored in a Git repository, and a controller running in the cluster automatically reconciles the actual state to match the desired state. Changes to the Git repository are automatically applied to the cluster without manual kubectl commands.
# Install the Flux extension
az k8s-extension create \
--name flux \
--cluster-name onprem-cluster \
--resource-group rg-arc-kubernetes \
--cluster-type connectedClusters \
--extension-type microsoft.flux
# Create a GitOps configuration
az k8s-configuration flux create \
--name app-deployment \
--cluster-name onprem-cluster \
--resource-group rg-arc-kubernetes \
--cluster-type connectedClusters \
--scope cluster \
--namespace flux-system \
--url https://github.com/myorg/k8s-manifests \
--branch main \
--kustomization name=infrastructure path=./infrastructure prune=true \
--kustomization name=apps path=./apps prune=true dependsOn='["infrastructure"]'
# Create a GitOps configuration with Helm charts
az k8s-configuration flux create \
--name helm-apps \
--cluster-name onprem-cluster \
--resource-group rg-arc-kubernetes \
--cluster-type connectedClusters \
--scope namespace \
--namespace production \
--url https://github.com/myorg/helm-releases \
--branch main \
--kustomization name=releases path=./production prune=true
# Check GitOps configuration status
az k8s-configuration flux show \
--name app-deployment \
--cluster-name onprem-cluster \
--resource-group rg-arc-kubernetes \
--cluster-type connectedClusters \
--query '{Name: name, Status: complianceState, Source: sourceKind, URL: gitRepository.url, Branch: gitRepository.branch}' \
--output tableGitOps Best Practices
Structure your Git repository with separate directories for infrastructure components (namespaces, RBAC, network policies) and application deployments. Use Kustomize overlays for environment-specific configurations (dev, staging, production) within the same repository. Set prune=true on Kustomization configurations so resources removed from Git are also removed from the cluster. Use branch-based promotion: merge to the main branch to deploy to production.
Arc-Enabled Data Services
Arc-enabled data services bring Azure SQL Managed Instance and Azure Database for PostgreSQL to any Kubernetes cluster, whether on-premises or in another cloud. These are the same managed database engines available in Azure, but running on your infrastructure with Azure management capabilities including elastic scaling, automated updates, point-in-time restore, and Azure portal integration.
# Create a data controller (manages Arc data services)
az arcdata dc create \
--name arc-data-controller \
--resource-group rg-arc-data \
--connectivity-mode indirect \
--location eastus \
--k8s-namespace arc-data \
--storage-class managed-premium \
--infrastructure onpremises \
--use-k8s
# Create an Arc-enabled SQL Managed Instance
az sql mi-arc create \
--name sql-prod-01 \
--resource-group rg-arc-data \
--location eastus \
--k8s-namespace arc-data \
--cores-limit 8 \
--cores-request 4 \
--memory-limit 32Gi \
--memory-request 16Gi \
--storage-class-data managed-premium \
--storage-class-datalogs managed-premium \
--storage-class-logs managed-premium \
--volume-size-data 100Gi \
--volume-size-datalogs 50Gi \
--volume-size-logs 20Gi \
--tier GeneralPurpose \
--license-type LicenseIncluded \
--use-k8s
# List Arc SQL Managed Instances
az sql mi-arc list \
--k8s-namespace arc-data \
--use-k8s \
--query '[].{Name: name, Status: status.state, Cores: spec.scheduling.default.resources.limits.cpu, Memory: spec.scheduling.default.resources.limits.memory}'Azure Arc Extensions and Services
Arc extensions bring additional Azure services to your connected resources. These include monitoring, security, machine learning, application services, and custom extensions. Extensions are deployed and managed centrally through Azure and run on the connected resource.
Available Arc Extensions
| Extension | Resource Type | Purpose |
|---|---|---|
| Azure Monitor Agent | Servers | Collect logs and metrics |
| Microsoft Defender | Servers, Kubernetes | Threat detection and vulnerability scanning |
| Azure Key Vault | Kubernetes | Secrets management via CSI driver |
| Container Insights | Kubernetes | Container monitoring and alerting |
| Azure ML | Kubernetes | Train and deploy ML models on-premises |
| App Service | Kubernetes | Run App Service, Functions, Logic Apps on K8s |
| Event Grid | Kubernetes | Event routing on Kubernetes |
# List available extensions for a connected cluster
az k8s-extension list \
--cluster-name onprem-cluster \
--resource-group rg-arc-kubernetes \
--cluster-type connectedClusters \
--query '[].{Name: name, Type: extensionType, Status: provisioningState, Version: version}' \
--output table
# Install Azure Key Vault Secrets Provider
az k8s-extension create \
--name akvsecretsprovider \
--cluster-name onprem-cluster \
--resource-group rg-arc-kubernetes \
--cluster-type connectedClusters \
--extension-type Microsoft.AzureKeyVaultSecretsProvider \
--configuration-settings "secrets-store-csi-driver.syncSecret.enabled=true"
# Install App Service extension (run Azure App Service on K8s)
az k8s-extension create \
--name appservice-ext \
--cluster-name onprem-cluster \
--resource-group rg-arc-kubernetes \
--cluster-type connectedClusters \
--extension-type Microsoft.Web.Appservice \
--auto-upgrade-minor-version true \
--configuration-settings "kube.environment.name=arc-appservice-env" \
--configuration-settings "kube.storage.class=managed-premium"Direct vs. Indirect Connectivity
Arc supports two connectivity modes. Direct mode requires continuous outbound connectivity from the resource to Azure endpoints. Data flows in near real-time, and you can manage resources directly from the Azure portal. Indirect mode supports scenarios where the resource has limited or intermittent connectivity. Data is exported periodically (at least once per month) and uploaded to Azure. Use indirect mode for air-gapped environments, edge locations with limited bandwidth, or environments with strict data residency requirements.
Best Practices for Production
Successful Azure Arc deployments require planning around security, networking, and governance. Use managed identities instead of service principals where possible. Implement resource locks on critical Arc resources to prevent accidental deletion. Use Azure Policy initiatives to enforce compliance across all Arc resources consistently. Monitor agent health and connectivity status to catch issues before they impact management capabilities.
For large-scale deployments, automate onboarding with service principals and configuration management tools (Ansible, Chef, Puppet). Use tags consistently to organize resources by environment, location, owner, and application. Implement Azure Lighthouse for multi-tenant management if managing Arc resources across multiple customers or business units. Regularly audit Arc resource compliance and remediate policy violations promptly.
Azure Virtual WAN GuideAzure Batch GuideAzure Event Hubs GuideKey Takeaways
- 1Azure Arc projects on-premises and multi-cloud resources into Azure Resource Manager for unified management.
- 2Arc-enabled servers support Azure Policy, Azure Monitor, Microsoft Defender, and VM extensions.
- 3GitOps with Flux v2 enables declarative application deployment to any connected Kubernetes cluster.
- 4Arc-enabled data services bring Azure SQL Managed Instance to any Kubernetes infrastructure.
Frequently Asked Questions
Is Azure Arc free?
What Kubernetes distributions does Arc support?
Written by CloudToolStack Team
Cloud engineers and architects with hands-on experience across AWS, Azure, and GCP. We write guides based on real-world production patterns, not just documentation rewrites.
Disclaimer: This guide is for educational purposes. Cloud services change frequently; always refer to official documentation for the latest information. AWS, Azure, and GCP are trademarks of their respective owners.