Skip to main content

Learn to Deploy FerretDB on Kubernetes on Taikun CloudWorks

· 7 min read
Alexander Fashakin
FerretDB Team

Learn to Deploy FerretDB on Kubernetes on Taikun CloudWorks

Are you looking to set up a highly scalable and reliable enterprise Kubernetes cluster for your FerretDB databases?

Taikun CloudWorks offers an open-source solution that simplifies the deployment and management of Kubernetes clusters. This setup is ideal for developers seeking robust infrastructure for their FerretDB deployments, which is critical for modern enterprise level applications.

You can package and deploy FerretDB on Taikun CloudWorks. Taikun's simplified Kubernetes platform offers a unified and user-friendly interface to deploy, manage, and monitor Kubernetes clusters across multiple cloud environments, including AWS, Azure, OpenStack, GCP.

By the end of this blog post, you will have a comprehensive understanding of how to deploy FerretDB with a Percona Distribution for PostgreSQL as the backend on a Kubernetes cluster on Taikun CloudWorks.

Prerequisites

  • Kubernetes cluster configured and running on Taikun CloudWorks
  • kubectl

Set up a Kubernetes cluster in Taikun cloud

Start by creating a Taikun project. It will act as a central management place for the Kubernetes cluster. Read the following documentation to learn how to create a Kubernetes cluster in Taikun:

Export your kubeconfig file to access the Kubernetes cluster:

export KUBECONFIG=/Users/<path>/<to>/kubeconfig.yaml

Next, create a namespace to isolate the workloads and resources in a custom namespace.

kubectl create namespace ferretdb

Install Percona PostgreSQL Operator

Percona Distribution for PostgreSQL will be used as the PostgreSQL backend for FerretDB. It consists of several open source components that enable high availability, robust performance, backup, and scalability for enterprise level deployments. You can set it up on a Kubernetes cluster through the Percona PostgreSQL Operator.

So start by installing the Operator with kubectl on your Kubernetes environment setup.

Apply the Percona PostgreSQL Operator within the ferretdb namepace:

kubectl apply --server-side -f https://raw.githubusercontent.com/percona/percona-postgresql-operator/v2.3.1/deploy/bundle.yaml -n ferretdb

You should see output indicating the resources have been server-side applied:

customresourcedefinition.apiextensions.k8s.io/perconapgbackups.pgv2.percona.com serverside-applied
customresourcedefinition.apiextensions.k8s.io/perconapgclusters.pgv2.percona.com serverside-applied
customresourcedefinition.apiextensions.k8s.io/perconapgrestores.pgv2.percona.com serverside-applied
customresourcedefinition.apiextensions.k8s.io/postgresclusters.postgres-operator.crunchydata.com serverside-applied
serviceaccount/percona-postgresql-operator serverside-applied
role.rbac.authorization.k8s.io/percona-postgresql-operator serverside-applied
rolebinding.rbac.authorization.k8s.io/service-account-percona-postgresql-operator serverside-applied
deployment.apps/percona-postgresql-operator serverside-applied

Deploy the PostgreSQL cluster

You need to configure the PostgreSQL database according to FerretDB requirements. That means setting up a ferretdb database and user credentials with the necessary privileges to it.

With that in mind, adjust the cr.yaml file to reflect that so it creates the database, user, password and other credentials in Secret.

apiVersion: pgv2.percona.com/v2
kind: PerconaPGCluster
metadata:
name: cluster1
spec:
crVersion: 2.3.1
users:
- name: ferretuser
databases:
- ferretdb
image: percona/percona-postgresql-operator:2.3.1-ppg16-postgres
imagePullPolicy: Always
postgresVersion: 16
instances:
- name: instance1
replicas: 3
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
podAffinityTerm:
labelSelector:
matchLabels:
postgres-operator.crunchydata.com/data: postgres
topologyKey: kubernetes.io/hostname
dataVolumeClaimSpec:
accessModes:
- ReadWriteOnce
storageClassName: cinder-csi
resources:
requests:
storage: 1Gi
proxy:
pgBouncer:
replicas: 3
image: percona/percona-postgresql-operator:2.3.1-ppg16-pgbouncer
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
podAffinityTerm:
labelSelector:
matchLabels:
postgres-operator.crunchydata.com/role: pgbouncer
topologyKey: kubernetes.io/hostname
backups:
pgbackrest:
image: percona/percona-postgresql-operator:2.3.1-ppg16-pgbackrest
repoHost:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
podAffinityTerm:
labelSelector:
matchLabels:
postgres-operator.crunchydata.com/data: pgbackrest
topologyKey: kubernetes.io/hostname
manual:
repoName: repo1
options:
- --type=full
repos:
- name: repo1
schedules:
full: '0 0 * * 6'
volume:
volumeClaimSpec:
accessModes:
- ReadWriteOnce
storageClassName: cinder-csi
resources:
requests:
storage: 1Gi
pmm:
enabled: false
image: percona/pmm-client:2.41.0
secret: cluster1-pmm-secret
serverHost: monitoring-service

Apply the custom resource YAML to create the PostgreSQL cluster:

kubectl apply -f deploy/cr.yaml -n ferretdb

Check the status of the cluster:

kubectl get pg -n ferretdb

Initially, the status will be initializing:

NAME       ENDPOINT                          STATUS         POSTGRES   PGBOUNCER   AGE
cluster1 cluster1-pgbouncer.ferretdb.svc initializing 13s

After some time, the status should change to ready:

kubectl get pg -n ferretdb
NAME ENDPOINT STATUS POSTGRES PGBOUNCER AGE
cluster1 cluster1-pgbouncer.ferretdb.svc ready 3 3 5m10s

Run kubectl get pods -n ferretdb to ensure all pods are running. The output should indicate that the pods are in the Running state:

NAME                                           READY   STATUS    RESTARTS   AGE
cluster1-backup-p25l-xh6dm 1/1 Running 0 52s
cluster1-instance1-dtj6-0 4/4 Running 0 97s
cluster1-instance1-j9jv-0 4/4 Running 0 97s
cluster1-instance1-k8tj-0 4/4 Running 0 97s
cluster1-pgbouncer-87c4d584d-dj52c 2/2 Running 0 97s
cluster1-pgbouncer-87c4d584d-ks87p 2/2 Running 0 97s
cluster1-pgbouncer-87c4d584d-pxlg8 2/2 Running 0 97s
cluster1-repo-host-0 2/2 Running 0 97s
percona-postgresql-operator-55fff7dd8b-x7kjx 1/1 Running 0 147m

Apply FerretDB deployment

Deploy FerretDB using the following configuration:

apiVersion: apps/v1
kind: Deployment
metadata:
name: ferretdb
namespace: ferretdb
labels:
app: ferretdb
spec:
replicas: 1
selector:
matchLabels:
app: ferretdb
template:
metadata:
labels:
app: ferretdb
spec:
containers:
- name: ferretdb
image: ghcr.io/ferretdb/ferretdb
ports:
- containerPort: 27017
env:
- name: POSTGRES_HOST
valueFrom:
secretKeyRef:
name: cluster1-pguser-ferretuser
key: host
- name: FERRETDB_POSTGRESQL_URL
value: postgres://postgres@$(POSTGRES_HOST):5432/ferretdb
---
apiVersion: v1
kind: Service
metadata:
name: ferretdb-service
namespace: ferretdb
spec:
selector:
app: ferretdb
ports:
- name: mongo
protocol: TCP
port: 27017
targetPort: 27017

Apply the yaml file:

kubectl apply -f ferretdeploy.yaml -n ferretdb

Check the status of the deployment:

kubectl get pods -n ferretdb

You should see the ferretdb pod in the Running state:

NAME                                           READY   STATUS    RESTARTS   AGE
ferretdb-5f6d9dfd59-szl78 1/1 Running 0 9s

Connect to FerretDB

Before connecting to FerretDB, get the MongoDB_URI user credential needed to set up the connection.

Start by retrieving the password for the ferretuser stored in Secret and the ferretdb-service address and port. The ferretuser Secret object is named as cluster1-pguser-ferretuser.

kubectl get secret cluster1-pguser-ferretuser -n ferretdb -o jsonpath="{.data.password}" | base64 --decode

Check the services created in the namespace:

kubectl get svc -n ferretdb

Example output:

kubectl get svc -n ferretdb
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cluster1-ha ClusterIP 10.233.60.147 <none> 5432/TCP 9m49s
cluster1-ha-config ClusterIP None <none> <none> 9m49s
cluster1-pgbouncer ClusterIP 10.233.36.128 <none> 5432/TCP 9m48s
cluster1-pods ClusterIP None <none> <none> 9m49s
cluster1-primary ClusterIP None <none> 5432/TCP 9m49s
cluster1-replicas ClusterIP 10.233.48.145 <none> 5432/TCP 9m49s
ferretdb-service ClusterIP 10.233.22.188 <none> 27017/TCP 3m36s

The ferretdb-service acts as the ClusterIP service, and allows you to connect to the FerretDB instance within the Kubernetes cluster (10.233.22.188:27017).

Run a mongosh to connect to FerretDB:

kubectl -n ferretdb run mongosh --image=rtsp/mongosh --rm -it -- bash

Once inside the container, connect to FerretDB using the URI:

mongosh 'mongodb://ferretuser:<password>@10.233.22.188:27017/ferretdb?authMechanism=PLAIN'

You should see a successful connection message. To verify, you can insert and query a document:

ferretdb> db.test.insert({a:34})
{
acknowledged: true,
insertedIds: { '0': ObjectId('664ff91b7207189218a26a13') }
}

ferretdb> db.test.find()
[ { _id: ObjectId('664ff91b7207189218a26a13'), a: 34 } ]

Check data in PostgreSQL

FerretDB stores all data on PostgreSQL. So if you find yourself wondering how that looks, you can check it out:

FERRETUSER_URI=$(kubectl get secret cluster1-pguser-ferretuser --namespace ferretdb -o jsonpath='{.data.uri}' | base64 --decode)
kubectl run -i --rm --tty pg-client --image=perconalab/percona-distribution-postgresql:16 --restart=Never -- psql $FERRETUSER_URI
ferretdb=> set search_path to ferretdb;
SET
ferretdb=> \dt
List of relations
Schema | Name | Type | Owner
----------+-----------------------------+-------+------------
ferretdb | _ferretdb_database_metadata | table | ferretuser
ferretdb | test_afd071e5 | table | ferretuser
(2 rows)

ferretdb=> table test_afd071e5;
_jsonb
------------------------------------------------------------------------------------------------------------------------------
{"a": 34, "$s": {"p": {"a": {"t": "int"}, "_id": {"t": "objectId"}}, "$k": ["_id", "a"]}, "_id": "664ff91b7207189218a26a13"}
(1 row)

Clean up resources

You can clean up all used resources by just deleting the namespace:

kubectl delete namespace ferretdb

Conclusion

Deploying FerretDB and Percona Distribution for PostgreSQL on a Kubernetes cluster using Taikun CloudWorks, offers a highly scalable, reliable, and open-source solution for managing enterprise databases.

By following the steps outlined in this guide, you can ensure your databases are resilient and performant on a simplified Kubernetes platform.

To learn read more about FerretDB and other solutions in this guide, explore: