From 2a225de2f992e59a5653abe801f6cf4baf6df858 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 24 Jul 2021 21:23:40 -0400 Subject: [PATCH 1/6] Create an echo service docker image. --- kubernetes/autoscale/service/Dockerfile | 17 +++++++++++ kubernetes/autoscale/service/Makefile | 21 ++++++++++++++ kubernetes/autoscale/service/gunicorn.conf.py | 10 +++++++ kubernetes/autoscale/service/main.py | 28 +++++++++++++++++++ kubernetes/autoscale/service/requirements.txt | 2 ++ 5 files changed, 78 insertions(+) create mode 100644 kubernetes/autoscale/service/Dockerfile create mode 100644 kubernetes/autoscale/service/Makefile create mode 100644 kubernetes/autoscale/service/gunicorn.conf.py create mode 100644 kubernetes/autoscale/service/main.py create mode 100644 kubernetes/autoscale/service/requirements.txt diff --git a/kubernetes/autoscale/service/Dockerfile b/kubernetes/autoscale/service/Dockerfile new file mode 100644 index 0000000..b9cf35f --- /dev/null +++ b/kubernetes/autoscale/service/Dockerfile @@ -0,0 +1,17 @@ +FROM python:3.9 + +RUN useradd -m -g nogroup server +USER server + +WORKDIR /home/server +ENV FLASK_APP=main.py + +# Perform the install of requirements first to avoid re-installing on every code change +COPY requirements.txt /home/server/ +RUN pip install -r /home/server/requirements.txt + +COPY *.py /home/server/ + +# CMD ["python", "/home/server/main.py"] + +CMD ["/home/server/.local/bin/gunicorn", "--config", "/home/server/gunicorn.conf.py", "main:app"] diff --git a/kubernetes/autoscale/service/Makefile b/kubernetes/autoscale/service/Makefile new file mode 100644 index 0000000..3de8eb0 --- /dev/null +++ b/kubernetes/autoscale/service/Makefile @@ -0,0 +1,21 @@ +IMAGE_NAME:=echoservice + +.PHONY: all +all: build push + +.PHONY: build +build: + docker build -t $(IMAGE_NAME) . + +.PHONY: push +push: + docker tag $(IMAGE_NAME) gcr.io/hip-wharf-319304/$(IMAGE_NAME) + docker push gcr.io/hip-wharf-319304/$(IMAGE_NAME) + +.PHONY: clean +clean: + docker rmi $(IMAGE_NAME) gcr.io/hip-wharf-319304/$(IMAGE_NAME) $(IMAGE_NAME) + +.PHONY: run +run: + docker run --rm -i -t -p "8080:8080" $(IMAGE_NAME) diff --git a/kubernetes/autoscale/service/gunicorn.conf.py b/kubernetes/autoscale/service/gunicorn.conf.py new file mode 100644 index 0000000..0a4a199 --- /dev/null +++ b/kubernetes/autoscale/service/gunicorn.conf.py @@ -0,0 +1,10 @@ +import multiprocessing +import os + +env_port = int(os.environ.get("PORT", 8080)) + +bind = f"0.0.0.0:{env_port}" +workers = max(2, multiprocessing.cpu_count() * 2 + 1) +preload_app = True +max_requests = 100 +max_requests_jitter = 50 diff --git a/kubernetes/autoscale/service/main.py b/kubernetes/autoscale/service/main.py new file mode 100644 index 0000000..0669613 --- /dev/null +++ b/kubernetes/autoscale/service/main.py @@ -0,0 +1,28 @@ +import json +import os + +from flask import Flask, request + +app = Flask(__name__) + + +def get_request_params(): + request_json = request.get_json(silent=True) + request_args = request.args + if request_json: + return request_json + elif request_args: + return request_args + else: + return None + + +@app.route("/", methods=("GET", "POST")) +def index(): + return json.dumps( + {"headers": {k: v for k, v in request.headers}, "params": get_request_params()} + ) + + +if __name__ == "__main__": + app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 8080)), debug=True) diff --git a/kubernetes/autoscale/service/requirements.txt b/kubernetes/autoscale/service/requirements.txt new file mode 100644 index 0000000..b94ded4 --- /dev/null +++ b/kubernetes/autoscale/service/requirements.txt @@ -0,0 +1,2 @@ +flask==1.1.2 +gunicorn==20.1.0 From 6f2ee8f88006bcb399ad5572edb7294a243bf899 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 24 Jul 2021 21:31:51 -0400 Subject: [PATCH 2/6] Make GCP project a variable also. --- kubernetes/autoscale/service/Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/kubernetes/autoscale/service/Makefile b/kubernetes/autoscale/service/Makefile index 3de8eb0..8688d0d 100644 --- a/kubernetes/autoscale/service/Makefile +++ b/kubernetes/autoscale/service/Makefile @@ -1,4 +1,5 @@ IMAGE_NAME:=echoservice +GCP_PROJECT:=hip-wharf-319304 .PHONY: all all: build push @@ -9,12 +10,12 @@ build: .PHONY: push push: - docker tag $(IMAGE_NAME) gcr.io/hip-wharf-319304/$(IMAGE_NAME) - docker push gcr.io/hip-wharf-319304/$(IMAGE_NAME) + docker tag $(IMAGE_NAME) gcr.io/$(GCP_PROJECT)/$(IMAGE_NAME) + docker push gcr.io/$(GCP_PROJECT)/$(IMAGE_NAME) .PHONY: clean clean: - docker rmi $(IMAGE_NAME) gcr.io/hip-wharf-319304/$(IMAGE_NAME) $(IMAGE_NAME) + docker rmi $(IMAGE_NAME) gcr.io/$(GCP_PROJECT)/$(IMAGE_NAME) $(IMAGE_NAME) .PHONY: run run: From 35f326565994853f28c6a3ec5874626546e53fc9 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 24 Jul 2021 21:48:24 -0400 Subject: [PATCH 3/6] Add auto scale deployment. --- kubernetes/autoscale/k8s/autoscale.yaml | 35 +++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 kubernetes/autoscale/k8s/autoscale.yaml diff --git a/kubernetes/autoscale/k8s/autoscale.yaml b/kubernetes/autoscale/k8s/autoscale.yaml new file mode 100644 index 0000000..cda317f --- /dev/null +++ b/kubernetes/autoscale/k8s/autoscale.yaml @@ -0,0 +1,35 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: autoscale-test + namespace: default +spec: + replicas: 3 + selector: + matchLabels: + app: autoscale-test + template: + metadata: + labels: + app: autoscale-test + spec: + containers: + - name: echoservice + image: gcr.io/hip-wharf-319304/echoservice:latest + imagePullPolicy: IfNotPresent + ports: + - name: http + containerPort: 8080 + protocol: TCP + livenessProbe: + httpGet: + path: / + port: http + readinessProbe: + httpGet: + path: / + port: http + resources: + requests: + cpu: "250m" + memory: "256Mi" From 922247644469305ad134bde4888e0c989584960b Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 24 Jul 2021 22:20:42 -0400 Subject: [PATCH 4/6] Expose it as a service. --- kubernetes/autoscale/k8s/autoscale.yaml | 14 +++++++++++++- kubernetes/autoscale/service/gunicorn.conf.py | 3 +-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/kubernetes/autoscale/k8s/autoscale.yaml b/kubernetes/autoscale/k8s/autoscale.yaml index cda317f..6d19918 100644 --- a/kubernetes/autoscale/k8s/autoscale.yaml +++ b/kubernetes/autoscale/k8s/autoscale.yaml @@ -4,7 +4,6 @@ metadata: name: autoscale-test namespace: default spec: - replicas: 3 selector: matchLabels: app: autoscale-test @@ -33,3 +32,16 @@ spec: requests: cpu: "250m" memory: "256Mi" +--- +apiVersion: v1 +kind: Service +metadata: + name: autoscale-test + namespace: default +spec: + selector: + app: autoscale-test + type: LoadBalancer + ports: + - port: 80 + targetPort: "http" diff --git a/kubernetes/autoscale/service/gunicorn.conf.py b/kubernetes/autoscale/service/gunicorn.conf.py index 0a4a199..984946b 100644 --- a/kubernetes/autoscale/service/gunicorn.conf.py +++ b/kubernetes/autoscale/service/gunicorn.conf.py @@ -1,10 +1,9 @@ -import multiprocessing import os env_port = int(os.environ.get("PORT", 8080)) bind = f"0.0.0.0:{env_port}" -workers = max(2, multiprocessing.cpu_count() * 2 + 1) +workers = int(os.environ.get("WORKERS", 8)) preload_app = True max_requests = 100 max_requests_jitter = 50 From fc7e54ea8a217af0018646eb0cbc512fd7a22f3f Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 24 Jul 2021 22:25:40 -0400 Subject: [PATCH 5/6] Always pull image. --- kubernetes/autoscale/k8s/autoscale.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kubernetes/autoscale/k8s/autoscale.yaml b/kubernetes/autoscale/k8s/autoscale.yaml index 6d19918..6f37a7b 100644 --- a/kubernetes/autoscale/k8s/autoscale.yaml +++ b/kubernetes/autoscale/k8s/autoscale.yaml @@ -15,7 +15,10 @@ spec: containers: - name: echoservice image: gcr.io/hip-wharf-319304/echoservice:latest - imagePullPolicy: IfNotPresent + imagePullPolicy: Always + env: + - name: "WORKERS" + value: "8" ports: - name: http containerPort: 8080 From c1d18e0fe57c9ed04ad84e7303da3ebcf5aedcd3 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 24 Jul 2021 22:36:48 -0400 Subject: [PATCH 6/6] Scaling based on CPU usage. --- kubernetes/autoscale/k8s/autoscale.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/kubernetes/autoscale/k8s/autoscale.yaml b/kubernetes/autoscale/k8s/autoscale.yaml index 6f37a7b..8e0a1f9 100644 --- a/kubernetes/autoscale/k8s/autoscale.yaml +++ b/kubernetes/autoscale/k8s/autoscale.yaml @@ -48,3 +48,17 @@ spec: ports: - port: 80 targetPort: "http" +--- +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: autoscale-test + namespace: default +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: autoscale-test + minReplicas: 1 + maxReplicas: 10 + targetCPUUtilizationPercentage: 50