Memecahkan masalah NFS dan DataPlane v2 Google Distributed Cloud

Dokumen ini menjelaskan prosedur manual untuk Google Distributed Cloud jika Anda mengalami masalah dengan pemasangan NFS dengan volume atau Pod yang macet dan Anda membuat cluster dengan mengaktifkan DataPlane v2.

Masalah ini telah diperbaiki untuk versi berikut:

  • Untuk versi minor 1.16, versi 1.16.4-gke.37 dan yang lebih tinggi.
  • Untuk versi minor 1.28, versi 1.28.200-gke.111 dan yang lebih tinggi.

Sebaiknya upgrade ke versi yang telah memperbaiki masalah ini. Jika Anda tidak dapat mengupgrade, gunakan prosedur yang diuraikan di bagian berikut.

Jika Anda menggunakan versi yang tidak memperbaiki masalah ini, Anda mungkin mengalami masalah jika memiliki beban kerja yang menggunakan volume ReadWriteMany yang didukung oleh driver penyimpanan yang rentan terhadap masalah ini, seperti (tetapi tidak terbatas pada):

  • Robin.io
  • Portworx (volume layanan sharedv4)
  • csi-nfs

Pemasangan NFS di beberapa arsitektur penyimpanan mungkin macet saat terhubung ke endpoint menggunakan Layanan Kubernetes (ClusterIP) dan DataPlane v2. Perilaku ini disebabkan oleh batasan cara kode soket kernel Linux berinteraksi dengan program eBPF Cillium. Penampung mungkin diblokir di I/O atau bahkan tidak dapat dihentikan, karena pemasangan NFS yang tidak berfungsi tidak dapat dilepas.

Anda mungkin mengalami masalah ini jika menggunakan penyimpanan RWX yang dihosting di server NFS yang berjalan di node Kubernetes, termasuk solusi penyimpanan hyperconverged atau yang ditentukan software seperti Ondat, Robin.io, atau Portworx.

Jika Anda memerlukan bantuan tambahan, hubungi Cloud Customer Care.

Meninjau konfigurasi cluster yang ada

Dapatkan beberapa nilai konfigurasi yang ada dari cluster Anda. Anda menggunakan nilai dari langkah-langkah ini untuk membuat manifes kube-proxy di bagian berikutnya.

  1. Dapatkan ClusterCIDR dari cm/cilium-config:

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

    Contoh output berikut menunjukkan bahwa Anda akan menggunakan 192.168.0.0/16 sebagai ClusterCIDR:

    ipv4-native-routing-cidr: 192.168.0.0/16
    native-routing-cidr: 192.168.0.0/16
    
  2. Dapatkan APIServerAdvertiseAddress dan APIServerPort dari DaemonSet anetd:

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

    Contoh output berikut menunjukkan bahwa Anda akan menggunakan 21.1.4.119 sebagai APIServerAdvertiseAddress dan 443 sebagai APIServerPort:

    - name: KUBERNETES_SERVICE_HOST
      value: 21.1.4.119
    - name: KUBERNETES_SERVICE_PORT
      value: "443"
    
  3. Dapatkan RegistryCredentialsSecretName dari DaemonSet anetd:

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

    Contoh output berikut menunjukkan bahwa Anda akan menggunakan private-registry-creds sebagai RegistryCredentialsSecretName:

    imagePullSecrets:
      - name: private-registry-creds
    
  4. Dapatkan Registry dari DameonSet anetd:

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

    Contoh output berikut menunjukkan bahwa Anda akan menggunakan gcr.io/gke-on-prem-release sebagai Registry:

    image: gcr.io/gke-on-prem-release/cilium/cilium:v1.12.6-anthos1.15-gke4.2.7
    
  5. Dapatkan KubernetesVersion dari tag image untuk kube-apiserver di namespace cluster dari cluster admin:

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

    Ganti ADMIN_KUBECONFIG dengan file kubeconfig untuk cluster admin dan CLUSTER_NAME dengan nama cluster pengguna Anda.

    Contoh output berikut menunjukkan bahwa Anda akan menggunakan v1.26.2-gke.1001 sebagai KubernetesVersion:

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

Menyiapkan manifes kube-proxy

Gunakan nilai yang diperoleh di bagian sebelumnya untuk membuat dan menerapkan manifes YAML yang akan men-deploy kube-proxy ke cluster Anda.

  1. Buat manifes bernama kube-proxy.yaml di editor pilihan Anda:

    nano kube-proxy.yaml
    
  2. Salin dan tempel definisi YAML berikut:

    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
    

    Dalam manifes YAML ini, tetapkan nilai berikut:

    • APIServerAdvertiseAddress: nilai KUBERNETES_SERVICE_HOST, seperti 21.1.4.119.
    • APIServerPort: nilai KUBERNETES_SERVICE_PORT, seperti 443.
    • Registry: awalan image Cilium, seperti gcr.io/gke-on-prem-release.
    • RegistryCredentialsSecretName: nama secret pull image, seperti private-registry-creds.
  3. Simpan dan tutup file manifes di editor Anda.

Menyiapkan patch anetd

Buat dan siapkan update untuk anetd:

  1. Buat manifes bernama cilium-config-patch.yaml di editor pilihan Anda:

    nano cilium-config-patch.yaml
    
  2. Salin dan tempel definisi YAML berikut:

    data:
      kube-proxy-replacement: "disabled"
      kube-proxy-replacement-healthz-bind-address: ""
      retry-kube-proxy-healthz-binding: "false"
      enable-host-reachable-services: "false"
    
  3. Simpan dan tutup file manifes di editor Anda.

Men-deploy kube-proxy dan mengonfigurasi ulang anetd

Terapkan perubahan konfigurasi ke cluster Anda. Buat cadangan konfigurasi yang ada sebelum menerapkan perubahan.

  1. Cadangkan konfigurasi anetd dan cilium-config saat ini:

    kubectl get ds -n kube-system anetd > anetd-original.yaml
    kubectl get cm -n kube-system cilium-config > cilium-config-original.yaml
    
  2. Terapkan kube-proxy.yaml menggunakan kubectl:

    kubectl apply -f kube-proxy.yaml
    
  3. Pastikan Pod adalah Running:

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

    Contoh output ringkas berikut menunjukkan bahwa Pod berjalan dengan benar:

    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. Terapkan patch pada ConfigMap cilium-config menggunakan kubectl:

    kubectl patch cm -n kube-system cilium-config --patch-file cilium-config-patch.yaml
    
  5. Edit anetd menggunakan kubectl:

    kubectl edit ds -n kube-system anetd
    

    Di editor yang terbuka, edit spesifikasi anetd. Masukkan kode berikut sebagai item pertama di bagian 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
    

    Ganti Image dengan image yang sama yang digunakan di penampung Cilium lain di DaemonSet anetd, seperti gcr.io/gke-on-prem-release/cilium/cilium:v1.12.6-anthos1.15-gke4.2.7.

  6. Simpan dan tutup file manifes di editor Anda.

  7. Untuk menerapkan perubahan ini, mulai ulang semua node di cluster Anda. Untuk meminimalkan gangguan, Anda dapat mencoba menghabiskan setiap node sebelum memulai ulang. Namun, Pod yang menggunakan volume RWX mungkin macet dalam status Terminating karena pemasangan NFS yang rusak yang memblokir proses pembuangan.

    Anda dapat memaksa penghapusan Pod yang diblokir dan mengizinkan Node menghabiskan resource dengan benar:

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

    Ganti POD_NAME dengan Pod yang Anda coba hapus dan POD_NAMESPACE dengan namespace-nya.

Langkah selanjutnya

Jika Anda memerlukan bantuan tambahan, hubungi Cloud Customer Care.