Skip to content

Commit 305aa09

Browse files
Add Azure Kubernetes Services (AKS) documentation
1 parent a2e2735 commit 305aa09

1 file changed

Lines changed: 399 additions & 0 deletions

File tree

  • src/content/docs/azure/services
Lines changed: 399 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,399 @@
1+
---
2+
title: "Azure Kubernetes Service (AKS)"
3+
description: Get started with Azure Kubernetes Service on LocalStack
4+
template: doc
5+
resourceProvider: Microsoft.ContainerService
6+
resourceType: Microsoft.ContainerService/managedClusters
7+
---
8+
9+
import AzureFeatureCoverage from "../../../../components/feature-coverage/AzureFeatureCoverage";
10+
11+
## Introduction
12+
13+
Azure Kubernetes Service (AKS) is Azure's managed Kubernetes offering. Azure operates the control
14+
plane while you manage node pools of worker machines that run your workloads. For more information,
15+
see [What is Azure Kubernetes Service?](https://learn.microsoft.com/en-us/azure/aks/what-is-aks).
16+
17+
LocalStack for Azure creates real, working Kubernetes clusters on your machine. `az aks create`
18+
produces a cluster backed by [k3d](https://k3d.io/) that you can reach with `kubectl`, so manifests,
19+
Helm charts, and operators behave as they would against a cluster in the cloud. The supported APIs
20+
are available on our [API Coverage section](#api-coverage), which provides information on the extent
21+
of AKS's integration with LocalStack.
22+
23+
## Getting started
24+
25+
This guide is designed for users new to AKS and assumes basic knowledge of the Azure CLI, `kubectl`,
26+
and our `lstk az` proxy.
27+
28+
Launch LocalStack using your preferred method. For more information, see
29+
[Introduction to LocalStack for Azure](/azure/getting-started/). Once the container is running,
30+
enable Azure CLI interception by running:
31+
32+
```bash
33+
lstk az start-interception
34+
```
35+
36+
This command points the `az` CLI away from the public Azure management REST API and toward the
37+
LocalStack for Azure emulator API. To revert this configuration, run:
38+
39+
```bash
40+
lstk az stop-interception
41+
```
42+
43+
This reconfigures the `az` CLI to send commands to the official Azure management REST API.
44+
45+
### Create a resource group
46+
47+
Create a resource group to hold the cluster:
48+
49+
```bash
50+
az group create \
51+
--name rg-aks-demo \
52+
--location westeurope
53+
```
54+
55+
```bash title="Output"
56+
{
57+
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-aks-demo",
58+
"location": "westeurope",
59+
"managedBy": null,
60+
"name": "rg-aks-demo",
61+
"properties": {
62+
"provisioningState": "Succeeded"
63+
},
64+
"tags": null,
65+
"type": "Microsoft.Resources/resourceGroups"
66+
}
67+
```
68+
69+
### Create a cluster
70+
71+
Create a cluster with a single node in its system node pool:
72+
73+
```bash
74+
az aks create \
75+
--resource-group rg-aks-demo \
76+
--name aks-demo \
77+
--node-count 1 \
78+
--generate-ssh-keys
79+
```
80+
81+
The command returns when the cluster is ready to use. Locally that takes a couple of minutes: the
82+
emulator provisions a k3d cluster, so what you get back is a live API server, not a mock.
83+
84+
```bash title="Output"
85+
{
86+
"currentKubernetesVersion": "1.34.4",
87+
"fqdn": "aks-demo-rg-aks-demo-000000-oq7mpqgx.hcp.westeurope.azmk8s.io",
88+
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/rg-aks-demo/providers/Microsoft.ContainerService/managedClusters/aks-demo",
89+
"kubernetesVersion": "1.34",
90+
"location": "westeurope",
91+
"name": "aks-demo",
92+
"nodeResourceGroup": "MC_rg-aks-demo_aks-demo_westeurope",
93+
"powerState": {
94+
"code": "Running"
95+
},
96+
"provisioningState": "Succeeded",
97+
...
98+
}
99+
```
100+
101+
### Show and list clusters
102+
103+
Retrieve the details of a single cluster:
104+
105+
```bash
106+
az aks show \
107+
--resource-group rg-aks-demo \
108+
--name aks-demo
109+
```
110+
111+
```bash title="Output"
112+
{
113+
"currentKubernetesVersion": "1.34.4",
114+
"dnsPrefix": "aks-demo-rg-aks-demo-000000",
115+
"kubernetesVersion": "1.34",
116+
"location": "westeurope",
117+
"name": "aks-demo",
118+
"nodeResourceGroup": "MC_rg-aks-demo_aks-demo_westeurope",
119+
"provisioningState": "Succeeded",
120+
...
121+
}
122+
```
123+
124+
List the clusters in a resource group:
125+
126+
```bash
127+
az aks list \
128+
--resource-group rg-aks-demo \
129+
--output table
130+
```
131+
132+
```bash title="Output"
133+
Name Location ResourceGroup KubernetesVersion CurrentKubernetesVersion ProvisioningState Fqdn
134+
-------- ---------- --------------- ------------------- -------------------------- ------------------- -------------------------------------------------------------
135+
aks-demo westeurope rg-aks-demo 1.34 1.34.4 Succeeded aks-demo-rg-aks-demo-000000-oq7mpqgx.hcp.westeurope.azmk8s.io
136+
```
137+
138+
### Update a cluster
139+
140+
`az aks update` changes the properties of an existing cluster. The following example sets resource
141+
tags:
142+
143+
```bash
144+
az aks update \
145+
--resource-group rg-aks-demo \
146+
--name aks-demo \
147+
--tags environment=local team=platform
148+
```
149+
150+
```bash title="Output"
151+
{
152+
"name": "aks-demo",
153+
"provisioningState": "Succeeded",
154+
"tags": {
155+
"environment": "local",
156+
"team": "platform"
157+
},
158+
...
159+
}
160+
```
161+
162+
### Connect with kubectl
163+
164+
Merge the cluster credentials into your local kubeconfig:
165+
166+
```bash
167+
az aks get-credentials \
168+
--resource-group rg-aks-demo \
169+
--name aks-demo \
170+
--overwrite-existing
171+
```
172+
173+
```bash title="Output"
174+
Merged "aks-demo" as current context in /home/user/.kube/config
175+
```
176+
177+
Query the nodes:
178+
179+
```bash
180+
kubectl get nodes
181+
```
182+
183+
```bash title="Output"
184+
NAME STATUS ROLES AGE VERSION
185+
aks-nodepool1-5829393-vmss000000 Ready <none> 99s v1.36.2+k3s1
186+
k3d-aks-demo-7da4c24d-server-0 Ready control-plane 2m1s v1.36.2+k3s1
187+
```
188+
189+
:::note
190+
Unlike in the cloud, where the control plane is hidden, the local cluster also lists its k3d
191+
control-plane node. Agent nodes carry the same `aks-<pool>-...-vmss` naming scheme as real AKS
192+
nodes, and the `VERSION` column reflects the underlying k3s runtime rather than the cluster's
193+
`kubernetesVersion`.
194+
:::
195+
196+
### Manage node pools
197+
198+
Add a user node pool with two nodes:
199+
200+
```bash
201+
az aks nodepool add \
202+
--resource-group rg-aks-demo \
203+
--cluster-name aks-demo \
204+
--name workers \
205+
--mode User \
206+
--node-count 2
207+
```
208+
209+
```bash title="Output"
210+
{
211+
"count": 2,
212+
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/rg-aks-demo/providers/Microsoft.ContainerService/managedClusters/aks-demo/agentPools/workers",
213+
"mode": "User",
214+
"name": "workers",
215+
"orchestratorVersion": "1.34",
216+
"osType": "Linux",
217+
"provisioningState": "Succeeded",
218+
...
219+
}
220+
```
221+
222+
List the node pools of the cluster:
223+
224+
```bash
225+
az aks nodepool list \
226+
--resource-group rg-aks-demo \
227+
--cluster-name aks-demo \
228+
--output table
229+
```
230+
231+
```bash title="Output"
232+
Name OsType VmSize Count MaxPods ProvisioningState Mode
233+
--------- -------- -------- ------- --------- ------------------- ------
234+
nodepool1 Linux 1 250 Succeeded System
235+
workers Linux 2 250 Succeeded User
236+
```
237+
238+
Inspect a single node pool:
239+
240+
```bash
241+
az aks nodepool show \
242+
--resource-group rg-aks-demo \
243+
--cluster-name aks-demo \
244+
--name workers
245+
```
246+
247+
```bash title="Output"
248+
{
249+
"count": 2,
250+
"mode": "User",
251+
"name": "workers",
252+
"orchestratorVersion": "1.34",
253+
"osType": "Linux",
254+
"powerState": {
255+
"code": "Running"
256+
},
257+
"provisioningState": "Succeeded",
258+
...
259+
}
260+
```
261+
262+
Delete the node pool when you no longer need it:
263+
264+
```bash
265+
az aks nodepool delete \
266+
--resource-group rg-aks-demo \
267+
--cluster-name aks-demo \
268+
--name workers
269+
```
270+
271+
### Stop, start, and delete
272+
273+
Stop the cluster to free local resources while preserving its state:
274+
275+
```bash
276+
az aks stop \
277+
--resource-group rg-aks-demo \
278+
--name aks-demo
279+
```
280+
281+
Verify that the cluster has stopped by confirming that `powerState` reports `Stopped`:
282+
283+
```bash
284+
az aks show \
285+
--resource-group rg-aks-demo \
286+
--name aks-demo \
287+
--query powerState.code \
288+
--output tsv
289+
```
290+
291+
Start the cluster again. It restarts with the previous control plane state and number of agent nodes:
292+
293+
```bash
294+
az aks start \
295+
--resource-group rg-aks-demo \
296+
--name aks-demo
297+
```
298+
299+
Delete the cluster once you are done. A deleted cluster cannot be recovered:
300+
301+
```bash
302+
az aks delete \
303+
--resource-group rg-aks-demo \
304+
--name aks-demo \
305+
--yes
306+
```
307+
308+
### Teardown
309+
310+
Remove the resource group and any resources it still contains:
311+
312+
```bash
313+
az group delete \
314+
--name rg-aks-demo \
315+
--yes
316+
```
317+
318+
Disable Azure CLI interception to point the `az` CLI back to the official Azure management REST API:
319+
320+
```bash
321+
lstk az stop-interception
322+
```
323+
324+
## Features
325+
326+
The local control plane implements the following capabilities:
327+
328+
- **Networking**: Azure CNI overlay with the Cilium data plane, Cilium and Calico network
329+
policies, Hubble observability, and the managed Gateway API add-on with NGINX Gateway Fabric
330+
as its implementation.
331+
- **Storage**: The Secrets Store CSI driver for Azure Key Vault and the Azure Files CSI driver.
332+
The Azure Disk CSI driver is in progress.
333+
- **Scaling**: The cluster autoscaler, node auto-provisioning based on the AKS Karpenter provider,
334+
the Kubernetes Event-driven Autoscaling (KEDA) add-on, and the Vertical Pod Autoscaler.
335+
- **Identity**: Microsoft Entra Workload ID with a working OIDC issuer, so pods can exchange
336+
service account tokens for Azure credentials without secrets.
337+
- **Operations**: Multiple node pools with tags, labels, and taints, the Azure cloud controller
338+
manager reconciling `LoadBalancer` services, and cluster stop and start.
339+
- **Tooling**: The same clusters can be provisioned with the Azure CLI, Terraform, or Bicep.
340+
341+
## Cluster-creation scripts
342+
343+
The [aks-samples](https://github.com/localstack-samples/aks-samples) repository provides two
344+
interchangeable scripts that provision a production-shaped cluster, complete with a virtual
345+
network, a container registry, a Log Analytics workspace, and system and user node pools. The
346+
repository maintains both scripts to run against real Azure and the emulator; they differ in the
347+
cluster identity:
348+
349+
| Script | Cluster identity | When to use |
350+
| ------ | ---------------- | ----------- |
351+
| [01-system-assigned-managed-identity.sh](https://github.com/localstack-samples/aks-samples/blob/main/scripts/01-system-assigned-managed-identity.sh) | System-assigned managed identity | Simplest option: Azure creates and manages the identity lifecycle together with the cluster. |
352+
| [01-user-assigned-managed-identity.sh](https://github.com/localstack-samples/aks-samples/blob/main/scripts/01-user-assigned-managed-identity.sh) | User-assigned managed identity | Use when you need a stable, pre-created identity that can be reused across resources and granted role assignments ahead of time. |
353+
354+
Both scripts are idempotent and safe to re-run. The same folder also contains optional add-on
355+
installers for [Prometheus](https://github.com/localstack-samples/aks-samples/blob/main/scripts/02-install-prometheus.sh),
356+
the [NGINX ingress controller](https://github.com/localstack-samples/aks-samples/blob/main/scripts/03-install-nginx-ingress-controller.sh),
357+
the [Gateway API CRDs](https://github.com/localstack-samples/aks-samples/blob/main/scripts/04-install-gateway-api.sh),
358+
[NGINX Gateway Fabric](https://github.com/localstack-samples/aks-samples/blob/main/scripts/05-install-nginx-gateway-fabric.sh),
359+
and [cert-manager](https://github.com/localstack-samples/aks-samples/blob/main/scripts/06-install-cert-manager.sh).
360+
361+
## Samples
362+
363+
Every sample deploys the same Vacation Planner web application, a small Python
364+
[Flask](https://flask.palletsprojects.com/) single-page app. Only the data service, its
365+
provisioning, and the way the app authenticates to it change from one sample to the next.
366+
367+
| Sample | Description |
368+
| ------ | ----------- |
369+
| [web-app-sql-database](https://github.com/localstack-samples/aks-samples/tree/main/samples/web-app-sql-database) | Stores activities in an Azure SQL Database, connecting with a SQL login over TDS. |
370+
| [web-app-mysql-flexible-server](https://github.com/localstack-samples/aks-samples/tree/main/samples/web-app-mysql-flexible-server) | Stores activities in an Azure Database for MySQL flexible server. |
371+
| [web-app-postgresql-flexible-server](https://github.com/localstack-samples/aks-samples/tree/main/samples/web-app-postgresql-flexible-server) | Stores activities in an Azure Database for PostgreSQL flexible server. |
372+
| [web-app-in-cluster-postgresql](https://github.com/localstack-samples/aks-samples/tree/main/samples/web-app-in-cluster-postgresql) | Stores activities in an in-cluster PostgreSQL database deployed as a Kubernetes StatefulSet, with a primary and two streaming replicas. |
373+
| [web-app-cosmosdb-mongodb-api](https://github.com/localstack-samples/aks-samples/tree/main/samples/web-app-cosmosdb-mongodb-api) | Stores activities in a collection of an Azure Cosmos DB for MongoDB account. |
374+
| [web-app-cosmosdb-nosql-api](https://github.com/localstack-samples/aks-samples/tree/main/samples/web-app-cosmosdb-nosql-api) | Stores activities in a container of an Azure Cosmos DB for NoSQL account. |
375+
| [web-app-blob-storage](https://github.com/localstack-samples/aks-samples/tree/main/samples/web-app-blob-storage) | Stores activities in an Azure Blob Storage container, using a connection string. |
376+
| [web-app-file-storage](https://github.com/localstack-samples/aks-samples/tree/main/samples/web-app-file-storage) | Stores activities as text files on an Azure Files share mounted by the Azure Files CSI driver, over either SMB or NFS. |
377+
| [web-app-managed-identity](https://github.com/localstack-samples/aks-samples/tree/main/samples/web-app-managed-identity) | Stores activities in Azure Blob Storage, authenticating with Microsoft Entra Workload ID instead of a secret, and optionally exposes the app through the Gateway API with a managed TLS certificate. |
378+
379+
## Tutorials
380+
381+
The same repository includes standalone tutorials that exercise individual AKS capabilities. Unlike
382+
the samples, they do not deploy the web application:
383+
384+
| Tutorial | Description |
385+
| -------- | ----------- |
386+
| [policies](https://github.com/localstack-samples/aks-samples/tree/main/tutorials/policies) | Kubernetes network policies that enforce zero-trust traffic control with Calico and Cilium: cluster-wide default-deny, DNS-aware egress, and L3/L4/L7 ingress. |
387+
| [ccm](https://github.com/localstack-samples/aks-samples/tree/main/tutorials/ccm) | Exercises the Azure cloud controller manager: public and internal `LoadBalancer` services, source ranges, the nodeIP backend-pool variant, and an NGINX ingress controller. |
388+
| [gateway-api](https://github.com/localstack-samples/aks-samples/tree/main/tutorials/gateway-api) | Enables the managed Gateway API CRDs, installs NGINX Gateway Fabric, and routes traffic to a backend through a `Gateway` and an `HTTPRoute`. |
389+
| [keda](https://github.com/localstack-samples/aks-samples/tree/main/tutorials/keda) | Event-driven autoscaling with the KEDA add-on: a producer creates a backlog on an Azure event source and a `ScaledObject` scales a consumer from zero to four replicas and back. |
390+
| [keda/service-bus](https://github.com/localstack-samples/aks-samples/tree/main/tutorials/keda/service-bus) | Scales a consumer on an Azure Service Bus queue with the `azure-servicebus` scaler, authenticating with Microsoft Entra Workload ID. Start here if you are new to KEDA. |
391+
| [keda/queue-storage](https://github.com/localstack-samples/aks-samples/tree/main/tutorials/keda/queue-storage) | Scales a consumer on an Azure Storage queue with the `azure-queue` scaler. Workload identity is used end to end, so no data-plane secret exists anywhere. |
392+
| [keda/event-hubs](https://github.com/localstack-samples/aks-samples/tree/main/tutorials/keda/event-hubs) | Scales a consumer on an Azure Event Hubs hub with the `azure-eventhub` scaler, whose backlog is the distance between the last enqueued event and the consumer group's blob checkpoints. |
393+
| [key-vault-csi-driver](https://github.com/localstack-samples/aks-samples/tree/main/tutorials/key-vault-csi-driver) | Mounts secrets from Azure Key Vault into a pod with the Secrets Store CSI driver, in both the workload identity and the user-assigned managed identity access modes. |
394+
| [terraform/tags-labels-taints](https://github.com/localstack-samples/aks-samples/tree/main/tutorials/terraform/tags-labels-taints) | Deploys a modular, feature-rich AKS stack with Terraform, steering workloads across agent pools with Azure resource tags, node labels, and taints, then validates them through both the ARM and Kubernetes APIs. |
395+
| [bicep/tags-labels-taints](https://github.com/localstack-samples/aks-samples/tree/main/tutorials/bicep/tags-labels-taints) | The same modular AKS stack built with Bicep, with parameters and outputs that mirror the Terraform tutorial one-to-one. |
396+
397+
## API Coverage
398+
399+
<AzureFeatureCoverage service="Microsoft.ContainerService" client:load />

0 commit comments

Comments
 (0)