本文介紹在ACK叢集中部署工作負載的過程中可能遇到的常見問題及對應解決方案。
在ACK叢集中使用容器運行應用的大致流程是什嗎?
應用代碼可部署線上下或者雲上。不論何種語言的代碼,都可以將其以容器化的方式部署、交付及運行。從開發代碼到運行容器化應用,大致需要以下四個階段。
編寫業務代碼。
使用Dockerfile構建鏡像。
上傳鏡像至鏡像倉庫,可以使用Container RegistryACR來存放鏡像,並進行版本管理、分發拉取等操作。
ACR提供個人版和企業版,分別面向個人開發人員和企業客戶。更多資訊,請參見什麼是Container RegistryACR。
在ACK叢集中部署工作負載,運行容器化應用,使用ACK提供的多種容器化應用管理能力,請參見工作負載。
為什麼拉取鏡像速度慢或拉取失敗?
問題現象
容器拉取鏡像時花費時間過長或拉取失敗。
問題原因
下列原因都可能導致上述情況:
通過公網拉取鏡像時,沒有為叢集開啟公網訪問能力,或公網IP頻寬峰值設定較低。
從ACR拉取鏡像時,鏡像密鑰不正確,或免密組件配置錯誤。
解決方案
通過公網拉取時,叢集與鏡像倉庫都需擁有公網訪問能力。具體操作,請參見為叢集開啟訪問公網的能力。如使用ACR樣本,請參見配置ACR公網存取控制。
鏡像密鑰的配置方式請參見如何使用imagePullSecrets?。
如何進行ACK應用程式中斷排查?
ACK應用程式中斷主要是由Pod、Deployment(StatefulSet/DaemonSet)控制器和Service的問題導致,請檢查以下幾類問題。
檢查Pod
關於Pod異常問題的處理,請參見Pod異常問題排查。
檢查Deployment
建立Deployment、DaemonSet、StatefulSet或Job等資源時,可能為Pod的問題。請參見Pod異常問題排查檢查Pod的問題。
通過查看和Deployment相關的事件及日誌來定位問題:
本文以Deployment為例進行介紹,在DaemonSet、StatefulSet或Job等資源中查看事件和日誌的操作類似。
登入Container Service管理主控台,在左側導覽列選擇叢集列表。
在叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇。
在無狀態頁面,單擊目標Deployment名稱。然後單擊事件或日誌,即可通過異常資訊定位問題。
檢查Service
服務(Service)可以為一組Pod提供負載平衡的功能。以下介紹如何定位與Service相關的幾類常見問題:
檢查Service的Endpoints。
執行以下命令,查看Service的Endpoints。
以下代碼中
<service_name>為目標Service的名稱。kubectl get endpoints <service_name>請確保ENDPOINTS值的地址個數與期望該Service匹配的Pod個數相同。例如,Deployment副本數為3,那麼ENDPOINTS值的地址個數一定是3個。
Service中缺少Endpoints地址
如果Service中缺少Endpoints地址,可以通過Service的selector查詢Service與Pod是否相關聯,樣本如下:
若Service的YAML檔案資訊如下圖所示時。

替換下方命令中的
<app>及<namespace>,核對返回的Pod是否為Service已關聯的Pod。kubectl get pods -l app=<app> -n <namespace>說明<app>為Pod的app標籤(Label)所對應的值。<namespace>為服務所在的命名空間,如果服務在預設空間,則無需指定。
如果返回的Pod是關聯的Pod,但沒有Endpoints地址,很可能是沒有為Service指定正確的連接埠。如果Service中指定的連接埠實際上在Pod中沒有被監聽,那麼該Pod不會被添加到ENDPOINTS列表中,因此,請確保Service指定的容器連接埠在Pod中可以訪問,命令如下。
curl <ip>:<port>說明<ip>為第1步YAML檔案中的clusterIP。<port>為第1步YAML檔案中的port值。具體測試方法以實際環境為準。
網路轉寄問題
如果用戶端可以串連Service,並且Endpoints中的地址正確,但串連很快斷開,那麼可能是流量不能轉寄到Pod上,通常需要進行以下檢查:
Pod是否正常工作。
定位Pod問題。具體操作,請參見Pod異常問題排查。
Pod地址是否正常連通。
執行以下命令,擷取Pod的IP地址。
kubectl get pods -o wide登入任意節點,使用ping命令測試Pod的IP地址,確認網路連接正常。
應用程式是否正常監聽連接埠。
如果應用程式監聽80連接埠,那麼需要在Service中指定容器連接埠為80。在任意節點上執行
curl <ip>:<Port>命令,查看Pod中容器的連接埠是否正常。
如何手動升級Helm的版本?
由於Helm v2 Tiller服務端在社區一直存在已知的安全問題,攻擊者可以通過tiller在叢集內安裝未經授權的應用,因此推薦升級至Helm v3版本。具體操作,請參見將Helm V2升級遷移至Helm V3。
如何在國外地區的ACK叢集中使用中國內地地區的Container Registry企業版的鏡像?
在此情境下,需要在中國內地購買標準版和進階版的Container Registry企業版,在國外購買基礎版的Container Registry企業版。
完成購買後,使用同步執行個體將中國內地地區的鏡像同步到國外地區,具體操作請參見同帳號同步執行個體。在國外的Container Registry企業版中擷取鏡像地址,並在ACK叢集中使用該地址建立應用。
使用ACR個人版同步速度較慢,自建倉庫需購買GA加速。自建倉庫和GA加速成本較高,推薦使用Container Registry企業版。Container Registry企業版的計費方式請參見計費說明。
更新應用時,如何?零中斷變換?
在舊的應用刪除、新的應用建立過程中,可能會產生短暫的5XX訪問錯誤。這是因為Pod變更同步到CLB時存在秒級延遲。可以通過配置優雅中斷等方式解決此問題,實現K8s零中斷變換。具體操作,請參見如何?K8s零中斷變換?。
如何擷取容器鏡像?
拉取工作負載容器鏡像的準備工作及注意事項,請參見拉取鏡像。
如何重啟容器?
無法直接操作重啟單個容器,可以通過以下方式實現同樣的效果:
執行以下命令查看容器狀態,並確定待重啟的容器。
kubectl get pods刪除Pod:直接刪除Pod也會觸發控制器(例如Deployment、DaemonSet等)重新建立新的Pod執行個體,從而達到重啟容器的目的。刪除單個Pod的命令如下:
kubectl delete pod <pod-name>刪除Pod後,Kubernetes會根據對應的控制器自動建立一個新的Pod進行替換。
說明在實際生產環境中,應避免手動直接操作Pod,而是通過控制ReplicaSet、Deployment等對象來進行容器的管理和更新,以確保叢集狀態的一致性和正確性。
執行以下命令驗證容器狀態,確認容器狀態為Running重啟成功。
kubectl get pods
如何修改Deployment的命名空間?
如果期望將服務從一個命名空間轉移到另一個命名空間,需要將服務的歸屬命名空間進行相應的修改。當執行命名空間變更時,還需要手動修改服務的持久化卷聲明、設定物件(ConfigMaps)、保密字典(Secrets)以及其他依賴資源的命名空間,確保服務正常運行。
通過
kubectl get命令以YAML格式匯出資源配置。kubectl get deploy <deployment-name> -n <old-namespace> -o yaml > deployment.yaml編輯deployment.yaml,將
namespace參數替換成新的命名空間後儲存並退出。apiVersion: apps/v1 kind: Deployment metadata: annotations: generation: 1 labels: app: nginx name: nginx-deployment namespace: new-namespace # 替換為新的命名空間。 ... ...使用
kubectl apply命令將服務更新至新命名空間。kubectl apply -f deployment.yaml使用
kubectl get命令在新命名空間下查看服務。kubectl get deploy -n new-namespace
如何將Pod資訊呈現給容器?
ACK與社區Kubernetes保持一致性,遵循社區規範。將Pod資訊呈現給容器時可通過兩種方式:
如何使用imagePullSecrets?
2024年09月09日及之後建立的ACR個人版不支援使用免密組件。使用建立的ACR個人版執行個體時,建議通過Secret儲存使用者名稱與登入密碼的方式,在imagePullSecrets欄位中使用。
免密組件不支援與手動填入
imagePullSecrets欄位同時使用。Secret需與工作負載處於同一命名空間。
執行以下命令並替換其中的參數,即可通過使用者名稱和密碼建立密鑰Secret。
kubectl create secret docker-registry image-secret \ --docker-server=<ACR-registry> \ --docker-username=<username> \ --docker-password=<password> \ --docker-email=<email@example.com>docker-server:填入ACR執行個體地址,需與鏡像地址的網路類型相同(內網或公網地址)。docker-username:ACR訪問憑證使用者名稱。docker-password:ACR訪問憑證密碼。docker-email:選填。
建立Secret後,可以通過在Service Account或工作負載中配置
imagePullSecrets欄位使用使用者名稱和密碼。通過Service Account使用
在Service Account中添加
imagePullSecrets欄位,以default命名空間的預設Service Accountdefault為例:apiVersion: v1 kind: ServiceAccount metadata: name: default namespace: default imagePullSecrets: - name: image-secret # 填入ACR密鑰Secret工作負載在使用該Service Account時,即可拉取鏡像。
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-test namespace: default labels: app: nginx spec: serviceAccountName: default # 如果使用命名空間預設SA,可以不指定 replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: <acrID>.cr.aliyuncs.com/<repo>/nginx:latest # 替換為ACR執行個體連結在工作負載中直接使用
在工作負載中通過
imagePullSecrets欄位使用密鑰。apiVersion: apps/v1 kind: Deployment metadata: name: nginx-test namespace: default labels: app: nginx spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: imagePullSecrets: - name: image-secret # 使用上一步建立的Secret containers: - name: nginx image: <acrID>.cr.aliyuncs.com/<repo>/nginx:latest # 替換為ACR倉庫的鏡像地址
為什麼配置免密組件後仍然拉取失敗?
一個可能的原因是免密組件配置錯誤,例如:
免密組件中的執行個體資訊與ACR執行個體不符。
拉取鏡像使用的鏡像地址與免密組件中執行個體資訊的網域名稱不符。
請按照同帳號拉取鏡像中的操作進行排查。
如組件配置正確時,仍出現了拉取失敗情況,可能是因工作負載YAML中手動填入的imagePullSecrets與免密組件產生衝突。請手動刪除imagePullSecrets欄位,並刪除舊Pod重建以解決此問題。
為什麼開啟節點池鏡像加速後,在新增節點容器啟動失敗?
為節點池開啟容器鏡像加速後,容器啟動失敗,且報錯為:
failed to create containerd container: failed to attach and mount for snapshot 46: failed to enable target for /sys/kernel/config/target/core/user_99999/dev_46, failed:failed to open remote file as tar file xxxx該問題的原因是:開啟容器鏡像加速後,如需拉取私人鏡像,必須同時安裝aliyun-acr-acceleration-suite組件,並配置拉取憑證,請參見配置容器鏡像拉取憑證。
如果安裝組件後問題未解決,建議關閉容器鏡像加速優先恢複業務,後續再重新嘗試配置。