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
Image Credits - Udacity
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
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
-
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": [] } ]
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
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-secret
Getting 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-config
b. /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-secret
Under /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 |
- 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
- 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
-
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 svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 20m
# Install
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
# Test
kubectl get deployment metrics-server -n kube-system
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
...
...
# 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 services
Copy 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.
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