The purpose of this tutorial is to guide a Kubernetes user to incorporate SlashDB API generation into their cluster.
The database often functions as the “brain” of an application. In a software infrastructure, the database can be housed as a service that can be reached from other services. The resultant system can satisfy a user’s availability and scalability needs.
This tutorial shows how to transform a database into an HTTP-based service, through SlashDB REST API generation and Kubernetes components. The outcome will be a highly-available and scalable database service that takes in external HTTP traffic.
Requirements for this tutorial:
-
A running, single-node Kubernetes cluster (such as Minikube’s Kubernetes cluster)
-
Installed SlashDB through the Docker image, logged in, and the desired database is configured to be auto-connected to upon the application starting
Steps to Build the Service Using SlashDB
1.Prepare the configuration of the Kubernetes Deployment, Service, and Ingress objects.
The Deployment, Service, and Ingress objects function as the foundation of our application.
As a refresher, the Deployment is a Kubernetes object that runs multiple replicas of application Pods. Deployment objects have the ability to start a new Pod when a Pod goes down. This feature of Deployment objects supports high availability. The Deployment object here will be managing the Pods running SlashDB. A powerful feature of Deployments is that they can be easily scaled up or down with a single kubectl command while the Deployment is running.
The Service object allows for internal cluster traffic to be routed to running Pods. The Service object here will send traffic to the Pods running SlashDB that are part of the Deployment object.
The Ingress object can route external HTTP (or HTTPS) traffic to the Pods in the cluster. The Ingress object here will take in external HTTP traffic and move it to the Pods running SlashDB.
Here are the YAML files of the configurations of the Kubernetes objects:
#slash-db-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: slash-db-deployment
labels:
app: slash-db
spec:
replicas: 3
selector:
matchLabels:
app: slash-db
template:
metadata:
labels:
app: slash-db
spec:
containers:
- name: slash-db
image: slashdb/slashdb
ports:
- containerPort: 80
volumeMounts:
- name: config-volume
mountPath: /etc/slashdb
- name: log-volume
mountPath: /var/log/slashdb
volumes:
- name: config-volume
hostPath:
path: /slashdb
- name: log-volume
hostPath:
path: /slashdb-log
#slash-db-service.yaml
apiVersion: v1
kind: Service
metadata:
name: slash-db-service
spec:
selector:
app: slash-db
ports:
- protocol: TCP
port: 80
targetPort: 80
#slash-db-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: slash-db-service
port:
number: 80
2.Prepare the Deployment and Service objects for the Memcached server.
The Memcached server enables state synchronization for all the SlashDB Pods. The Deployment object is the Memcached server, and its accompanying Service object sends traffic to the server. Here are the YAML files of the configurations of the Kubernetes Deployment and Service objects:
#memcached-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: memcached-deployment
labels:
app: memcached
spec:
replicas: 1
selector:
matchLabels:
app: memcached
template:
metadata:
labels:
app: memcached
spec:
containers:
- name: memcached
image: memcached
ports:
- containerPort: 11211
#memcached-service.yaml
apiVersion: v1
kind: Service
metadata:
name: memcached-service
spec:
selector:
app: memcached
ports:
- protocol: TCP
port: 11211
targetPort: 11211
3.Create the Kubernetes objects for Memcached by running these commands:
kubectl apply -f memcached-deployment.yaml
kubectl apply -f memcached-service.yaml
4.Uncomment the Memcached server settings in the slashdb.ini file located in the SlashDB configuration folder.
Replace the IP Address for memcached_server with the IP address of the memcached-service. The IP address is in by examining the CLUSTER-IP column for the memcached-service in the table shown after running the command:
kubectl get services
Here is a an example of Memcached server settings that could be in a slashdb.ini file:
#slashdb/slashdb.ini
# Memcached Server Settings
memcached_server = 127.0.0.1:11211
memcache_root_key = slashdb
# name of SlashDB memcache lock key
;memcache_lock_key = slashdb_registry_lock
# max time in seconds to wait before trying to access memcache when lock exists
;memcache_lock_sleep_interval = 0.1
Remove the semicolons at the beginning of each of the Memcached server settings to uncomment the setting.
5.Mount both the SlashDB configuration and log folders to the node in the cluster.
These folders allow the application to perform appropriately.
If you are using Minikube, use this command:
minikube mount <source directory>:<target directory>
The <source directory> is the location of one of the folders (either the configuration or the log folder) that are given when SlashDB is downloaded. The <target directory> must match the appropriate volumes’s hostPath.path field in the SlashDB Deployment object configuration shown above.
For example, the <target-directory> for mounting the configuration folder is the hostPath.path field of the volume called config-volume found in the SlashDB Deployment object configuration. This command runs twice, once for the configuration folder mount, and another time for the log folder mount. Each command runs in a separate window.
6.Create the Kubernetes objects for SlashDB by running these commands:
kubectl apply -f slash-db-deployment.yaml
kubectl apply -f slash-db-service.yaml
kubectl apply -f slash-db-ingress.yaml
7.Ensure your environment can handle LoadBalancer services.
If you are using Minikube, run this command:
minikube tunnel
to connect to LoadBalancer services. This command runs in a separate window.
8.Locate the external IP address of the ingress by running the command:
kubectl get services -n ingress-nginx
and examining the EXTERNAL-IP column for the ingress-nginx-controller service.
9.The external IP address now finds our database service, try to make some API calls with it!
Scaling the Service
Kubernetes Deployments provide high availability, but scalability is also a consideration. Scalability needs to be a feature for the system. In the modern technical landscape, systems meet with increases in traffic and need to be able to scale up in order to meet the demand. Kubernetes provides ways to scale up (and scale down) the SlashDB deployment mentioned above. One way is to use the command:
kubectl scale deployment slash-db-deployment --replicas=<n>
where <n> is the number of Pods wanted. This command can also reduce the number of Pods.
The ability to dynamically scale the number of Pods up and down is powerful and can make managing the system easier. One way to do this by utilizing monitoring for the SlashDB deployment where an alert triggers a script to either scale up or down in response to the current load the SlashDB system is facing.
The script takes in the current number of Pods as input (the system stores current number of Pods prior to this and kept updated), and then does some incrementing (scaling up) or decrementing (scaling down) calculation. There are two scripts in this example, where one script runs to scale up, and the other runs to scale down. There are also two different alerts the monitoring system would use, one alert that triggers the scaling-up script, and the other alert triggers the scaling-down script. For example, an implementation of the scaling-up script would increment the input by 2, store the result in a variable x, and then run the kubectl scale command mentioned above with x inputted as the number of Pods wanted.
Automatic Scaling
Another way to dynamically scale up (and scale down) the SlashDB deployment is by using Kubernetes’s horizontal Pod autoscaling. Horizontal Pod autoscaling in Kubernetes can scale the number of Pods up (or down) by in a way that maintains an average percent CPU usage based on all the running Pods. When setting up the autoscaler, Kubernetes takes in input for choosing the maximum and minimum number of Pods wanted at any point in the deployment, as well as the average percent CPU usage wanted among all the running Pods.
The command to set up the horizontal Pod autoscaling is:
kubectl autoscale deployment slash-db-deployment --min=<x> --max=<y> --cpu-percent=<z>
where <x> and <y> is the minimum number and maximum number of Pods wanted at any point in the deployment, and <z> is the average percent CPU usage wanted for all the running Pods. The horizontal Pod autoscaler scales up (or down) to try to maintain the average percent CPU usage.
Further Enhancements
This tutorial uses a single-node Kubernetes cluster, but the content is adaptable to work in multi-node Kubernetes clusters.
The Ingress object in this tutorial takes in HTTP traffic. If the Ingress object needs to take in HTTPS traffic, visit this link. The structure of the service is robust and can fit well in a production environment.
Key Takeaways
SlashDB’s REST API generation smooths out the process of developing an API for your database.
Kubernetes helps by providing a highly-available and scalable Deployment object that runs SlashDB in multiple Pods, and that can take in external HTTP traffic (with the help of the Ingress and Service objects).