├── create_service.sh ├── kubia-qps ├── Dockerfile └── app.js ├── qps-autoscaler.yaml ├── qps-deployment.yaml └── run-load-generator.sh /create_service.sh: -------------------------------------------------------------------------------- 1 | 2 | kubectl expose deployment kubia --port=80 --target-port=8080 3 | 4 | -------------------------------------------------------------------------------- /kubia-qps/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:0.12 2 | ADD app.js /app.js 3 | CMD node app.js 4 | -------------------------------------------------------------------------------- /kubia-qps/app.js: -------------------------------------------------------------------------------- 1 | var http = require('http'); 2 | var os = require('os'); 3 | 4 | var qps = []; 5 | 6 | const SECONDS = 5; 7 | 8 | var handler = function(request, response) { 9 | var now = new Date().getTime(); 10 | 11 | var total = 0; 12 | for (var time in qps) { 13 | if (qps.hasOwnProperty(time)) { 14 | if (time < now - SECONDS * 1000) { 15 | qps[time] = null; 16 | } else { 17 | total += qps[time]; 18 | } 19 | } 20 | } 21 | 22 | var avgQps = total / SECONDS; 23 | 24 | if (request.url == "/metrics") { 25 | response.writeHead(200); 26 | response.end("# TYPE qps gauge\nqps " + avgQps + "\n"); 27 | console.log("Received request for /qps: " + avgQps); 28 | return; 29 | } 30 | 31 | if (qps[now] == null) { 32 | qps[now] = 0; 33 | } 34 | qps[now]++; 35 | 36 | response.writeHead(200); 37 | response.end("You've hit " + os.hostname() + ". QPS in last " + SECONDS + " seconds has been " + avgQps + "\n"); 38 | }; 39 | 40 | var www = http.createServer(handler); 41 | www.listen(8080); 42 | 43 | -------------------------------------------------------------------------------- /qps-autoscaler.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: autoscaling/v1 2 | kind: HorizontalPodAutoscaler 3 | metadata: 4 | name: kubia 5 | annotations: 6 | alpha/target.custom-metrics.podautoscaler.kubernetes.io: '{"items":[{"name":"qps", "value": "20"}]}' 7 | spec: 8 | maxReplicas: 5 9 | minReplicas: 1 10 | scaleTargetRef: 11 | apiVersion: extensions/v1beta1 12 | kind: Deployment 13 | name: kubia 14 | targetCPUUtilizationPercentage: 1000000 15 | -------------------------------------------------------------------------------- /qps-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | name: kubia 5 | spec: 6 | replicas: 1 7 | template: 8 | metadata: 9 | name: kubia 10 | labels: 11 | app: kubia 12 | annotations: 13 | pod.beta.kubernetes.io/init-containers: '[ 14 | { 15 | "name": "setup", 16 | "image": "busybox", 17 | "imagePullPolicy": "IfNotPresent", 18 | "command": ["sh", "-c", "echo \"{\\\"endpoint\\\": \\\"http://$POD_IP:8080/metrics\\\"}\" > /etc/custom-metrics/definition.json"], 19 | "env": [{ 20 | "name": "POD_IP", 21 | "valueFrom": { 22 | "fieldRef": { 23 | "apiVersion": "v1", 24 | "fieldPath": "status.podIP" 25 | } 26 | } 27 | }], 28 | "volumeMounts": [ 29 | { 30 | "name": "config", 31 | "mountPath": "/etc/custom-metrics" 32 | } 33 | ] 34 | } 35 | ]' 36 | spec: 37 | containers: 38 | - image: luksa/kubia:qps 39 | name: nodejs 40 | ports: 41 | - containerPort: 8080 42 | volumeMounts: 43 | - name: config 44 | mountPath: /etc/custom-metrics 45 | resources: 46 | requests: 47 | cpu: 100m 48 | volumes: 49 | - name: config 50 | emptyDir: 51 | -------------------------------------------------------------------------------- /run-load-generator.sh: -------------------------------------------------------------------------------- 1 | kubectl run -it --rm --restart=Never loadgenerator --image=busybox -- sh -c "while true; do wget -O - -q http://kubia.default; done" 2 | 3 | --------------------------------------------------------------------------------