En este documento, se detalla un procedimiento manual para Google Distributed Cloud si tienes problemas con las activaciones de NFS con un volumen o un pod bloqueados y creaste tu clúster con DataPlane v2 habilitado.
Este problema se corrigió en las siguientes versiones:
- Para la versión secundaria 1.16, la versión 1.16.4-gke.37 y versiones posteriores
- Para la versión secundaria 1.28, la versión 1.28.200-gke.111 y versiones posteriores
Te recomendamos que actualices a una versión en la que se haya solucionado este problema. Si no puedes actualizar, usa los procedimientos que se describen en las siguientes secciones.
Si usas una versión en la que no se corrigió este problema, es posible que tengas problemas si tienes cargas de trabajo que usan volúmenes ReadWriteMany
con controladores de almacenamiento susceptibles a este problema, como los siguientes (sin limitaciones):
- Robin.io
- Portworx (volúmenes de servicio
sharedv4
) csi-nfs
Es posible que los activaciones de NFS en algunas arquitecturas de almacenamiento se bloqueen cuando se conectan a un extremo con un servicio de Kubernetes (ClusterIP) y DataPlane v2. Este comportamiento se debe a las limitaciones en la forma en que el código de socket del kernel de Linux interactúa con el programa eBPF de Cillium. Los contenedores pueden bloquearse en la E/S o incluso no poder finalizarse, ya que no se puede desactivar la activación de NFS inactiva.
Es posible que experimentes este problema si usas el almacenamiento RWX
alojado en servidores NFS que se ejecutan en un nodo de Kubernetes, incluidas las soluciones de almacenamiento definidas por software o hiperconvergentes, como Ondat, Robin.io o Portworx.
Revisa la configuración del clúster existente
Obtén algunos valores de configuración existentes de tu clúster. Usarás los valores de estos pasos para crear un manifiesto kube-proxy
en la siguiente sección.
Obtén el
ClusterCIDR
decm/cilium-config
:kubectl get cm -n kube-system cilium-config -o yaml | grep native-routing-cidr
En el siguiente resultado de ejemplo, se muestra que usarías
192.168.0.0/16
comoClusterCIDR
:ipv4-native-routing-cidr: 192.168.0.0/16 native-routing-cidr: 192.168.0.0/16
Obtén
APIServerAdvertiseAddress
yAPIServerPort
del DaemonSetanetd
:kubectl get ds -n kube-system anetd -o yaml | grep KUBERNETES -A 1
En el siguiente ejemplo de salida, se muestra que usarías
21.1.4.119
comoAPIServerAdvertiseAddress
y443
comoAPIServerPort
:- name: KUBERNETES_SERVICE_HOST value: 21.1.4.119 - name: KUBERNETES_SERVICE_PORT value: "443"
Obtén el
RegistryCredentialsSecretName
del DaemonSetanetd
:kubectl get ds -n kube-system anetd -o yaml | grep imagePullSecrets -A 1
En el siguiente resultado de ejemplo, se muestra que usarías
private-registry-creds
comoRegistryCredentialsSecretName
:imagePullSecrets: - name: private-registry-creds
Obtén el
Registry
del daemonsetanetd
:kubectl get ds -n kube-system anetd -o yaml | grep image
En el siguiente resultado de ejemplo, se muestra que usarías
gcr.io/gke-on-prem-release
comoRegistry
:image: gcr.io/gke-on-prem-release/cilium/cilium:v1.12.6-anthos1.15-gke4.2.7
Obtén el
KubernetesVersion
de la etiqueta de imagen parakube-apiserver
en el espacio de nombres del clúster del clúster de administrador:KUBECONFIG=ADMIN_KUBECONFIG kubectl get sts -n CLUSTER_NAME kube-apiserver -o yaml | grep image
Reemplaza
ADMIN_KUBECONFIG
por el archivo kubeconfig de tu clúster de administrador yCLUSTER_NAME
por el nombre de tu clúster de usuario.En el siguiente ejemplo de salida, se muestra que usarías
v1.26.2-gke.1001
comoKubernetesVersion
:image: gcr.io/gke-on-prem-release/kube-apiserver-amd64:v1.26.2-gke.1001 imagePullPolicy: IfNotPresent
Prepara los manifiestos kube-proxy
Usa los valores obtenidos en la sección anterior para crear y aplicar un manifiesto YAML que implementará kube-proxy
en tu clúster.
Crea un manifiesto llamado
kube-proxy.yaml
en el editor que elijas:nano kube-proxy.yaml
Copia y pega la siguiente definición de 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
En este manifiesto YAML, establece los siguientes valores:
APIServerAdvertiseAddress
: Es el valor deKUBERNETES_SERVICE_HOST
, como21.1.4.119
.APIServerPort
: Es el valor deKUBERNETES_SERVICE_PORT
, como443
.Registry
: Es el prefijo de la imagen de Cilium, comogcr.io/gke-on-prem-release
.RegistryCredentialsSecretName
: Es el nombre del secreto para extraer imágenes, comoprivate-registry-creds
.
Guarda y cierra el archivo de manifiesto en tu editor.
Prepara el parche anetd
Crea y prepara una actualización para anetd
:
Crea un manifiesto llamado
cilium-config-patch.yaml
en el editor que elijas:nano cilium-config-patch.yaml
Copia y pega la siguiente definición de YAML:
data: kube-proxy-replacement: "disabled" kube-proxy-replacement-healthz-bind-address: "" retry-kube-proxy-healthz-binding: "false" enable-host-reachable-services: "false"
Guarda y cierra el archivo de manifiesto en tu editor.
Implementa kube-proxy
y vuelve a configurar anetd
Aplica los cambios de configuración al clúster. Crea copias de seguridad de tu configuración existente antes de aplicar los cambios.
Crea una copia de seguridad de la configuración actual de
anetd
ycilium-config
:kubectl get ds -n kube-system anetd > anetd-original.yaml kubectl get cm -n kube-system cilium-config > cilium-config-original.yaml
Aplica
kube-proxy.yaml
conkubectl
:kubectl apply -f kube-proxy.yaml
Verifica que los Pods sean
Running
:kubectl get pods -n kube-system -o wide | grep kube-proxy
En el siguiente ejemplo, el resultado condensado muestra que los Pods se ejecutan correctamente:
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) [...]
Aplica un parche al ConfigMap
cilium-config
conkubectl
:kubectl patch cm -n kube-system cilium-config --patch-file cilium-config-patch.yaml
Edita
anetd
conkubectl
:kubectl edit ds -n kube-system anetd
En el editor que se abre, edita las especificaciones de
anetd
. Inserta lo siguiente como el primer elemento eninitContainers
:- 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
Reemplaza
Image
por la misma imagen que se usa en los otros contenedores de Cilium en el DaemonSetanetd
, comogcr.io/gke-on-prem-release/cilium/cilium:v1.12.6-anthos1.15-gke4.2.7
.Guarda y cierra el archivo de manifiesto en tu editor.
Para aplicar estos cambios, reinicia todos los nodos del clúster. Para minimizar la interrupción, puedes intentar drenar cada nodo antes del reinicio. Sin embargo, los pods que usan volúmenes RWX pueden quedar atascados en un estado
Terminating
debido a activaciones de NFS dañadas que bloquean el proceso de drenaje.Puedes forzar la eliminación de Pods bloqueados y permitir que el nodo se drene correctamente:
kubectl delete pods -–force -–grace-period=0 --namespace POD_NAMESPACE POD_NAME
Reemplaza
POD_NAME
por el Pod que intentas borrar yPOD_NAMESPACE
por su espacio de nombres.