Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kubernetes hpa update merge #70

Merged
merged 17 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions HPA-SETUP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
N8: Scalability
## Kubernetes and Horizontal Pod Auto-scaler (HPA)
The application uses Horizontal Pod Autoscalers (HPAs) to manage scalability based on CPU utilization. The HPAs automatically adjust the number of pods for each service based on the load.

### Configuration Infomation
Each microservice has its own HPA configuration file located in the `./k8` directory.
- The HPA settings by default are:
- Min Replicas: The minimum number of pod replicas (e.g., 1).
- Max Replicas: The maximum number of pod replicas (e.g., 10).
- Target CPU Utilization: The desired average CPU utilization (e.g., 50%).
- The HPA configuration files for each service are:
- Frontend: `k8/hpas/frontend-hpa.yaml`
- Collaboration Service: `k8/hpas/collaboration-service-hpa.yaml`
- Matching Service: `k8/hpas/matching-service-hpa.yaml`
- Question Service: `k8/hpas/question-service-hpa.yaml`
- User Service: `k8/hpas/user-service-hpa.yaml`
- History Service: `k8/hpas/history-service-hpa.yaml`

### Setup Instructions
- **Step 1: Setting up Docker Images.**
Ensure repository is cloned, and `.env` file is added. **Note:** `./k8/app-config.yaml` should hold the same ports and urls variables as the .env file. If there are discrepencies, update them to match. If you would like to change the ports for the services, you need to update ports in the app-config, and the relevant deployment and service `.yaml` files.
- If you want to use your own Docker Hub repository (where you will need to then push to), specify your Docker Hub ID in the .env **and** change image names in `.yaml`s in `./k8/deployments` for the microservices (so excluding redis and metrics-server deployments) to replace `wuemily` with your docker hub ID.
- After building the Docker images (e.g. with `docker compose up`), push them with:
`docker push dockerhubid/question-service:latest`
`docker push dockerhubid/user-service:latest`
`docker push dockerhubid/matching-service:latest`
`docker push dockerhubid/collaboration-service:latest`
`docker push dockerhubid/frontend:latest`
`docker push dockerhubid/api-gateway:latest`
`docker push dockerhubid/history-service:latest`
- Alternatively, you can also use existing public reposity by setting the Docker Hub ID to wuemily; no need to push images or make changes in `.yaml` files.
- **Step 2: Setting up Minikube and Kubernetes.**
This assumes some basic understanding of Minikube and Kubernetes and they are both installed.
- Start Minikube with: ``minikube start --driver=docker``
- To apply the HPA configurations to your Kubernetes cluster, use the following commands (from root folder):
`kubectl apply -f ./k8`
`kubectl apply -f ./k8/deployments`
`kubectl apply -f ./k8/services`
`kubectl apply -f ./k8/statefulsets`
`kubectl apply -f ./k8/hpas`
- If load balancers appear to be not working, it may be because of the local hosting. Make sure `minikube tunnel` is running.
- **Step 3: Monitoring**
You can monitor the scaling behavior using `kubectl` commands.
- `kubectl get hpa`displays the current status of all HPAs in the cluster, including the current and desired number of replicas based on CPU usage.
- If CPU usage is `unknown`, check if Minikube metrics server addon is enabled with `minikube adddons list`, if it isn't, enable with `minikube addons enable metrics-server`.
- Can also observe pods and their status with `kubectl get pods` and `minikube dashboard`, depending on your preference.
11 changes: 8 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ services:
context: ./services/question-service
args:
- PORT=${QUESTION_PORT}
image: ${DOCKER_USERNAME}/question-service:latest
ports:
- "${QUESTION_PORT}:${QUESTION_PORT}"
environment:
Expand All @@ -34,6 +35,7 @@ services:
context: ./services/user-service
args:
- PORT=${USER_PORT}
image: ${DOCKER_USERNAME}/user-service:latest
ports:
- "${USER_PORT}:${USER_PORT}"
environment:
Expand Down Expand Up @@ -68,6 +70,7 @@ services:
- REDIS_PORT=6379
ports:
- "${MATCHING_PORT}:${MATCHING_PORT}"
image: ${DOCKER_USERNAME}/matching-service:latest
environment:
PORT: ${MATCHING_PORT}
REDIS_HOST: redis
Expand All @@ -85,7 +88,7 @@ services:
context: ./services/collaboration-service
args:
- PORT=${COLLAB_PORT}
- HISTORY_PORT=${HISTORY_PORT}
image: ${DOCKER_USERNAME}/collaboration-service:latest
ports:
- "${COLLAB_PORT}:${COLLAB_PORT}"
environment:
Expand Down Expand Up @@ -120,6 +123,7 @@ services:
- USER_URL=http://user-service
- QUESTION_URL=http://question-service
- COLLAB_URL=http://collaboration-service
image: ${DOCKER_USERNAME}/api-gateway:latest
ports:
- "${GATEWAY_PORT}:${GATEWAY_PORT}"
environment:
Expand All @@ -142,6 +146,7 @@ services:

frontend:
build: ./frontend
image: ${DOCKER_USERNAME}/frontend:latest
ports:
- "3000:3000"
volumes:
Expand All @@ -159,7 +164,7 @@ services:
context: ./services/history-service
args:
- PORT=${HISTORY_PORT}
- QUESTION_PORT=${QUESTION_PORT}
image: ${DOCKER_USERNAME}/history-service:latest
ports:
- "${HISTORY_PORT}:${HISTORY_PORT}"
environment:
Expand All @@ -182,4 +187,4 @@ services:

networks:
app-network:
driver: bridge
driver: bridge
19 changes: 19 additions & 0 deletions k8/app-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
QUESTION_PORT: "3001"
USER_PORT: "3002"
MATCHING_PORT: "8080"
COLLAB_PORT: "8081"
GATEWAY_PORT: "4000"
HISTORY_PORT: "8082"
ENV: "PROD"
MATCHING_URL: "https://matching-service"
REACT_APP_QUESTION_API_URL: "http://question-service:3001"
REACT_APP_USER_API_URL: "http://user-service:3002"
REACT_APP_MATCHING_API_URL: "http://matching-service:8080"
REACT_APP_COLLAB_WS_URL: "ws://collaboration-service:8081"
REACT_APP_COLLAB_API_URL: "http://collaboration-service:8081"
REACT_APP_GATEWAY_URL: "http://api-gateway:4000/api"
203 changes: 203 additions & 0 deletions k8/components.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
k8s-app: metrics-server
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rbac.authorization.k8s.io/aggregate-to-edit: "true"
rbac.authorization.k8s.io/aggregate-to-view: "true"
name: system:aggregated-metrics-reader
rules:
- apiGroups:
- metrics.k8s.io
resources:
- pods
- nodes
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
k8s-app: metrics-server
name: system:metrics-server
rules:
- apiGroups:
- ""
resources:
- nodes/metrics
verbs:
- get
- apiGroups:
- ""
resources:
- pods
- nodes
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
k8s-app: metrics-server
name: metrics-server-auth-reader
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
k8s-app: metrics-server
name: metrics-server:system:auth-delegator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
k8s-app: metrics-server
name: system:metrics-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:metrics-server
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: v1
kind: Service
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
spec:
ports:
- name: https
port: 443
protocol: TCP
targetPort: https
selector:
k8s-app: metrics-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
spec:
selector:
matchLabels:
k8s-app: metrics-server
strategy:
rollingUpdate:
maxUnavailable: 0
template:
metadata:
labels:
k8s-app: metrics-server
spec:
containers:
- args:
- --cert-dir=/tmp
- --secure-port=10250
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --kubelet-use-node-status-port
- --metric-resolution=15s
- --secure-port=443
- --kubelet-insecure-tls
image: registry.k8s.io/metrics-server/metrics-server:v0.7.2
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
httpGet:
path: /livez
port: https
scheme: HTTPS
periodSeconds: 10
name: metrics-server
ports:
- containerPort: 10250
name: https
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /readyz
port: https
scheme: HTTPS
initialDelaySeconds: 20
periodSeconds: 10
resources:
requests:
cpu: 100m
memory: 200Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
seccompProfile:
type: RuntimeDefault
volumeMounts:
- mountPath: /tmp
name: tmp-dir
nodeSelector:
kubernetes.io/os: linux
priorityClassName: system-cluster-critical
serviceAccountName: metrics-server
volumes:
- emptyDir: {}
name: tmp-dir
---
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
labels:
k8s-app: metrics-server
name: v1beta1.metrics.k8s.io
spec:
group: metrics.k8s.io
groupPriorityMinimum: 100
insecureSkipTLSVerify: true
service:
name: metrics-server
namespace: kube-system
version: v1beta1
versionPriority: 100
22 changes: 22 additions & 0 deletions k8/deployments/api-gateway-deplyoment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-gateway
spec:
replicas: 1
selector:
matchLabels:
app: api-gateway
template:
metadata:
labels:
app: api-gateway
spec:
containers:
- name: api-gateway
image: wuemily/api-gateway:latest
ports:
- containerPort: 4000
envFrom:
- configMapRef:
name: app-config
30 changes: 30 additions & 0 deletions k8/deployments/collaboration-service-deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: collaboration-service
spec:
replicas: 1
selector:
matchLabels:
app: collaboration-service
template:
metadata:
labels:
app: collaboration-service
spec:
containers:
- name: collaboration-service
image: wuemily/collaboration-service:latest
ports:
- containerPort: 8081
resources:
limits:
cpu: 500m
requests:
cpu: 200m
env:
- name: PORT
value: "8081"
envFrom:
- configMapRef:
name: app-config
Loading