How To Use KubeDB and Postgres Sidecar for Database Integrations in Kubernetes
In this article I describe the most popular approaches for integrating databases and web applications within the Kubernetes ecosystem to align with the Twelve-Factor App.
Join the DZone community and get the full member experience.
Join For FreeIn contemporary web development, a recurring challenge revolves around harmonizing the convenience and simplicity of using a database with a web application. My name is Viacheslav Aksenov, and in this article, I aim to explore several of the most popular approaches for integrating databases and web applications within the Kubernetes ecosystem. These examples are examined within the context of a testing environment, where constraints are more relaxed. However, these practices can serve as a foundation applicable to production environments as well.
One Service, One Database. Why?
Running a database alongside a microservice aligns with the principles outlined in the Twelve-Factor App methodology. One key factor is "Backing Services" (Factor III), which suggests treating databases, message queues, and other services as attached resources to be attached or detached seamlessly.
By co-locating the database with the microservice, we adhere to the principle of having a single codebase that includes the application and its dependencies, making it easier to manage, scale, and deploy.
Additionally, it promotes encapsulation and modularity, allowing the microservice to be self-contained and portable across different environments, following the principles of the Twelve-Factor App. This approach enhances the maintainability and scalability of the entire application architecture.
For this task, you can leverage various tools, and one example is using KubeDB.
What Is KubeDB?
KubeDB is an open-source project that provides a database management framework for Kubernetes, an open-source container orchestration platform. KubeDB simplifies the deployment, management, and scaling of various database systems within Kubernetes clusters.
We used the following benefits from using this tool:
- Database operators: Postgres operator to simplify the process of deploying and managing database instances on Kubernetes.
- Monitoring and alerts: KubeDB integrates with monitoring and alerting tools like Prometheus and Grafana, enabling you to keep an eye on the health and performance of your database instances.
- Security: KubeDB helps you set up secure access to your databases using authentication mechanisms and secrets management.
And it is very easy to set up the deployment.
deployment.yaml
:
apiVersion: kubedb.com/v1alpha2
kind: PostgreSQL
metadata:
name: your-postgresql
spec:
version: "11"
storageType: Durable
storage:
storageClassName: <YOUR_STORAGE_CLASS>
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
terminationPolicy: WipeOut
databaseSecret:
secretName: your-postgresql-secret
databaseURLFromSecret: true
replicas: 1
users:
- name: <YOUR_DB_USER>
passwordSecret:
secretName: your-postgresql-secret
passwordKey: password
databaseName: <YOUR_DB_NAME>
Then, you can use the credentials and properties of this database to connect your service's pod to it with deployment.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: your-microservice
spec:
replicas: 1
selector:
matchLabels:
app: your-microservice
template:
metadata:
labels:
app: your-microservice
spec:
containers:
- name: your-microservice-container
image: your-microservice-image:tag
ports:
- containerPort: 80
env:
- name: DATABASE_URL
value: "postgres://<YOUR_DB_USER>:<YOUR_DB_PASSWORD>@<YOUR_DB_HOST>:<YOUR_DB_PORT>/<YOUR_DB_NAME>"
---
apiVersion: v1
kind: Service
metadata:
name: your-microservice-service
spec:
selector:
app: your-microservice
ports:
- protocol: TCP
port: 80
targetPort: 80
And if, for some reason, you are not ready to use KubeDB or don't require the full functional of their product, you can use the Postgresql container as a sidecar for your test environment.
Postgres Container as a Sidecar
In the context of Kubernetes and databases like PostgreSQL, a sidecar is a separate container that runs alongside the main application container within a pod. The sidecar pattern is commonly used to enhance or extend the functionality of the main application container without directly impacting its core logic.
Let's see the example of a configuration for a small Spring Boot Kotlin service that handles cat names.
deployment.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: cat-svc
labels:
app: cat-svc
spec:
replicas: 1
selector:
matchLabels:
app: cat-svc
template:
metadata:
labels:
app: cat-svc
type: http
spec:
containers:
- name: cat-svc
image: cat-svc:0.0.1
ports:
- name: http
containerPort: 8080
protocol: TCP
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 30
timeoutSeconds: 10
periodSeconds: 10
livenessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 10
periodSeconds: 30
env:
- name: PLACES_DATABASE
value: localhost:5432/cats
- name: POSTGRES_USER
value: pwd
- name: POSTGRES_PASSWORD
value: postgres
- name: cat-postgres
image: postgres:11.1
ports:
- name: http
containerPort: 5432
protocol: TCP
env:
- name: POSTGRES_USER
value: pwd
- name: POSTGRES_PASSWORD
value: postgres
- name: POSTGRES_DB
value: cats
FROM gradle:8.3.0-jdk17
COPY . .
EXPOSE 8080
CMD ["gradle", "bootRun"]
And for local run, it is possible to use docker-compose with the following configuration.
docker-compose.yaml
:
version: '3.8'
services:
cat-postgres:
image: postgres:12.13
restart: always
ports:
- "5432:5432"
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
POSTGRES_DB: cats
# volumes:
# - ./init.sql:/docker-entrypoint-initdb.d/create_tables.sql - if you want to run any script before an app
# - ./db-data/:/var/lib/postgresql/data/
service:
image: cat-svc:0.0.1
restart: always
ports:
- '8080:8080'
environment:
SPRING_PROFILES_ACTIVE: prod
PLACES_DATABASE: cat-postgres:5432/cats
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
Migrations
The big thing that has to be decided before using this approach is the migration question. The best option in this approach is to delegate the migration process to any tool that can work within your app infrastructure. For example, for Java World, you could use Flyway or Liquibase.
- Flyway is a popular open-source database migration tool. It allows you to version control your database schema and apply changes in a structured manner. Flyway supports multiple databases, including PostgreSQL, MySQL, and Oracle.
- Liquibase is an open-source database migration tool that supports tracking, managing, and applying database changes. It provides a way to define database changes using XML, YAML, or SQL, and it supports various databases.
Pros of Using a PostgreSQL Sidecar in Kubernetes
- Separation of concerns: Sidecars allow you to separate specific functionalities (e.g., database migrations, backups) from the main application logic. Сompliance with microservice architecture.
- Simplified deployment: Sidecars can be deployed and managed alongside the main application using the same deployment configurations, simplifying the overall deployment process. You don't need to support separated database for testing the environment. And it leads to decreasing the complexity of tests (you don't need to think about collisions while you are running many CI with tests for the same table)
Cons of Using a PostgreSQL Sidecar in Kubernetes
- Resource overhead: Running additional containers consumes resources (CPU, memory) on the node, which may impact the overall performance and resource utilization of the Kubernetes cluster. It's best to use as few resources as possible.
- Startup order: The main application may become dependent on the sidecar for certain functionalities, potentially leading to issues if there are discrepancies or version mismatches between the main application and the sidecar. Arranging containers in a specific order without additional configuration can be somewhat challenging. However, this shouldn't pose a problem in test environments due to the quick startup of the PostgreSQL container. In most scenarios, the PostgreSQL container will initiate before any of your business applications. Even if the application attempts to run before PostgreSQL is ready, it will encounter a failure and be automatically restarted by the default Kubernetes mechanism until the database becomes available.
- Learning curve: Adopting the sidecar pattern may require a learning curve for development and operations teams, particularly if they are new to the concept of containerized sidecar architectures. Once the setup is complete, new team members should encounter no issues with this approach.
Conclusion
In conclusion, the choice between using KubDB and the PostgreSQL sidecar approach for integrating web applications and databases in a test environment ultimately depends on your specific requirements and preferences. KubDB offers a comprehensive solution with Kubernetes-native features, streamlining the management of databases alongside web services. On the other hand, the PostgreSQL sidecar approach provides flexibility and fine-grained control over how databases and web applications interact.
Whether you opt for the simplicity and seamless integration provided by KubDB or the customization potential inherent in the sidecar pattern, both approaches lay a solid foundation for test environments. The key lies in understanding the unique demands of your project and selecting the method that aligns best with your development workflow, scalability needs, and overall application architecture. Whichever path you choose, the insights gained from exploring these approaches in a test setting can pave the way for a robust and efficient integration strategy in your production environment.
Opinions expressed by DZone contributors are their own.
Comments