排解 Google Distributed Cloud NFS 和 DataPlane v2 問題

如果使用 NFS 掛接時發生問題,導致磁碟區或 Pod 停滯,且您建立叢集時已啟用 DataPlane v2,請按照本文的詳細手動程序操作。

下列版本已修正這個問題:

  • 次要版本 1.16,版本 1.16.4-gke.37 以上。
  • 次要版本 1.28:1.28.200-gke.111 以上版本。

建議升級至已修正這個問題的版本。如果無法升級,請按照下列各節所述程序操作。

如果您使用的版本未修正這個問題,且工作負載使用由儲存空間驅動程式支援的 ReadWriteMany 磁碟區,而這些驅動程式容易發生這個問題 (例如但不限於):

  • Robin.io
  • Portworx (sharedv4 服務量)
  • csi-nfs

透過 Kubernetes 服務 (ClusterIP) 和 DataPlane v2 連線至端點時,某些儲存空間架構上的 NFS 掛接點可能會停滯。這是因為 Linux 核心通訊端程式碼與 Cillium 的 eBPF 程式互動時,會受到限制。由於無法解除掛接已停用的 NFS 掛接點,容器可能會遭到 I/O 封鎖,甚至無法終止。

如果您使用 Kubernetes 節點上執行的 NFS 伺服器代管的 RWX 儲存空間,包括軟體定義或超融合儲存空間解決方案 (例如 Ondat、Robin.io 或 Portworx),就可能會遇到這個問題。

查看現有叢集設定

從叢集取得一些現有的設定值。您可以使用這些步驟中的值,在下一節中建立 kube-proxy 資訊清單。

  1. cm/cilium-config 取得 ClusterCIDR

    kubectl get cm -n kube-system cilium-config -o yaml | grep native-routing-cidr
    

    下列輸出範例顯示您會使用 192.168.0.0/16 做為 ClusterCIDR

    ipv4-native-routing-cidr: 192.168.0.0/16
    native-routing-cidr: 192.168.0.0/16
    
  2. anetd DaemonSet 取得 APIServerAdvertiseAddressAPIServerPort

    kubectl get ds -n kube-system  anetd -o yaml | grep KUBERNETES -A 1
    

    下列範例輸出內容顯示您會使用 21.1.4.119 做為 APIServerAdvertiseAddress,並使用 443 做為 APIServerPort

    - name: KUBERNETES_SERVICE_HOST
      value: 21.1.4.119
    - name: KUBERNETES_SERVICE_PORT
      value: "443"
    
  3. anetd DaemonSet 取得 RegistryCredentialsSecretName

    kubectl get ds -n kube-system  anetd -o yaml | grep imagePullSecrets -A 1
    

    下列輸出範例顯示您會使用 private-registry-creds 做為 RegistryCredentialsSecretName

    imagePullSecrets:
      - name: private-registry-creds
    
  4. anetd DaemonSet 取得 Registry

    kubectl get ds -n kube-system  anetd -o yaml | grep image
    

    下列輸出範例顯示您會使用 gcr.io/gke-on-prem-release 做為 Registry

    image: gcr.io/gke-on-prem-release/cilium/cilium:v1.12.6-anthos1.15-gke4.2.7
    
  5. 在管理員叢集的叢集命名空間中,從映像檔標記取得 KubernetesVersionkube-apiserver

    KUBECONFIG=ADMIN_KUBECONFIG
    kubectl get sts -n CLUSTER_NAME kube-apiserver -o yaml | grep image
    

    ADMIN_KUBECONFIG 替換為管理員叢集的 kubeconfig 檔案,並將 CLUSTER_NAME 替換為使用者叢集的名稱。

    以下輸出範例顯示您會將 v1.26.2-gke.1001 用做 KubernetesVersion

    image: gcr.io/gke-on-prem-release/kube-apiserver-amd64:v1.26.2-gke.1001
    imagePullPolicy: IfNotPresent
    

準備 kube-proxy 資訊清單

使用上一節取得的值建立並套用 YAML 資訊清單,將 kube-proxy 部署至叢集。

  1. 在您選擇的編輯器中建立名為 kube-proxy.yaml 的資訊清單:

    nano kube-proxy.yaml
    
  2. 複製並貼上下列 YAML 定義:

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      labels:
        k8s-app: kube-proxy
      name: kube-proxy
      namespace: kube-system
    spec:
      selector:
        matchLabels:
          k8s-app: kube-proxy
      template:
        metadata:
          annotations:
            scheduler.alpha.kubernetes.io/critical-pod: ""
          labels:
            k8s-app: kube-proxy
        spec:
          containers:
          - command:
            - kube-proxy
            - --v=2
            - --profiling=false
            - --iptables-min-sync-period=10s
            - --iptables-sync-period=1m
            - --oom-score-adj=-998
            - --ipvs-sync-period=1m
            - --ipvs-min-sync-period=10s
            - --cluster-cidr=ClusterCIDR
            env:
            - name: KUBERNETES_SERVICE_HOST
              value:APIServerAdvertiseAddress
            - name: KUBERNETES_SERVICE_PORT
              value: "APIServerPort"
            image: Registry/kube-proxy-amd64:KubernetesVersion
            imagePullPolicy: IfNotPresent
            name: kube-proxy
            resources:
              requests:
                cpu: 100m
                memory: 15Mi
            securityContext:
              privileged: true
            volumeMounts:
            - mountPath: /run/xtables.lock
              name: xtables-lock
            - mountPath: /lib/modules
              name: lib-modules
          imagePullSecrets:
          - name: RegistryCredentialsSecretName
          nodeSelector:
            kubernetes.io/os: linux
          hostNetwork: true
          priorityClassName: system-node-critical
          serviceAccount: kube-proxy
          serviceAccountName: kube-proxy
          tolerations:
          - effect: NoExecute
            operator: Exists
          - effect: NoSchedule
            operator: Exists
          volumes:
          - hostPath:
              path: /run/xtables.lock
              type: FileOrCreate
            name: xtables-lock
          - hostPath:
              path: /lib/modules
              type: DirectoryOrCreate
            name: lib-modules
      ---
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRoleBinding
      metadata:
        name: system:kube-proxy
      roleRef:
        apiGroup: rbac.authorization.k8s.io
        kind: ClusterRole
        name: system:node-proxier
      subjects:
        - kind: ServiceAccount
          name: kube-proxy
          namespace: kube-system
      ---
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: kube-proxy
        namespace: kube-system
    

    在這個 YAML 資訊清單中,請設定下列值:

    • APIServerAdvertiseAddressKUBERNETES_SERVICE_HOST 的值,例如 21.1.4.119
    • APIServerPortKUBERNETES_SERVICE_PORT 的值,例如 443
    • Registry:Cilium 映像檔的前置字串,例如 gcr.io/gke-on-prem-release
    • RegistryCredentialsSecretName:圖片提取密碼名稱,例如 private-registry-creds
  3. 在編輯器中儲存並關閉資訊清單檔案。

準備 anetd 修補程式

anetd 建立及準備更新:

  1. 在您選擇的編輯器中建立名為「cilium-config-patch.yaml」的資訊清單:

    nano cilium-config-patch.yaml
    
  2. 複製並貼上下列 YAML 定義:

    data:
      kube-proxy-replacement: "disabled"
      kube-proxy-replacement-healthz-bind-address: ""
      retry-kube-proxy-healthz-binding: "false"
      enable-host-reachable-services: "false"
    
  3. 在編輯器中儲存並關閉資訊清單檔案。

部署 kube-proxy 及重新設定 anetd

將設定變更套用至叢集。請先備份現有設定,再套用變更。

  1. 備份目前的 anetdcilium-config 設定:

    kubectl get ds -n kube-system anetd > anetd-original.yaml
    kubectl get cm -n kube-system cilium-config > cilium-config-original.yaml
    
  2. 使用 kubectl 套用 kube-proxy.yaml

    kubectl apply -f kube-proxy.yaml
    
  3. 確認 Pod 處於 Running 狀態:

    kubectl get pods -n kube-system -o wide | grep kube-proxy
    

    以下範例的精簡輸出內容顯示 Pod 正常運作:

    kube-proxy-f8mp9    1/1    Running   1 (4m ago)    [...]
    kube-proxy-kndhv    1/1    Running   1 (5m ago)    [...]
    kube-proxy-sjnwl    1/1    Running   1 (4m ago)    [...]
    
  4. 使用 kubectl 修補 cilium-config ConfigMap:

    kubectl patch cm -n kube-system cilium-config --patch-file cilium-config-patch.yaml
    
  5. 使用 kubectl 編輯 anetd

    kubectl edit ds -n kube-system anetd
    

    在開啟的編輯器中,編輯 anetd 的規格。在 initContainers 底下插入下列內容做為第一個項目:

    - name: check-kube-proxy-rules
      image: Image
      imagePullPolicy: IfNotPresent
      command:
      - sh
      - -ec
      - |
        if [ "$KUBE_PROXY_REPLACEMENT" != "strict" ]; then
          kube_proxy_forward() { iptables -L KUBE-FORWARD; }
          until kube_proxy_forward; do sleep 2; done
        fi;
      env:
      - name: KUBE_PROXY_REPLACEMENT
        valueFrom:
          configMapKeyRef:
            key: kube-proxy-replacement
            name: cilium-config
            optional: true
      securityContext:
        privileged: true
    

    Image 換成 anetd DaemonSet 中其他 Cilium 容器使用的相同映像檔,例如 gcr.io/gke-on-prem-release/cilium/cilium:v1.12.6-anthos1.15-gke4.2.7

  6. 在編輯器中儲存並關閉資訊清單檔案。

  7. 如要套用這些變更,請重新啟動叢集中的所有節點。為盡量減少中斷,您可以在重新啟動前嘗試排空每個節點。不過,由於 NFS 掛接中斷,導致 Pod 無法順利排空,因此使用 RWX 磁碟區的 Pod 可能會停留在 Terminating 狀態。

    您可以強制刪除遭封鎖的 Pod,並允許節點正確排空:

    kubectl delete pods -–force -–grace-period=0 --namespace POD_NAMESPACE POD_NAME
    

    POD_NAME 替換為要刪除的 Pod,並將 POD_NAMESPACE 替換為該 Pod 的命名空間。

後續步驟

如需其他協助,請與 Cloud Customer Care 團隊聯絡。

如要進一步瞭解支援資源,包括下列項目,請參閱「取得支援」: