Résoudre les problèmes liés à Google Distributed Cloud NFS et DataPlane v2

Ce document décrit une procédure manuelle pour Google Distributed Cloud si vous rencontrez des problèmes avec les installations NFS avec un volume ou un pod bloqué et que vous avez créé votre cluster avec DataPlane v2 activé.

Ce problème a été résolu dans les versions suivantes:

  • Pour la version mineure 1.16, la version 1.16.4-gke.37 et les versions ultérieures.
  • Pour la version mineure 1.28, la version 1.28.200-gke.111 et les versions ultérieures.

Nous vous recommandons de effectuer une mise à niveau vers une version permettant de résoudre ce problème. Si vous ne parvenez pas à effectuer la mise à niveau, suivez les procédures décrites dans les sections suivantes.

Si vous utilisez une version où ce problème n'est pas résolu, vous pouvez rencontrer des problèmes si vos charges de travail utilisant des volumes ReadWriteMany alimentés par des pilotes de stockage sont susceptibles d'être confrontées à ce problème, par exemple :

  • Robin.io
  • Portworx (sharedv4 volumes de service)
  • csi-nfs

Les installations NFS sur certaines architectures de stockage peuvent être bloquées lorsqu'elles sont connectées à un point de terminaison à l'aide d'un service Kubernetes (ClusterIP) et de DataPlane v2. Ce comportement est dû aux limites d'interaction du code du socket du noyau Linux avec le programme eBPF de Cillium. Les conteneurs peuvent être bloqués sur les E/S ou même être impossibles à tuer, car le montage NFS obsolète ne peut pas être désinstallé.

Vous pouvez rencontrer ce problème si vous utilisez un espace de stockage RWX hébergé sur des serveurs NFS qui s'exécutent sur un nœud Kubernetes, y compris des solutions de stockage définies par logiciel ou hyperconvergées telles que Ondat, Robin.io ou Portworx.

Si vous avez besoin d'aide supplémentaire, contactez l'assistance Cloud Customer Care.

Examiner la configuration de cluster existante

Récupérez certaines valeurs de configuration existantes de votre cluster. Vous allez utiliser les valeurs de ces étapes pour créer un fichier manifeste kube-proxy dans la section suivante.

  1. Obtenez le ClusterCIDR à partir de cm/cilium-config:

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

    L'exemple de résultat suivant montre que vous utiliseriez 192.168.0.0/16 comme ClusterCIDR:

    ipv4-native-routing-cidr: 192.168.0.0/16
    native-routing-cidr: 192.168.0.0/16
    
  2. Obtenez les valeurs APIServerAdvertiseAddress et APIServerPort à partir du DaemonSet anetd:

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

    L'exemple de résultat suivant montre que vous utiliseriez 21.1.4.119 comme APIServerAdvertiseAddress et 443 comme APIServerPort:

    - name: KUBERNETES_SERVICE_HOST
      value: 21.1.4.119
    - name: KUBERNETES_SERVICE_PORT
      value: "443"
    
  3. Récupérez le RegistryCredentialsSecretName à partir du DaemonSet anetd:

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

    L'exemple de résultat suivant montre que vous utiliseriez private-registry-creds comme RegistryCredentialsSecretName:

    imagePullSecrets:
      - name: private-registry-creds
    
  4. Obtenez le Registry à partir du DameonSet anetd:

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

    L'exemple de résultat suivant montre que vous utiliseriez gcr.io/gke-on-prem-release comme Registry:

    image: gcr.io/gke-on-prem-release/cilium/cilium:v1.12.6-anthos1.15-gke4.2.7
    
  5. Récupérez la valeur KubernetesVersion à partir du tag d'image pour kube-apiserver dans l'espace de noms du cluster d'administrateur:

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

    Remplacez ADMIN_KUBECONFIG par le fichier kubeconfig de votre cluster d'administrateur et CLUSTER_NAME par le nom de votre cluster d'utilisateur.

    L'exemple de résultat suivant montre que vous utiliseriez v1.26.2-gke.1001 comme KubernetesVersion:

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

Préparer kube-proxy fichier manifeste

Utilisez les valeurs obtenues à la section précédente pour créer et appliquer un fichier manifeste YAML qui déploiera kube-proxy sur votre cluster.

  1. Créez un fichier manifeste nommé kube-proxy.yaml dans l'éditeur de votre choix:

    nano kube-proxy.yaml
    
  2. Copiez et collez la définition YAML suivante :

    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
    

    Dans ce fichier manifeste YAML, définissez les valeurs suivantes:

    • APIServerAdvertiseAddress: valeur de KUBERNETES_SERVICE_HOST (par exemple 21.1.4.119).
    • APIServerPort: valeur de KUBERNETES_SERVICE_PORT, par exemple 443.
    • Registry: préfixe de l'image Cilium, par exemple gcr.io/gke-on-prem-release.
    • RegistryCredentialsSecretName: nom du secret d'extraction d'image, par exemple private-registry-creds.
  3. Enregistrez et fermez le fichier manifeste dans l'éditeur.

Préparer anetd correctif

Créez et préparez une mise à jour pour anetd:

  1. Créez un fichier manifeste nommé cilium-config-patch.yaml dans l'éditeur de votre choix:

    nano cilium-config-patch.yaml
    
  2. Copiez et collez la définition YAML suivante :

    data:
      kube-proxy-replacement: "disabled"
      kube-proxy-replacement-healthz-bind-address: ""
      retry-kube-proxy-healthz-binding: "false"
      enable-host-reachable-services: "false"
    
  3. Enregistrez et fermez le fichier manifeste dans l'éditeur.

Déployer kube-proxy et reconfigurer anetd

Appliquez les modifications de configuration à votre cluster. Créez des sauvegardes de votre configuration existante avant d'appliquer les modifications.

  1. Sauvegardez votre configuration anetd et cilium-config actuelle:

    kubectl get ds -n kube-system anetd > anetd-original.yaml
    kubectl get cm -n kube-system cilium-config > cilium-config-original.yaml
    
  2. Appliquez kube-proxy.yaml à l'aide de kubectl:

    kubectl apply -f kube-proxy.yaml
    
  3. Vérifiez que les pods sont à l'état Running:

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

    L'exemple de résultat condensé suivant montre que les pods s'exécutent correctement:

    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. Appliquez un correctif au ConfigMap cilium-config à l'aide de kubectl:

    kubectl patch cm -n kube-system cilium-config --patch-file cilium-config-patch.yaml
    
  5. Modifiez anetd à l'aide de kubectl:

    kubectl edit ds -n kube-system anetd
    

    Dans l'éditeur qui s'ouvre, modifiez la spécification de anetd. Insérez le code suivant en tant que premier élément sous 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
    

    Remplacez Image par la même image que celle utilisée dans les autres conteneurs Cilium du DaemonSet anetd, par exemple gcr.io/gke-on-prem-release/cilium/cilium:v1.12.6-anthos1.15-gke4.2.7.

  6. Enregistrez et fermez le fichier manifeste dans l'éditeur.

  7. Pour appliquer ces modifications, redémarrez tous les nœuds de votre cluster. Pour minimiser les perturbations, vous pouvez essayer de drainer chaque nœud avant le redémarrage. Toutefois, les pods utilisant des volumes RWX peuvent être bloqués à l'état Terminating en raison d'installations NFS défectueuses qui bloquent le processus de drainage.

    Vous pouvez forcer la suppression des pods bloqués et permettre au nœud de drainer correctement:

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

    Remplacez POD_NAME par le pod que vous essayez de supprimer et POD_NAMESPACE par son espace de noms.

Étapes suivantes

Si vous avez besoin d'une aide supplémentaire, contactez Cloud Customer Care.