Martes de Postgres #5: «PostgreSQL y Kubernetes. CI/CD. Automatización de pruebas»

Martes de Postgres #5: «PostgreSQL y Kubernetes. CI/CD. Automatización de pruebas»

A finales del año pasado, se llevó a cabo una nueva transmisión en vivo de la comunidad rusa de PostgreSQL #RuPostgres, durante la cual su cofundador Nikolai Samokhvalov habló con el director técnico de 'Flanta', Dmitry Stolyarov, sobre esta base de datos en el contexto de Kubernetes.

Publicamos la transcripción de la parte principal de esta discusión, y en el canal de YouTube de la comunidad se ha publicado la grabación completa:

Reproducir video

Bases de datos y Kubernetes

HS: Hoy no hablaremos sobre VACUUM y CHECKPOINT. Queremos hablar de Kubernetes. Sé que tienes muchos años de experiencia. He visto tus videos y algunos los he revisitado… Comencemos directamente: ¿por qué usar Postgres o MySQL en K8s?

DS: No hay una respuesta definitiva a esta pregunta, y no puede haberla. Pero, en general, se trata de simplicidad y conveniencia… potenciales. A todos les gustaría tener servicios gestionados.

HS: ¿Para que sea como RDS, solo que en casa?

DS: Sí, que sea como RDS, pero en cualquier lugar.

HS: 'En cualquier lugar' es un buen comentario. En las grandes empresas, todo está ubicado en diferentes lugares. Entonces, si se trata de una gran empresa, ¿por qué no optar por una solución lista para usar? Por ejemplo, Nutanix tiene sus propios desarrollos, otras empresas (VMware…) tienen lo mismo: 'RDS, pero en casa'.

DS: Pero hablamos de una implementación específica que funcionará solo en ciertas condiciones. Cuando se trata de Kubernetes, hay una gran variedad de infraestructuras (que pueden existir en K8s). En esencia, es un estándar para API en la nube…

HS: ¡Además, es gratis!

DS: Eso no es tan importante. La gratuidad importa a un segmento de mercado no muy grande. Lo que realmente importa es… Seguramente recuerdas la presentación 'Bases de datos y Kubernetes»?

HS: Sí.

DS: Entendí que se recibió de manera muy ambigua. Algunas personas pensaron que decía: '¡Vamos a llevar todas las bases de datos a Kubernetes!', mientras que otros creyeron que son horribles bicicletas. Yo quería realmente decir algo diferente: 'Miren lo que está pasando, cuáles son los problemas y cómo se pueden resolver. ¿Deberíamos llevar bases a Kubernetes ahora? ¿En producción? Bueno, solo si te gusta… hacer ciertas cosas. Pero para desarrollo, puedo decir que lo recomiendo. Para desarrollo, la dinamismo en la creación/eliminación de entornos es muy importante'.

HS: ¿Con desarrollo te refieres a todos los entornos que no son prod? Staging, QA…

DS: Si hablamos de los perf-stands, probablemente no, porque allí los requisitos son específicos. Si hablamos de casos especiales donde se necesita una base de datos muy grande en staging, tampoco sería el caso... Si es un entorno estático, de larga duración, ¿cuál es la ventaja de que la base esté ubicada en K8s?

HS: Ninguna. Pero, ¿dónde vemos entornos estáticos? El entorno estático quedó obsoleto ayer.

DS: Staging puede ser estático. Tenemos clientes...

HS: Sí, yo también tengo. Es un gran problema si tienes una base de 10 Tb y staging es de 200 Gb...

DS: ¡Tengo un caso muy interesante! En staging se encuentra la base de producción, en la que se realizan cambios. Y hay un botón diseñado: 'desplegar en producción'. Estos cambios — las deltas — se agregan (creo que simplemente se sincronizan a través de API) en producción. Esta es una opción muy exótica.

HS: He visto startups en el Valle que todavía están en RDS o incluso en Heroku — son historias de hace 2-3 años — y descargan un volcado en su laptop. Porque la base aún tiene solamente 80 Gb y hay espacio en la laptop. Luego compran discos adicionales para cada uno, para tener 3 bases y poder llevar a cabo diferentes desarrollos. También sucede así. También he visto que no temen copiar de prod a staging — depende mucho de la empresa. Pero también he visto que tienen mucho miedo, y que a menudo falta tiempo y manos. Pero antes de que pasemos a este tema, quiero escuchar sobre Kubernetes. ¿Entiendo correctamente que todavía no hay nadie en prod?

DS: Tenemos algunas bases pequeñas en prod. Hablamos de volúmenes de decenas de gigabytes y servicios no críticos, para los cuales daba pereza hacer réplicas (y tampoco había necesidad). Y suponiendo que bajo Kubernetes hay un almacenamiento adecuado. Esta base funcionaba en una máquina virtual — condicionalmente en VMware, sobre un sistema de almacenamiento. La colocamos en PV y ahora podemos trasladarla de máquina a máquina.

HS: Bases de ese tamaño, hasta 100 Gb, en buenos discos y con una buena red se pueden extender en unos minutos, ¿verdad? Una velocidad de 1 Gb por segundo ya no es una excentricidad.

DS: Sí, para una operación lineal no es un problema.

HS: Ok, sobre prod solo debemos pensar. Pero si consideramos Kubernetes para entornos no prod, ¿cómo proceder? Veo que en Zalando hacen un operador, en Crunchy están desarrollando, hay otras opciones. Y hay OnGres — es nuestro buen amigo Alvaro de España: ellos hacen no solo un operador, sino todo un distribuidor (StackGres), en el que además de Postgres también decidieron incluir respaldo, el proxy Envoy…

DS: ¿Envoy para qué? ¿Para equilibrar precisamente el tráfico de Postgres?

HS: Sí. Es decir, lo ven así: si tomas una distribución de Linux y el núcleo, el PostgreSQL normal sería el núcleo, y ellos quieren crear una distribución que sea amigable con la nube y que funcione en Kubernetes. Están integrando componentes (respaldo, etc.) y ajustando para que funcionen bien.

DS: ¡Muy bien! En esencia, es software para construir su propio Postgres gestionado.

HS: Las distribuciones de Linux tienen problemas eternos: cómo hacer drivers para que todo el hardware sea soportado. Y ellos tienen la idea de que funcionarán en Kubernetes. Sé que en el operador de Zalando recientemente vimos una dependencia de AWS y eso no es muy bueno. No debería haber una dependencia de una infraestructura concreta, ¿cuál sería entonces el sentido?

DS: No sé en qué situación exactamente se ató Zalando, pero en Kubernetes actualmente el almacenamiento está hecho de tal manera que no se puede hacer un respaldo de disco de forma genérica. Recientemente en el estándar — en la última versión especificación CSI — se hizo posible la creación de instantáneas, pero ¿dónde se ha implementado? Honestamente, todavía está bastante crudo… Estamos probando CSI sobre AWS, GCE, Azure, vSphere, pero en cuanto comienzas a usarlo, se hace evidente que aún no está listo.

HS: Por eso a veces hay que depender de la infraestructura. Creo que esto sigue siendo una fase temprana — problemas de crecimiento. La pregunta: ¿qué aconsejarías a los novatos que quieren probar PgSQL en K8s? ¿Qué operador, tal vez?

DS: El problema es que Postgres para nosotros es solo el 3%. Tenemos también una lista muy grande de otro software en Kubernetes, ni siquiera voy a enumerar todo. Por ejemplo, Elasticsearch. Hay un montón de operadores: algunos se desarrollan activamente, otros no. Para nosotros hemos establecido requisitos sobre lo que debe tener un operador para que lo tomemos en serio. En un operador específicamente para Kubernetes — no en 'un operador para hacer algo en las condiciones de Amazon'… De hecho, usamos de manera bastante masiva (= casi todos los clientes) un solo operador — para Redis (pronto publicaremos un artículo sobre él).

HS: ¿Y para MySQL tampoco hay? Sé que Percona… ya que ahora se ocupan de MySQL, MongoDB y Postgres, deberían desarrollar algo universal: para todas las bases, para todos los proveedores de nube.

DS: No hemos tenido tiempo de mirar los operadores para MySQL. Ahora mismo no es nuestro principal enfoque. MySQL funciona bien en modo standalone. ¿Para qué un operador si puedes simplemente lanzar la base de datos...? Se puede iniciar un contenedor Docker con Postgres, o hacerlo de forma sencilla.

HS: También hubo preguntas al respecto. ¿Totalmente sin operador?

DS: Sí, al 100% tenemos PostgreSQL ejecutándose sin operador. Por ahora es así. Usamos activamente el operador para Prometheus, para Redis. Planeamos encontrar un operador para Elasticsearch, ya que es el que más urgencia tiene, porque queremos implementarlo en Kubernetes en el 100% de los casos. También queremos que MongoDB siempre se ejecute en Kubernetes. Aparecen ciertas necesidades, y tenemos la sensación de que en estos casos se puede hacer algo. Pero en cuanto a Postgres, ni siquiera lo hemos mirado. Por supuesto, sabemos de la existencia de diferentes opciones, pero en la práctica, tenemos standalone.

Base de datos para pruebas en Kubernetes

HS: Pasemos al tema de las pruebas. ¿Cómo desplegar cambios en la base de datos desde la perspectiva de DevOps? Hay microservicios, muchas bases, siempre hay algo que cambia. ¿Cómo asegurar un CI/CD adecuado para que desde la perspectiva de la base de datos todo esté en orden? ¿Cuál es tu enfoque?

DS: No puede haber una única respuesta. Hay varios parámetros. El primero es el tamaño de la base de datos que queremos desplegar. Tú mismo mencionaste que las empresas tienen diferentes enfoques sobre tener una copia de la base de datos de producción en dev y stage.

HS: Y en el contexto del GDPR, creo que son cada vez más cautelosos... Puedo decir que en Europa ya han comenzado a aplicar multas.

DS: Pero a menudo se puede escribir un software que haga un volcado de producción y lo ofusque. Se obtienen datos de producción (snapshot, volcado, copia binaria...), pero son anonimizados. En su lugar, pueden haber scripts de generación: pueden ser fixtures o simplemente un script que genere una gran base de datos. El problema es: ¿cuánto tiempo se necesita para crear la imagen base? ¿Y cuánto tiempo lleva desplegarla en el entorno adecuado?

: Hemos llegado a un esquema: si el cliente tiene un conjunto de datos de fixture (versión mínima de la base), por defecto los usamos. Si se trata de entornos de revisión, cuando creamos una rama, se despliega una instancia de la aplicación — ahí desplegamos una base de datos pequeña. Pero resultó bien también. una variante, cuando desde producción hacemos un volcado una vez al día (de noche) y construimos en base a él un contenedor Docker con PostgreSQL y MySQL con estos datos cargados. Si necesitamos desplegar esta imagen 50 veces, se hace de manera bastante simple y rápida.

HS: ¿Simplemente copiando?

DS: Los datos se almacenan directamente en la imagen de Docker. Es decir, tenemos una imagen lista, de 100 GB. Gracias a las capas en Docker podemos desplegar rápidamente esta imagen el número necesario de veces. Es un método rudimentario, pero funciona bastante bien.

HS: Luego, cuando estás probando, ¿cambia directamente dentro de Docker, verdad? Copy-on-write dentro de Docker — eliminamos y reiniciamos, todo bien. ¡Genial! ¿Y ya lo estás utilizando plenamente?

DS: Desde hace tiempo.

HS: Nos dedicamos a cosas muy similares. Solo que nosotros no utilizamos el copy-on-write de Docker, sino alguna otra cosa.

DS: No es genérico. La versión de Docker funciona en todas partes.

HS: En teoría, sí. Pero también tenemos módulos, se pueden hacer diferentes módulos y trabajar con distintos sistemas de archivos. Aquí hay un punto importante. Desde la perspectiva de Postgres, vemos esto de manera diferente. Ahora miré desde el lado de Docker y vi que todo funciona. Pero si la base es enorme, por ejemplo, 1 TB, entonces ya es un proceso largo: operativas nocturnas y meter todo en Docker... ¿Y si hay 5 TB que meter en Docker... o todo está bien?

DS: ¿Cuál es la diferencia? Son blobs, solo bits y bytes.

HS: La diferencia es: ¿lo haces a través de volcado y restauración?

DS: No necesariamente. Los métodos de generación de esta imagen pueden ser variados.

HS: Para algunos clientes hemos hecho que, en lugar de generar regularmente la imagen base, la mantenemos constantemente actualizada. En esencia, es una réplica, pero los datos no provienen directamente del maestro, sino a través de un archivo de respaldo. Un archivo binario, donde los WAL se combinan todos los días, allí también se realizan las copias de seguridad... Estos WAL luego llegan — con un pequeño retraso (literalmente 1-2 segundos) — a la imagen base. Desde esa imagen clonamos de cualquier manera — actualmente por defecto tenemos ZFS.

DS: Pero con ZFS estás limitado a un nodo.

HS: Sí. Pero ZFS también tiene el mágico send: con él puedes enviar un snapshot e incluso (esto aún no lo he probado mucho, pero...) puedes enviar la delta entre dos PGDATA. En realidad, tenemos otra herramienta que no hemos considerado mucho para tales tareas. En PostgreSQL existe pg_rewind, que funciona como un «rsync» inteligente, omitiendo mucho de lo que no se necesita ver, ya que realmente no ha cambiado nada. Podemos hacer una rápida sincronización entre dos servidores y retroceder de la misma manera.

Así que intentamos crear una herramienta, desde el lado más DBA, que permita hacer lo mismo de lo que hablabas: tenemos una base de datos, pero queremos probar algo 50 veces, casi simultáneamente.

DS: 50 veces significa que necesitas pedir 50 instancias Spot.

HS: No, lo hacemos todo en una máquina.

DS: Pero, ¿cómo desplegarás 50 veces si esta única base de datos, digamos, es de un terabyte? Probablemente necesite, digamos, 256 GB de RAM.

HS: Sí, a veces se necesita mucha memoria, eso es normal. Pero un ejemplo de la vida real. En una máquina de producción hay 96 núcleos y 600 GB. Para la base de datos se utilizan 32 núcleos (incluso a veces 16 núcleos ahora) y de 100 a 120 GB de memoria.

DS: ¿Y ahí caben 50 copias?

HS: La copia es una, luego funciona copy-on-write (de ZFS)… Te contaré más en detalle.

Por ejemplo, tenemos una base de datos de 10 TB. Hicimos un disco para ella, ZFS compressó su tamaño en un 30-40%. Como no hacemos pruebas de carga, no nos importa el tiempo de respuesta exacto: si es dos veces más lento, está bien.

Le damos a los programadores, QA, DBA, etc., la posibilidad de hacer pruebas en 1-2 hilos. Por ejemplo, pueden iniciar alguna migración. No requiere 10 núcleos de inmediato; le necesita 1 backend de Postgres, 1 núcleo. La migración se iniciará, puede que autovacuum también se inicie la segunda, entonces se usará el segundo núcleo. Tenemos asignados de 16 a 32 núcleos, así que 10 personas pueden trabajar simultáneamente, no hay problemas.

Dado que físicamente PGDATA son iguales, resulta que realmente estamos engañando a Postgres. La cuestión es esta: se inician, por ejemplo, 10 Postgres al mismo tiempo. ¿Cuál es el problema normalmente? Se establece shared_buffers, digamos, en un 25%. Por lo tanto, son 200 GB. No puedes iniciar más de tres así, porque se te acabará la memoria.

Pero en algún momento nos dimos cuenta de que eso no era necesario: establecemos shared_buffers en 2 GB. PostgreSQL tiene effective_cache_size, y en realidad solo eso influye en los planes. Lo configuramos en 0.5 TB. Y no importa que en realidad no existan: él construye planes como si existieran.

Por lo tanto, cuando probamos alguna migración, podemos reunir todos los planes: veremos cómo ocurrirá en producción. Los segundos serán diferentes (más lentos), pero los datos que realmente leemos y los propios planes (los JOIN y similares) resultan exactamente iguales que en producción. Y, al mismo tiempo, se pueden ejecutar múltiples verificaciones de este tipo en una sola máquina.

DS: ¿No crees que aquí hay varios problemas? Primero: es una solución que solo funciona en PostgreSQL. Este enfoque es muy específico, no es genérico. Segundo: Kubernetes (y todo a donde van las tecnologías en la nube) implica múltiples nodos, y estos nodos son efímeros. En tu caso, es un nodo stateful, persistente. Estas cosas me generan contradicciones.

HS: Primero, estoy de acuerdo, es una historia puramente de Postgres. Creo que si tenemos alguna IO directa y un buffer pool casi para toda la memoria, ese enfoque no será adecuado: los planes serán diferentes. Pero por ahora solo trabajamos con Postgres y no pensamos en otros.

Sobre Kubernetes. Tú mismo lo cuentas por todas partes, que nuestra base de datos es persistente. Si una instancia falla, lo principal es conservar el disco. También tenemos toda la plataforma en Kubernetes, y el componente con Postgres es separado (aunque alguna vez estará allí). Por lo tanto, es así: la instancia falla, pero hemos conservado su PV y simplemente lo conectamos a otra instancia (nueva), como si nada hubiera pasado.

DS: Desde mi punto de vista, creamos pods en Kubernetes. K8s es elástico: los nodos se provisionan según sea necesario. La tarea es simplemente crear un pod y decirle que necesita X recursos, y después K8s se encargará. Pero el soporte para almacenamiento en Kubernetes sigue siendo inestable: en 1.16, en 1.17 (esta versión salió hace semanas ) estas características se vuelven solo beta.

Pasará medio año o un año: se volverá más o menos estable, o al menos se anunciará como tal. Entonces la posibilidad de instantáneas y redimensionamiento resolverá completamente tu tarea. Porque tienes una base de datos. Sí, puede que no sea muy rápida, pero la velocidad depende de lo que hay "bajo el capó", porque algunas implementaciones son capaces de copiar y copiar-en-escritura a nivel del subsistema de disco.

HS: Aquí también necesitamos que todos los motores (Amazon, Google…) comiencen a soportar esta versión, eso también lleva tiempo.

DS: Por ahora no los usamos. Usamos el nuestro.

Desarrollo local en Kubernetes

HS: ¿Te has encontrado con esa necesidad de levantar todos los pod en una sola máquina y hacer una pequeña prueba? Para obtener rápidamente una prueba de concepto y ver si la aplicación funciona en Kubernetes, sin dedicarle un montón de máquinas. Hay Minikube, ¿verdad?

DS: Creo que este caso — desplegar en un solo nodo — se refiere exclusivamente al desarrollo local. O a algunas manifestaciones de ese patrón. Hay Minikube, hay k3s, KIND. Estamos avanzando hacia el uso de Kubernetes en Docker. Ya hemos comenzado a trabajar con ello para pruebas.

HS: Antes pensaba que era un intento de empaquetar todos los pod en una sola imagen de Docker. Pero resultó ser algo muy diferente. Aún hay contenedores separados, pod separados — simplemente en Docker.

DS: Sí. Y hay una imitación bastante divertida hecha, pero la idea es esta… Tenemos una herramienta para el despliegue — werf. Queremos hacer un modo — condicionalmente werf up: «Levanta un Kubernetes local para mí». Y luego ejecutar un werf follow. Entonces, el desarrollador podrá editar en el IDE, mientras que en el sistema hay un proceso en ejecución que ve los cambios y reconstruye las imágenes, redistribuyéndolas en el K8s local. Así queremos intentar resolver el problema del desarrollo local.

Instantáneas y clonación de bases de datos en el contexto de K8s

HS: Si volvemos al copy-on-write. He notado que en la nube también hay instantáneas. Funcionan de forma diferente. Por ejemplo, en GCP: tienes una instancia de múltiples terabytes en la costa este de EE. UU. Haces instantáneas periódicamente. Levantas una copia del disco desde la instantánea en la costa oeste — en unos minutos ya está todo listo, funciona muy rápido, solo hay que llenar la caché en memoria. Pero esos clones (instantáneas) son para 'aprovisionar' un nuevo volumen. Es genial cuando necesitas crear muchas instancias.

Pero para pruebas, me parece que las instantáneas de las que hablas en Docker o de las que hablo en ZFS, btrfs e incluso LVM… — permiten, precisamente, no generar nuevos datos realmente en una sola máquina. En la nube hay que pagar por ellos cada vez y esperar ya no segundos, sino minutos (y en caso de lazy load, posiblemente, horas).

En lugar de eso, puedes obtener esos datos en uno o dos segundos, ejecutar pruebas y descartarlas. Estas instantáneas resuelven diferentes tareas. En el primer caso — para escalar y obtener nuevas réplicas, y en el segundo — para pruebas.

DS: No estoy de acuerdo. Hacer una clonación completa de volúmenes es una tarea de la nube. No he mirado su implementación, pero sé cómo lo hacemos nosotros en hardware. Tenemos Ceph, y se puede indicar a cualquier volumen físico (RBD) clone y recibir en decenas de milisegundos un segundo volumen con las mismas características, IOPSy similares. Hay que entender que internamente hay un astuto copy-on-write. ¿Por qué la nube no lo hace igual? Estoy seguro de que de una forma u otra están tratando de hacerlo.

HS: Pero aún les llevará segundos, decenas de segundos, levantar una instancia, llevar ahí Docker, etc.

DS: ¿Por qué necesariamente levantar toda una instancia? Nosotros tenemos instancias de 32 núcleos, de 16... y en ella cabe cierta cantidad, por ejemplo, cuatro. Cuando pedimos la quinta, ya se levantará una instancia y luego se eliminará.

HS: Sí, es interesante, en Kubernetes es otra historia. Nuestra base de datos no está en K8s, y tenemos una instancia. Sin embargo, para clonar una base de datos de varios terabytes no se tarda más de dos segundos.

DS: Eso es genial. Pero mi mensaje original es que esto no es una solución genérica. Sí, es impresionante, pero solo sirve para Postgres y solo en un nodo.

HS: No solo es para Postgres: estos planes, como describí, funcionarán solo en él. Pero si no nos preocupamos por los planes y solo necesitamos todos los datos para pruebas funcionales, entonces esto sirve para cualquier SGBD.

DS: Hace muchos años hicimos algo parecido con instantáneas de LVM. Es un clásico. Este enfoque se utilizaba muy activamente. Simplemente, los nodos con estado son un problema. Porque no se pueden caer, siempre hay que recordar de ellos...

HS: ¿No ves aquí alguna posibilidad de hibridación? Supongamos que el estado es un pod, funciona para varias personas (muchos testers). Tenemos un volumen, pero gracias al sistema de archivos, los clones son locales. Si el pod falla, el disco permanece; se levantará el pod, leerá la información sobre todos los clones, lo levantará todo de nuevo y dirá: «Aquí están sus clones en estos puertos, sigan trabajando con ellos».

DS: Técnicamente, esto significa que dentro de Kubernetes es un solo pod, dentro del cual ejecutamos muchos Postgres.

HS: Sí. Tiene un límite: supongamos que no más de 10 personas trabajan con él al mismo tiempo. Si se necesitan 20, levantaremos un segundo pod de este tipo. Es completamente posible clonarlo, obteniendo un segundo volumen completo, en el cual habrá 10 clones "delgados" iguales. ¿No ves esta posibilidad?

DS: Debes agregar aquí preguntas de seguridad. Esta forma de organización implica que este pod tiene altos privilegios (capabilities), porque puede realizar operaciones no estándar en el sistema de archivos... Pero repito: creo que a medio plazo en Kubernetes se solucionará el almacenamiento, en la nube se resolverá toda la historia con los volúmenes — todo funcionará «simplemente». Habrá redimensionamiento, clonación... Hay un volumen — decimos: «Crea uno nuevo basado en ese», — y en un segundo y medio obtenemos lo que necesitamos.

HS: No creo que sea posible en un segundo y medio para varios terabytes. En Ceph lo haces tú mismo, pero hablas de la nube. Ve a la nube, haz un clón de un volumen EBS de varios terabytes en EC2 y observa qué rendimiento obtienes. No tomará unos segundos. Me interesa mucho cuándo alcanzarán ese indicador. Entiendo a lo que te refieres, pero me permitiré no estar de acuerdo.

DS: Está bien, pero dije que a medio plazo, no a corto plazo. En un par de años.

Sobre el operador para PostgreSQL de Zalando

A mitad de esta reunión también se unió Alexey Klyukin, un exdesarrollador de Zalando, quien habló sobre la historia del operador PostgreSQL:

Es genial que se haya abordado este tema: tanto Postgres como Kubernetes. Cuando comenzamos a trabajarlo en Zalando en 2017, era un tema que todos querían, pero nadie hacía. Todos ya contaban con Kubernetes, pero cuando se preguntaba cómo manejar las bases de datos, incluso personas como Kelsey Hightower, que predicaban sobre K8s, decían algo como esto:

«Ve a los servicios administrados y utilízalos, no ejecutes bases de datos en Kubernetes. De lo contrario, tu K8s decidirá, por ejemplo, hacer una actualización, apagará todos los nodos y tus datos se irán lejos, muy lejos».

Decidimos crear un operador que, en contra de ese consejo, ejecutaría bases de datos Postgres en Kubernetes. Y teníamos una buena base — Patroni. Es un failover automático para PostgreSQL, diseñado correctamente, es decir, que utiliza etcd, consul o ZooKeeper como almacén de información sobre el clúster. Ese almacén de datos que proporcionará a todos los que pregunten, por ejemplo, quién es el líder actualmente, la misma información — a pesar de que todo está distribuido — para evitar que haya un split brain. Además, teníamos un imagen de Docker para ello.

En general, la necesidad de auto failover surgió en la empresa después de migrar de un centro de datos interno a la nube. La nube se basaba en una solución PaaS (Plataforma como Servicio) propia. Era de código abierto, pero para implementarla era necesario esforzarse bastante. Se llamaba STUPS.

Inicialmente no había Kubernetes. Más bien, cuando se implementó la solución propia, K8s ya existía, pero era tan inestable que no servía para producción. Creo que fue en 2015 o 2016. Para 2017, Kubernetes había madurado un poco, y se hizo necesario migrar allí.

Y ya teníamos un contenedor Docker. Había una PaaS que utilizaba Docker. ¿Por qué no probar K8s? ¿Por qué no escribir nuestro propio operador? Murat Kabilov, que vino a nosotros de Avito, comenzó esto como un proyecto por iniciativa propia: 'jugar un poco', y el proyecto 'despegó'.

Pero en realidad quería hablar sobre AWS. ¿Por qué había código históricamente relacionado con AWS?

Cuando lanzas algo en Kubernetes, necesitas entender que K8s es un trabajo en progreso. Está en constante desarrollo, mejora y a veces incluso se rompe. Debes estar atento a todos los cambios en Kubernetes y estar preparado para sumergirte en él y aprender cómo funciona en detalle, posiblemente más de lo que te gustaría. Esto aplica, en principio, a cualquier plataforma donde ejecutas tus bases de datos...

Así que, cuando hicimos el operador, teníamos Postgres que trabajaba con un volumen externo (en este caso, EBS, ya que estábamos en AWS). La base de datos creció y, en algún momento, fue necesario hacer un cambio de tamaño: por ejemplo, el tamaño inicial de EBS era de 100 TB, la base llegó a ese tamaño y ahora queríamos hacer EBS de 200 TB. ¿Cómo? Supongamos que podríamos hacer un volcado/restauración en una nueva instancia, pero eso tarda y causa inactividad.

Por lo tanto, queríamos un cambio de tamaño que aumentara la partición de EBS y luego le dijera a la sistema de archivos que utilizara el nuevo espacio. Y lo hicimos, pero en ese momento Kubernetes no tenía ninguna API para la operación de cambio de tamaño. Dado que estábamos trabajando en AWS, escribimos código para su API.

Nada impide hacer lo mismo para otras plataformas. En el operador no hay ninguna dependencia de que solo se pueda ejecutar en AWS, y que no funcione en todo lo demás. En resumen, es un proyecto de código abierto: si alguien quiere acelerar la aparición de un nuevo uso de la API, es bienvenido. Hay GitHub, los pull requests — el equipo de Zalando intenta reaccionar rápidamente a ellos y promover al operador. Hasta donde sé, el proyecto participó en Google Summer of Code y otras iniciativas similares. Zalando está trabajando muy activamente en ello.

P.D. ¡Bonus!

Si te interesa el tema de PostgreSQL y Kubernetes, también queremos señalar que la semana pasada tuvo lugar el próximo Postgres Martes, donde Nikolay habló con Alexander Kukushkin de Zalando. El video está disponible aquí.

P.P.D.

También puedes leer en nuestro blog:

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster