Skip to content

durbin-164/UdaConnect

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

UdaConnect

Overview

Background

Conferences and conventions are hotspots for making connections. Professionals in attendance often share the same interests and can make valuable business and personal connections with one another. At the same time, these events draw a large crowd and it's often hard to make these connections in the midst of all of these events' excitement and energy. To help attendees make connections, we are building the infrastructure for a service that can inform attendees if they have attended the same booths and presentations at an event.

Application

UdaConnect

Application Architecture

Architecture

Person database will use for only person information and Location database will use for only Person visit information. If Udaconnect have millions of users then separated database will help to load balancing.

Only connection-api microservice will use for external application Udaconnect frontend that's why this microservice is REST. And person service use gRPC technology as an internal API. Though location-api microservice used REST but we can also make it gRPC because it is also an internal API.

When Udaconnect have millions of user, user visit information will huge. To store this huge visit information needs robost technology. That`s why here used Kafka server. A gRPC API get request for storing user visit information, and then it will produce it for kafka server. Then a kafka consumer one by one receive this messages and store it in location database.

Technologies

  • Flask - API webserver
  • SQLAlchemy - Database ORM
  • PostgreSQL - Relational database
  • PostGIS - Spatial plug-in for PostgreSQL enabling geographic queries]
  • Vagrant - Tool for managing virtual deployed environments
  • VirtualBox - Hypervisor allowing you to run multiple operating systems
  • K3s - Lightweight distribution of K8s to easily develop against a local cluster
  • Kafka - Queueing Message Passing

Running the app

The project has been set up such that you should be able to have the project up and running with Kubernetes.

Prerequisites

We will be installing the tools that we'll need to use for getting our environment set up properly.

  1. Install Docker
  2. Set up a DockerHub account
  3. Set up kubectl
  4. Install VirtualBox with at least version 6.0
  5. Install Vagrant with at least version 2.0

Environment Setup

To run the application, you will need a K8s cluster running locally and to interface with it via kubectl. We will be using Vagrant with VirtualBox to run K3s.

Initialize K3s

In this project's root, run vagrant up.

$ vagrant up

The command will take a while and will leverage VirtualBox to load an openSUSE OS and automatically install K3s. When we are taking a break from development, we can run vagrant suspend to conserve some ouf our system's resources and vagrant resume when we want to bring our resources back up. Some useful vagrant commands can be found in this cheatsheet.

Set up kubectl

After vagrant up is done, you will SSH into the Vagrant environment and retrieve the Kubernetes config file used by kubectl. We want to copy the contents of this file into our local environment so that kubectl knows how to communicate with the K3s cluster.

$ vagrant ssh

You will now be connected inside of the virtual OS. Run sudo cat /etc/rancher/k3s/k3s.yaml to print out the contents of the file. You should see output similar to the one that I've shown below. Note that the output below is just for your reference: every configuration is unique and you should NOT copy the output I have below.

Copy the contents from the output issued from your own command into your clipboard -- we will be pasting it somewhere soon!

$ sudo cat /etc/rancher/k3s/k3s.yaml

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJWekNCL3FBREFnRUNBZ0VBTUFvR0NDcUdTTTQ5QkFNQ01DTXhJVEFmQmdOVkJBTU1HR3N6Y3kxelpYSjIKWlhJdFkyRkFNVFU1T1RrNE9EYzFNekFlRncweU1EQTVNVE13T1RFNU1UTmFGdzB6TURBNU1URXdPVEU1TVROYQpNQ014SVRBZkJnTlZCQU1NR0dzemN5MXpaWEoyWlhJdFkyRkFNVFU1T1RrNE9EYzFNekJaTUJNR0J5cUdTTTQ5CkFnRUdDQ3FHU000OUF3RUhBMElBQk9rc2IvV1FEVVVXczJacUlJWlF4alN2MHFseE9rZXdvRWdBMGtSN2gzZHEKUzFhRjN3L3pnZ0FNNEZNOU1jbFBSMW1sNXZINUVsZUFOV0VTQWRZUnhJeWpJekFoTUE0R0ExVWREd0VCL3dRRQpBd0lDcERBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDSVFERjczbWZ4YXBwCmZNS2RnMTF1dCswd3BXcWQvMk5pWE9HL0RvZUo0SnpOYlFJZ1JPcnlvRXMrMnFKUkZ5WC8xQmIydnoyZXpwOHkKZ1dKMkxNYUxrMGJzNXcwPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    server: https://127.0.0.1:6443
  name: default
contexts:
- context:
    cluster: default
    user: default
  name: default
current-context: default
kind: Config
preferences: {}
users:
- name: default
  user:
    password: 485084ed2cc05d84494d5893160836c9
    username: admin

Type exit to exit the virtual OS and you will find yourself back in your computer's session. Create the file (or replace if it already exists) ~/.kube/config and paste the contents of the k3s.yaml output here.

Afterwards, you can test that kubectl works by running a command like kubectl describe services. It should not return any errors.

Steps

person_microservice_grpc

  1. cd modules/person_microservice_grpc - Go in person_microservice_grpc module
  2. kubectl apply -f deployment/ - Deploy the Person gRPC service and Person Postgres Database
  3. Use the command sh scripts/run_db_command.sh <POD_NAME> against the person postgres pod.

location_microservice

  1. cd modules/location_microservice - Go in location_microservice module
  2. kubectl apply -f deployment/ - Deploy the Location REST service and Location Postgres Database
  3. Use the command sh scripts/run_db_command.sh <POD_NAME> against the location postgres pod.

connection_microservice

  1. cd modules/connection_microservice - Go in connection_microservice module
  2. kubectl apply -f deployment/ - Deploy the Connection REST service

UdaConnect Frontend

  1. cd modules/frontend - Go in UdaConnect frontend module
  2. kubectl apply -f deployment/ - Deploy the UdaConnect Frontend App

Kafka

Install and Run kafka server

Run Kafka server

  1. bin/zookeeper-server-start.sh config/zookeeper.properties
  2. bin/kafka-server-start.sh config/server.properties

Create Kafka Topics [person_location_visits]

  1. bin/kafka-topics.sh --create --topic person_location_visits --partitions 1 --replication-factor 1 --bootstrap-server localhost:9092

Microservice for kafka

person_visit_microservice_grpc

  1. cd modules/person_visit_microservice_grpc - Go in person_visit_microservice module
  2. kubectl apply -f deployment/ - Deploy the gRPC Person Visit Location Producer

person_visit_consumer

  1. cd modules/person_visit_consumer - Go in person_visit_consumer module
  2. kubectl apply -f deployment/ - Deploy the Person Visit Location Consumer Python App

Verifying it Works

Once the project is up and running, you should be able to see 3 deployments and 3 services in Kubernetes: kubectl get pods and kubectl get services - should both return udaconnect-app, udaconnect-api, and postgres

These pages should also load on your web browser:

  • http://localhost:30015/ - OpenAPI Documentation for Connection microservice
  • http://localhost:30016/ - OpenAPI Documentation for Location microservice
  • http://localhost:30015/api/ - Base path for API
  • http://localhost:30030/ - Frontend ReactJS UdaConnect Application

Other API base path

  • localhost:30017/ - gRPC person microservice
  • http://localhost:30020/ - gRPC person Visit Producer
  • http://localhost:30019/ - Python Person Visit Consumer

Deployment Note

You may notice the odd port numbers being served to localhost. By default, Kubernetes services are only exposed to one another in an internal network. This means that udaconnect-app and udaconnect-api can talk to one another. For us to connect to the cluster as an "outsider", we need to a way to expose these services to localhost.

Connections to the Kubernetes services have been set up through a NodePort. (While we would use a technology like an Ingress Controller to expose our Kubernetes services in deployment, a NodePort will suffice for development.)

Development

New Services

New services can be created inside of the modules/ subfolder. You can choose to write something new with Flask, copy and rework the modules/service-name service into something new, or just create a very simple Python application.

As a reminder, each module should have:

  1. Dockerfile
  2. Its own corresponding DockerHub repository
  3. requirements.txt for pip packages
  4. __init__.py

Docker Images

udaconnect-app and udaconnect-api use docker images from isjustintime/udaconnect-app and isjustintime/udaconnect-api. To make changes to the application, build your own Docker image and push it to your own DockerHub repository. Replace the existing container registry path with your own.

Configs and Secrets

In deployment/db-secret.yaml, the secret variable is d293aW1zb3NlY3VyZQ==. The value is simply encoded and not encrypted -- this is not secure! Anyone can decode it to see what it is.

# Decodes the value into plaintext
echo "d293aW1zb3NlY3VyZQ==" | base64 -d

# Encodes the value to base64 encoding. K8s expects your secrets passed in with base64
echo "hotdogsfordinner" | base64

This is okay for development against an exclusively local environment and we want to keep the setup simple so that you can focus on the project tasks. However, in practice we should not commit our code with secret values into our repository. A CI/CD pipeline can help prevent that.

PostgreSQL Database

The database uses a plug-in named PostGIS that supports geographic queries. It introduces GEOMETRY types and functions that we leverage to calculate distance between ST_POINT's which represent latitude and longitude.

You may find it helpful to be able to connect to the database. In general, most of the database complexity is abstracted from you. The Docker container in the starter should be configured with PostGIS. Seed scripts are provided to set up the database table and some rows.

Database Connection

While the Kubernetes service for postgres is running (you can use kubectl get services to check), you can expose the service to connect locally:

kubectl port-forward svc/postgres 5432:5432

This will enable you to connect to the database at localhost. You should then be able to connect to postgresql://localhost:5432/geoconnections. This is assuming you use the built-in values in the deployment config map.

Software

To manually connect to the database, you will need software compatible with PostgreSQL.

  • CLI users will find psql to be the industry standard.
  • GUI users will find pgAdmin to be a popular open-source solution.

Architecture Diagrams

  1. Lucidchart
  2. Google Docs Drawings (In a Google Doc, Insert - Drawing - + New)
  3. Diagrams.net

Tips

  • We can access a running Docker container using kubectl exec -it <pod_id> sh. From there, we can curl an endpoint to debug network issues.
  • The starter project uses Python Flask. Flask doesn't work well with asyncio out-of-the-box. Consider using multiprocessing to create threads for asynchronous behavior in a standard Flask application.

Open API endpoint

Connection microservice

Connection

Location microservice

Location

Kubernets

Services

Services

Pods

pods

Kafka

Kafka Topics consumer console

kafka topics

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published