Una breve descripción general de las declaraciones de PostgreSQL para Kubernetes, nuestras elecciones y experiencia

Una breve descripción general de las declaraciones de PostgreSQL para Kubernetes, nuestras elecciones y experiencia

Cada vez más, los clientes reciben las siguientes solicitudes: “Lo queremos como Amazon RDS, pero más barato”; "Lo queremos como RDS, pero en todas partes y en cualquier infraestructura". Para implementar una solución administrada de este tipo en Kubernetes, analizamos el estado actual de los operadores más populares para PostgreSQL (Stolon, operadores de Crunchy Data y Zalando) e hicimos nuestra elección.

Este artículo es nuestra experiencia tanto desde un punto de vista teórico (una revisión de soluciones) como desde un punto de vista práctico (qué se eligió y qué resultó de ello). Pero primero, definamos cuáles son los requisitos generales para un potencial reemplazo de RDS...

¿Qué es el RDS?

Cuando la gente habla de RDS, según nuestra experiencia, se refiere a un servicio DBMS administrado que:

  1. fácil de configurar;
  2. tiene la capacidad de trabajar con instantáneas y recuperarse de ellas (preferiblemente con soporte PITR);
  3. le permite crear topologías maestro-esclavo;
  4. tiene una rica lista de extensiones;
  5. proporciona auditoría y gestión de usuarios/acceso.

En términos generales, los enfoques para implementar la tarea en cuestión pueden ser muy diferentes, pero el camino con Ansible condicional no está cerca de nosotros. (Los colegas de 2GIS llegaron a una conclusión similar como resultado de su intento cree una "Herramienta de implementación rápida de clústeres de conmutación por error basada en Postgres".)

Los operadores son un enfoque común para resolver problemas similares en el ecosistema de Kubernetes. El director técnico de “Flanta” ya ha hablado con más detalle de ellos en relación a las bases de datos lanzadas dentro de Kubernetes. destilarEn uno de sus informes.

NB: Para crear rápidamente operadores simples, le recomendamos que preste atención a nuestra utilidad de código abierto. operador de shell. Al usarlo, puede hacerlo sin conocimientos de Go, pero de formas más familiares para los administradores del sistema: en Bash, Python, etc.

Existen varios operadores K8 populares para PostgreSQL:

  • estolón;
  • Operador PostgreSQL de datos crujientes;
  • Operador Zalando Postgres.

Veámoslos más de cerca.

selección de operador

Además de las características importantes ya mencionadas anteriormente, nosotros, como ingenieros de operaciones de infraestructura de Kubernetes, también esperábamos lo siguiente de los operadores:

  • implementar desde Git y con Recursos personalizados;
  • soporte antiafinidad de pods;
  • instalar afinidad de nodos o selector de nodos;
  • instalación de tolerancias;
  • disponibilidad de opciones de ajuste;
  • tecnologías comprensibles e incluso comandos.

Sin entrar en detalles sobre cada uno de los puntos (pregunte en los comentarios si aún tiene dudas al respecto después de leer el artículo completo), señalaré en general que estos parámetros son necesarios para describir con mayor precisión la especialización de los nodos del clúster para poder pídalos para aplicaciones específicas. De esta manera podemos conseguir el equilibrio óptimo en términos de rendimiento y coste.

Ahora, a los propios operadores de PostgreSQL.

1. estolón

Estolón de la empresa italiana Sorint.lab en informe ya mencionado fue considerado como una especie de estándar entre los operadores del DBMS. Este es un proyecto bastante antiguo: su primer lanzamiento público tuvo lugar en noviembre de 2015(!), y el repositorio de GitHub cuenta con casi 3000 estrellas y más de 40 contribuyentes.

De hecho, Stolon es un excelente ejemplo de arquitectura reflexiva:

Una breve descripción general de las declaraciones de PostgreSQL para Kubernetes, nuestras elecciones y experiencia
El dispositivo de este operador se puede encontrar en detalle en el informe o documentación del proyecto. En general, basta decir que puede hacer todo lo descrito: conmutación por error, servidores proxy para un acceso transparente al cliente, copias de seguridad... Además, los servidores proxy proporcionan acceso a través de un servicio de punto final, a diferencia de las otras dos soluciones que se analizan a continuación (cada uno tiene dos servicios para acceder a la base).

Sin embargo, estolón sin recursos personalizados, razón por la cual no se puede implementar de tal manera que sea fácil y rápido – “como pan caliente” – crear instancias de DBMS en Kubernetes. La gestión se realiza a través de la utilidad. stolonctl, la implementación se realiza a través del gráfico Helm y los personalizados se definen y especifican en ConfigMap.

Por un lado, resulta que el operador no es realmente un operador (porque no utiliza CRD). Pero por otro lado, es un sistema flexible que te permite configurar los recursos en K8 como quieras.

En resumen, a nosotros personalmente no nos pareció la mejor manera de iniciar un gráfico separado para cada base de datos. Entonces empezamos a buscar alternativas.

2. Operador PostgreSQL de datos crujientes

Operador de Crunchy Data, una joven startup estadounidense, parecía una alternativa lógica. Su historia pública comienza con el primer lanzamiento en marzo de 2017; desde entonces, el repositorio de GitHub ha recibido poco menos de 1300 estrellas y más de 50 contribuyentes. Se probó que la última versión de septiembre funciona con Kubernetes 1.15-1.18, OpenShift 3.11+ y 4.4+, GKE y VMware Enterprise PKS 1.3+.

La arquitectura del operador Crunchy Data PostgreSQL también cumple con los requisitos establecidos:

Una breve descripción general de las declaraciones de PostgreSQL para Kubernetes, nuestras elecciones y experiencia

La gestión es a través de la utilidad. pgo, sin embargo, a su vez genera recursos personalizados para Kubernetes. Por lo tanto, el operador nos complació como usuarios potenciales:

  • hay control a través de CRD;
  • cómoda gestión de usuarios (también mediante CRD);
  • integración con otros componentes Suite de contenedores de datos crujientes - una colección especializada de imágenes de contenedores para PostgreSQL y utilidades para trabajar con él (incluidas pgBackRest, pgAudit, extensiones de contrib, etc.).

Sin embargo, los intentos de empezar a utilizar el operador de Crunchy Data revelaron varios problemas:

  • No había posibilidad de tolerancias: solo se proporciona nodeSelector.
  • Los pods creados formaron parte de la implementación, a pesar de que estábamos implementando una aplicación con estado. A diferencia de los StatefulSets, las implementaciones no pueden crear discos.

El último fallo lleva a momentos divertidos: en el entorno de prueba logramos ejecutar 3 réplicas con un disco almacenamiento local, por lo que el operador informó que 3 réplicas estaban funcionando (aunque no fue así).

Otra característica de este operador es su integración lista para usar con varios sistemas auxiliares. Por ejemplo, es fácil instalar pgAdmin y pgBounce, y en documentación Se consideran Grafana y Prometheus preconfigurados. En una reciente versión 4.5.0-beta1 integración mejorada con el proyecto señalada por separado pgMonitor, gracias al cual el operador ofrece una visualización clara de las métricas de PgSQL listas para usar.

Sin embargo, la extraña elección de los recursos generados por Kubernetes nos llevó a encontrar una solución diferente.

3. Operador de Zalando Postgres

Conocemos los productos Zalando desde hace mucho tiempo: tenemos experiencia usando Zalenium y, por supuesto, hemos probado patrón es su popular solución HA para PostgreSQL. Sobre el enfoque de la empresa para la creación. Operador PostgreSQL dijo uno de sus autores, Alexei Klyukin, al aire Postgres-Martes #5y nos gustó.

Esta es la solución más reciente analizada en el artículo: el primer lanzamiento tuvo lugar en agosto de 2018. Sin embargo, a pesar del pequeño número de lanzamientos formales, el proyecto ha recorrido un largo camino, superando ya la popularidad de la solución de Crunchy Data con más de 1300 estrellas en GitHub y el número máximo de contribuyentes (70+).

“Debajo del capó” de este operador se utilizan soluciones probadas en el tiempo:

  • Patroni y espilo Para conducir,
  • WAL-E - para copias de seguridad,
  • PgBouncer - como grupo de conexiones.

Así se presenta la arquitectura del operador de Zalando:

Una breve descripción general de las declaraciones de PostgreSQL para Kubernetes, nuestras elecciones y experiencia

El operador se administra completamente a través de Recursos personalizados, crea automáticamente un StatefulSet a partir de contenedores, que luego se puede personalizar agregando varios sidecars al pod. Todo esto es una ventaja significativa en comparación con el operador de Crunchy Data.

Dado que elegimos la solución de Zalando entre las 3 opciones consideradas, a continuación se presentará una descripción más detallada de sus capacidades, junto con la práctica de aplicación.

Practica con el operador Postgres de Zalando

La implementación del operador es muy simple: simplemente descargue la versión actual de GitHub y aplique los archivos YAML del directorio. manifiestos. Alternativamente, también puedes usar OperadorHub.

Después de la instalación, debes cuidar la configuración. almacenamiento para registros y copias de seguridad. Se hace a través de ConfigMap. postgres-operator en el espacio de nombres donde configuró el operador. Con los repositorios configurados, puede implementar su primer clúster de PostgreSQL.

Por ejemplo, nuestra implementación estándar se ve así:

apiVersion: acid.zalan.do/v1
kind: postgresql
metadata:
 name: staging-db
spec:
 numberOfInstances: 3
 patroni:
   synchronous_mode: true
 postgresql:
   version: "12"
 resources:
   limits:
     cpu: 100m
     memory: 1Gi
   requests:
     cpu: 100m
     memory: 1Gi
 sidecars:
 - env:
   - name: DATA_SOURCE_URI
     value: 127.0.0.1:5432
   - name: DATA_SOURCE_PASS
     valueFrom:
       secretKeyRef:
         key: password
         name: postgres.staging-db.credentials
   - name: DATA_SOURCE_USER
     value: postgres
   image: wrouesnel/postgres_exporter
   name: prometheus-exporter
   resources:
     limits:
       cpu: 500m
       memory: 100Mi
     requests:
       cpu: 100m
       memory: 100Mi
 teamId: staging
 volume:
   size: 2Gi

Este manifiesto implementa un grupo de 3 instancias con un sidecar del formulario postgres_exportador, del cual recopilamos métricas de la aplicación. Como puede ver, todo es muy simple y, si lo desea, puede crear un número literalmente ilimitado de grupos.

Vale la pena prestar atención panel de administración web - operador-ui-postgres. Viene con el operador y permite crear y eliminar clusters, así como trabajar con copias de seguridad que realiza el operador.

Una breve descripción general de las declaraciones de PostgreSQL para Kubernetes, nuestras elecciones y experiencia
Lista de clústeres de PostgreSQL

Una breve descripción general de las declaraciones de PostgreSQL para Kubernetes, nuestras elecciones y experiencia
Gestión de copias de seguridad

Otra característica interesante es el soporte. API de Teams. Este mecanismo crea automáticamente roles en PostgreSQL, según la lista resultante de nombres de usuario. Después de eso, la API le permite devolver una lista de usuarios para los cuales se crean roles automáticamente.

Problemas y soluciones

Sin embargo, el uso del operador pronto reveló varios inconvenientes importantes:

  1. falta de soporte para nodeSelector;
  2. incapacidad para desactivar las copias de seguridad;
  3. cuando se utiliza la función de crear bases, los privilegios predeterminados no aparecen;
  4. periódicamente no hay suficiente documentación o está desactualizada.

Afortunadamente, muchos de ellos pueden solucionarse. Empecemos por el final: problemas con documentación.

Lo más probable es que se encuentre con el hecho de que no siempre está claro cómo registrar una copia de seguridad y cómo conectar un depósito de copia de seguridad a la interfaz de usuario del operador. Esto se menciona en la documentación de pasada, pero la descripción real está en PR:

  1. necesitas guardar un secreto;
  2. pasarlo al operador como parámetro pod_environment_secret_name en CRD con configuración del operador o en ConfigMap (dependiendo de cómo elija instalar el operador).

Sin embargo, como resultó, por el momento esto no es posible. Por eso recogimos tu versión del operador con algunos desarrollos adicionales de terceros. Para obtener más información al respecto, consulte a continuación.

Si pasa parámetros al operador para realizar una copia de seguridad, a saber: wal_s3_bucket y claves de acceso en AWS S3, luego hará una copia de seguridad de todo: no sólo se basa en la producción, sino también en la puesta en escena. Esto no nos convenía.

En la descripción de los parámetros de Spilo, que es el contenedor Docker básico para PgSQL cuando se usa el operador, resultó que se puede pasar un parámetro WAL_S3_BUCKET vacío, deshabilitando así las copias de seguridad. Además, con gran alegría encontré relaciones públicas listas, que aceptamos inmediatamente en nuestra bifurcación. Ahora es bastante fácil agregar enableWALArchiving: false a un recurso de clúster de PostgreSQL.

Sí, existía la oportunidad de hacerlo de manera diferente ejecutando 2 operadores: uno para la puesta en escena (sin respaldos) y el segundo para la producción. Pero pudimos arreglárnoslas con uno.

Ok, aprendimos cómo transferir el acceso a las bases de datos para S3 y las copias de seguridad comenzaron a almacenarse. ¿Cómo hacer que las páginas de respaldo funcionen en la interfaz de usuario del operador?

Una breve descripción general de las declaraciones de PostgreSQL para Kubernetes, nuestras elecciones y experiencia

En la interfaz de usuario del operador, deberá agregar 3 variables:

  • SPILO_S3_BACKUP_BUCKET
  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY

Después de eso, la administración de copias de seguridad estará disponible, lo que en nuestro caso simplificará el trabajo con la puesta en escena, permitiéndole entregar partes de la producción allí sin scripts adicionales.

Otra ventaja fue el trabajo con la API de Teams y amplias oportunidades para crear bases de datos y roles utilizando herramientas de operador. Sin embargo, el creado Los roles no tenían permisos por defecto.. En consecuencia, un usuario con derechos de lectura no podría leer tablas nuevas.

¿Porqué es eso? A pesar de que en el código есть necesario GRANT, no siempre se utilizan. Hay 2 métodos: syncPreparedDatabases и syncDatabases. En syncPreparedDatabases - a pesar de que en la sección preparedDatabases есть hay una condición defaultRoles и defaultUsers Para crear roles, no se aplican los derechos predeterminados. Estamos en el proceso de preparar un parche para que estos derechos se apliquen automáticamente.

Y el último momento de las mejoras que son relevantes para nosotros: parcheA que agrega una afinidad de nodo al StatefulSet generado. Nuestros clientes a menudo prefieren reducir costos utilizando instancias puntuales y claramente no valen la pena alojar servicios de bases de datos. Este problema podría resolverse mediante tolerancias, pero la presencia de Node Affinity da mayor confianza.

¿Qué pasó?

Como resultado de resolver los problemas anteriores, bifurcamos el operador Postgres de Zalando en tu repositoriohacia dónde se dirige con parches tan útiles. Y para mayor comodidad, también recopilamos imagen acoplable.

Lista de RP aceptados en la bifurcación:

Sería fantástico si la comunidad apoyara a estos RP para que avancen con la próxima versión del operador (1.6).

¡Prima! Historia de éxito de la migración de producción

Si utiliza Patroni, la producción en vivo se puede migrar al operador con un tiempo de inactividad mínimo.

Spilo le permite crear clústeres en espera a través del almacenamiento S3 con Wal-Ecuando el registro binario de PgSQL se almacena por primera vez en S3 y luego la réplica lo extrae. Pero ¿y si tienes? no ¿Utilizado por Wal-E en infraestructura antigua? La solución a este problema ya está fue sugerido en el centro.

La replicación lógica de PostgreSQL viene al rescate. Sin embargo, no entraremos en detalles sobre cómo crear publicaciones y suscripciones, porque… nuestro plan falló.

El hecho es que la base de datos tenía varias tablas cargadas con millones de filas, que, además, se reponían y eliminaban constantemente. Suscripción sencilla с copy_data, cuando la nueva réplica copia todo el contenido del maestro, simplemente no puede seguir el ritmo del maestro. La copia de contenido funcionó durante una semana, pero nunca alcanzó al maestro. Al final, ayudó a resolver el problema. artículo colegas de Avito: puede transferir datos usando pg_dump. Describiré nuestra versión (ligeramente modificada) de este algoritmo.

La idea es que pueda crear una suscripción deshabilitada vinculada a una ranura de replicación específica y luego corregir el número de transacción. Hubo réplicas para el trabajo de producción. Esto es importante porque la réplica ayudará a crear un volcado coherente y seguirá recibiendo cambios del maestro.

Los comandos posteriores que describen el proceso de migración utilizarán la siguiente notación para los hosts:

  1. dominar — servidor de origen;
  2. réplica1 - réplica en streaming de la producción anterior;
  3. réplica2 - una nueva réplica lógica.

Plan de migración

1. Cree una suscripción a todas las tablas del esquema en el asistente. public base dbname:

psql -h master -d dbname -c "CREATE PUBLICATION dbname FOR ALL TABLES;"

2. Cree una ranura de replicación en el maestro:

psql -h master -c "select pg_create_logical_replication_slot('repl', 'pgoutput');"

3. Detenga la replicación en la réplica anterior:

psql -h replica1 -c "select pg_wal_replay_pause();"

4. Obtenga el número de transacción del maestro:

psql -h master -c "select replay_lsn from pg_stat_replication where client_addr = 'replica1';"

5. Volcado de la réplica antigua. Haremos esto en varios hilos, lo que ayudará a acelerar el proceso:

pg_dump -h replica1 --no-publications --no-subscriptions -O -C -F d -j 8 -f dump/ dbname

6. Cargue el volcado en el nuevo servidor:

pg_restore -h replica2 -F d -j 8 -d dbname dump/

7. Después de descargar el volcado, puede iniciar la replicación en la réplica de transmisión:

psql -h replica1 -c "select pg_wal_replay_resume();"

7. Cree una suscripción en una nueva réplica lógica:

psql -h replica2 -c "create subscription oldprod connection 'host=replica1 port=5432 user=postgres password=secret dbname=dbname' publication dbname with (enabled = false, create_slot = false, copy_data = false, slot_name='repl');"

8. Obtener oid suscripciones:

psql -h replica2 -d dbname -c "select oid, * from pg_subscription;"

9. Digamos que fue recibido. oid=1000. Apliquemos el número de transacción a la suscripción:

psql -h replica2 -d dbname -c "select pg_replication_origin_advance('pg_1000', 'AA/AAAAAAAA');"

10. Comencemos la replicación:

psql -h replica2 -d dbname -c "alter subscription oldprod enable;"

11. Verifique el estado de la suscripción, la replicación debería funcionar:

psql -h replica2 -d dbname -c "select * from pg_replication_origin_status;"
psql -h master -d dbname -c "select slot_name, restart_lsn, confirmed_flush_lsn from pg_replication_slots;"

12. Una vez iniciada la replicación y sincronizadas las bases de datos, puede cambiar.

13. Después de deshabilitar la replicación, debes arreglar las secuencias. esto esta bien descrito en el artículo sobre wiki.postgresql.org.

Gracias a este plan, la transición se realizó con retrasos mínimos.

Conclusión

Los operadores de Kubernetes le permiten simplificar varias acciones reduciéndolas a la creación de recursos K8. Sin embargo, después de haber logrado una automatización notable con su ayuda, vale la pena recordar que también puede traer una serie de matices inesperados, así que elija sabiamente a sus operadores.

Después de revisar los tres operadores de Kubernetes más populares para PostgreSQL, elegimos el proyecto de Zalando. Tuvimos que superar algunas dificultades, pero el resultado fue realmente satisfactorio, por lo que planeamos extender esta experiencia a otras instalaciones de PgSQL. Si tiene experiencia en el uso de soluciones similares, ¡estaremos encantados de ver los detalles en los comentarios!

PS

Lea también en nuestro blog:

Fuente: habr.com

Añadir un comentario