Azure AKS Cluster
Azure AKS Cluster Provisioner
The Azure AKS Cluster Provisioner deploys a production-ready Kubernetes cluster on Microsoft Azure, using dynamic credentials — no hardcoded secrets or service account keys needed.
AKS Specification
The aks struct configures the AKS provisioner.
subscriptionId: Required Azure subscription ID (UUID format).resourceGroup: Required Azure resource group name.kubernetesVersion: Optional field for Kubernetes version (e.g.,1.30or1.30.5).nodeOsUpgradeChannel: Optional field for node OS upgrade behavior (SecurityPatch,NodeImage,None,Unmanaged).autoUpgradeChannel: Optional field for cluster auto-upgrade cadence (patch,stable,rapid,node-image,none).enableWorkloadIdentity: Optional boolean to enable Microsoft Entra Workload Identity.enableOidcIssuer: Optional boolean to enable the OIDC issuer on the cluster.privateCluster: Optional boolean to enable private API server access.networkPlugin: Optional field for AKS networking (azure,kubenet,none).networkPluginMode: Optional field for Azure CNI overlay mode.vnetSubnetId: Optional full Azure subnet resource ID for BYOVNet.authorizedIPRanges: Optional list of CIDR ranges to restrict API server access.tags: Optional Azure resource tags.credentials: Required field for cloud provider credentials.
vnetSubnetId and optionally authorizedIPRanges are used for BYOVNet deployments.
Prerequisites
Required tools
- Azure CLI — required for kubeconfig token generation
- kubectl (optional) — for direct cluster interaction
- astroctl — for cluster management
Finding your Azure credentials
You need your Azure subscription ID and a resource group in the target region.
Find your subscription ID:
az account show --query id -o tsv
Example output: 12345678-1234-1234-1234-123456789abc
Create a resource group if you don't have one:
az group create --name <YOUR_RESOURCE_GROUP> --location <YOUR_REGION>
Example:
az group create --name rg-astropulse --location eastus
astroctl cloud azure regions list
Connect your Azure subscription
Run this once per cluster before creating it. Omitting this step will cause an error during cluster creation.
Step 1 — generate the setup script:
astroctl cloud azure connect \
--subscription-id <YOUR_SUBSCRIPTION_ID> \
--resource-group <YOUR_RESOURCE_GROUP> \
--cluster-name <YOUR_CLUSTER_NAME> \
--region <YOUR_REGION>
Example:
astroctl cloud azure connect \
--subscription-id 12345678-1234-1234-1234-123456789abc \
--resource-group rg-astropulse \
--cluster-name my-aks-cluster \
--region eastus
The CLI saves the setup script as astro-azure-setup-<YOUR_CLUSTER_NAME>.sh in the current directory.
Step 2 — run the script in Azure Cloud Shell or any shell where az is logged into the target tenant:
bash astro-azure-setup-<YOUR_CLUSTER_NAME>.sh
The CLI waits and confirms when the subscription is connected.
Use --output <filename> to save the script under a different name:
astroctl cloud azure connect ... --output my-setup.sh
bash my-setup.sh
Complete Field Reference
The aks struct configures the AKS provisioner. This is the authoritative reference for all available fields.
Core Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
subscriptionId | string | Yes | - | Azure subscription ID (UUID format) |
resourceGroup | string | Yes | - | Azure resource group name where the cluster will be created |
credentials | object | Yes | - | Cloud provider credentials. Use type: dynamic (set up via astroctl cloud azure connect). The type: vault is only supported for self-hosted provisioners. |
Networking Fields (BYOVNet)
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
vnetSubnetId | string | No | - | Full Azure subnet resource ID for BYOVNet (e.g., /subscriptions/.../subnets/default) |
authorizedIPRanges | []string | No | - | CIDR ranges that can access the API server (e.g., ["10.0.0.0/8", "203.0.113.0/24"]) |
networkPlugin | string | No | azure | Networking plugin: azure (Azure CNI), kubenet, or none |
networkPluginMode | string | No | - | Azure CNI overlay mode configuration |
privateCluster | bool | No | false | Enable private API server access (no public endpoint) |
Cluster Configuration Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
kubernetesVersion | string | No | Latest | Kubernetes version. Accepts: 1.30 or 1.30.5 format |
nodeOsUpgradeChannel | string | No | - | Node OS upgrade behavior: SecurityPatch, NodeImage, None, Unmanaged |
autoUpgradeChannel | string | No | - | Cluster auto-upgrade cadence: patch, stable, rapid, node-image, none |
enableWorkloadIdentity | bool | No | false | Enable Microsoft Entra Workload Identity for pod-level Azure access |
enableOidcIssuer | bool | No | false | Enable OIDC issuer on the cluster (required for Workload Identity) |
tags | map[string]string | No | - | Key-value pairs for Azure resource tagging |
Field Validation Rules
| Field | Validation |
|---|---|
subscriptionId | Must be a valid UUID format |
resourceGroup | Must be a valid Azure resource group name |
kubernetesVersion | Must be valid K8s version format: 1.30 or 1.30.5 |
nodeOsUpgradeChannel | Must be one of: SecurityPatch, NodeImage, None, Unmanaged |
autoUpgradeChannel | Must be one of: patch, stable, rapid, node-image, none |
networkPlugin | Must be one of: azure, kubenet, none |
authorizedIPRanges | Each entry must be valid CIDR notation |
tags | Each key and value must be at least 1 character |
Bring Your Own Account (BYOA)
The astro platform allows you to bring your own Azure subscription for AKS cluster creation. The following example illustrates the AKS specification, with the platform managing VNet, subnet, and other networking configurations. You only need to provide the subscription ID, resource group, and ensure proper quota for these configurations.
apiVersion: platform.astropulse.io/v1
kind: K8sCluster
spec:
clusterName: my-aks-cluster
provider: azure
region: eastus
provisioner:
type: aks
aks:
subscriptionId: "12345678-1234-1234-1234-123456789abc"
resourceGroup: "my-resource-group"
tags:
environment: "dev"
owner: "foo@bar.com"
credentials:
type: dynamic
clusterSpec:
dataPlane:
nodeGroups:
# The first nodeGroup is always the system node pool (name can be anything).
- name: default-pool
minNode: 2
maxNode: 3
instanceType: ondemand # system pools cannot use spot — AKS enforces this
machineTypes:
- Standard_D2s_v7 # use az vm list-skus to check your subscription's allowed sizes
labels:
environment: dev
Node Pool Constraints
System Node Pool
The first nodeGroup in your spec is always treated as the system node pool — the name does not matter. This is enforced by Azure: every AKS cluster must have exactly one system node pool. System pools have hard constraints enforced by Azure:
instanceTypemust beondemand— Spot VMs are not allowed for system pools. Azure rejects spot withSystemPoolMustBeRegular(see AKS system pool docs).minNode≥ 2 for production — Azure requires at least 2 nodes in the system pool for a production cluster. 3 nodes is recommended for improved fault tolerance with availability zones. A 1-node system pool is only acceptable for dev/test clusters. See Azure AKS reliability best practices.
VM Size Subscription Restrictions
Some Azure subscriptions restrict which VM sizes are available for AKS node pools. If you see an error like The VM size Standard_D2s_v3 is not allowed in your subscription, choose a different size.
Check allowed sizes for your subscription and region:
az vm list-skus --location eastus --resource-type virtualMachines \
--query "[?not_null(restrictions)].{name:name, reasonCode:restrictions[0].reasonCode}" \
-o table
Confirm the size is available on the platform:
astroctl cloud azure machines list --region eastus
Upgrade Capacity Requirements
AKS node pool upgrades use a surge strategy: one extra node is created during the upgrade before the old node is drained. Ensure your subscription vCPU quota has headroom for at least one additional node of your chosen VM size before starting an upgrade. The platform's upgrade preflight check verifies this and blocks the upgrade if quota is insufficient.
Bring Your Own VNet (BYOVNet)
For BYOVNet deployments, provide the full Azure subnet resource ID. The platform will deploy the AKS cluster into your existing network infrastructure.
apiVersion: platform.astropulse.io/v1
kind: K8sCluster
spec:
clusterName: my-aks-vnet-cluster
provider: azure
region: eastus
provisioner:
type: aks
aks:
subscriptionId: "12345678-1234-1234-1234-123456789abc"
resourceGroup: "my-resource-group"
vnetSubnetId: "/subscriptions/12345678-1234-1234-1234-123456789abc/resourceGroups/my-rg/providers/Microsoft.Network/virtualNetworks/my-vnet/subnets/default"
authorizedIPRanges:
- "10.0.0.0/8"
- "203.0.113.0/24"
networkPlugin: "azure"
tags:
environment: "dev"
owner: "foo@bar.com"
credentials:
type: dynamic # dynamic credentials
clusterSpec:
dataPlane:
nodeGroups:
- name: default-pool
minNode: 2
maxNode: 3
instanceType: ondemand # system pools cannot use spot
machineTypes:
- Standard_D2s_v7
labels:
environment: dev
For BYOVNet, the astroctl validates quota, permissions, and configurations before cluster creation. Ensure the subnet has sufficient IP address space for your node and pod requirements.
Cluster Updates
AKS clusters support updates to Kubernetes version, agent pool configurations, and cluster settings. You can use either the Console UI or the CLI.
Option 1: Console (Upgrade Wizard)
The Console provides a guided 5-step upgrade wizard:
- Preflight Check - Validates upgrade paths and checks for issues
- Readiness Report - Generates comprehensive upgrade analysis with risk score
- Pre-Upgrade Checklist - Interactive checklist with verification commands
- Configuration - Select target version and rolling update settings
- Confirmation - Review summary and confirm by typing cluster name
To access: Go to Clusters → Select cluster → Click Upgrade button
The wizard shows:
- Visual version timeline (current → next → locked future versions)
- Agent pool scaling controls (min/max nodes)
- Rolling update settings (maxSurge, maxUnavailable)
- Impact summary before execution
Option 2: CLI Commands
Version Discovery
# List available versions for this cluster
astroctl infra k8s upgrade <cluster-name> --list-versions
# Check versions for a region
astroctl cloud azure k8s-versions
astroctl cloud azure k8s-versions -r eastus
astroctl cloud azure k8s-versions --show-upgrade-paths
Kubernetes Version Upgrade
# Dry-run validation first
astroctl infra k8s upgrade <cluster-name> 1.30 --dry-run
# Generate readiness report
astroctl infra k8s upgrade <cluster-name> 1.30 --generate-report
# Execute upgrade
astroctl infra k8s upgrade <cluster-name> 1.30
# Skip confirmation (for automation)
astroctl infra k8s upgrade <cluster-name> 1.30 --yes
Rollback Agent Pools
AKS control plane cannot be rolled back. Agent pools will be downgraded to the target version.
# List versions available for rollback
astroctl infra k8s rollback <cluster-name> --list-versions
# Dry-run first — validates rollback path and warns about limitations
astroctl infra k8s rollback <cluster-name> 1.29 --dry-run
# Execute rollback
astroctl infra k8s rollback <cluster-name> 1.29 --yes
Scaling Agent Pools
# List agent pools
astroctl infra k8s scale <cluster-name> --list
# Preview changes first (dry-run)
astroctl infra k8s scale <cluster-name> <pool-name> --min 3 --max 10 --dry-run
# Apply the scale
astroctl infra k8s scale <cluster-name> <pool-name> --min 3 --max 10
Advanced Updates (YAML)
# Show YAML examples for your cluster
astroctl infra k8s update <cluster-name> --example
# Dry-run validation first
astroctl infra k8s update <cluster-name> -f update.yaml --dry-run
# Apply update
astroctl infra k8s update <cluster-name> -f update.yaml
# Skip confirmation (for automation)
astroctl infra k8s update <cluster-name> -f update.yaml --auto-approve
Monitor Progress
# Stream real-time progress
astroctl infra k8s progress stream <cluster-name>
# Get current status
astroctl infra k8s progress get <cluster-name>
# View operation history
astroctl infra k8s progress history <cluster-name>
Update File Reference
apiVersion: platform.astropulse.io/v1
kind: K8sClusterUpdate
spec:
# Kubernetes version
kubernetesVersion: "1.30"
# Rolling update configuration
updateConfig:
maxSurge: "1" # Nodes added during update (number or %)
maxUnavailable: "1" # Nodes down during update (number or %)
dryRun: false # Validate without applying
generateReport: false # Generate readiness report
# Agent pools (additional user pools can use spot; system pool must use ondemand)
nodeGroups:
- name: "default-pool"
minNode: 2
maxNode: 8
machineTypes: ["Standard_D2s_v7"]
instanceType: "ondemand"
labels:
workload: "general"
# AKS-specific settings
aks:
nodeOsUpgradeChannel: "SecurityPatch"
autoUpgradeChannel: "stable"
# Resource tags
tags:
environment: "production"
Rolling Update Strategy
Control the speed and safety of agent pool upgrades with --max-unavailable and --max-surge flags:
# Configure rolling update speed
astroctl infra k8s upgrade my-cluster 1.30 --max-unavailable 2 --max-surge 1
# Use percentage-based configuration
astroctl infra k8s upgrade my-cluster 1.30 --max-unavailable 25%
Smart Defaults: If you don't specify these flags, AstroPulse automatically determines optimal values:
| Agent Pool Type | Default Strategy | Why |
|---|---|---|
| Small (1-3 nodes) | surge=1, unavailable=0 | Maintain full capacity |
| Medium (4-10 nodes) | surge=2, unavailable=1 | Balance speed and safety |
| Large (10+ nodes) | surge=10%, unavailable=10% | Percentage-based scaling |
| GPU nodes | surge=1, unavailable=0 | Protect expensive resources |
| System/Critical | surge=1, unavailable=0 | Ensure cluster stability |
Upgrade Process
- Control plane is upgraded first (Azure managed)
- Agent pools are upgraded sequentially with rolling updates
- System add-ons are updated to compatible versions
- Progress is tracked and reported in real-time
- AKS only supports upgrades to sequential minor versions (cannot skip versions)
- Control plane cannot be downgraded after upgrade
- Agent pools use rolling update strategy for zero-downtime upgrades
- Always test upgrades in a non-production environment first
KubeConfig
With a simple command, you can set the context to the cluster and access it. Make sure to have kubectl installed.
astroctl infra k8s set-context <cluster-name>
The cluster managed by the astro platform uses Microsoft Entra tokens for kubectl authentication. Ensure the Azure CLI is installed for token refresh.
Added Capabilities
The AKS provisioner supports the following capabilities for AKS clusters:
- Azure CNI: Advanced container networking with native Azure VNet integration. Choose between standard Azure CNI or overlay mode for flexible IP address management.
- Workload Identity: Enable Microsoft Entra Workload Identity for pod-level access to Azure resources without managing credentials. Requires
enableWorkloadIdentityandenableOidcIssuer. - OIDC Issuer: Enable the OIDC issuer endpoint on the cluster for federated identity scenarios.
- Node OS Auto-Upgrade: Configure automatic OS-level patching for cluster nodes via
nodeOsUpgradeChannel.
AKS supports cluster auto-upgrade channels to keep your cluster up to date automatically:
| Channel | Behavior | Use Case |
|---|---|---|
patch | Auto-upgrade to latest patch version | Production (recommended) |
stable | Upgrade to latest stable patch of N-1 minor | Conservative production |
rapid | Upgrade to latest supported patch of latest minor | Testing, development |
node-image | Upgrade node images weekly | Node OS freshness |
none | No auto-upgrades | Full manual control |
Set the channel in your cluster spec or update it later via astroctl infra k8s update.
Security
What you get out of the box
| What | How |
|---|---|
| No stored credentials | The platform mints short-lived Azure AD tokens per connection. No static kubeconfigs or long-lived secrets are stored in AstroPulse infrastructure. |
| Managed Azure AD + Azure RBAC | Enabled automatically. Access to your cluster is governed by Azure RBAC — not local cluster accounts. |
| Short-lived token rotation | Tokens are refreshed automatically before expiry. If a token is ever leaked, it expires within minutes. |
| Scoped platform identity | The platform identity is granted only the permissions it needs in your subscription — no standing admin access. |
How to harden further
Restrict API server access with authorized IP ranges (recommended for production)
By default, the AKS API server accepts connections from any IP. Use authorizedIPRanges to restrict it to known CIDRs.
authorizedIPRanges applies to all connections — including the platform's deployment service. If you set this field, you must include the platform's NAT egress IP (35.206.79.104/32) or deployments and syncs will fail with connection errors.
Contact support to confirm the current platform egress IP before applying this to production.
provisioner:
type: aks
aks:
authorizedIPRanges:
- "35.206.79.104/32" # AstroPulse platform egress IP (required)
- "203.0.113.10/32" # your office / VPN egress IP
- "198.51.100.0/24" # your CI/CD egress range
BYOVNet for additional network control
Use vnetSubnetId to deploy AKS into your existing Virtual Network. Combined with authorizedIPRanges, this gives you control over both the API server exposure and the data plane network.
Fully private AKS clusters (no public endpoint) are not yet supported for managed provisioning. If your security policy requires a private API server, contact us — we are working on a solution.