Usa el grupo de conexiones de PgBouncer

En esta página, se describe cómo habilitar y usar el grupo de conexiones de PgBouncer para AlloyDB Omni con el operador de Kubernetes de AlloyDB Omni.

Muchas aplicaciones, en especial las web, abren y cierran conexiones de bases de datos con frecuencia, lo que puede generar una carga significativa en la instancia de la base de datos. PgBouncer ayuda a reducir la carga de instancias administrando las conexiones de manera más eficiente. Cuando se reutilizan las conexiones, PgBouncer minimiza la cantidad de conexiones a la instancia de base de datos, lo que libera recursos en la instancia.

Crea un servicio de PgBouncer

El operador de Kubernetes de AlloyDB Omni te permite crear un servicio de PgBouncer dedicado para tu base de datos. Luego, puedes acceder a la base de datos a través del servicio de PgBouncer para beneficiarte del grupo de conexiones.

Hay una definición de recurso personalizado (CRD) exclusiva para configurar tu servicio de PgBouncer según sea necesario.

Para crear un servicio de PgBouncer para tu base de datos, sigue estos pasos:

  1. Crea un recurso personalizado PgBouncer en tu clúster de Kubernetes de la siguiente manera:

    apiVersion: alloydbomni.dbadmin.goog/v1
    kind: PgBouncer
    metadata:
      name: PGBOUNCER_NAME
    spec:
      dbclusterRef: DB_CLUSTER_NAME
      allowSuperUserAccess: true
      podSpec:
        resources:
          memory: 1Gi
          cpu: 1
        image: "gcr.io/alloydb-omni/operator/pgbouncer:1.23.1"
      parameters:
        pool_mode: POOL_MODE
        ignore_startup_parameters: IGNORE_STARTUP_PARAMETERS
        default_pool_size: DEFAULT_POOL_SIZE
        max_client_conn: MAXIMUM_CLIENT_CONNECTIONS
        max_db_connections: MAXIMUM_DATABASE_CONNECTIONS
      serviceOptions:
        type: "ClusterIP"

    Reemplaza lo siguiente:

    • PGBOUNCER_NAME: Es el nombre de tu recurso personalizado de PgBouncer.
    • DB_CLUSTER_NAME: Es el nombre del clúster de bases de datos de AlloyDB Omni. Es el mismo nombre de clúster de base de datos que declaraste cuando lo creaste.
    • POOL_MODE: Especifica cuándo otros clientes pueden volver a usar una conexión de base de datos. Establece el parámetro en uno de los siguientes valores:
      • session: La conexión de la base de datos se vuelve a liberar al grupo después de que se desconecta el cliente. Se usa de forma predeterminada.
      • transaction: La conexión a la base de datos se libera al grupo después de que finaliza la transacción.
      • statement: La conexión a la base de datos se vuelve a liberar al grupo después de que finaliza la consulta. En este modo, no se permiten transacciones que abarquen varias instrucciones.
    • IGNORE_STARTUP_PARAMETERS: Especifica los parámetros que PgBouncer no permite para que se ignoren durante el inicio, por ejemplo, extra_float_digits. Para obtener más información, consulta Configuración de PgBouncer.
    • DEFAULT_POOL_SIZE: Es la cantidad de conexiones de bases de datos que se permiten por par de usuario-base de datos, por ejemplo, 8.
    • MAXIMUM_CLIENT_CONNECTIONS: Es la cantidad máxima de conexiones de clientes, por ejemplo, 800.
    • MAXIMUM_DATABASE_CONNECTIONS: Es la cantidad máxima de conexiones de base de datos, por ejemplo, 160.
  2. Aplica el manifiesto

    kubectl apply -f PATH_TO_MANIFEST -n NAMESPACE

    Reemplaza PATH_TO_MANIFEST por la ruta de acceso a tu archivo de manifiesto, por ejemplo, /fleet/config/pgbouncer.yaml.

  3. Para verificar que el objeto PgBouncer que creaste esté listo, ejecuta la siguiente consulta:

    kubectl get pgbouncers.alloydbomni.dbadmin.goog PGBOUNCER_NAME  -n NAMESPACE -w
    

    Reemplaza NAMESPACE por el nombre del espacio de nombres de Kubernetes para tu objeto PgBouncer.

    El resultado es similar a este:

    NAMESPACE   NAME          ENDPOINT        STATE
    dbv2        mypgbouncer
    dbv2        mypgbouncer
    dbv2        mypgbouncer
    dbv2        mypgbouncer                   WaitingForDeploymentReady
    dbv2        mypgbouncer                   Acquiring IP
    dbv2        mypgbouncer   10.138.15.231   Ready
    

Cómo conectarse al extremo del agrupador de conexiones

Puedes conectarte al grupo de conexiones de PgBouncer desde dentro o fuera de un clúster de Kubernetes.

Cómo conectarse desde un clúster de Kubernetes

Para conectarte al extremo del grupo de conexiones con el cliente psql, sigue estos pasos:

  1. Crea un Pod de la siguiente manera:

    apiVersion: v1
    kind: Pod
    metadata:
      name: postgres
    spec:
      containers:
      - image: "docker.io/library/postgres:latest"
        command:
         - "sleep"
         - "604800"
        name: db-client
    
  2. Aplica el manifiesto

    kubectl apply -f PATH_TO_MANIFEST -n NAMESPACE
    
  3. Conéctate a la aplicación alojada en contenedores:

    kubectl exec -it postgres -n NAMESPACE -- bash
    
  4. Verifica la conexión SSL al extremo de PgBouncer con el cliente psql:

    export PGSSLMODE="require"; psql -h HOST -d postgres -U postgres -p PORT
    

    Reemplaza lo siguiente:

    • HOST: Es el extremo del grupo de conexiones que obtienes con el comando kubectl get pgbouncers.alloydbomni.dbadmin.goog -n NAMESPACE. Si PgBouncer no está expuesto como un servicio, usa su dirección IP.
    • PORT: Es el puerto en el que escucha PgBouncer.

    La ventana de la terminal muestra el texto de acceso de psql que termina con un mensaje postgres=#.

Cómo conectarse desde fuera de un clúster de Kubernetes

Para acceder al grupo de conexiones de PgBouncer desde fuera de un clúster de Kubernetes, establece el campo type en el atributo serviceOptions en LoadBalancer, lo que crea un servicio loadbalancer.

  1. Crea un recurso personalizado PgBouncer en tu clúster de Kubernetes de la siguiente manera:

    apiVersion: alloydbomni.dbadmin.goog/v1
    kind: PgBouncer
    metadata:
    name: PGBOUNCER_NAME
    spec:
    dbclusterRef: DB_CLUSTER_NAME
    allowSuperUserAccess: true
    replicaCount: 2
    parameters:
      pool_mode: POOL_MODE
      ignore_startup_parameters: IGNORE_STARTUP_PARAMETERS
      default_pool_size: DEFAULT_POOL_SIZE
      max_client_conn: MAXIMUM_CLIENT_CONNECTIONS
      max_db_connections: MAXIMUM_DATABASE_CONNECTIONS
    podSpec:
      resources:
        memory: 1Gi
        cpu: 1
      image: "gcr.io/alloydb-omni/operator/pgbouncer:1.23.1"
    serviceOptions:
      type: "LoadBalancer"
  2. Aplica el manifiesto

    kubectl apply -f PATH_TO_MANIFEST
  3. Para verificar que el objeto PgBouncer que creaste esté listo, ejecuta la siguiente consulta:

    kubectl get pgbouncers.alloydbomni.dbadmin.goog PGBOUNCER_NAME  -n NAMESPACE -w

    El resultado es similar a este:

    NAME          ENDPOINT       STATE
    mypgbouncer   10.138.15.207   Ready
    

Configura PgBouncer

Usa los siguientes parámetros para configurar PGBouncer:

Parámetro Descripción Valor predeterminado
pool_mode Especifica cuándo otros clientes pueden volver a usar una conexión a la base de datos.
Los valores permitidos son los siguientes:
  • session: La conexión de la base de datos se vuelve a liberar al grupo después de que se desconecta el cliente.
  • transaction: La conexión a la base de datos se libera al grupo después de que finaliza la transacción.
  • statement: La conexión de la base de datos se libera al grupo después de que finaliza la consulta.
    En este modo, no se permiten transacciones que abarcan varias instrucciones.
session
ignore_startup_parameters Especifica los parámetros que PgBouncer no permite para que se ignoren durante el inicio.
default_pool_size Es la cantidad de conexiones de base de datos que se permiten por par de usuario-base de datos. 20
max_client_conn Es la cantidad máxima de conexiones de cliente. 100
max_db_connections Es la cantidad máxima de conexiones a la base de datos. 0

Personaliza la implementación de PgBouncer

AlloyDB Omni usa recursos personalizados para administrar sus componentes. Para personalizar la implementación de PgBouncer en tu AlloyDB Omni en Kubernetes, modifica el recurso personalizado PgBouncer de la siguiente manera:

  1. Haz una lista de los recursos personalizados de PgBouncer:

    kubectl get pgbouncers -n NAMESPACE

    Reemplaza NAMESPACE por el espacio de nombres en el que implementaste AlloyDB Omni.

  2. Para modificar el recurso, abre el archivo de declaración del recurso PgBouncer en tu editor predeterminado:

    kubectl edit pgbouncers PGBOUNCER_NAME -n NAMESPACE
  3. En el archivo de declaración, busca la sección podSpec que contiene la configuración y modifica cualquiera de los siguientes campos según sea necesario:

    • resources: Son los cpu y memory definidos para tu contenedor:

      apiVersion: alloydbomni.dbadmin.goog/v1
      kind: PgBouncer
      metadata:
        name: PGBOUNCER_NAME
      spec:
        dbclusterRef: DB_CLUSTER_NAME
        replicaCount: 2
        parameters:
          pool_mode: POOL_MODE
          ignore_startup_parameters: IGNORE_STARTUP_PARAMETERS
          default_pool_size: DEFAULT_POOL_SIZE
          max_client_conn: MAXIMUM_CLIENT_CONNECTIONS
          max_db_connections: MAXIMUM_DATABASE_CONNECTIONS
        podSpec:
          resources:
            memory: 1Gi
            cpu: 1
      ...
      
    • image: Es la ruta de acceso a la etiqueta de imagen de PgBouncer:

      ...
        podSpec:
          resources:
            memory: 1Gi
            cpu: 1
          image: IMAGE
      ...
      
    • schedulingconfig: Incluye la sección nodeaffinity para controlar dónde se programan los pods de PgBouncer:

      ...
        podSpec:
          resources:
            memory: 1Gi
            cpu: 1
          image: IMAGE
          schedulingconfig:
            nodeaffinity:
              NODE_AFFINITY_TYPE:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: LABEL_KEY
                    operator: OPERATOR_VALUE
                    values:
                    - pgbouncer
      ...
      

      Reemplaza lo siguiente:

      • NODE_AFFINITY_TYPE: Establece el parámetro en una de las siguientes opciones:
        • requiredDuringSchedulingIgnoredDuringExecution: Kubernetes programa el Pod exactamente según las reglas definidas.
        • preferredDuringSchedulingIgnoredDuringExecution: El programador de Kubernetes intenta encontrar un nodo que cumpla con la regla definida para la programación. Sin embargo, si no hay un nodo de ese tipo, Kubernetes programa en un nodo diferente del clúster.
      • LABEL_KEY: Es la etiqueta del nodo para la clave que funciona como indicador de ubicación y facilita la distribución uniforme de Pods en el clúster, por ejemplo, nodetype.
      • OPERATOR_VALUE: Representa la relación de una clave con un conjunto de valores. Establece el parámetro en uno de los siguientes valores:
        • In: El array de valores no debe estar vacío.
        • NotIn: El array de valores no debe estar vacío.
        • Exists: El array de valores debe estar vacío.
        • DoesNotExist: El array de valores debe estar vacío.
        • Gt: El array de valores debe tener un solo elemento, que se interpreta como un número entero.
        • Lt: El array de valores debe tener un solo elemento, que se interpreta como un número entero.
  4. Después de realizar los cambios, guarda el archivo de declaración. El operador de Kubernetes de AlloyDB Omni aplica automáticamente los cambios a tu implementación de PgBouncer.

Borra el recurso PgBouncer

Para borrar un recurso personalizado de PgBouncer, ejecuta el siguiente comando:

kubectl delete pgbouncers.alloydbomni.dbadmin.goog PGBOUNCER_NAME -n NAMESPACE

El resultado es similar a este:

pgbouncer.alloydbomni.dbadmin.goog "mypgbouncer" deleted

Consulta los registros de PgBouncer

Puedes ver y analizar los registros de cualquier instancia de réplica de PgBouncer en tu implementación de AlloyDB Omni en Kubernetes de la siguiente manera:

  1. Obtén una lista de todos los pods de PgBouncer en tu espacio de nombres:

    kubectl get pods -n NAMESPACE

    El resultado es similar a este:

    NAME                                          READY   STATUS    RESTARTS   AGE
    al-092d-dbcluster-sample-0                    3/3     Running   0          3d1h
    mypgbouncer-pgb-deployment-659869f95c-4kbgv   1/1     Running   0          27m
    
  2. Visualiza los registros de un Pod en particular:

    kubectl logs -f POD_NAME -n NAMESPACE

    El resultado es similar a este:

    2025-01-21 06:57:39.549 UTC [7] LOG kernel file descriptor limit: 1048576 (hard: 1048576); max_client_conn: 800, max expected fd use: 812
    2025-01-21 06:57:39.550 UTC [7] LOG listening on 0.0.0.0:6432
    2025-01-21 06:57:39.550 UTC [7] LOG listening on [::]:6432
    2025-01-21 06:57:39.550 UTC [7] LOG listening on unix:/tmp/.s.PGSQL.6432
    2025-01-21 06:57:39.550 UTC [7] LOG process up: PgBouncer 1.23.0, libevent 2.1.12-stable (epoll), adns: evdns2, tls: OpenSSL 3.0.13 30 Jan 2024
    2025-01-21 06:58:17.012 UTC [7] LOG C-0x55f2b1b322a0: (nodb)/(nouser)@10.138.15.215:48682 registered new auto-database: alloydbadmin
    2025-01-21 06:58:17.012 UTC [7] LOG S-0x55f2b1b4ecb0: alloydbadmin/alloydbpgbouncer@10.138.0.48:5432 new connection to server (from 10.12.1.113:53156)
    2025-01-21 06:58:17.042 UTC [7] LOG S-0x55f2b1b4ecb0: alloydbadmin/alloydbpgbouncer@10.138.0.48:5432 SSL established: TLSv1.3/TLS_AES_256_GCM_SHA384/ECDH=prime256v1
    2025-01-21 06:58:17.052 UTC [7] LOG C-0x55f2b1b322a0: pgbouncer/statsuser@10.138.15.215:48682 login attempt: db=pgbouncer user=statsuser tls=TLSv1.3/TLS_AES_256_GCM_SHA384 replication=no
    2025-01-21 06:58:19.526 UTC [7] LOG C-0x55f2b1b322a0: pgbouncer/statsuser@10.138.15.215:48682 closing because: client close request (age=2s)
    2025-01-21 06:58:20.344 UTC [7] LOG C-0x55f2b1b322a0: pgbouncer/statsuser@10.138.15.215:46796 login attempt: db=pgbouncer user=statsuser tls=TLSv1.3/TLS_AES_256_GCM_SHA384 replication=no
    

Supervisa el rendimiento y la actividad de PgBouncer

Puedes ver las métricas del grupo de conexiones de PgBouncer con solo un statsuser dedicado para acceder a la base de datos de estadísticas internas de PgBouncer. statsuser se usa para la autenticación cuando te conectas a la base de datos de PgBouncer.

  1. Conéctate a tu AlloyDB Omni como superusuario o usuario con el privilegio CREATE ROLE con el cliente psql:

    export PGPASSWORD="ChangeMe123"; export PGSSLMODE="require"; psql -h HOST -d postgres -U postgres -p PORT
    

    El resultado es similar a este:

    psql (16.6 (Ubuntu 16.6-0ubuntu0.24.04.1), server 15.7)
    SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
    Type "help" for help.
    
  2. Crea el statsuser en tu AlloyDB Omni:

    postgres=# CREATE USER "statsuser" WITH PASSWORD 'tester';
    

    El resultado es similar a este:

    CREATE ROLE
    postgres=#
    
  3. Conéctate a la base de datos de PgBouncer como statsuser:

    export PGPASSWORD="ChangeMe123"; export PGSSLMODE="require"; psql -h HOST -d pgbouncer -U statsuser -p PORT
    

    El resultado es similar a este:

    psql (16.6 (Ubuntu 16.6-0ubuntu0.24.04.1), server 1.23.0/bouncer)
    WARNING: psql major version 16, server major version 1.23.
    Some psql features might not work.
    SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
    Type "help" for help.
    
  4. Ejecuta el comando SHOW STATS para ver el rendimiento de PgBouncer y, luego, identificar posibles problemas:

    pgbouncer=# SHOW STATS;
    

    El resultado es similar a este:

         database   | total_server_assignment_count | total_xact_count | total_query_count | total_received | total_sent | total_xact_time | total_query_time | total_wait_time | avg_server_assignment_count | avg_xact_count | avg_query_count | avg_recv | avg_sent | avg_xact_time | avg_query_time | avg_wait_time
       -------------+-------------------------------+------------------+-------------------+----------------+------------+-----------------+------------------+-----------------+-----------------------------+----------------+-----------------+----------+----------+---------------+----------------+---------------
       alloydbadmin |                             1 |                0 |                 0 |              0 |        330 |               0 |                0 |           41730 |                           0 |              0 |               0 |        0 |        2 |             0 |              0 |         41730
       pgbouncer    |                             0 |                5 |                 5 |              0 |          0 |               0 |                0 |               0 |                           0 |              0 |               0 |        0 |        0 |             0 |              0 |             0
       (2 rows)
    

Inhabilita el grupo de conexiones de PgBouncer

Si necesitas desactivar o revertir el grupo de conexiones de PgBouncer, sigue estos pasos:

  1. Verifica el estado del grupo de conexiones:

    kubectl get deployment fleet-controller-manager --namespace alloydb-omni-system  -o json | jq '.spec.template.spec.containers[0].args'

    Este comando muestra el manifiesto de implementación del controlador principal para administrar la flota de AlloyDB Omni. Busca la opción --enable-pgbouncer en la sección args del array containers:

    ...
     spec:
      containers:
      - name: fleet-controller-manager
        image:...
        args:
        --health-probe-bind-address=:8081",
        --metrics-bind-address=127.0.0.1:8080",
        --leader-elect",
        --image-registry=gcr.io",
        --data-plane-image-repository=alloydb-omni-staging",
        --control-plane-agents-image-repository=aedi-gbox",
        --control-plane-agents-tag=jan19v3",
        --additional-db-versions-for-test-only=latest",
        --enable-multiple-backup-solutions=true",
        --enable-pgbouncer=true
    
  2. Edita la configuración de la implementación del controlador para inhabilitar el grupo de conexiones:

    kubectl edit deployment fleet-controller-manager --namespace alloydb-omni-system
  3. En el manifiesto de implementación, cambia el valor de la opción --enable-pgbouncer de true a false:

    ...
    --enable-pgbouncer=false
    
  4. Guarda el archivo y sal del editor. kubectl aplica el cambio automáticamente.

¿Qué sigue?