Published on

Enhancing Chat Application Architecture with Terraform and Kubernetes

Authors

Introduction

In this blog post, we will discuss how to enhance the architecture of a chat application by migrating the server to a Kubernetes cluster using Terraform.

Previous Architecture

Blabber-Hive is a chat application that allows users to communicate with each other in real time. It's a simple chat application in which users can create chat rooms, join chat rooms, and send messages to each other. Frontend is SPA (Single-Page Application) built with React TypeScript, bundled with Vite, and hosted on Cloudflare pages. The backend is built with the Golang Gin framework, dockerized, and hosted on Fly.io. And I use Supabase only for authentication and authorization. The database is PostgreSQL, hosted on Fly.io as well. There's a Redis server for caching, and Kafka cluster for batch-inserting chat messages to Postgres. The overall architecture is shown below:

Blabber-Hive Architecture



Here's the docker-compose file I've been using for local backend services:

services:
  blabber-hive:
    image: blabber-hive:v1
    container_name: blabber-hive
    ports:
      - "8080:8080"
    depends_on:
      - postgres
      - redis
      - broker
      - zookeeper
    env_file:
      - backend/.env.docker
    environment:
      - REDIS_URL=redis://redis:6379
      - KAFKA_BROKER_URL=broker:9092
      - TZ=Asia/Seoul
    networks:
      - blabber-hive

  fastapi:
    container_name: sentiment-analysis-server
    ports:
      - "8000:8000"
    image: sentiment-analysis:v1
    environment:
      - TZ=Asia/Seoul
    networks:
      - blabber-hive

  nginx:
    container_name: nginx
    image: nginx:latest
    ports:
      - "8001:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - blabber-hive
      - fastapi
    networks:
      - blabber-hive

  zookeeper: # ZooKepper for Kafka
    image: confluentinc/cp-zookeeper:7.4.3
    container_name: blabber-hive-zookeeper
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_TICK_TIME: 2000
    networks:
      - blabber-hive

  broker: # Kafka Broker
    image: confluentinc/cp-kafka:7.4.3
    container_name: blabber-hive-broker
    ports:
      - "9092:9092"
    depends_on:
      - zookeeper
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181"
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_INTERNAL:PLAINTEXT
      KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,PLAINTEXT_INTERNAL://0.0.0.0:29092
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://broker:9092,PLAINTEXT_INTERNAL://broker:29092
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
    volumes:
      - ./wait-for-it.sh:/wait-for-it.sh
    #command:
    #  ["/wait-for-it.sh", "zookeeper:2181", "--", "/etc/confluent/docker/run"]
    networks:
      - blabber-hive

  postgres: # Postgres Container
    image: postgres:15.5-alpine
    container_name: blabber-hive-postgres
    ports:
      - "5432:5432"
    networks:
      - blabber-hive
    env_file:
      - backend/.env.docker
    volumes:
      - ./database:/var/lib/postgresql/data

  redis: # Redis Container
    image: redis:7.2.3-alpine3.18
    container_name: blabber-hive-redis
    ports:
      - "6379:6379"
    networks:
      - blabber-hive
  kafka-setup:
    image: confluentinc/cp-kafka:latest
    container_name: blabber-hive-kafka-setup
    depends_on:
      - broker
    volumes:
      - ./backend/create-kafka-topics.sh:/tmp/create-kafka-topics.sh
    command: "/tmp/create-kafka-topics.sh"
    networks:
      - blabber-hive

  prometheus:
    image: prom/prometheus
    container_name: blabber-hive-prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./backend/prometheus.yml:/etc/prometheus/prometheus.yml
    networks:
      - blabber-hive
  grafana:
    image: grafana/grafana
    container_name: blabber-hive-grafana
    ports:
      - "3001:3000"
    networks:
      - blabber-hive

networks:
  blabber-hive:
    driver: bridge

Plans for Migration

Since I want to integrate more features into the chat application, such as FastAPI ML model server for sentiment analysis,I decided to migrate the backend services to a Kubernetes cluster.
I will try running the backend in local Kubernetes cluster first, then try deploying it to AWS EKS using Terraform.

I generated the Kubernetes manifests for the backend services using Kompose.

kompose

After generating the Kubernetes manifests, I categorized the generated Kubernetes manifests into different directories:

  • 'deployments' for deployment manifests
  • 'services' for service manifests
  • 'configmaps' for configmap manifests
  • 'backup' for backup manifests

k8s-initial

For the next articles, I will keep updating the progress of the migration.