Memecahkan masalah GKE pada VMware NFS dan DataPlane v2

Dokumen ini menjelaskan prosedur manual untuk GKE di VMware jika Anda mengalami masalah terkait pemasangan NFS dengan volume atau pod yang macet, dan Anda membuat cluster dengan DataPlane v2 diaktifkan. Anda mungkin mengalami masalah jika memiliki workload yang menggunakan volume ReadWriteMany yang didukung oleh driver penyimpanan yang rentan terhadap masalah ini, seperti (tetapi tidak terbatas pada):

  • Robin.io
  • Portworx (sharedv4 volume layanan)
  • 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 adanya keterbatasan pada cara kode soket kernel Linux berinteraksi dengan program eBPF Cillium. Container dapat diblokir di I/O atau bahkan tidak dapat dinonaktifkan, karena dudukan NFS yang sudah tidak berfungsi tidak dapat dilepas.

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

Tinjau konfigurasi cluster yang ada

Dapatkan beberapa nilai konfigurasi yang ada dari cluster Anda. Anda akan 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 gambar untuk kube-apiserver dalam namespace cluster 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 Anda 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 gambar Cilium, seperti gcr.io/gke-on-prem-release.
    • RegistryCredentialsSecretName: nama rahasia pull image, seperti private-registry-creds.
  3. Simpan dan tutup file manifes di editor Anda.

Siapkan patch anetd

Membuat dan menyiapkan 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.

Deploy kube-proxy dan konfigurasi ulang anetd

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

  1. Cadangkan konfigurasi anetd dan cilium-config Anda 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 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. Lakukan 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 berikut sebagai item pertama di bawah 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 gambar yang sama yang digunakan dalam penampung Cilium lainnya 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 mulai ulang. Namun, Pod yang menggunakan volume RWX mungkin terjebak dalam status Terminating karena pemasangan NFS rusak yang memblokir proses pengosongan.

    Anda dapat menghapus otomatis Pod yang diblokir dan mengizinkan Node untuk dikosongkan dengan benar:

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

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

Langkah selanjutnya

Jika Anda memerlukan bantuan tambahan, hubungi Layanan Pelanggan Cloud .