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.

In 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:

1.     Database operators: Postgres operator to simplify the process of deploying and managing database instances on Kubernetes.

2.     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.

3.     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:

YAML

apiVersion: kubedb.com/v1alpha2
kind: PostgreSQL
metadata:
  name: your-postgresql
spec:
  version: "11"
  storageType: Durable
  storage:
    storageClassName: 
    accessModes:
    - ReadWriteOnce
    resources:
      requests:
        storage: 1Gi
  terminationPolicy: WipeOut
  databaseSecret:
    secretName: your-postgresql-secret
    databaseURLFromSecret: true
    replicas: 1
    users:
      - name: 
        passwordSecret:
          secretName: your-postgresql-secret
          passwordKey: password
        databaseName: 
  

Then, you can use the credentials and properties of this database to connect your service's pod to it with deployment.yaml:

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://:@:/"
---
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:

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

 

Dockerfile

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:

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.

1.     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.

2.     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

1.     Separation of concerns: Sidecars allow you to separate specific functionalities (e.g., database migrations, backups) from the main application logic. Сompliance with microservice architecture.

2.     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

1.     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.

2.     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.

3.     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.

We Provide consulting, implementation, and management services on DevOps, DevSecOps, DataOps, Cloud, Automated Ops, Microservices, Infrastructure, and Security

 

Services offered by us: https://www.zippyops.com/services

Our Products: https://www.zippyops.com/products

Our Solutions: https://www.zippyops.com/solutions

For Demo, videos check out YouTube Playlist: https://www.youtube.com/watch?v=4FYvPooN_Tg&list=PLCJ3JpanNyCfXlHahZhYgJH9-rV6ouPro

 

 If this seems interesting, please email us at [email protected] for a call.



Relevant Blogs:

An In-Depth Exploration of REST, gRPC, and GraphQL in Web Projects 

Mastering Microservices: Best Practices for Seamless Implementation 

Ultimate Guide to Kubernetes StatefulSets With a MongoDB Example 

Understanding and Using Docker Containers in Web Development: A Guide


Recent Comments

No comments

Leave a Comment