Risolvere i problemi relativi a Google Distributed Cloud NFS e DataPlane v2

Questo documento descrive una procedura manuale per Google Distributed Cloud in caso di problemi con i montaggi NFS con un volume o un pod bloccato e se hai creato il cluster con DataPlane v2 abilitato.

Questo problema è stato risolto per le seguenti versioni:

  • Per la versione secondaria 1.16, versione 1.16.4-gke.37 e successive.
  • Per la versione secondaria 1.28, versione 1.28.200-gke.111 e successive.

Ti consigliamo di eseguire l'upgrade a una versione in cui questo problema è stato risolto. Se non riesci a eseguire l'upgrade, utilizza le procedure descritte nelle sezioni seguenti.

Se utilizzi una versione in cui questo problema non è stato risolto, potresti riscontrare problemi se hai carichi di lavoro che utilizzano volumi ReadWriteMany basati su driver di archiviazione sensibili a questo problema, ad esempio (ma non solo):

  • Robin.io
  • Portworx (volumi di servizio sharedv4)
  • csi-nfs

I montaggi NFS su alcune architetture di archiviazione potrebbero bloccarsi quando sono connessi a un endpoint utilizzando un servizio Kubernetes (ClusterIP) e DataPlane v2. Questo comportamento è dovuto alle limitazioni nel modo in cui il codice socket del kernel Linux interagisce con il programma eBPF di Cillium. I container potrebbero bloccarsi su I/O o addirittura non essere eliminabili, poiché il montaggio NFS non funzionante non può essere smontato.

Potresti riscontrare questo problema se utilizzi l'archiviazione RWX ospitata su server NFS in esecuzione su un nodo Kubernetes, incluse soluzioni di archiviazione software-defined o iperconvergenti come Ondat, Robin.io o Portworx.

Esaminare la configurazione del cluster esistente

Recupera alcuni valori di configurazione esistenti dal cluster. Utilizzerai i valori di questi passaggi per creare un manifest kube-proxy nella sezione successiva.

  1. Recupera ClusterCIDR da cm/cilium-config:

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

    L'output di esempio seguente mostra che utilizzeresti 192.168.0.0/16 come ClusterCIDR:

    ipv4-native-routing-cidr: 192.168.0.0/16
    native-routing-cidr: 192.168.0.0/16
    
  2. Recupera APIServerAdvertiseAddress e APIServerPort dal DaemonSet anetd:

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

    L'output di esempio seguente mostra che utilizzeresti 21.1.4.119 come APIServerAdvertiseAddress e 443 come APIServerPort:

    - name: KUBERNETES_SERVICE_HOST
      value: 21.1.4.119
    - name: KUBERNETES_SERVICE_PORT
      value: "443"
    
  3. Recupera RegistryCredentialsSecretName dal DaemonSet anetd:

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

    L'output di esempio seguente mostra che utilizzeresti private-registry-creds come RegistryCredentialsSecretName:

    imagePullSecrets:
      - name: private-registry-creds
    
  4. Recupera Registry dal DaemonSet anetd:

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

    L'output di esempio seguente mostra che utilizzeresti gcr.io/gke-on-prem-release come Registry:

    image: gcr.io/gke-on-prem-release/cilium/cilium:v1.12.6-anthos1.15-gke4.2.7
    
  5. Recupera KubernetesVersion dal tag dell'immagine per kube-apiserver nello spazio dei nomi del cluster di amministrazione:

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

    Sostituisci ADMIN_KUBECONFIG con il file kubeconfig per il cluster di amministrazione e CLUSTER_NAME con il nome del cluster utente.

    L'output di esempio seguente mostra che utilizzeresti v1.26.2-gke.1001 come KubernetesVersion:

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

Preparare i manifest kube-proxy

Utilizza i valori ottenuti nella sezione precedente per creare e applicare un manifest YAML che eseguirà il deployment di kube-proxy nel cluster.

  1. Crea un manifest denominato kube-proxy.yaml nell'editor che preferisci:

    nano kube-proxy.yaml
    
  2. Copia e incolla la seguente definizione 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
    

    In questo manifest YAML, imposta i seguenti valori:

    • APIServerAdvertiseAddress: il valore di KUBERNETES_SERVICE_HOST, ad esempio 21.1.4.119.
    • APIServerPort: il valore di KUBERNETES_SERVICE_PORT, ad esempio 443.
    • Registry: il prefisso dell'immagine Cilium, ad esempio gcr.io/gke-on-prem-release.
    • RegistryCredentialsSecretName: il nome del secret di pull dell'immagine, ad esempio private-registry-creds.
  3. Salva e chiudi il file manifest nell'editor.

Preparare la patch anetd

Crea e prepara un aggiornamento per anetd:

  1. Crea un manifest denominato cilium-config-patch.yaml nell'editor che preferisci:

    nano cilium-config-patch.yaml
    
  2. Copia e incolla la seguente definizione YAML:

    data:
      kube-proxy-replacement: "disabled"
      kube-proxy-replacement-healthz-bind-address: ""
      retry-kube-proxy-healthz-binding: "false"
      enable-host-reachable-services: "false"
    
  3. Salva e chiudi il file manifest nell'editor.

Eseguire il deployment di kube-proxy e riconfigurare anetd

Applica le modifiche alla configurazione al cluster. Crea backup della configurazione esistente prima di applicare le modifiche.

  1. Esegui il backup della configurazione attuale di anetd e cilium-config:

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

    kubectl apply -f kube-proxy.yaml
    
  3. Verifica che i pod siano Running:

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

    L'output di esempio seguente mostra che i pod sono in esecuzione correttamente:

    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. Applica la patch al ConfigMap cilium-config utilizzando kubectl:

    kubectl patch cm -n kube-system cilium-config --patch-file cilium-config-patch.yaml
    
  5. Modifica anetd utilizzando kubectl:

    kubectl edit ds -n kube-system anetd
    

    Nell'editor che si apre, modifica la specifica di anetd. Inserisci quanto segue come primo elemento in 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
    

    Sostituisci Image con la stessa immagine utilizzata negli altri container Cilium nel DaemonSet anetd, ad esempio gcr.io/gke-on-prem-release/cilium/cilium:v1.12.6-anthos1.15-gke4.2.7.

  6. Salva e chiudi il file manifest nell'editor.

  7. Per applicare queste modifiche, riavvia tutti i nodi nel cluster. Per ridurre al minimo le interruzioni, puoi provare a svuotare ogni nodo prima del riavvio. Tuttavia, i pod che utilizzano volumi RWX potrebbero rimanere bloccati nello stato Terminating a causa di montaggi NFS interrotti che bloccano il processo di svuotamento.

    Puoi forzare l'eliminazione dei pod bloccati e consentire lo svuotamento corretto del nodo:

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

    Sostituisci POD_NAME con il pod che stai tentando di eliminare e POD_NAMESPACE con il relativo spazio dei nomi.

Passaggi successivi

Se hai bisogno di ulteriore assistenza, contatta l'assistenza clienti Google Cloud.

Per ulteriori informazioni sulle risorse di assistenza, inclusi i seguenti, consulta anche Richiedere assistenza:

  • Requisiti per l'apertura di una richiesta di assistenza.
  • Strumenti per la risoluzione dei problemi, come log e metriche.
  • Componenti , , and supportati, versioni e funzionalità di Google Distributed Cloud per VMware (solo software).