vCluster Platform v4.1 - External Database Connector

Mike Petersen
9 Minute Read

When you create a vCluster, it needs a backing store. By default, it will be created with SQLite, but there are other options, such as etcd, MySQL, and PostgreSQL. Let's take a look at one of the new features that launched with vCluster Platform 4.1 - External Database Connector.

You can read more about the updates for vCluster Platform v4.1 in our changelog

Intro

In this blog post we will walk through how to get the External Database Connector working with MySQL running in a vCluster. Why would you want to use anything other than the lightweight default?

  • You are already running a relational database at scale
  • You want to offload database HA clustering
  • Backup / Recovery using a Cloud Provider

Previously, you would need to specify the database you were going to use for each vCluster, which required a connection string similar to:

"mysql://username:password@hostname:5432/vcluster-1"

This required manual configuration and was per vCluster. With the updates, you can now create a configuration using a secret and then reference it at the time of creation in the vCluster configuration, you can even use a template!

Requirements

In this demo, we are running everything on-prem. The username and password used for the MySQL database are not suggested for production. 

This demo assumes that you have installed the following:

If you already have a Database, you can skip much of the demo setup and start with the External Database Connector Secret section. To teach some of the other concepts of the vCluster Platform, we are going to use Templates and Apps. 

Once you have vCluster Platform running (you could also use vcluster.cloud and then connect a cluster), move on to the next section where we will template out and create a vCluster that will host our MySQL Database.

MySQL Database App

We will start by creating an App in the UI. Head to Templates > Apps > Add app template. We will create this with kubectl. You could also use Helm if you have a Helm chart for MySQL. 

This is a basic configuration for MySQL. Some of the configuration options we selected for this application are:

  • Persistent Volume using the default Storage Class
  • 20Gi storage request, which is probably too much for a demo
  • Load Balancer for the service; other examples use NodePort
  • Plain text MySQL credentials for demo purposes (using root:password)

For this demo we are just updating the Definition section and the Name so that we can find it when we configure the app within the vCluster template. Go ahead and fill in the definition with the application YAML below in the vCluster Platform UI and save.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv-volume
  labels:
    type: local
spec:
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
---
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  type: LoadBalancer
  ports:
  - port: 3306
  selector:
    app: mysql
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - image: mysql:latest
        name: mysql
        env:
          # Use secret in real usage
        - name: MYSQL_ROOT_PASSWORD
          value: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim

MySQL vCluster Template

Now that we have an App defined we can create a template and add the App to the template. To do this you will navigate to Templates > Virtual Clusters > Add Virtual Cluster Template. 

Name your template something like vCluster MySQL. The definition section can either be left with the default options, or you can add the option to sync the ingress class fromHost with this YAML:

sync:
  toHost:
    ingresses:
      enabled: true
  fromHost:
    ingressClasses:
      enabled: true
controlPlane:
  coredns:
    enabled: true
    embedded: true

The main section we want to focus on is the App section. This is where we will add the MySQL App that we created to the template. In the drop-down, you should see the App you just created; in my demo environment, I named it MySQL. Add the app and save the template.

Create the MySQL vCluster

Now that we have a template, we can create the MySQL virtual cluster and verify that we can connect to the database. In the Virtual Cluster section under your project, select “Create virtual cluster”, then select the template we just created. In my demo, it is named vCluster MySQL.

Once the vCluster has launched we can connect to it and verify connectivity to MySQL. Reference the name of the vCluster in the UI. You can also find it with `vcluster list`

$ vcluster list
         NAME      |           NAMESPACE           | STATUS  |    VERSION     | CONNECTED |    AGE      
  -----------------+-------------------------------+---------+----------------+-----------+-------------
    vcluster-42r7g | loft-default-v-vcluster-42r7g | Running | 0.21.1         |           | 20h7m57s    
    vcluster-fgkb2 | loft-default-v-vcluster-fgkb2 | Running | 0.21.1         |           | 142h36m49s  
    vcluster-t2kjh | loft-default-v-vcluster-t2kjh | Running | 0.21.1         |           | 118h56m16s  
    vcluster-w8zwn | loft-default-v-vcluster-w8zwn | Running | 0.21.1         |           | 20h16m32s 

In our example, the vCluster we want to connect to is w8zwn - so we can head to the command line and connect to the cluster using:

vcluster connect vcluster-w8zwn

This will port forward and connect you directly to the vCluster, so you’ll need to open another terminal to interact with it. 

The main reason we are connecting to the cluster is to pull the LoadBalancer IP and familiarize ourselves with using vcluster connect. You can also find this information on the host cluster however you may have a ton of resources to look through. I’ll give you the commands to find it on both:

vCluster

$ kubectl get svc | grep -i mysql
NAME         TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)          AGE
mysql        LoadBalancer   10.43.177.29   192.168.86.16   3306:32037/TCP   20h


Host Cluster

$ kubectl get svc --all-namespaces | grep -i w8zwn | grep -i loadbalancer
loft-default-v-vcluster-w8zwn   mysql-x-default-x-vcluster-w8zwn                             LoadBalancer   10.43.177.29    192.168.86.16   3306:32037/TCP               20h

Now we know the IP address associated with our MySQL Database, let’s connect to it!

On a Mac:

mysqlsh --uri root@192.168.86.16:3306

Once connected, you can use show databases; to see what has been populated. This information will update once we create a new vCluster using the External Database Connector, but first, we need to create the secret so that we can connect.

External Database Connector Secret

Now that we know the Database information we can create a secret with the relevant connection information. The secret will need to live in the vcluster-platform namespace, or whichever namespace was used for the vCluster Platform installation. In this demo the namespace is just vclsuter-platform so we can use that for the example secret.

We will need to name it something relevant (save this information for the next step), select the namespace where vCluster Platform is installed, update the endpoint with the LoadBalancer IP address we created, update the password with “password” (super secure), update the port with 3306 since we left it default, and update the user as “root” which is the default. 

apiVersion: v1
kind: Secret
metadata:
  name: mysql-ext-db # this is a normal metadata name. A descriptive name is recommended. This will be used in a tenet vCluster's config to reference the connector secret
  namespace: vcluster-platform # this is the namespace that vCluster Platform is installed in. "vcluster-platform" and "loft" are common values.
  labels:
    loft.sh/connector-type: "shared-database"
stringData:
  endpoint: "192.168.86.16" # this could be a service endoint or an external hostname endpoint
  password: "password"
  port: "3306" # 3306 is a common port for database servers
  user: "root"

Save the above configuration in a mysql-ext-db.yaml file and then create it on the host cluster. You might need to verify your context before creating this if you connected to the vCluster previously. If you have kubectx installed, you can run the following:

$ kubectx
default
vcluster_vcluster-pqlxz_loft-default-v-vcluster-pqlxz_default
vcluster_vcluster-tk2c2_loft-default-v-vcluster-tk2c2_default
vcluster_vcluster-w8zwn_loft-default-v-vcluster-w8zwn_default

In my demo the “default” context is the host cluster. I’ll run this to switch contexts:

kubectx default

Then, create the secret:

kubectl create -f mysql-ext-db.yaml

$ kubectl get secret -n vcluster-platform | grep -i mysql
mysql-ext-db                              Opaque               4      20h

Now, we can actually create a virtual cluster using the MySQL Database as the backingStore.

vCluster Using the External Database

Head back to the UI and create a new template: Templates > Virtual Clusters > Add Virtual Cluster Template. Name this template “vCluster with ext-db” and this time we are going to update the Definition. We need to update the control plane to use a new backingStore. The backingStore is going to reference the secret we just created. 

sync:
  toHost:
    ingresses:
      enabled: true
controlPlane:
  coredns:
    enabled: true
    embedded: true
  backingStore:
    database:
      external:
        connector: "mysql-ext-db"

Update the definition then save the template. Now it’s time to create the virtual cluster. Head back to Virtual Clusters > Create virtual cluster. Use the template we just created. Wait for the virtual cluster to come up. Once it’s up we can verify that a new database has been created for the virtual cluster in MySQL.

mysqlsh --uri root@192.168.86.16:3306

show databases; (removed other default MySQL DBs to show the desired DB)

+----------------------------------+
| Database                         |
+----------------------------------+
| 19ae9b4871dbde0e5146e4d6ae31c8e8 |
+----------------------------------+
5 rows in set (0.0075 sec)

The new database has been created: 19ae9b4871dbde0e5146e4d6ae31c8e8.

If you want to explore further, you can use 19ae9b4871dbde0e5146e4d6ae31c8e8; and then show tables;

+--------------------------------------------+
| Tables_in_19ae9b4871dbde0e5146e4d6ae31c8e8 |
+--------------------------------------------+
| kine                                       |
+--------------------------------------------+
1 row in set (0.0181 sec)

Success! We created a new vCluster that uses our MySQL database for the dataStore.

Conclusion

In this post we showed some of the useful features of the vCluster Platform. If you already are managing a database, backing it up with the ability to restore, or just want to store your vCluster information somewhere specific, then this will make it easier to set up and scale out.

As always, your feedback is valuable and something we are interested in. Join our slack to ask questions. If you run into issues head to GitHub and open an issue.

Sign up for our newsletter

Be the first to know about new features, announcements and industry insights.