kmanadkat/ud-monolith-to-microservices-project
Udacity Cloud Developer Nanodegree Monolith To Microservices Project
Udagram Microservices
Udagram is a simple cloud application developed alongside the Udacity Cloud Developer Nanodegree. It allows users to register and log into a web client and post photos to the feed
The project is composed of following microservices:
- M1 Frontend - Angular web application built with Ionic Framework
- M2 Backend
/feed- Node & Express js - M3 Backend
/user- Node & Express js - M4 NGINX Reverse Proxy
All credentials or secrets show below are revoked for security reasons. They are shown only for learning purposes.
Image Credits - Udacity Mentor Juan D
Kubernetes Cluster
Image Credits - Udacity
Continuous Integration
On commit push to main Continuous Integration pipeline (travis ci) is triggered following steps in .travis.yml . It builds new docker images for all microservices listed above and pushes to Docker Hub
AWS Services Used
Following AWS services are used to deploy and host Udagram:
- Amazon Relational Database Service - PostgreSQL based for storing users feed & auth information
- Amazon Simple Storage Service - for storing static image files upload by user in the form of posts
- Amazon Elastic Kubernetes Service - for docker containers orchestration
1. Setting Up AWS S3 Bucket
-
Bucket Name: udagram--dev
-
ACLs Disabled
-
Uncheck Block all public access
-
Bucket Version - disabled
-
Add Tag: project - mono-to-micro
-
Server-side encryption - disabled
-
Object lock - disabled
-
Add bucket policy to grant full access of bucket to other aws services
{ "Version": "2012-10-17", "Id": "Policy1666448178136", "Statement": [ { "Sid": "Stmt1666447767633", "Effect": "Allow", "Principal": "*", "Action": "s3:*", "Resource": "arn:aws:s3:::udagram-<account-id>-dev" } ] } -
Add CORs policy to allow request from any origin
[ { "AllowedHeaders": [ "*" ], "AllowedMethods": [ "POST", "GET", "PUT", "DELETE", "HEAD" ], "AllowedOrigins": [ "*" ], "ExposeHeaders": [] } ]
2. Setting Up AWS RDS PosgreSQL
Creating Postgres RDS Instance
- Standard Create
- Engine PostgreSQL
- Template - Free tier
- Database Identifier - udagram-rds-dev
- Master Username - postgres
- Master Password -
- Allocated Storage - 20GB
- Uncheck Enabled storage autoscaling
- Don't Connect to EC2 computer resource
- Default VPC
- Public Access - Yes
- Default Security Group
- DB Authentication - password
- Turn on Performance Monitoring (free tier - 7 days)
- Uncheck Enhanced Monitoring
- Initial Database Name - postgres
- Uncheck - Backup, Encryption, Maintenance
3. Setting Up AWS EKS Cluster
This step is bit involved because it needs various yaml files created first and then make use of them to setup containers in kubernetes cluster.
a. /deployment/environment-variables/aws-secret.yaml
apiVersion: v1
kind: Secret
type: Opaque
data:
credentials: <Base 64 encoding of AWS Credentials files>
metadata:
name: aws-secretGetting base64 encoding value in macOS:
cat ~/.aws/credentials | head -n 3 | base64
You need to have the profile set before running above command, check aws configure
b. /deployment/environment-variables/env-configmap.yaml
apiVersion: v1
kind: ConfigMap
data:
AWS_BUCKET: udagram-<account-id>-dev
AWS_PROFILE: default
AWS_REGION: ap-south-1
JWT_SECRET: <some-secret>
POSTGRES_DB: postgres
POSTGRES_HOST: <hostname found at RDS>Database>Connectivity & security>
URL: http://localhost:8100
metadata:
name: env-configb. /deployment/environment-variables/env-secret.yaml
apiVersion: v1
kind: Secret
type: Opaque
data:
POSTGRES_USERNAME: <base64 encoded rds db username>
POSTGRES_PASSWORD: <base64 encoded rds db master password>
metadata:
name: env-secretUnder /deployment folder create folders for each micro service & create deployment.yaml & service.yaml files inside it. These are the files that will container information on how to create & orchestrate docker containers inside kubernetes cluster.
| Microservice | Deployment File | Service File |
|---|---|---|
| udagram-api-feed | deployment.yaml | service.yaml |
| udagram-api-user | deployment.yaml | service.yaml |
| udagram-frontend | deployment.yaml | service.yaml |
| udagram-api-reverseproxy | deployment.yaml | service.yaml |
Create EKS Cluster
- Name: udagram-cluster-v3
- Cluster service role - create EKS cluster role
- Default VPC, Default Subnets, Default Security Group
- Cluster endpoint access - Public
- Networking Add-ons - defaults
- Configure logging - defaults (all off)
- Create
Create Cluster Node Group
- Cluster > Compute > Add Node Group
- Name: udagram-node-group-prod
- Create Node IAM Role: IAM > Roles > Create role > AWS Service > EC2
Add permissions: AmazonEKSWorkerNodePolicy, AmazonEC2ContainerRegistryReadOnly, AmazonEKS_CNI_Policy
Next > Role Name: AmazonEKSNodeRole > Create Role - Instance Type > m5.large > Disk Size: 20 GiB
- Min size: 2, max size: 3
- Node group update config: defaults
- Default Subnets, enable Configure SSH > select key pair (or create new)
- Select default security group
- Create
Configure kubectl
-
Test aws user
aws sts get-caller-identity -
update kubectl config
aws eks update-kubeconfig --region ap-south-1 --name udagram-cluster-v4
-
Test
kubectl get svcNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 20m
Install Kubernetes Metrics Server
# Install
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
# Test
kubectl get deployment metrics-server -n kube-systemDeploy container to cluster
Link all environment-variable yaml files and deployment.yaml , service.yaml files with following:
kubectl apply -f deployment/environment-variables/aws-secret.yaml
kubectl apply -f deployment/environment-variables/env-configmap.yaml
kubectl apply -f deployment/environment-variables/env-secret.yaml
kubectl apply -f deployment/feed/deployment.yaml
kubectl apply -f deployment/feed/service.yaml
...
...Expose Frontend & Reverseproxy
# Check the deployment names and their pod status
kubectl get deployments
# Create a Service object that exposes the frontend deployment
# The command below will ceates an external load balancer and assigns a fixed, external IP to the Service.
kubectl expose deployment udagram-frontend --type=LoadBalancer --name=publicfrontend
kubectl expose deployment udagram-reverseproxy --type=LoadBalancer --name=publicreverseproxy
kubectl get servicesCopy external IP of publicreverseproxy and put it udagram-frontend/src/environments/environment.ts & environment.prod.ts
Increment container versions in .travis.yml and push commit to git triggering travis CI pipeline.
Set up a Kubernetes HPA
kubectl autoscale deployment udagram-api-feed --cpu-percent=50 --min=1 --max=2
kubectl autoscale deployment udagram-api-user --cpu-percent=50 --min=1 --max=2
kubectl autoscale deployment udagram-frontend --cpu-percent=50 --min=1 --max=2
kubectl autoscale deployment udagram-reverseproxy --cpu-percent=50 --min=1 --max=2












