En este documento, se detalla un procedimiento manual para GKE en VMware si tienes problemas con las activaciones de NFS con un volumen o Pod atascado y creaste tu clúster con DataPlane v2 habilitado. Es posible que encuentres problemas si tienes cargas de trabajo que usan volúmenes ReadWriteMany
con tecnología de controladores de almacenamiento que son susceptibles a este problema, como los siguientes:
- Robin.io
- Portworx (
sharedv4
volúmenes de servicio) csi-nfs
Las activaciones de NFS en algunas arquitecturas de almacenamiento pueden detenerse cuando se conectan a un extremo mediante un Service de Kubernetes (ClusterIP) y DataPlane v2. Este comportamiento se debe a las limitaciones en la forma en que el código del socket del kernel de Linux interactúa con el programa eBPF de Cillium. Es posible que los contenedores se bloqueen en la E/S o que incluso no se puedan desactivar, ya que la activación de NFS en desuso no se puede desactivar.
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 de 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 DaemonSet deanetd
:kubectl get ds -n kube-system anetd -o yaml | grep KUBERNETES -A 1
En el siguiente resultado de ejemplo, 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 DaemonSet deanetd
:kubectl get ds -n kube-system anetd -o yaml | grep imagePullSecrets -A 1
En el siguiente resultado de ejemplo, se muestra que deberías usar
private-registry-creds
comoRegistryCredentialsSecretName
:imagePullSecrets: - name: private-registry-creds
Obtén el
Registry
delanetd
DameonSet:kubectl get ds -n kube-system anetd -o yaml | grep image
En el siguiente resultado de ejemplo, se muestra que deberías usar
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 dekube-apiserver
en el espacio de nombres 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 para el clúster de administrador yCLUSTER_NAME
por el nombre del clúster de usuario.En el siguiente resultado de ejemplo, 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 prefieras: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, configura 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 de extracción de la imagen, 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 prefieras: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 tu 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 resultado condensado de ejemplo, se muestra que los Pods se ejecutan de forma correcta:
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 la especificación 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 DaemonSet deanetd
, 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 vaciar 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 desvío.Puedes forzar la eliminación de Pods bloqueados y permitir que el nodo se desvíe de forma correcta:
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.