iT邦幫忙

2026 iThome 鐵人賽

DAY 27
0
AI Engineering

Agent 開發, 從本地到雲端: AI 工程師的 K8s 筆記系列 第 27 篇

Day 27|同一個 agent workload 上 AKS 最小集;與 Azure Container Apps 的分界

  • 分享至 

  • xImage
  •  

cover

POV:你把 Day 24 那份 agent-api.yaml 原封不動 kubectl apply 到另一朵雲,Pod 起來了,但 image 拉不下來、Ingress 一直沒有 IP,你開始懷疑「K8s 可攜」是不是一句行銷話。

昨天用對照表講 AKS 跟 GKE 的名詞怎麼對應。今天動手:同一個 agent-api,Day 23 上過 Cloud Run、Day 24 上過 GKE Autopilot,現在搬到 AKS。目的不是比誰好,而是驗證昨天那句話:Deployment 與 Service 的 YAML 一樣,主要會卡的是 registry、ingress、identity 三件事。

先講清楚:我在 AKS 上的實戰時數比 GKE 少很多,這篇的指令是照官方文件整理的最小路徑,寫的時候還沒重新實跑一遍(verified: false),旗標請以文中連結的官方頁為準。

前置:叢集、ACR、憑證

AKS 上有三個 GCP 那邊不用特別做的前置動作:先有一個 Resource Group(昨天講過,Azure 的資源都掛在它底下)、把 image 推到 Azure Container Registry(ACR)、讓叢集拿得到 ACR 的拉取權限。推 image 我用 az acr build,它會在雲端把目前目錄的 Dockerfile 建成 image 並直接推進 ACR,本機不用裝 Docker;沒有這一步,後面 Deployment 引用的 tag 不存在,Pod 一定卡 ImagePullBackOff。拉取權限官方 quickstart 用 --attach-acr 在建叢集時一次綁定,之後也可以用 az aks update --attach-acr 補綁;Ingress 要先開 application routing add-on(下一節解釋):

az group create --name RG_NAME --location eastasia
az acr create --resource-group RG_NAME --name REGISTRY --sku Basic
az acr build --registry REGISTRY --image agents/agent-api:v1 .
az aks create --resource-group RG_NAME --name AKS_NAME \
  --node-count 1 --attach-acr REGISTRY --generate-ssh-keys
az aks approuting enable --resource-group RG_NAME --name AKS_NAME
az aks get-credentials --resource-group RG_NAME --name AKS_NAME

kubectl create namespace agents
kubectl -n agents create secret generic llm-api-key \
  --from-literal=LLM_API_KEY="$LLM_API_KEY"
kubectl -n agents apply -f agent-api.yaml -f agent-api-ingress.yaml
kubectl -n agents get pods,svc,ingress

注意空行之後那五行:除了多套一份 Ingress 檔,跟 Day 24 一樣。kubectl 不在乎底下是 GKE 還是 AKS,這是 K8s 可攜性最具體的一面。--node-count 1 是因為 quickstart 提到不指定時預設會開三個節點,對一隻 replicas 1 的 agent 來說太多;--attach-acr 則是把「拉 image 的權限」問題在建叢集時就解決掉,不然就算 image 推上去了,Pod 一樣會卡在 ImagePullBackOff,那是 Day 14 五種錯裡的第一種。

YAML:Deployment 與 Service 只改 image 那一行

apiVersion: apps/v1
kind: Deployment
metadata: {name: agent-api, namespace: agents}
spec:
  replicas: 1
  selector: {matchLabels: {app: agent-api}}
  template:
    metadata: {labels: {app: agent-api}}
    spec:
      containers:
      - name: agent-api
        image: REGISTRY.azurecr.io/agents/agent-api:v1   # 唯一的差異
        ports: [{containerPort: 8080}]
        envFrom: [{secretRef: {name: llm-api-key}}]
        resources:
          requests: {cpu: 250m, memory: 512Mi}
          limits: {memory: 1Gi}
        readinessProbe: {httpGet: {path: /healthz, port: 8080}}
---
apiVersion: v1
kind: Service
metadata: {name: agent-api, namespace: agents}
spec: {selector: {app: agent-api}, ports: [{port: 80, targetPort: 8080}]}

Deployment 與 Service 跟 Day 24 逐行相同,只有 image 換成 ACR 路徑。requests / limits、readinessProbe、Service 的 port 對應,全都不用動。

順帶一提,這裡的 containerPort 跟 readinessProbe,對應的是 compose 裡的 ports 與 healthcheck,跟我 dev-box 上那隻 LINE bot 的 compose(Day 03 貼過的 "127.0.0.1:8092:8080" 與 pgrep -x openab)是同一類東西。Day 13 從 compose 翻譯到 k3s 時寫過一次,之後不管是 GKE 還是 AKS,這幾行都不用再改。真正跟著雲走的,從頭到尾只有 image 路徑。

Ingress 物件的規格也一樣,差別在「誰來實作」。GKE 有內建的 Ingress 控制器;AKS 官方的對應做法是前面那行 az aks approuting enable,它會替你裝一個代管的 NGINX ingress controller,然後 Ingress 要指名這個 class。這是 Day 24 那份 YAML 之外,要多改的就這一行:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata: {name: agent-api, namespace: agents}
spec:
  ingressClassName: webapprouting.kubernetes.azure.com   # AKS 才有的那一行
  rules:
  - http:
      paths:
      - {path: /, pathType: Prefix, backend: {service: {name: agent-api, port: {number: 80}}}}

這行 class 名稱就是「YAML 一樣,行為不一樣」的那一行:物件是標準 K8s,但沒有人實作它,它就只是一筆靜靜躺在 etcd 裡的資料,kubectl get ingress 也等不到 IP。

三個真正卡關的地方,再對一次

跑完上面兩塊,昨天的預測可以逐條核對:

  1. Registry:image 要先推進 ACR(az acr build),叢集還要有拉取權限(--attach-acr)。後者是 identity 問題,不是 YAML 問題,所以解法在 az aks 那一層而不是 kubectl 那一層。
  2. Ingress:物件相同,實作不同,要先啟用 add-on,並在 Ingress 上指定 ingressClassName。
  3. Identity:Day 24 在 GKE 上是靠 service account 給 Pod 權限,AKS 對應的是 Managed Identity 與 workload identity。今天刻意只用 K8s 原生 Secret 放 API key,就是為了先避開這一層;等真的需要串 Key Vault 再回頭處理,那已經超出「最小集」的範圍。

以最小集來說,我目前看到的就這三件;真的上了生產環境,網路、儲存、監控各家還會有自己的細節。但這已經是昨天說「換雲要重學的是方言,不是語言」的具體證據:要重做的主要是三件事,不是三十件。

那 Azure Container Apps 呢

看到這裡你可能會問:Azure 上有沒有像 Cloud Run 那種「不想管叢集,跑容器就好」的東西?有,就是 Azure Container Apps(ACA)。它的位置對應 Cloud Run,AKS 對應 GKE;官方自己也有一頁在講 Container Apps 跟其他 Azure 容器選項怎麼比。

同一個 image 上 ACA,官方最短路徑是先 az extension add --name containerapp --upgrade,再一行 az containerapp up --name agent-api --image REGISTRY.azurecr.io/agents/agent-api:v1 --ingress external --target-port 8080,它會順手建 Resource Group、environment 跟 Log Analytics workspace。有一個坑要先講:ACR 預設是私有的,前面 --attach-acr 給的拉取權限只有 AKS 拿得到,ACA 不會繼承;所以這行還要補 --registry-server REGISTRY.azurecr.io 加憑證,或改用 --registry-identity 讓 ACA 用 managed identity 拉 image(正式環境官方建議後者,做法見延伸閱讀)。scale 用 --min-replicas 0 --max-replicas N 加 scale rule 設定,minReplicas: 0 就是縮到零。

分界線跟 Day 21 問的是同一個問題:一段時間沒人碰,它該不該活著? 可以接受縮到零跟冷啟動的 request-driven API,走 ACA;必須常駐、或者你要自己控制排程與資源的,走 AKS。今天這份 YAML 是給 AKS 的,上 ACA 不需要它,就像 Cloud Run 不吃 Deployment 一樣。

明天把 GKE、Cloud Run、AKS、ACA 四個放進同一張表,用同一個 agent workload 的五個面向對照。

今日一句話

Deployment 與 Service 從 GKE 搬到 AKS,只改了 image 那一行;Ingress 多一行 class 名稱;剩下要重做的主要是 registry 授權、ingress 實作、identity,三件事,不是三十件。

延伸閱讀


上一篇
Day 26|AKS 對 GKE:概念對照表(Resource Group、node pool、ingress、identity),平台中立視角
下一篇
Day 28|GCP 與 Azure 對照總表:GKE / Cloud Run / AKS / ACA,同一個 agent workload 的 5 個面向
系列文
Agent 開發, 從本地到雲端: AI 工程師的 K8s 筆記 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言