云托管 K8s 实战(二):Azure AKS 端到端

写在前面

版本说明:Azure CLI 2.x + AKS GA 特性(2026);命令在 Azure Global 验证,Azure China 流程相同、域名/Portal 不同。

承接总览篇。本篇在 Azure 上把一个 web 应用跑进 AKS,全程 7 步,跟着做完你就掌握了 AKS 的核心姿势。

1
2
3
4
5
6
7
8
本篇路线(7 步):
  ① 准备:账号 + CLI 登录
  ② 建资源组 + ACR + 推镜像
  ③ 创建 AKS 集群(一条命令)
  ④ 身份:Managed Identity 拉私有镜像
  ⑤ 部署 + 暴露(Azure LB)
  ⑥ 接监控(Container Insights)
  ⑦ 清理 + 算账

demo 用一个最小 nginx 镜像(避免业务干扰,专注云侧)。


一、准备:账号 + CLI

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 装 Azure CLI(略,见官方)
# 登录(会开浏览器)
az login

# 列订阅,选一个
az account list --output table
az account set --subscription "<订阅 ID 或名字>"

# 设默认位置(Azure 数据中心)
az configure --defaults location=eastus

国内用 Azure China(世纪互联):az cloud set --name AzureChinaCloud 后再 az login。命令一样,资源域名从 azure.comazure.cn


二、建资源组 + ACR + 推镜像

资源组(Resource Group)是 Azure 的"资源文件夹",把本场的 AKS/ACR/LB 全装进去,最后一把删。

1
2
RG=rg-aks-demo
az group create --name $RG --location eastus

ACR(Azure Container Registry)——镜像仓库,对应 ECR / Artifact Registry。

1
2
ACR=acraksdemo$RANDOM   # ACR 名全局唯一,加随机后缀
az acr create --resource-group $RG --name $ACR --sku Basic --admin-enabled false
  • --sku Basic:入门档(~$5/月),还有 Standard/Premium(更多存储和并发)。
  • --admin-enabled false:不开 admin 账号,我们用 Managed Identity 拉镜像(更安全,第四节讲)。

构建并推一个 demo 镜像:

1
2
3
4
5
6
7
8
# 最小 Dockerfile(nginx 起一个静态页)
cat > Dockerfile <<'EOF'
FROM nginx:alpine
RUN echo "<h1>Hello from AKS</h1>" > /usr/share/nginx/html/index.html
EOF

# 用 ACR 的 build 任务直接构建并推送(不用本地装 docker)
az acr build --image demo/web:v1 --registry $ACR Dockerfile

推完确认:

1
2
az acr repository list --name $ACR --output table
# demo/web

三、创建 AKS 集群(一条命令)

AKS 最爽的地方:一条 az aks create 搞定集群 + 控制平面 + 节点池 + 网络插件 + 身份。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
AKS=myAKS
az aks create \
  --resource-group $RG \
  --name $AKS \
  --node-count 2 \
  --node-vm-size Standard_D2s_v5 \
  --enable-managed-identity \
  --attach-acr $ACR \
  --generate-ssh-keys \
  --network-plugin azure \
  --load-balancer-sku standard

参数解读:

参数含义
--node-count 22 个 worker 节点(控制平面不在此列,微软托管)
--node-vm-size节点机型(D 系列通用,v5 是最新)
--enable-managed-identity用托管身份(不用旧的 Service Principal,免密钥轮换)
--attach-acr $ACR关键:给集群身份授 ACR 的 AcrPull 角色,Pod 能直接拉私有镜像
--generate-ssh-keys自动生成 SSH key(应急登节点用)
--network-plugin azureAzure CNI(Pod 拿 VNet IP);要 Overlay 加 --network-plugin-mode overlay
--load-balancer-sku standardStandard LB(生产推荐,带 SLA)

控制平面免费,这条命令的代价就是 2 个 D2s_v5 VM 的钱(约 $0.10/h × 2)。

接入集群(把凭证写入本地 kubeconfig):

1
2
3
4
5
az aks get-credentials --resource-group $RG --name $AKS
kubectl get nodes
# NAME                              STATUS   ROLES   AGE   VERSION
# aks-nodepool1-12345678-vmss000000 Ready    agent   1m    v1.30.x
# aks-nodepool1-12345678-vmss000001 Ready    agent   1m    v1.30.x

到这一步,你已经有一个能用的托管 K8s 集群了。后面就是标准的 kubectl 流程。


四、身份:Managed Identity 拉私有镜像

第三节 --attach-acr 已经把活干了:它给 AKS 的 kubelet 托管身份分配了 ACR 的 AcrPull 角色。原理:

1
2
3
Pod 拉镜像 → kubelet 用自己的 Managed Identity
           → 该 identity 在 ACR 上有 AcrPull 角色(attach-acr 自动加)
           → 拿到 token,匿名拉取成功

不需要在 K8s 里建 imagePullSecret,也不需要 ACR admin 密码——这是 AKS 的"零配置拉私有镜像",比 EKS/GKE 省事一点点(它俩要显式配 IRSA / Workload Identity,第 3、4 篇会看到)。

写一个 Deployment:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# web.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 2
  selector:
    matchLabels: { app: web }
  template:
    metadata:
      labels: { app: web }
    spec:
      containers:
      - name: web
        image: <ACR 名>.azurecr.io/demo/web:v1   # 换成你的 ACR
        ports: [{ containerPort: 80 }]

部署并验证:

1
2
3
4
5
6
7
8
9
# 替换镜像里的 ACR 名
ACR_FQDN=$(az acr show -n $ACR --query loginServer -o tsv)
sed -i "s|<ACR 名>|$ACR_FQDN|" web.yaml

kubectl apply -f web.yaml
kubectl get pods
# NAME                   READY   STATUS    AGE
# web-xxx                1/1     Running   10s
# web-yyy                1/1     Running   10s

Pod Running = 私有镜像拉取成功 = Managed Identity 链路通了。

给特定 Pod 单独授权(不是整个集群):用 Workload Identity——SA 绑定某个 Azure AD 应用,对比篇详讲。


五、暴露服务:Azure Load Balancer

把 web 暴露到公网,加一个 type: LoadBalancer 的 Service:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# web-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  type: LoadBalancer      # AKS 自动创建 Azure Standard LB
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 80
1
2
3
4
5
kubectl apply -f web-svc.yaml
kubectl get svc web -w
# NAME   TYPE           EXTERNAL-IP      ...
# web    LoadBalancer   <pending>        # 等 30 秒
# web    LoadBalancer   20.x.x.x         # Azure 分配的公网 IP

EXTERNAL-IP 从 pending 变成公网 IP,浏览器访问 http://20.x.x.x → 看到 “Hello from AKS”。

1
2
3
4
5
6
背后发生了什么:
  Service type=LoadBalancer
    → AKS 的 cloud-controller-manager 监测到
    → 调 Azure API 创建 Standard LB + 公网 IP + 规则
    → 把 LB 后端指向节点池里跑 web 的节点
    → 外部流量: 公网IP → LB → 节点 → Pod

七层(HTTP/HTTPS、基于域名路由)用 Application Gateway Ingress Controller(AGIC),基于 Azure Application Gateway。本篇先到此,Ingress 细节留对比篇。


六、接监控:Container Insights

AKS 一键启用 Container Insights(Azure Monitor 的一部分),自动采集 Pod/节点/控制平面指标和日志到 Log Analytics Workspace。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 建个工作区(或复用已有的)
LAW=law-aks-demo
az monitor log-analytics workspace create \
  --resource-group $RG --workspace-name $LAW

# 给 AKS 开 Container Insights 插件
az aks enable-addons \
  --resource-group $RG --name $AKS \
  --addons monitoring \
  --workspace-resource-id $(az monitor log-analytics workspace show -g $RG -n $LAW --query id -o tsv)

开完几分钟,Portal → AKS → Insights 面板就有节点 CPU/内存、Pod 状态、控制器指标。

想用 KQL 查原始日志(Log Analytics 里):

1
2
3
4
5
ContainerLog
| where TimeGenerated > ago(1h)
| where LogEntry contains "Hello"
| project TimeGenerated, LogEntry
| take 50

这是云托管监控的"零配置"姿势——不用自己搭 Prometheus+Grafana。生产想精细化(多租户、长留存、PromQL)也可以接 Azure Monitor managed Prometheus。


七、清理 + 算账

AKS 控制平面免费,但节点、LB、公网 IP、ACR、出口流量、监控都要钱。做完实验务必清理:

1
2
# 删资源组 = 一键销毁本场所有资源(最干净)
az group delete --name $RG --yes --no-wait

跑一小时的成本(粗算,美东按需价,仅参考):

1
2
3
4
5
6
7
8
9
资源                    一小时成本(美元,粗算)
─────────────────────────────────────────────
2 × D2s_v5 节点          ~$0.20
Standard LB + 公网 IP    ~$0.02 + 流量
ACR Basic                ~$0.007(按月均摊)
Log Analytics(少量摄入)~$0.01
出口流量(按 GB)        ~$0.087/GB
─────────────────────────────────────────────
合计空载一小时           ~$0.25 左右

注意公网 IP:即使没流量,LB + IP 的小时费照收。所以测试环境记得删。生产用 Reserved Instance 可省节点费 30-60%。


八、踩坑速记

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
坑 1:--attach-acr 忘了
  → Pod 拉镜像 ImagePullBackOff
  → 补:az aks update -g $RG -n $AKS --attach-acr $ACR

坑 2:节点配额不足
  → az aks create 卡在创建节点
  → 查订阅的 vCPU 配额,提工单加额

坑 3:Azure CNI IP 耗尽
  → 大规模时子网 IP 不够
  → 用 Azure CNI Overlay 或动态 IP 分配

坑 4:标准 LB 费用
  → 每个 type=LoadBalancer Service 都起一组 LB 规则
  → 多 Service 用 Ingress 复用一个 LB

九、小结

在 AKS 上跑一个应用,核心就这么几步:

1
2
3
4
5
az group create → az acr create → az acr build
→ az aks create --attach-acr(一条命令搞定集群 + 身份)
→ kubectl apply deployment + svc(LoadBalancer)
→ az aks enable-addons monitoring
→ az group delete(清理)

AKS 的体感:免费控制平面 + Managed Identity 零配置拉镜像 + 一条命令建集群,是三家里上手最顺的之一(和 GKE 争第一)。代价是 Azure 生态绑定(ACR/Monitor/LB)。

下一篇:AWS EKS 端到端实战——同样的 demo,看 EKS 的 eksctl 和 IRSA 怎么玩,对比"控制平面收费"和"配置更繁"的真实体感。