全部產品
Search
文件中心

Container Service for Kubernetes:工作負載FAQ

更新時間:Dec 05, 2024

本文介紹在ACK叢集中部署工作負載的過程中可能遇到的常見問題及對應解決方案。

在ACK叢集中使用容器運行應用的大致流程是什嗎?

您的應用代碼可部署線上下或者雲上。不論何種語言的代碼,您都可以將其以容器化的方式部署、交付及運行。從開發代碼到運行容器化應用,大致需要以下四個階段。

  1. 編寫業務代碼。

  2. 使用Dockerfile構建鏡像。

    展開查看相關概念

    • Dockerfile:一個文字檔,包含了將代碼打包成鏡像所需的指令。具體操作,請參見在Dockerfile中使用構建打包鏡像並運行

    • 鏡像:軟體交付的載體。相較於傳統的如JAR、WAR、RPM包等,除了代碼外,鏡像還包含應用所依賴的軟體環境(容器運行時所需要的所有的檔案集合)。使用鏡像可以快速產生一個容器,即啟動並執行應用。

    • 容器是一組具有隔離特性的進程集合,其特點是視圖隔離、資源可限制、具備獨立檔案系統。您可以通過ACK對您所有的容器化應用進行全生命週期的高效管理。例如將某些Pod調度到指定的節點上,或者在業務負載升高時進行擴容操作。

  3. 上傳鏡像至鏡像倉庫。您可以使用Container RegistryACR來存放鏡像,並進行版本管理、分發拉取等操作。

    ACR提供個人版和企業版,分別面向個人開發人員和企業客戶。更多資訊,請參見什麼是Container RegistryACR

  4. 在ACK叢集中部署工作負載,運行容器化應用,使用ACK提供的多種容器化應用管理能力,請參見工作負載

為什麼拉取鏡像速度慢或拉取失敗?

您可以按照以下方式對拉取鏡像慢或失敗的問題進行排查:

  • 如果您使用ACR拉取鏡像,請確認使用者名稱或密碼是否正確。建議使用免密外掛程式拉取鏡像,具體操作,請參見使用免密組件拉取容器鏡像

  • 確認發起請求的用戶端是否具備公網能力,如果沒有,您需要為用戶端設定公網。

如何進行ACK應用程式中斷排查?

ACK應用程式中斷主要是由Pod、Deployment(StatefulSet/DaemonSet)控制器和Service的問題導致,您需要檢查以下幾類問題。

檢查Pod

關於Pod異常問題的處理,請參見Pod異常問題排查

檢查Deployment

  • 建立Deployment、DaemonSet、StatefulSet或Job等資源時,可能為Pod的問題。請參見Pod異常問題排查檢查Pod的問題。

  • 您也可以通過查看和Deployment相關的事件及日誌來定位問題:

    本文以Deployment為例進行介紹,在DaemonSet、StatefulSet或Job等資源中查看事件和日誌的操作類似。

    1. 登入Container Service管理主控台,在左側導覽列選擇叢集

    2. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇工作負載 > 無狀態叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇工作負載 > 無狀態

    3. 無狀態頁面,單擊目標Deployment名稱。然後單擊事件日誌,即可通過異常資訊定位問題。

關於建立StatefulSet遇到的更多問題。請參見Forced Rollback

檢查Service

服務(Service)可以為一組Pod提供負載平衡的功能。以下介紹如何定位與Service相關的幾類常見問題:

  1. 檢查Service的Endpoints。

  2. 登入Kubernetes叢集的Master節點。詳情請參見擷取叢集KubeConfig並通過kubectl工具串連叢集

  3. 執行以下命令,查看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是否相關聯,樣本如下:

  1. 若您服務的YAML檔案資訊如下圖所示時。123..png

  2. 執行以下命令,核對返回的Pod是否為您已關聯的Pod。

    kubectl get pods --selector=app=[$App] -n [$Namespace]
    說明
    • [$App]為關聯的Pod名稱。

    • [$Namespace]為服務所在的命名空間,如果服務在預設空間,則無需指定。

  3. 如果返回的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地址是否正常連通。

    1. 執行以下命令,擷取Pod的IP地址。

      kubectl get pods -o wide
    2. 登入任意節點,使用ping命令測試Pod的IP地址,確認網路連接正常。

  • 應用程式是否正常監聽連接埠。

    如果您的應用程式監聽80連接埠,那麼您需要在Service中指定容器連接埠為80。在任意節點上執行curl [$IP]:[$Port]命令,查看Pod中容器的連接埠是否正常。

如何手動升級Helm的版本?

  1. 登入到Kubernetes叢集。更多資訊,請參見擷取叢集KubeConfig並通過kubectl工具串連叢集

  2. 執行以下命令安裝Tiller。

    其中鏡像地址可使用對應地區的VPC網域名稱,例如,杭州地區的機器替換為registry-vpc.cn-hangzhou.aliyuncs.com/acs/tiller:v2.11.0

    helm init --tiller-image registry.cn-hangzhou.aliyuncs.com/acs/tiller:v2.11.0 --upgrade
  3. 等待tiller健全狀態檢查通過,執行helm version命令查看版本升級情況。

    說明
    • 這裡只會升級Helm服務端版本,用戶端可以通過直接下載對應的Client Binary使用。

    • 請下載阿里雲支援的最新用戶端版本Helm client 2.11.0

  4. Helm用戶端和服務端版本都升級完畢後,執行以下命令查看Helm版本。

    helm version

    預期輸出:

    Client: &version.Version{SemVer:"v2.11.0", GitCommit:"2e55dbe1fdb5fdb96b75ff144a339489417b****", GitTreeState:"clean"}
    Server: &version.Version{SemVer:"v2.11.0", GitCommit:"2e55dbe1fdb5fdb96b75ff144a339489417b****", GitTreeState:"clean"}

如何支援私人鏡像?

執行以下命令建立Secret。

kubectl create secret docker-registry regsecret --docker-server=registry-internal.cn-hangzhou.aliyuncs.com --docker-username=abc****@aliyun.com --docker-password=**** --docker-email=abc****@aliyun.com
說明
  • regsecret:指密鑰的鍵名稱,可自訂。

  • --docker-server:指Docker倉庫地址。

  • --docker-username:指Docker倉庫使用者名稱。

  • --docker-password:指Docker倉庫登入密碼。

  • 可選:--docker-email:指郵件地址。

您可以通過以下兩種方法進行操作:

  • 手動設定私人鏡像

    在YAML檔案中加入密鑰參數。

    containers:
        - name: foo
          image: registry-internal.cn-hangzhou.aliyuncs.com/abc/test:1.0
    imagePullSecrets:
        - name: regsecret
    說明
    • imagePullSecrets是聲明拉取鏡像時需要指定的密鑰。

    • regsecret必須和上面產生密鑰的鍵名一致。

    • image中的Docker倉庫名稱必須和--docker-server中的Docker倉庫名一致。

    更多資訊,請參見使用私人倉庫

  • 自動設定私人鏡像實現無密鑰編排

    說明

    為了避免每次使用私人鏡像部署時都需要引用密鑰,您可以將Secret添加到Namespace的Default Service Account中。更多資訊,請參見Add ImagePullSecrets to a service account

    1. 執行以下命令,查看建立的拉取私人鏡像的Secret。

      kubectl get secret regsecret

      預期輸出:

      NAME        TYPE                             DATA      AGE
      regsecret   kubernetes.io/dockerconfigjson   1         13m

      本例中採用手動設定的方式,修改命名空間的預設服務帳號Default,從而將此Secret作為imagePullSecret

    2. 建立一個sa.yaml設定檔,將服務帳號Default的配置匯入到該檔案中。

      kubectl get serviceaccounts default -o yaml > ./sa.yaml
    3. 執行以下命令查看sa.yaml檔案的詳情。

      cat  sa.yaml

      預期輸出:

      apiVersion: v1
      kind: ServiceAccount
      metadata:
        creationTimestamp: 2015-08-07T22:02:39Z
        name: default
        namespace: default
        resourceVersion: "243024"             #注意該項selfLink: /api/v1/namespaces/default/serviceaccounts/default。
        uid: 052fb0f4-3d50-11e5-b066-42010af0****
      secrets:
      - name: default-token-uudgeoken-uudge
    4. 執行vim sa.yaml命令,刪除resourceVersion,並增加拉取鏡像的密鑰配置項imagePullSecrets。修改後的配置如下所示:

      apiVersion: v1
      kind: ServiceAccount
      metadata:
        creationTimestamp: 2015-08-07T22:02:39Z
        name: default
        namespace: default
        selfLink: /api/v1/namespaces/default/serviceaccounts/default
        uid: 052fb0f4-3d50-11e5-b066-42010af0****
      secrets:
      - name: default-token-uudge
      imagePullSecrets:                 #增加該項。
      - name: regsecret                                    
    5. 執行以下命令將sa.yaml設定檔替換Default的服務帳號配置。

      kubectl replace serviceaccount default -f ./sa.yaml

      預期輸出:

      serviceaccount "default" replaced
    6. 建立Tomcat樣本應用。

      Tomcat編排樣本tomcat.yaml檔案如下所示:

      apiVersion: apps/v1 
      kind: Deployment
      metadata:
        name: tomcat-deployment
        labels:
          app: tomcat
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: tomcat
        template:
          metadata:
            labels:
              app: tomcat
          spec:
            containers:
            - name: tomcat
              image: registry-internal.cn-hangzhou.aliyuncs.com/abc/test:1.0              #替換為您自己的私人鏡像地址Ports。
              - containerPort: 8080

      執行以下命令建立Tomcat應用。

      kubectl create -f tomcat.yaml
    7. Pod啟動成功後執行以下命令,可以看到預期的配置。

      kubectl get pod tomcat-**** -o yaml

      預期輸出:

      spec:
        imagePullSecrets:
      - nameregsecretey

如何在國外地區的ACK叢集中使用中國內地地區的Container Registry企業版的鏡像?

在此種情境下,您需要在中國內地地區購買標準版和進階版的Container Registry企業版,在國外地區購買基礎版的Container Registry企業版。

完成購買後,您需要使用同步執行個體的方法將中國內地地區的鏡像同步到國外地區,具體操作,請參見同帳號同步執行個體。在國外地區的Container Registry企業版中擷取鏡像地址,然後在國外地區的ACK叢集中使用鏡像地址建立應用。

如果您使用Container Registry個人版,同步鏡像的速度將非常慢。如果您使用的是自建倉庫,您需要購買GA加速。

說明

自建倉庫和購買GA加速的成本比購買Container Registry企業版高,推薦您使用Container Registry企業版。

關於Container Registry企業版的計費方式,請參見計費說明

更新應用時,如何?K8s零中斷變換?

舊的應用刪除,新的應用在建立過程中產生了短暫的5XX訪問錯誤。此問題是由於應用變換時,Pod變更同步到CLB會存在秒級延遲,因此會出現5XX錯誤。您可以通過配置優雅中斷等方式解決此問題,以實現K8s零中斷變換。具體操作,請參見如何?K8s零中斷變換?

如何擷取鏡像?

您可以使用Container RegistryACR,來構建以及拉取鏡像。具體資訊,請參見管理鏡像

如何重啟容器?

無法直接操作重啟單個容器,您可以通過以下方式實現同樣的效果:

  1. 執行以下命令查看容器狀態,並確定待重啟的容器。

    kubectl get pods
  2. 刪除Pod:直接刪除Pod也會觸發控制器(例如Deployment、DaemonSet等)重新建立新的Pod執行個體,從而達到重啟容器的目的。刪除單個Pod的命令如下:

    kubectl delete pod <pod-name>
  3. 刪除Pod後,Kubernetes會根據對應的控制器自動建立一個新的Pod進行替換。

    說明

    在實際生產環境中,應避免手動直接操作Pod,而是通過控制ReplicaSet、Deployment等對象來進行容器的管理和更新,以確保叢集狀態的一致性和正確性。

  4. 執行以下命令驗證容器狀態,確認容器狀態為Running重啟成功。

    kubectl get pods

如何修改Deployment的命名空間?

如果您期望將服務從一個命名空間轉移到另一個命名空間,您需要將服務的歸屬命名空間進行相應的修改。當執行命名空間變更時,還需要手動修改服務的持久化卷聲明、設定物件(ConfigMaps)、保密字典(Secrets)以及其他依賴資源的命名空間,確保服務正常運行。

  1. 通過kubectl get命令以YAML格式匯出資源配置。

    kubectl get deploy <deployment-name> -n <old-namespace> -o yaml > deployment.yaml
  2. 編輯deployment.yaml,在namespace參數替換成新的命名空間後儲存並退出。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      annotations:
      generation: 1
      labels:
        app: nginx
      name: nginx-deployment
      namespace: new-namespace # 替換為新的命名空間。
      ... ...
  3. 使用kubectl apply命令將服務更新至新命名空間。

    kubectl apply -f deployment.yaml 
  4. 使用kubectl get命令在新命名空間下查看服務。

    kubectl get deploy -n new-namespace

如何將Pod資訊呈現給容器?

ACK與社區Kubernetes保持一致性,遵循社區規範。將Pod資訊呈現給容器時可通過兩種方式:

  • 環境變數:通過設定環境變數的方式,將Pod的資訊傳遞給容器。

  • 通過檔案方式:通過掛載檔案的方式,將Pod的資訊以檔案的形式提供給容器。