The cloud has become an undeniably crucial part of our lives. It's pretty much everywhere across the entire IT sector. And for those who haven't jumped on board yet, honestly, it's not a matter of if but when.
Table of Contents
The simple reality is, if you are not in the cloud or at least making plans to be, you are seriously risking falling behind in the fast-paced digital world.
Now, when we are talking about modern cloud infrastructure, especially for running dynamic, scalable applications, there is one thing we just cannot imagine it without: Kubernetes.
It is the orchestrator that brings real order and efficiency to the massive power of distributed cloud computing. Whether you are building a straightforward web service or a complex microservices setup, Kubernetes gives you the solid foundation for resilience, scalability, and easy management. It is not just another tool; it's the absolute backbone of the cloud-native future.
Kubernetes does not only power up web services, but also PostgreSQL. escpecially with the help of Cloud Native PostgreSQL (CNPG). It lets us declaratively manage our PostgreSQL clusters, handle backups, scaling, and a whole lot more, all through simple Kubernetes manifests.
I want to give you a quick guide on how to get the CNPG operator up and running on your Minikube environment. It’s pretty straightforward, so let's dive in!
First things first, we need to apply the CNPG operator's core manifest. The following command sets up everything required for the operator to function:
1 |
kubectl apply -f https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.26/releases/cnpg-1.26.0.yaml |
With this command, a lot happens under the hood. Specifically, this manifest will deploy:
Namespaces: It initializes the dedicated cnpg-system namespace where the operator itself will reside.
Custom Resources (CRDs): This is where the magic happens! It defines new Kubernetes resource types like Backup, Cluster, Publication, ScheduledBackup, Subscription, and many more. These CRDs allow you to manage your PostgreSQL aspects directly through kubectl.
RBAC (Role-Based Access Control): Necessary ClusterRoles, ClusterRoleBindings, and ServiceAccounts are set up. These control the permissions, ensuring the operator can interact with your Kubernetes cluster securely and effectively.
Webhooks: Mutating and validating webhook configurations are deployed. These are crucial for validating your custom resource definitions and potentially mutating them (e.g., adding default values) as they are created or updated.
Controller Deployment: The cnpg-controller-manager Deployment is created within the cnpg-system namespace. This is the heart of the operator, responsible for watching your CRDs and orchestrating PostgreSQL operations.
Once you have applied the manifest, it is always a good practice to check that the controller has successfully deployed and is running without issues. We can check its rollout status with this command:
1 |
kubectl rollout status deployment -n cnpg-system cnpg-controller-manager |
If everything went smoothly, you should see an output similar to this:
1 |
deployment "cnpg-controller-manager" successfully rolled out |
This confirms that the CNPG operator is ready to accept your PostgreSQL cluster definitions.
From this point onwards, we will primarily be interacting within the cnpg-system namespace, especially when defining or managing our PostgreSQL clusters via CNPG. To save ourselves some typing and always targeting the correct namespace, we can set our default Kubernetes context:
1 |
kubectl config set-context --current --namespace=cnpg-system |
Now, all subsequent kubectl commands (unless you explicitly specify a different namespace with -n) will automatically operate within the cnpg-system namespace. This just makes life a little easier.
Our Minikube environment is now equipped with the powerful Cloud Native PostgreSQL operator. We are all set to start defining and managing your PostgreSQL clusters in a truly cloud-native way.
So let's create our very first PostgreSQL cluster on Minikube. I am going to keep it super simple and create a single-instance database cluster without getting into too many fancy options just yet.
Let' s create a manifest file named single.yaml. Its content will be:
1 2 3 4 5 6 7 8 9 |
apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-example spec: instances: 1 storage: size: 1Gi |
In this brief manifest:
instances: 1: This line is pretty straightforward. It tells CNPG that we want a single PostgreSQL pod to be deployed for our cluster.
storage.size: 1Gi: This is where we request our persistent storage. We're asking for a 1 Gigabyte persistent volume to hold our PostgreSQL data.
With our single.yaml file ready, it's time to tell Kubernetes to create our PostgreSQL cluster.
1 |
kubectl apply -f single.yaml |
If everything goes well, you should see an output confirming the creation:
1 |
cluster.postgresql.cnpg.io/cluster-example created |
This means Kubernetes has accepted your request, and the CNPG operator is now getting to work creating your PostgreSQL instance.
Now, let's confirm that our PostgreSQL pod is actually up and running. We can check the status of our pods with kubectl get pods:
1 |
kubectl get pods |
Your output should look something like this, showing your cluster-example-1 pod in a Running state:
1 2 |
NAME READY STATUS RESTARTS AGE cluster-example-1 1/1 Running 0 2m |
Connecting to our brand-new PostgreSQL pod's container and get to the psql shell.
1 |
kubectl exec -it pod/cluster-example-1 -- /bin/bash |
You will see some initial messages, and then you will be inside the container. From there, just type psql to enter the PostgreSQL client:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
Defaulted container "postgres" out of: postgres, bootstrap-controller (init) psql psql (17.5 (Debian 17.5-1.pgdg110+1)) Type "help" for help. postgres=# \du List of roles Role name | Attributes -------------------+------------------------------------------------------------ app | postgres | Superuser, Create role, Create DB, Replication, Bypass RLS streaming_replica | Replication postgres=# \l List of databases Name | Owner | Encoding | Locale Provider | Collate | Ctype | Locale | ICU Rules | Access privileges -----------+----------+----------+-----------------+---------+-------+--------+-----------+----------------------- app | app | UTF8 | libc | C | C | | | postgres | postgres | UTF8 | libc | C | C | | | template0 | postgres | UTF8 | libc | C | C | | | =c/postgres + | | | | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | libc | C | C | | | =c/postgres + | | | | | | | | postgres=CTc/postgres (4 rows) |
However, if you don't specify any database options in your CNPG cluster manifest like we did, the operator automatically creates an app user and an app database, with the app user as the owner.
Leave a Reply