Override the default configurations

Kubegres allows to override its default configurations and bash scripts based on your requirements.

For each namespace where a Kubegres resource is created, Kubegres controller creates a base ConfigMap resource with this contents. That base ConfigMap contains the default configs for all Kubegres resource(s) in that namespace. It defines default contents for "postgres.conf", "pg_hba.conf" and a backup logic in "backup_database.sh".

You can override the following configurations in that base ConfigMap:

  • primary_init_script.sh: a bash script which runs the 1st time a Primary PostgreSql container is created. This happens when a new Kubegres resource is deployed to create a new PostgreSql cluster. It is the right place to add instructions creating custom database(s) and user(s) for your requirement.
  • backup_database.sh: if you enabled backup for your Kubegres resource, this bash script defines the actions to perform during a backup. It is executed regularly by a dedicated CronJob.
  • postgres.conf: the official PostgreSql configs used for both Primary and Replica servers.
  • pg_hba.conf: the host-based authentication configs for both Primary and Replica servers.

Examples from Kubegres user(s)

@laukaichung published a great example in GitHub showing how the scripts "backup_database.sh" and "primary_init_script.sh" were overridden in order to use S3 for backup storage and initialization.

How to override the default configurations for all running Kubegres resources?

As mentioned above, Kubegres automatically creates a base ConfigMap named base-kubegres-config in each namespace where Kubegres resources are running.

If you would like to change that base ConfigMap, you can do so by using the tool "kubectl" and edit the resource with name "base-kubegres-config". That change would apply to all Kubegres resources in the same namespace:

kubectl edit configmap base-kubegres-config -n [namespace]
                    

How to override the default configurations for a specific Kubegres resource?

If you would like to override the default configs for a specific PostgreSql cluster only, you can create a custom ConfigMap in that namespace and set its name to the property "spec.customConfig" in your Kubegres YAML, as follows:

apiVersion: kubegres.reactive-tech.io/v1
kind: Kubegres
metadata:
  name: mypostgres
  namespace: default

spec:

   replicas: 3
   image: postgres:13.2
   port: 5432

   database:
      size: 200Mi

   customConfig: mypostgres-conf

   env:
      - name: POSTGRES_PASSWORD
        valueFrom:
           secretKeyRef:
              name: mySecretResource
              key: superUserPassword

      - name: POSTGRES_REPLICATION_PASSWORD
        valueFrom:
           secretKeyRef:
              name: mySecretResource
              key: replicationUserPassword

                    

And in your custom ConfigMap you can override one or many of these configs: primary_init_script.sh, backup_database.sh, postgres.conf and pg_hba.conf. Please see the examples below.

Override primary_init_script.sh

The bash script below runs only the 1st time a Primary PostgreSql container is created. It overrides "primary_init_script.sh" in a custom ConfigMap, by creating a custom user and a database and grant to that user access rights:

apiVersion: v1
kind: ConfigMap
metadata:
  name: mypostgres-conf
  namespace: default

data:

  primary_init_script.sh: |
    #!/bin/bash
    set -e

    # This script assumes that the env-var $POSTGRES_MY_DB_PASSWORD contains the password of the custom user to create.
    # You can add any env-var in your Kubegres resource config YAML.

    dt=$(date '+%d/%m/%Y %H:%M:%S');
    echo "$dt - Running init script the 1st time Primary PostgreSql container is created...";

    customDatabaseName="my_app_db"
    customUserName="my_username"

    echo "$dt - Running: psql -v ON_ERROR_STOP=1 --username $POSTGRES_USER --dbname $POSTGRES_DB ...";

    psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
    CREATE DATABASE $customDatabaseName;
    CREATE USER $customUserName WITH PASSWORD '$POSTGRES_MY_DB_PASSWORD';
    GRANT ALL PRIVILEGES ON DATABASE "$customDatabaseName" to $customUserName;
    EOSQL

    echo "$dt - Init script is completed";
                    

This script above assumes that the env-var $POSTGRES_MY_DB_PASSWORD contains the password of the custom user to create. Please see an example about how to add a custom env-variable.

Override backup_database.sh

Please see below an example of an overridden "backup_database.sh" in a custom ConfigMap, which contains the logic to dump PostgreSql Primary's database:

apiVersion: v1
kind: ConfigMap
metadata:
  name: mypostgres-conf
  namespace: default

data:

  backup_database.sh: |
    #!/bin/bash
    set -e

    dt=$(date '+%d/%m/%Y %H:%M:%S');
    fileDt=$(date '+%d_%m_%Y_%H_%M_%S');
    backUpFileName="$KUBEGRES_RESOURCE_NAME-backup-$fileDt.gz"
    backUpFilePath="$BACKUP_DESTINATION_FOLDER/$backUpFileName"

    echo "$dt - Starting DB backup of Kubegres resource $KUBEGRES_RESOURCE_NAME into file: $backUpFilePath";
    echo "$dt - Running: pg_dumpall -h $BACKUP_SOURCE_DB_HOST_NAME -U postgres -c | gzip > $backUpFilePath"

    pg_dumpall -h $BACKUP_SOURCE_DB_HOST_NAME -U postgres -c | gzip > $backUpFilePath

    if [ $? -ne 0 ]; then
      rm $backUpFilePath
      echo "Unable to execute a BackUp. Please check DB connection settings"
      exit 1
    fi

    echo "$dt - DB backup completed for Kubegres resource $KUBEGRES_RESOURCE_NAME into file: $backUpFilePath";
                    

Override postgres.conf

When overriding postgres.conf, there are 2 properties to be aware of:

  • "listen_addresses": by default PostgreSql set it to "localhost". But Kubegres explicitly set it to "*". When defining your own postgres.conf, do not forget to set it to "*". Not setting it or using an alternative value could break Kubegres replication capability.
  • "wal_level": You cannot set a value for this config because it is passed as an argument to the PostgreSql container. This restriction is part of the design.

Please see below an example of an overridden "postgres.conf" in a custom ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: mypostgres-conf
  namespace: default

data:

  postgres.conf: |

    # Replication configs
    listen_addresses = '*'
    max_wal_senders = 10
    wal_keep_segments = 48 #in Mb
    max_connections = 100
    shared_buffers = 128MB

    # Logging
    log_destination = 'stderr,csvlog'
    logging_collector = on
    log_directory = 'pg_log'
    log_filename= 'postgresql-%Y-%m-%d_%H%M%S.log'
                    

Override pg_hba.conf

Please see below an example of an overridden "pg_hba.conf" in a custom ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: mypostgres-conf
  namespace: default

data:

  pg_hba.conf: |
    # TYPE  DATABASE        USER            ADDRESS                 METHOD
    # Replication connections by a user with the replication privilege
    host    replication     replication     all                     md5
    # As long as it is authenticated, all connections allowed except from "0.0.0.0/0"
    local   all             all                                     md5
    host    all             all             all                     md5
    host    all             all             0.0.0.0/0               reject
                    

Note about applying ConfigMap changes to existing PostgreSql pods

When we make a change to a ConfigMap, Kubernetes does not notify the Kubegres controller about that update. Consequently, if we want to apply those changes to existing running PostgreSql pods, when have to manually restart them.

However, restarting pods could trigger the failover process and Kubegres may wrongly think that the primary PostgreSql pod is not available and would failover to a Replica PostgreSql pod. To avoid Kubegres controller to failover, we need to pause it.

The instructions to follows are:

  • Update your ConfigMap (e.g. "base-kubegres-config", or your custom ConfigMap)
  • Pause the Kubegres controller by running:
    kubectl scale --replicas=0 deployment.apps/kubegres-controller-manager -n kubegres-system
                                    
  • Restart the StatefulSets of your Postgres cluster (in this example my cluster's name is "mypostgres" and I have 3 pods running):
    kubectl rollout restart statefulset mypostgres-1 mypostgres-2 mypostgres-3
                                    
  • From that point your pods are using the latest version of the ConfigMap. Check the pods are in a running state:
    kubectl get pods
                                    
  • If the pods are running and healthy, then resume the Kubegres controller by running:
    kubectl scale --replicas=1 deployment.apps/kubegres-controller-manager -n kubegres-system