Installing PostgreSQL on Kubernetes Using CloudNativePG (CNPG)

Create CNPG Directory & postgres.yaml Manifest

—————————————————————–

Create a directory for CNPG configuration and add the postgres.yaml file:

vi postgres.yaml

-----------------------------------------------------------------
Cluster 1 — app-db-cluster (Application Database)
-----------------------------------------------------------------

apiVersion: postgresql.cnpg.io/v1
kind: Cluster

metadata:
  name: app-db-cluster
  namespace: prod-database

spec:

  instances: 2
  imageName: ghcr.io/cloudnative-pg/postgresql:16.2

  affinity:
    nodeSelector:
      role: "database"

    tolerations:
      - key: "database"
        operator: "Equal"
        value: "true"
        effect: "NoSchedule"

  bootstrap:

    initdb:
      database: appdb
      owner: appuser
      dataChecksums: true
      encoding: 'UTF8'
  enableSuperuserAccess: true

  postgresql:

    parameters:
      checkpoint_timeout: "15min"
      max_connections: "512"
      max_locks_per_transaction: "512"
      max_wal_size: "16GB"
      random_page_cost: "1"
      shared_buffers: "2GB"

  resources:

    requests:
      cpu: "4"
      memory: "8Gi"

    limits:

      cpu: "4"
      memory: "8Gi"

  storage:
    size: 40Gi
    storageClass: standard-local-storage

-----------------------------------------------------------------
Cluster 2 — customer-db-cluster (Customer Database)
-----------------------------------------------------------------

apiVersion: postgresql.cnpg.io/v1
kind: Cluster

metadata:
  name: customer-db-cluster
  namespace: prod-database

spec:
  instances: 2
  imageName: ghcr.io/cloudnative-pg/postgresql:16.2

  affinity:
    nodeSelector:
      role: "database"

    tolerations:
      - key: "database"
        operator: "Equal"
        value: "true"
        effect: "NoSchedule"

  bootstrap:

    initdb:
      database: customerdb
      owner: custowner
      dataChecksums: true
      encoding: 'UTF8'
  enableSuperuserAccess: true

  postgresql:

    parameters:
      checkpoint_timeout: "15min"
      max_connections: "512"
      max_locks_per_transaction: "512"
      max_wal_size: "16GB"
      random_page_cost: "1"
      shared_buffers: "3GB"

  resources:

    requests:
      cpu: "6"
      memory: "12Gi"

    limits:
      cpu: "6"
      memory: "12Gi"

  storage:
    size: 50Gi
    storageClass: standard-local-storage

-----------------------------------------------------------------
Add CNPG Helm Repo & Install Operator
-----------------------------------------------------------------
This command will add the CloudNativePG repository to your Helm configuration.
helm repo add cnpg https://cloudnative-pg.github.io/charts

This command installs the CloudNativePG Helm chart under the release name cnpg into the cnpg-system namespace
helm upgrade --install cnpg   --namespace cnpg-system   --create-namespace   cnpg/cloudnative-pg

-----------------------------------------------------------------
Validate Configuration (Dry Run)
-----------------------------------------------------------------
Dry Run the Manifest to Check for any Syntax Errors:
kubectl apply -f postgres.yaml --dry-run=server

-----------------------------------------------------------------
Deploy Both Clusters
-----------------------------------------------------------------
kubectl apply -f postgres.yaml

-----------------------------------------------------------------
Verify Pods
-----------------------------------------------------------------
This command is used to list all the pods in the ped-prod namespace:
kubectl get pods -n prod-database

This command is useful for keeping an eye on your database-related pods and their status:
kubectl get pods-n ped-prod-o wide-w |grep database

-----------------------------------------------------------------
 List Secrets
-----------------------------------------------------------------

The command kubectl get secrets-n ped-prod is used to list all the secrets in the ped-prod namespace:
kubectl get secrets -n prod-database

-----------------------------------------------------------------
Validate Replication Roles
-----------------------------------------------------------------
kubectl exec -t app-db-cluster-1 -n prod-database -- psql -U postgres -c "SELECT pg_is_in_recovery();"

-----------------------------------------------------------------
Install CNPG Plugin (kubectl cnpg)
-----------------------------------------------------------------
curl -sSfL https://github.com/cloudnative-pg/cloudnative-pg/raw/main/hack/install-cnpg-plugin.sh | sudo sh -s -- -b /usr/local/bin

Expected Output:
cloudnative-pg/cloudnative-pg info checking GitHub for latest tag cloudnative-pg/cloudnative-pg info found version: 1.25.1 for v1.25.1/linux/x86_64 cloudnative-pg/cloudnative-pg info installed /usr/local/bin/kubectl-cnpg

Now check status by running below command:
kubectl cnpg status

-----------------------------------------------------------------
List CNPG Clusters
-----------------------------------------------------------------
kubectl get clusters.postgresql.cnpg.io -n prod-database

-----------------------------------------------------------------
Check Status of customer-db-cluster
-----------------------------------------------------------------
kubectl cnpg status customer-db-cluster customer-db-cluster-1 -n prod-database

-----------------------------------------------------------------
Check Status of app-db-cluster
-----------------------------------------------------------------
kubectl cnpg status app-db-cluster app-db-cluster-1 -n prod-database
-----------------------------------------------------------------

 Conclusion

With CNPG:

• PostgreSQL becomes fully declarative

• Replication & failover are automatic

• Secrets and TLS are handled by the operator

• Pod placement & resource policies are cleanly managed

• You get production-grade HA PostgreSQL on Kubernetes

This deployment includes:

• app-db-cluster

• customer-db-cluster

running reliably inside the prod-database namespace.