I’ve been working with Kubernetes and databases for the past few months, and I’m enjoying learning and exploring more about Percona Everest’s features. Percona Everest is a free, open source tool that makes it easier for teams to manage databases in the cloud.
In a Cloud Native world, everything is programmable, including databases. Percona Everest provides a REST API that lets you manage databases like any other Kubernetes resource, using code, automation, and complete control. To explore this more deeply, I created a friendly and straightforward Python demo app to show how to integrate Everest’s APIs with internal tools.
In this article, we’ll explore how to use APIs to interact with databases in a Kubernetes environment using Percona Everest. I’ve built a simple Python demo, everest-api-demo, that shows how to create, manage, and delete database clusters without using the UI or CLI.
We will cover:
Note: Percona Everest also supports MySQL and MongoDB, but we’ll save those for another blog post.
When I started, I wondered if I had to do everything through the UI. There had to be a better way.
An API (Application Programming Interface) lets two systems talk to each other. You send a request (like “create a database”), and the system responds with data or performs an action.
For example, travel sites don’t own the aeroplanes; they use APIs to get real-time info from different airlines. Percona Everest works similarly: instead of clicking through a UI, you can use its API to automate database operations.
For databases, this means no more manual clicking or editing YAML files. With Percona Everest, you can provision PostgreSQL, MySQL, or MongoDB clusters using simple HTTP requests.

One of the best things about working with the Percona Everest is its excellent, beginner-friendly documentation, which includes APIs. You can explore it here: Percona Everest API Reference.
For every API call, in this picture, the Percona Everest docs show you:

To try Percona Everest’s APIs without writing code, use Postman, a visual tool for sending and inspecting API requests.
Tip: If you’re running Percona Everest locally (e.g., localhost:8080), use the Postman Desktop Agent to allow web-based Postman to send requests through your local machine.



In our Python demo (everest-api-demo), we use variables like these to make the code reusable:
|
1 |
EVEREST_API = "http://localhost:8080"<br>NAMESPACE = "everest"<br>CLUSTER_NAME = "demo-pg-cluster"<br>HEADERS = {<br> "Authorization": f"Bearer {API_TOKEN}",<br> "Content-Type": "application/json"<br>}<br> |
Let’s create a PostgreSQL cluster using the API. Here’s what the setup includes:
In our everest-api-demo, all of this is handled inside the create_cluster() function:
|
1 |
def create_cluster():<br> payload = {<br> "apiVersion": "everest.percona.com/v1alpha1",<br> "kind": "DatabaseCluster",<br> "metadata": {<br> "name": CLUSTER_NAME<br> },<br> "spec": {<br> "engine": {<br> "type": "postgresql",<br> "version": "17.4",<br> "replicas": 1,<br> "storage": {<br> "size": "25Gi",<br> "class": "standard-rwo"<br> },<br> "resources": {<br> "cpu": "1",<br> "memory": "2G"<br> }<br> },<br> "proxy": {<br> "type": "pgbouncer",<br> "replicas": 1,<br> "expose": {<br> "type": "external",<br> },<br> "resources": {<br> "cpu": "1",<br> "memory": "30M"<br> }<br> },<br> "backup": {<br> "pitr": {<br> "enabled": False<br> }<br> },<br> "monitoring": {<br> "resources": {}<br> },<br> "podSchedulingPolicyName": "everest-default-postgresql"<br> }<br> }<br><br> url = f"{EVEREST_API}/v1/namespaces/{NAMESPACE}/database-clusters"<br> response = requests.post(url, headers=HEADERS, json=payload)<br> response.raise_for_status()<br> logging.info(f"[✓] Percona Everest Cluster '{CLUSTER_NAME}' created successfully with API.")<br> logging.info(f"[ℹ️] API endpoint used: {url}")<br> logging.info("[ℹ️] Cluster details:n" + json.dumps(payload, indent=2, sort_keys=False))<br> |
The create_cluster() function prepares all the required database configuration (like PostgreSQL version, storage, resources, and proxy settings) inside a payload dictionary. It then makes a POST request to the Percona Everest API using Python’s requests library to create the cluster.
If the request is successful, the function logs a confirmation message and shows the full payload that was sent; this helps you verify that everything went as expected.
The line response.raise_for_status() ensures the script stops and throws an error if the API returns a failure status (like 400 or 500). This is useful for debugging and makes the script more robust.
To create your PostgreSQL cluster, you simply run:
|
1 |
python3 main.py create-cluster<br> |
Sample output:
|
1 |
[✓] Percona Everest Cluster 'demo-pg-cluster' created successfully with API.<br>[ℹ️] API endpoint used: http://localhost:8080/v1/namespaces/everest/database-clusters |
The same could be done using the following curl:
|
1 |
curl -X POST http://localhost:8080/v1/namespaces/everest/database-clusters <br> -H "Authorization: Bearer $EVEREST_API_TOKEN" <br> -H "Content-Type: application/json" <br> -d @payload.json<br> |
Once our database is created, the next step is to check what’s running in our cluster. Let’s list all available clusters. The Percona Everest API also provides an endpoint to list all database clusters in a specific namespace.
You can list all clusters in your namespace using this function:
|
1 |
def list_clusters():<br> url = f"{EVEREST_API}/v1/namespaces/{NAMESPACE}/database-clusters"<br> response = requests.get(url, headers=HEADERS)<br> response.raise_for_status()<br> clusters = response.json()<br> logging.info("[✓] List of clusters:")<br> for cluster in clusters.get("items", []):<br> name = cluster.get("metadata", {}).get("name")<br> engine = cluster.get("spec", {}).get("engine", {}).get("type")<br> status = cluster.get("status", {}).get("status", "unknown")<br> logging.info(f" - Name: {name}, Engine: {engine}, Status: {status}")<br> |
This function:
GET request to the Percona Everest API
To list your active clusters, just run:
|
1 |
python3 main.py list<br> |
And here’s what the output looks like:
|
1 |
[✓] List of clusters:<br> - Name: demo-pg-cluster, Engine: postgresql, Status: ready<br> - Name: postgresql-3a2, Engine: postgresql, Status: ready |
This is especially useful when you want to verify the state of your environments, or if you’re managing multiple clusters and want to see what’s deployed quickly.
Now that our cluster is running, how do we connect to it? Let’s use the API to retrieve credentials programmatically.
|
1 |
def get_credentials():<br> url = f"{EVEREST_API}/v1/namespaces/{NAMESPACE}/database-clusters/{CLUSTER_NAME}/credentials"<br> response = requests.get(url, headers=HEADERS)<br> response.raise_for_status()<br> creds = response.json()<br> dsn = f"postgres://{creds['username']}:{creds['connectionUrl']}"<br> logging.info(f"[✓] DSN: {dsn}")<br> return dsn<br> |
Run the script:
|
1 |
python3 main.py get-creds<br> |
Sample output:
|
1 |
[✓] DSN: postgres://postgres:n%3B%2FAn%3B6wHV%5D%3E-nWhmz%3Dc6%3BD%2B@demo-pg-cluster-pgbouncer.everest.svc:5432<br> |
Using curl instead:
|
1 |
curl --request GET <br> --url http://localhost:8080/v1/namespaces/everest/database-clusters/demo-pg-cluster/credentials <br> --header 'accept: application/json' <br> --header 'authorization: Bearer <YOUR_API_TOKEN>'<br> |
You can then use it directly with a psql command to connect from your Kubernetes cluster:
|
1 |
kubectl run psql-client --rm -it --image=postgres -- psql postgres://postgres:<your-password>@<host>:5432<br> |
This is a great way to quickly test your cluster connection without exposing anything externally.
Once you’re done with your PostgreSQL cluster, you can delete the cluster using the Percona Everest API.
|
1 |
def delete_cluster():<br> url = f"{EVEREST_API}/v1/namespaces/{NAMESPACE}/database-clusters/{CLUSTER_NAME}"<br> response = requests.delete(url, headers=HEADERS)<br> response.raise_for_status()<br> logging.info(f"[✓] Cluster '{CLUSTER_NAME}' deleted successfully.")<br> logging.info(f"[ℹ️] DELETE request sent to: {url}")<br> |
Run the script:
|
1 |
python3 main.py delete<br> |
Sample output:
|
1 |
[✓] Cluster 'demo-pg-cluster' deleted successfully.<br>[ℹ️] DELETE request sent to: http://localhost:8080/v1/namespaces/everest/database-clusters/demo-pg-cluster |
Using curl instead:
|
1 |
curl --request DELETE <br> --url http://localhost:8080/v1/namespaces/everest/database-clusters/demo-pg-cluster <br> --header 'accept: application/json' <br> --header 'authorization: Bearer <YOUR_API_TOKEN>'<br> |
This simple step completes the lifecycle of our database cluster, from creation and connection to deletion, all through API calls.
Feel free to explore the Percona Everest documentation to learn more about what’s possible. You can also check out and use this demo project: everest-api-demo, fork it, modify it, and share improvements!
Do you have questions or feedback? We’d love to hear from you in the Percona Community Forum. Let us know how Percona Everest works for you and how you use it in your projects!
Learn more about Percona Everest