dbaas-operator is Yeat Another DBaaS Kubernetes operator (need to suggest yadbko as a name) that tries to simplify and unify Database Cluster deployments by building a higher abstraction layer on top of Percona Kubernetes Operators.
So it becomes much easier to deploy the DB cluster with dbaas-operator
and PMM DBaaS on top of it.
But another part of the picture is applications and their workloads to connect to the deployed DB Clusters.
On Kubernetes, application deployment could be done in many ways, either manually or as part of automatic deployments.
PMM DBaaS offers both - UI to create DB Clusters and get credentials and API to automate those actions.
dbaas-operator
adds Kubernetes native API to that batch as well.
But both require additional automation to join the application and the database in one deployment and provide a service to the end user.
And that operation is a challenging task, as every application could expect credentials in some specific format: secrets with hardcoded structures, environment variables with custom names, mount point secrets in particular locations, etc.
Database services add their complexity to that picture by exposing their connections and secrets in a format that is convenient or makes sense for them.
Usually, some Continues Delivery system or deployment package (helm, etc.) ensures all components' correct deployment sequence and health. So many custom pipelines and packages exist to connect a specific application to a database service.
But for simplicity and scalability, it would be nice to have some standard for connection or software that automates such a connection.
Connecting services is a known pattern: Service Discovery (broker, registry, repository) for the Service-Oriented Architecture.
servicebinding.io is another pattern to bind applications and workloads to the services (REST APIs, databases, event buses, etc.). This specification aims to create a Kubernetes-wide specification for communicating service secrets to workloads in a consistent way.
Service Binding Operator glues services and Kubernetes workflows together. It does so for the services and applications that support ServiceBinding specifications and those that don't.
Out of the box Service Binding Operator supports Percona Operator for MySQL based on Percona XtraDB Cluster (PXC), so we will deploy Database Cluster with dbaas-operator
and connect it to the simple Java application. We will use Spring PetClinic application that supports Spring Cloud Bindings.
We need to have Kubernetes cluster, Operator Lifecycle Manager (OLM) to install operators, and all required operators installed. In this blog, I would use minikube and assume that operator-sdk
is installed on the system
Here is a link to the script that:
- setups multi-node Kubernetes cluster
- installs OLM
- installs needed operators with the help of OLM
As a result we get cluster with all needed operators:
$ kubectl get sub -A
NAMESPACE NAME PACKAGE SOURCE CHANNEL
default dbaas-operator dbaas-operator dbaas-catalog stable-v0
default percona-server-mongodb-operator percona-server-mongodb-operator dbaas-catalog stable-v1
default percona-xtradb-cluster-operator percona-xtradb-cluster-operator dbaas-catalog stable-v1
operators my-service-binding-operator service-binding-operator operatorhubio-catalog stable
We will use dbaas-operator
to demonstrate how easy it is to create DB Cluster with it:
$ cat <<EOF | kubectl apply -f -
apiVersion: dbaas.percona.com/v1
kind: DatabaseCluster
metadata:
name: test-pxc-cluster
spec:
databaseType: pxc
databaseImage: percona/percona-xtradb-cluster:8.0.27-18.1
databaseConfig: |
[mysqld]
wsrep_provider_options="debug=1;gcache.size=1G"
wsrep_debug=1
wsrep_trx_fragment_unit='bytes'
wsrep_trx_fragment_size=3670016
secretsName: pxc-sample-secrets
clusterSize: 1
loadBalancer:
type: haproxy
exposeType: ClusterIP
size: 1
image: percona/percona-xtradb-cluster-operator:1.11.0-haproxy
dbInstance:
cpu: "1"
memory: 1G
diskSize: 15G
EOF
$ kubectl get db
NAME SIZE READY STATUS ENDPOINT AGE
test-pxc-cluster 2 2 ready test-pxc-cluster-haproxy.default 5m
$ kubectl apply -f https://raw.githubusercontent.com/redhat-developer/service-binding-operator/master/samples/apps/spring-petclinic/petclinic-mysql-deployment.yaml
deployment.apps/spring-petclinic created
service/spring-petclinic created
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
spring-petclinic-f7f587c5c-rvq2v 0/1 CrashLoopBackOff 2 (17s ago) 67s
As we didn't create a binding yet, the application can't connect to the database and thus fails.
Let us connect it and verify it is working:
$ cat <<EOF | kubectl apply -f -
apiVersion: binding.operators.coreos.com/v1alpha1
kind: ServiceBinding
metadata:
name: spring-petclinic
namespace: default
spec:
services:
- group: pxc.percona.com
version: v1
kind: PerconaXtraDBCluster
name: test-pxc-cluster
application:
name: spring-petclinic
group: apps
version: v1
resource: deployments
EOF
$ kubectl get servicebindings
NAME READY REASON AGE
spring-petclinic True ApplicationsBound 4m47s
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
spring-petclinic 1/1 1 1 17m
$ minikube service spring-petclinic --url
http://192.168.39.215:31181
What we have done above:
- Created
kind: ServiceBinding
, which takes PXC secrets and maps them to the application as mount points. - As PetClinic supports ServiceBinding spec with Spring framework, it understands those mount points and connects to the database.
Here is what mount point by ServiceBinding specification that Spring Cloud Bindings library parsed and connected to the database:
$ kubectl exec deployment/spring-petclinic -- ls -la /bindings/spring-petclinic/..2023_01_20_21_33_47.4121788695
total 56
drwxr-xr-x 2 root root 320 Jan 20 21:33 .
drwxrwxrwt 3 root root 360 Jan 20 21:33 ..
-rw-r--r-- 1 root root 18 Jan 20 21:33 clustercheck
-rw-r--r-- 1 root root 5 Jan 20 21:33 database
-rw-r--r-- 1 root root 32 Jan 20 21:33 host
-rw-r--r-- 1 root root 17 Jan 20 21:33 monitor
-rw-r--r-- 1 root root 17 Jan 20 21:33 operator
-rw-r--r-- 1 root root 18 Jan 20 21:33 password
-rw-r--r-- 1 root root 4 Jan 20 21:33 port
-rw-r--r-- 1 root root 7 Jan 20 21:33 provider
-rw-r--r-- 1 root root 17 Jan 20 21:33 proxyadmin
-rw-r--r-- 1 root root 18 Jan 20 21:33 replication
-rw-r--r-- 1 root root 18 Jan 20 21:33 root
-rw-r--r-- 1 root root 5 Jan 20 21:33 type
-rw-r--r-- 1 root root 4 Jan 20 21:33 username
-rw-r--r-- 1 root root 17 Jan 20 21:33 xtrabackup
$ kubectl exec deployment/spring-petclinic -- cat /bindings/spring-petclinic/..2023_01_20_21_33_47.4121788695/database
mysql
$ kubectl exec deployment/spring-petclinic -- cat /bindings/spring-petclinic/..2023_01_20_21_33_47.4121788695/host
test-pxc-cluster-haproxy.default
Check the url that was exposed by minikube:
There are many ways to deploy applications and services and connect them.
I am trying to collect some of them under my personal repo to understand the problem deeper. Please suggest other ways by commenting under this blog or in repo.
ServiceBinding specification is a standardized way that scales easily and allows you to connect Kubernetes workloads to the database services.
I will propose to dbaas-operator
to implement that specification so that it could expose different Database engines (mysql, mongo, pg) in a standard way.