Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Bear App

A microservices-based bear ordering application built with Node.js, TypeScript, Express, Kafka/Amazon SQS, and MySQL.

Architecture

System Overview

┌─────────────────────────────────────────────────────────────────────────────────┐
│                                   USER                                          │
│                              (Web Browser)                                      │
└─────────────────────────────────┬───────────────────────────────────────────────┘
                                  │ HTTP
                                  ▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│                           ORDER SERVICE (Port 3000)                             │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────────────────────┐  │
│  │   Static UI     │  │   REST API      │  │      Messaging Client           │  │
│  │  (Storefront)   │  │  POST /order    │  │  - Publish: order-created       │  │
│  │                 │  │  GET /order/:id │  │  - Subscribe: order-updates     │  │
│  └─────────────────┘  └─────────────────┘  └─────────────────────────────────┘  │
└───────────┬─────────────────────┬───────────────────────┬───────────────────────┘
            │                     │                       │
            │ Save/Read Orders    │                       │ Publish: order-created
            ▼                     │                       ▼
┌───────────────────────┐         │         ┌─────────────────────────────────────┐
│                       │         │         │                                     │
│   MySQL Database      │         │         │         KAFKA / SQS                 │
│                       │         │         │       (Message Broker)              │
│  ┌─────────────────┐  │         │         │                                     │
│  │ orders table    │  │         │         │  Topics:                            │
│  │ - order_id      │  │         │         │  ├─ order-created ─────────────┐    │
│  │ - status        │  │         │         │  │                             │    │
│  │ - paid          │  │         │         │  └─ order-updates ◄────────────┤    │
│  │ - stock         │  │         │         │                                │    │
│  │ - items (JSON)  │  │         │         └────────────┬───────────────────┤────┘
│  │ - total         │  │                                │                   │
│  └─────────────────┘  │                                │                   │
│                       │                                ▼                   ▼
└───────────┬───────────┘              ┌─────────────────────┐ ┌─────────────────────┐
            │                          │ INVENTORY SERVICE   │ │  PAYMENT SERVICE    │
            │                          │    (Port 3002)      │ │    (Port 3003)      │
            │                          │                     │ │                     │
            │  Read Order Items        │ - Subscribe:        │ │ - Subscribe:        │
            └──────────────────────────┤   order-created     │ │   order-created     │
                                       │                     │ │                     │
                                       │ - Check inventory   │ │ - Process payment   │
                                       │ - Deduct stock      │ │   (simulated)       │
                                       │                     │ │                     │
                                       │ - Publish:          │ │ - Publish:          │
                                       │   STOCK-OK or       │ │   PAID              │
                                       │   STOCK-FAILED      │ │                     │
                                       │   → order-updates   │ │   → order-updates   │
                                       └─────────────────────┘ └─────────────────────┘

Order Flow Sequence

┌──────┐     ┌───────────────┐     ┌─────────┐     ┌───────────┐     ┌───────────────┐     ┌─────────────────┐
│ User │     │ Order Service │     │  MySQL  │     │Kafka/SQS  │     │Inventory Svc  │     │ Payment Service │
└──┬───┘     └───────┬───────┘     └────┬────┘     └─────┬─────┘     └───────┬───────┘     └────────┬────────┘
   │                 │                  │                │                   │                      │
   │ 1. POST /order  │                  │                │                   │                      │
   │ ────────────────►                  │                │                   │                      │
   │                 │                  │                │                   │                      │
   │                 │ 2. Save Order    │                │                   │                      │
   │                 │ ─────────────────►                │                   │                      │
   │                 │                  │                │                   │                      │
   │                 │ 3. Publish       │                │                   │                      │
   │                 │    order-created │                │                   │                      │
   │                 │ ──────────────────────────────────►                   │                      │
   │                 │                  │                │                   │                      │
   │ 4. Response     │                  │                │                   │                      │
   │ ◄────────────────                  │                │                   │                      │
   │    (orderId)    │                  │                │                   │                      │
   │                 │                  │                │ 5a. Deliver       │                      │
   │                 │                  │                │ ───────────────────►                     │
   │                 │                  │                │                   │                      │
   │                 │                  │                │ 5b. Deliver       │                      │
   │                 │                  │                │ ─────────────────────────────────────────►
   │                 │                  │                │                   │                      │
   │                 │                  │ 6. Read Items  │                   │                      │
   │                 │                  │ ◄───────────────────────────────────                      │
   │                 │                  │                │                   │                      │
   │                 │                  │                │                   │ 7a. STOCK-OK        │
   │                 │                  │                │ ◄───────────────────                     │
   │                 │                  │                │                   │                      │
   │                 │                  │                │                   │        7b. PAID      │
   │                 │                  │                │ ◄─────────────────────────────────────────
   │                 │                  │                │                   │                      │
   │                 │ 8. Receive       │                │                   │                      │
   │                 │    order-updates │                │                   │                      │
   │                 │ ◄──────────────────────────────────                   │                      │
   │                 │                  │                │                   │                      │
   │                 │ 9. Update Order  │                │                   │                      │
   │                 │    Status        │                │                   │                      │
   │                 │ ─────────────────►                │                   │                      │
   │                 │                  │                │                   │                      │
   │ 10. Poll Status │                  │                │                   │                      │
   │ ────────────────►                  │                │                   │                      │
   │                 │                  │                │                   │                      │
   │ 11. FINISHED    │                  │                │                   │                      │
   │ ◄────────────────                  │                │                   │                      │
   │                 │                  │                │                   │                      │

Components Summary

The application consists of three microservices:

  • Order Service (Port 3000): Handles order creation and status tracking
  • Inventory Service (Port 3002): Manages inventory levels and stock updates
  • Payment Service (Port 3003): Processes payments via messaging (Kafka or SQS)

Messaging Infrastructure

The application supports two messaging backends:

  • Kafka (default): Self-hosted Kafka for local development and GKE
  • Amazon SQS: AWS-managed message queue service

You can switch between them using the MESSAGING_TYPE environment variable (kafka or sqs). See SQS Setup Guide for detailed AWS SQS configuration instructions.

Prerequisites

Local Development

  • Node.js 20+
  • Docker Desktop with Kubernetes enabled (or minikube/kind)
  • kubectl configured

GKE Deployment

  • GCP project with billing enabled
  • GKE cluster created
  • gcloud CLI installed and authenticated
  • kubectl configured to use your GKE cluster

Local Deployment

Step 1: Install Dependencies

./install-dependencies.sh

This installs npm dependencies for all services.

Step 2: Start Dependencies (MySQL & Kafka)

Start MySQL and Kafka in Kubernetes:

./start-dependencies-k8s.sh

This script:

  • Deploys MySQL and Kafka to your Kubernetes cluster
  • Sets up port-forwards for local access:
    • MySQL: localhost:3306
    • Kafka: localhost:9092

Note: Keep this terminal running to maintain port-forwards. Open a new terminal for the next steps.

Kafka Configuration:

  • Kafka is deployed as a StatefulSet (not Deployment) for persistent storage
  • Uses apache/kafka:4.1.1 image with KRaft mode (no Zookeeper)
  • Service name: kafka (headless service for direct pod access)
  • Persistent storage: 1Gi PVC per pod
  • Service discovery: kafka:9092 (same namespace) or kafka.bear-app.svc.cluster.local:9092 (cross-namespace)

Step 3: Configure Messaging (Optional)

By default, services use Kafka. To use SQS instead:

export MESSAGING_TYPE=sqs
export AWS_REGION=us-east-1
export AWS_SQS_ORDER_CREATED_QUEUE_URL=https://sqs.us-east-1.amazonaws.com/ACCOUNT_ID/order-created-queue
export AWS_SQS_ORDER_UPDATES_QUEUE_URL=https://sqs.us-east-1.amazonaws.com/ACCOUNT_ID/order-updates-queue

See SQS_SETUP.md for detailed setup instructions.

Step 4: Start Services

In separate terminals, start each service:

# Terminal 1: Order Service
cd order-service
npm run dev

# Terminal 2: Inventory Service
cd inventory-service
npm run dev

# Terminal 3: Payment Service
cd payment-service
npm run dev

Step 5: Access the Application

Stopping Local Services

Stop dependencies:

./stop-dependencies-k8s.sh

GKE Deployment

Messaging Configuration

For GKE deployments, you can choose between Kafka and SQS:

Using Kafka (Default):

  • Kafka is deployed as part of the base Kubernetes manifests
  • No additional configuration needed

Using SQS:

  1. Follow the SQS Setup Guide to create queues and IAM roles
  2. Update k8s/overlays/gke/kustomization.yaml:
    configMapGenerator:
      - name: bear-app-config
        literals:
          - MESSAGING_TYPE=sqs
          - AWS_REGION=us-east-1
          - AWS_SQS_ORDER_CREATED_QUEUE_URL=https://sqs.us-east-1.amazonaws.com/ACCOUNT/order-created-queue
          - AWS_SQS_ORDER_UPDATES_QUEUE_URL=https://sqs.us-east-1.amazonaws.com/ACCOUNT/order-updates-queue
  3. Configure AWS credentials (see SQS_SETUP.md for options)
  4. Deploy and restart services

Step 1: Configure GCP Project

Set your GCP project:

gcloud config set project YOUR_PROJECT_ID

Step 2: Configure GKE Cluster

Connect kubectl to your GKE cluster:

gcloud container clusters get-credentials CLUSTER_NAME --region REGION --project YOUR_PROJECT_ID

Step 3: Update Image References

Edit k8s/overlays/gke/kustomization.yaml and update the image references with your project ID:

images:
  - name: order-service
    newName: gcr.io/YOUR_PROJECT_ID/order-service
    newTag: latest
  - name: payment-service
    newName: gcr.io/YOUR_PROJECT_ID/payment-service
    newTag: latest
  - name: inventory-service
    newName: gcr.io/YOUR_PROJECT_ID/inventory-service
    newTag: latest

Step 4: Deploy to GKE

./deploy-to-k8s.sh gke

This script:

  • Builds Docker images for all services
  • Pushes images to Google Container Registry
  • Deploys all services and dependencies to GKE
  • Configures LoadBalancer for order-service

Step 5: Configure Image Pull Authentication

Your deployments need authentication to pull images from GCR. You have two options:

Option 1: Use Node Service Account (Recommended - No Scripts!)

This is the simplest approach - configure it once and forget about it:

./scripts/configure-gke-node-service-account.sh CLUSTER_NAME REGION

Then edit k8s/overlays/gke/kustomization.yaml and switch to no-secret mode:

patchesStrategicMerge:
  # Comment out:
  # - image-pull-secret-patch.yaml
  # Uncomment:
  - no-image-pull-secret-patch.yaml

Apply: kubectl apply -k k8s/overlays/gke

Benefits: No secrets to manage, more secure, works forever without maintenance.

Option 2: Use Image Pull Secrets

If you prefer using secrets, the deploy script will automatically create the gcr-json-key secret if it doesn't exist. You can also create/refresh it manually:

./scripts/create-gke-image-pull-secret.sh

Note: The deploy script (./deploy-to-k8s.sh gke) will automatically check and create the secret if missing when using Option 2.

If you see "ImagePullBackOff" errors, either:

  • Run configure-gke-node-service-account.sh and switch to Option 1, OR
  • Run create-gke-image-pull-secret.sh to refresh the secret (Option 2)

Step 6: Access the Application

Get the external IP:

kubectl get service order-service -n bear-app

Access the application at: http://EXTERNAL_IP

Troubleshooting GKE Deployment

Image Pull Errors: If your pods fail with ImagePullBackOff or ErrImagePull errors:

Option 1: Using Node Service Account (Recommended)

  1. Configure node service account permissions:
    ./scripts/configure-gke-node-service-account.sh CLUSTER_NAME REGION
  2. Switch to no-secret mode in k8s/overlays/gke/kustomization.yaml
  3. Apply and restart:
    kubectl apply -k k8s/overlays/gke
    kubectl rollout restart deployment -n bear-app

Option 2: Using Image Pull Secrets

  1. Verify the image pull secret exists:
    kubectl get secret gcr-json-key -n bear-app
  2. If missing or expired, refresh it:
    ./scripts/create-gke-image-pull-secret.sh
  3. Restart the deployments:
    kubectl rollout restart deployment -n bear-app

Check pod status:

kubectl get pods -n bear-app
kubectl describe pod <pod-name> -n bear-app

Stopping GKE Deployment

kubectl delete namespace bear-app

ArgoCD Deployment (GitOps)

ArgoCD provides GitOps-based continuous deployment for your bear-app. With ArgoCD, you can manage deployments through Git commits, with automatic synchronization and a web UI for monitoring.

Prerequisites for ArgoCD

  • Kubernetes cluster (GKE or local)
  • kubectl configured and connected to your cluster
  • Git repository (your code is already in Git)

Step 1: Install ArgoCD

Install ArgoCD in your cluster:

./scripts/install-argocd.sh

This script:

  • Creates the argocd namespace
  • Installs ArgoCD components (server, application controller, repo server)
  • Displays the initial admin password

Step 2: Access ArgoCD UI

Port-forward to access the ArgoCD UI:

kubectl port-forward svc/argocd-server -n argocd 8080:443

Then open your browser to: https://localhost:8080

  • Username: admin
  • Password: (shown in the installation output, or get it with):
    kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d && echo

For GKE: You can expose ArgoCD via LoadBalancer:

kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'

Then get the external IP:

kubectl get svc argocd-server -n argocd

Step 3: Bootstrap ArgoCD Applications

Create ArgoCD Applications for your environments:

# Create Applications for both environments
./scripts/setup-argocd-apps.sh

# Or create for specific environment
./scripts/setup-argocd-apps.sh local
./scripts/setup-argocd-apps.sh gke

This creates two Applications:

  • bear-app-local: Points to k8s/overlays/local (auto-sync enabled)
  • bear-app-gke: Points to k8s/overlays/gke (auto-sync enabled, self-heal disabled)

Step 4: Deploy with ArgoCD

Once Applications are created, ArgoCD will automatically sync from Git (if auto-sync is enabled).

Workflow:

  1. Make changes to your Kubernetes manifests in Git
  2. Commit and push to Git
  3. ArgoCD detects the changes and syncs to your cluster
  4. Monitor sync status in the ArgoCD UI

Manual Sync (if auto-sync is disabled):

  • Via UI: Click "Sync" button in the Application
  • Via CLI: argocd app sync bear-app-gke
  • Via kubectl: kubectl patch app bear-app-gke -n argocd --type merge -p '{"operation":{"initiatedBy":{"username":"admin"},"sync":{"revision":"master"}}}'

Sync Policies

  • Local Application: Auto-sync enabled with self-heal (good for development)
  • GKE Application: Auto-sync enabled but self-heal disabled (safer for production)

You can modify sync policies in k8s/argocd/applications/*.yaml.

Sync Waves

Deployments are synchronized in waves for proper ordering:

  • Wave 0: Infrastructure (MySQL, Kafka StatefulSet)
  • Wave 1: Dependencies (Kafka UI)
  • Wave 2: Microservices (order-service, inventory-service, payment-service)

Note: Kafka is deployed as a StatefulSet (not Deployment) for persistent storage and stable network identities.

Benefits of ArgoCD

  • Git as Single Source of Truth: All configuration in Git
  • Automatic Synchronization: Changes in Git are automatically deployed
  • Visual Monitoring: Web UI shows application health and sync status
  • Easy Rollbacks: Revert Git commits to roll back deployments
  • Audit Trail: All changes tracked through Git history
  • Multi-Environment Management: Manage local and GKE from the same codebase

Updating Images with ArgoCD

Current workflow (manual):

  1. Build and push images to GCR
  2. Update image tags in k8s/overlays/gke/kustomization.yaml
  3. Commit and push to Git
  4. ArgoCD automatically syncs the changes

Troubleshooting ArgoCD

  1. Check Application status:

    kubectl get applications -n argocd
    kubectl describe app bear-app-gke -n argocd
  2. View sync logs in ArgoCD UI or via CLI:

    argocd app get bear-app-gke
  3. Check ArgoCD pods:

    kubectl get pods -n argocd
  4. Repository connection issues: Ensure your Git repository is accessible (public or credentials configured)

Stopping ArgoCD

To remove ArgoCD:

kubectl delete namespace argocd

Note: This will also remove all ArgoCD Applications. Your deployed resources will remain, but ArgoCD will no longer manage them.

API Endpoints

Order Service

  • GET /order/health - Health check
  • POST /order - Create a new order
    {
      "items": [
        {"id": "cub", "name": "Cub", "price": 15.0, "qty": 1}
      ],
      "total": 15.0
    }
  • GET /order/:id - Get order status
  • GET /inventory - Proxy to inventory service

Inventory Service

  • GET /inventory/health - Health check
  • GET /inventory - Get current inventory levels

Testing

Unit Tests

To run unit tests locally:

# Unit tests for each service
cd order-service && npm test
cd inventory-service && npm test
cd payment-service && npm test

SQS Testing

See SQS_SETUP.md for detailed SQS setup and testing procedures.

Project Structure

bear-app/
├── order-service/          # Order management service
├── inventory-service/      # Inventory management service
├── payment-service/        # Payment processing service
├── k8s/                    # Kubernetes manifests
│   ├── base/              # Base configurations
│   ├── overlays/          # Environment-specific configs
│   │   ├── local/         # Local Kubernetes
│   │   └── gke/           # Google Kubernetes Engine
│   └── argocd/            # ArgoCD Application manifests
│       └── applications/  # Application definitions
├── scripts/                # Deployment scripts
│   ├── install-argocd.sh  # Install ArgoCD
│   └── setup-argocd-apps.sh # Bootstrap ArgoCD Applications
├── install-dependencies.sh # Install all dependencies
├── start-dependencies-k8s.sh # Start dependencies in k8s
├── stop-dependencies-k8s.sh  # Stop dependencies
├── deploy-to-k8s.sh        # Deploy to Kubernetes (manual)
└── README.md              # This file

Kafka Configuration

StatefulSet Deployment

Kafka is deployed as a StatefulSet (not Deployment) for the following benefits:

  • Persistent Storage: Data survives pod restarts via PersistentVolumeClaims (1Gi per pod)
  • Stable Network Identity: Pods have predictable names (kafka-0, kafka-1, etc.)
  • Ordered Scaling: StatefulSets support controlled, ordered scaling
  • Better for Stateful Workloads: Ideal for Kafka which requires stable storage and network identity

Service Configuration

  • Service Name: kafka (changed from kafka-service)
  • Service Type: Headless (clusterIP: None) for direct pod-to-pod communication
  • Port: 9092 (controller port 9093 handled internally)
  • Image: apache/kafka:4.1.1 (KRaft mode, no Zookeeper required)

Service Discovery

Services connect to Kafka using:

  • Same namespace: kafka:9092
  • Cross-namespace: kafka.bear-app.svc.cluster.local:9092
  • Direct pod access: kafka-0.kafka.bear-app.svc.cluster.local:9092

Storage

  • Storage Class: standard-rwo (ReadWriteOnce)
  • Size: 1Gi per pod
  • Persistence: Data persists across pod restarts and deletions
  • Location: /var/lib/kafka/data in the container

Troubleshooting Kafka

Kafka pod not starting:

# Check pod status
kubectl get pods -n bear-app -l app=kafka

# Check logs
kubectl logs -n bear-app kafka-0

# Check StatefulSet
kubectl describe statefulset kafka -n bear-app

# Check PVC
kubectl get pvc -n bear-app -l app=kafka

Services can't connect to Kafka:

# Verify service exists and is headless
kubectl get svc kafka -n bear-app

# Check service endpoints
kubectl get endpoints kafka -n bear-app

# Test DNS resolution from a pod
kubectl run -it --rm --restart=Never test-dns --image=busybox:1.36 -- nslookup kafka.bear-app.svc.cluster.local

# Verify ConfigMap has correct KAFKA_BROKER
kubectl get configmap bear-app-config -n bear-app -o yaml | grep KAFKA_BROKER

Kafka data persistence:

# Restart Kafka pod to test persistence
kubectl delete pod kafka-0 -n bear-app

# Wait for pod to restart
kubectl wait --for=condition=ready pod/kafka-0 -n bear-app --timeout=300s

# Verify pod restarted and data persists
kubectl logs -n bear-app kafka-0 --tail=10

Troubleshooting

Services won't start locally

  1. Ensure dependencies are running: kubectl get pods -n bear-app
  2. Check port-forwards: ps aux | grep "kubectl port-forward"
  3. Verify MySQL and Kafka are accessible:
    • MySQL: mysql -h localhost -P 3306 -u root -ppassword -e "SELECT 1"
    • Kafka: Check logs with kubectl logs -f statefulset/kafka -n bear-app
    • Kafka pod: kubectl get pods -n bear-app -l app=kafka

GKE deployment issues

  1. Check pod status: kubectl get pods -n bear-app
  2. View logs: kubectl logs -f deployment/order-service -n bear-app
  3. Verify images are pushed: gcloud container images list --project=YOUR_PROJECT_ID
  4. Check service configuration: kubectl describe service order-service -n bear-app

ArgoCD issues

  1. Check ArgoCD Applications: kubectl get applications -n argocd
  2. View Application details: kubectl describe app bear-app-gke -n argocd
  3. Check ArgoCD pods: kubectl get pods -n argocd
  4. View ArgoCD server logs: kubectl logs -f deployment/argocd-server -n argocd
  5. Verify Git repository connection in ArgoCD UI

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages