Migrating Kubernetes PostgreSQL Deployments to CloudNativePG
CloudNativePG (CNPG) is a Kubernetes-native PostgreSQL offering which provides high-availability, self-healing, seamless backups, and rolling updates. In short, if you like PostgreSQL and Kubernetes, you will love it. I won’t cover installing it, its pretty straight forward if you read their documentation. This is about migrating data from all the other deployments into a new CNPG cluster.
The PostgreSQL command line tools are expected to be on the path for any of this to work.
The Process
For this example, I’ll use NextCloud, because it was the most recent thing I migrated.
Collect Connection Details
First, collect all the information for the connection:
- Namespace: office
- Host/Service Name: nextcloud-postgresql
- User: nextcloud
- Password: some-very-secure-password
- Database: nextcloud
Connecting
Setup a port forward for the current database:
kubectl port-forward -n office svc/nextcloud-postgresql 5432:5432
Scale Down Application Deployment
Scale down the application so the database state doesn’t change between the dump and the load. That would be bad.
kubectl scale deployment -n office nextcloud --replicas 0
Dump the Data
Dump the schema using pg_dump
, you will be prompted for the password:
pg_dump -h localhost -U nextcloud nextcloud > nextcloud.sql
Scale Down Database StatefulSet
Now that its dumped, scale down the database so it doesn’t accidentally get in the way.
kubectl scale statefulset -n office nextcloud-postgresql --replicas 0
Creating and Loading
I created script to prompt for all the details. Use this script, or a variation of its commands to create the resources and load the dump.
#!/bin/sh
# Stop on any error
set -e
echo -n "Postgres Host: "
read PGHOST
echo -n "Postgres User: "
read PGUSER
echo -n "Postgres Password: "
read -s PGPASSWORD
echo
echo -n "Database: "
read DB_NAME
echo -n "Database User: "
read DB_USER
echo -n "Database Password: "
read -s DB_PASS
echo
echo -n "Database Dump: "
read DB_FILE
echo "Creating user"
createuser "${DB_USER}"
psql --command "alter user \"${DB_USER}\" with encrypted password '${DB_PASS}';"
echo "Creating database"
createdb --owner "${DB_USER}" -T template0 "${DB_NAME}"
echo "Granting privileges to user"
psql --command "grant all privileges on database \"${DB_NAME}\" to \"${DB_USER}\";"
echo "Loading dump"
psql "${DB_NAME}" -f "${DB_FILE}"
Update Configuration
This part is very application specific. In the NextCloud Helm chart I had to disable the PostgreSQL sub-chart and configure the external database configuration to use the new host and credentials.
If the deployment is managed with Helm, then pushing a new config update with the updated connection details should also scale up the deployment to the default. If it does not, just do the opposite of scaling down.
kubectl scale deployment -n office nextcloud --replicas 1
Now all thats left is cleaning up residual resources.