diff --git a/kubernetes/autoscale/k8s/autoscale.yaml b/kubernetes/autoscale/k8s/autoscale.yaml new file mode 100644 index 0000000..8e0a1f9 --- /dev/null +++ b/kubernetes/autoscale/k8s/autoscale.yaml @@ -0,0 +1,64 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: autoscale-test + namespace: default +spec: + selector: + matchLabels: + app: autoscale-test + template: + metadata: + labels: + app: autoscale-test + spec: + containers: + - name: echoservice + image: gcr.io/hip-wharf-319304/echoservice:latest + imagePullPolicy: Always + env: + - name: "WORKERS" + value: "8" + ports: + - name: http + containerPort: 8080 + protocol: TCP + livenessProbe: + httpGet: + path: / + port: http + readinessProbe: + httpGet: + path: / + port: http + resources: + 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" +--- +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 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..8688d0d --- /dev/null +++ b/kubernetes/autoscale/service/Makefile @@ -0,0 +1,22 @@ +IMAGE_NAME:=echoservice +GCP_PROJECT:=hip-wharf-319304 + +.PHONY: all +all: build push + +.PHONY: build +build: + docker build -t $(IMAGE_NAME) . + +.PHONY: push +push: + 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/$(GCP_PROJECT)/$(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..984946b --- /dev/null +++ b/kubernetes/autoscale/service/gunicorn.conf.py @@ -0,0 +1,9 @@ +import os + +env_port = int(os.environ.get("PORT", 8080)) + +bind = f"0.0.0.0:{env_port}" +workers = int(os.environ.get("WORKERS", 8)) +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