Tengo un problema en un proceso de larga duración llamado kube-proxy que forma parte de Kubernetes .
El problema es que de vez en cuando se deja una conexión en estado FIN_WAIT2.
$ sudo netstat -tpn | grep FIN_WAIT2
tcp6 0 0 10.244.0.1:33132 10.244.0.35:48936 FIN_WAIT2 14125/kube-proxy
tcp6 0 0 10.244.0.1:48340 10.244.0.35:56339 FIN_WAIT2 14125/kube-proxy
tcp6 0 0 10.244.0.1:52619 10.244.0.35:57859 FIN_WAIT2 14125/kube-proxy
tcp6 0 0 10.244.0.1:33132 10.244.0.50:36466 FIN_WAIT2 14125/kube-proxy
Estas conexiones se acumulan con el tiempo haciendo que el proceso se comporte mal. Ya informé un problema al rastreador de errores de Kubernetes, pero me gustaría entender por qué esas conexiones no están cerradas por el kernel de Linux.
De acuerdo con su documentación (buscar tcp_fin_timeout) la conexión en estado FIN_WAIT2 debe ser cerrada por el núcleo después de X segundos, donde X puede leerse desde / proc. En mi máquina está configurado en 60:
$ cat /proc/sys/net/ipv4/tcp_fin_timeout
60
así que si lo entiendo correctamente, tales conexiones deberían cerrarse por 60 segundos. Pero este no es el caso, se dejan en ese estado durante horas.
Si bien también entiendo que las conexiones FIN_WAIT2 son bastante inusuales (significa que el host está esperando un ACK desde el extremo remoto de la conexión que podría haber desaparecido) No entiendo por qué estas conexiones no están "cerradas" por el sistema .
¿Hay algo que pueda hacer al respecto?
Tenga en cuenta que reiniciar el proceso relacionado es un último recurso.
fuente
Respuestas:
El tiempo de espera del núcleo solo se aplica si la conexión es huérfana. Si la conexión todavía está conectada a un zócalo, el programa que posee ese zócalo es responsable de agotar el tiempo de espera de la conexión. Probablemente ha llamado
shutdown
y está esperando que la conexión se cierre limpiamente. La aplicación puede esperar todo el tiempo que quiera para que se complete el apagado.El flujo de apagado limpio típico es el siguiente:
La aplicación decide cerrar la conexión y cierra el lado de escritura de la conexión.
La aplicación espera a que el otro lado cierre su mitad de la conexión.
La aplicación detecta el apagado de la conexión del otro lado y cierra su zócalo.
La aplicación puede esperar en el paso 2 todo el tiempo que quiera.
Parece que la aplicación necesita un tiempo de espera. Una vez que decide cerrar la conexión, debe dejar de esperar que la otra parte realice un apagado limpio después de un período de tiempo razonable.
fuente
Si el socket está apagado (), pero aún no está cerrado (), el socket permanecerá en el estado FIN_WAIT2. Y dado que la aplicación aún posee el descriptor de archivo, el núcleo no se molestaría en limpiar.
fuente