Datos que Desaparecen en PostgreSQL

Posted by

Recientemente descubrí un problema interesante (y frustrante) al ejecutar PostgreSQL en Kubernetes. El problema técnicamente no es específico de Kubernetes, per se, pero ciertamente es fácil de encontrar en Kubernetes para los usuarios de la imagen oficial Docker PostgreSQL (y de muchas otras imágenes) montajando los volúmenes en otro lugar que no sea la ubicación tipica. Afortunadamente, no afectó nada en la producción, pero resultó que, incluso con una configuración de volumen para datos persistentes, fuera del contenedor… ¡reiniciar el contenedor hizo que mis datos desaparecieran!

Sí, sé que los contenedores necesitan volúmenes para almacenar datos fuera de su capa de escritura. De hecho, el problema está relacionado con cómo se debe montar un volumen con la imagen PostgreSQL. Después de buscar primero en el Dockerfile, descubrí que el problema está relacionado con el uso de la directiva VOLUME. Muchas, muchas personas se quejan del uso de la instrucción VOLUME en imágenes padres y por una buena razón.

La ubicación estándar para los datos en la imagen PostgreSQL es /var/lib/postgresql/data, pero el archivo README para la imagen tiene algunos consejos un poco confusos sobre cómo elegir una ubicación precisa. En mi Kubernetes StatefulSet, definí un volumen persistente y lo monté en /var/lib/postgresql, que parecía bastante inofensivo. Supuse que esto permitiría que el directorio de datos se creara, conservara, y transportara de forma segura a través de reinicios del Pod. Después de ejecutar la imagen durante algún tiempo, enumerar el contenido de este directorio se ve bien:

root@db-0:/var/lib/postgresql# ls
data

No hay nada más allí, y claramente PostgreSQL está creando y poniendo cosas allí como se esperaba. Sin embargo, resulta que usar este directorio padre para montar el volumen es importante, y mucho. Después de reiniciar este Pod durante un mantenimiento de rutina, ¡todos los datos desaparecieron! No solo eso, sino que la base de datos se reinicializó como si nunca tuviera datos. Aún más extraño, comprobar la marca de tiempo del directorio /var/lib/postgresql arrojó la fecha desde la primera vez que inicié el contenedor (como se esperaba). Al profundizar, vi que el volumen subyacente creado por Kubernetes en AWS era el mismo volumen, aún intacto. Entonces, el mismo volumen todavía está allí y montado, pero ya no tiene mis datos de PostgreSQL. ¿Cuál es el problema?

Resulta que usar la instrucción VOLUME dentro del Dockerfile tiene una consecuencia peculiar para escenarios como estos. Si no se adjunta ningún volumen precisamente donde se especifica en la instrucción VOLUME (Kubernetes o no), Docker crea lo que se llama un volumen anónimo en esa ubicación. Además, este comportamiento se exacerba en Kubernetes gracias a la distinción entre Pods y contenedores. Los volúmenes de Kubernetes se llevan a través del ciclo de vida del Pod, que comúnmente incluye el reemplazo de contenedores, mientras que los volúmenes creados por la directiva VOLUME son específicos del contenedor. Entonces, si bien creé un volumen para los datos de PostgreSQL y se montó correctamente en /var/lib/postgresql, Docker estaba creando un volumen separado, específico del contenedor, un nivel más profundo en /var/lib/postgresql/data.

¿Cuál es la lección aquí? Bueno, la idea general es no usar VOLUME en sus Dockerfiles; Es mucho menos flexible y no tiene una verdadera ventaja. En su lugar, proporcione variables de entorno que permitan especificar la ubicación del volumen de datos y que el usuario de su imagen decida cómo y dónde crear volúmenes. En este caso específico, donde se trata de una imagen proporcionada por el proveedor, asegúrese de leer detenidamente y comprender el Dockerfile utilizado para crearlo e intente atenerse a las ubicaciones y ejemplos proporcionados en su archivo README. Para la imagen PostgreSQL, terminé montando un volumen en /var/lib/postgresql/data e incluso especifiqué el PGDATA como un subdirectorio de este volumen como se recomienda en el archivo README.

Esto ciertamente no es un argumento en contra del uso de la imagen oficial de PostgreSQL u otras bases de datos en Docker/Kubernetes; Este es un argumento para profundizar y comprender cómo funcionan estas cosas. Ejecutar bases de datos de esta manera ofrece mucha flexibilidad, velocidad y puede ser muy robusto y confiable. Sin embargo, al igual que con todas las cosas, asegúrese de probar varios escenarios de falla para asegurarse de que todo funcione realmente como se esperaba. Obviamente, este problema fue muy frustrante, pero una vez que lo entendí, es bastante fácil de tener en cuenta.

¡Buena suerte Kuberneando!

Jonathan Gnagy es un arquitecto e ingeniero de infraestructura con una carrera de TI diversa. Se centra en las tecnologías del Internet y en la construcción de servicios web modernos. Jonathan tiene un amor por todas las cosas de código abierto, por el lenguaje de programación Ruby, y es un nerd matemático y científico de principio a fin. Por lo general, lo encontrarás blogueando en https://therubyist.org, pero es posible que haga apariciones especiales aquí de vez en cuando.

Leave a Reply

Tu dirección de correo electrónico no será publicada.

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.