Skip to content
Snippets Groups Projects
Commit ceeeb84f authored by Benedikt Wetzel's avatar Benedikt Wetzel
Browse files

Merge branch 'theodolite-kotlin' of...

Merge branch 'theodolite-kotlin' of git.se.informatik.uni-kiel.de:she/theodolite into 138-Introduce-ServiceMontor
parents df5ba270 ef613352
Branches
Tags
4 merge requests!159Re-implementation of Theodolite with Kotlin/Quarkus,!157Update Graal Image in CI pipeline,!101Add Service Monitor,!83WIP: Re-implementation of Theodolite with Kotlin/Quarkus
Showing
with 248 additions and 21 deletions
......@@ -28,7 +28,7 @@ stages:
paths:
- .gradle
before_script:
- cd benchmarks
- cd theodolite-benchmarks
- export GRADLE_USER_HOME=`pwd`/.gradle
build-benchmarks:
......@@ -37,8 +37,8 @@ build-benchmarks:
script: ./gradlew --build-cache assemble
artifacts:
paths:
- "benchmarks/build/libs/*.jar"
- "benchmarks/*/build/distributions/*.tar"
- "theodolite-benchmarks/build/libs/*.jar"
- "theodolite-benchmarks/*/build/distributions/*.tar"
expire_in: 1 day
test-benchmarks:
......@@ -50,7 +50,7 @@ test-benchmarks:
artifacts:
reports:
junit:
- "benchmarks/**/build/test-results/test/TEST-*.xml"
- "theodolite-benchmarks/**/build/test-results/test/TEST-*.xml"
checkstyle-benchmarks:
stage: check
......@@ -61,7 +61,7 @@ checkstyle-benchmarks:
script: ./gradlew checkstyle --continue
artifacts:
paths:
- "benchmarks/*/build/reports/checkstyle/main.html"
- "theodolite-benchmarks/*/build/reports/checkstyle/main.html"
when: on_failure
expire_in: 1 day
......@@ -74,7 +74,7 @@ pmd-benchmarks:
script: ./gradlew pmd --continue
artifacts:
paths:
- "benchmarks/*/build/reports/pmd/*.html"
- "theodolite-benchmarks/*/build/reports/pmd/*.html"
when: on_failure
expire_in: 1 day
......@@ -87,7 +87,7 @@ spotbugs-benchmarks:
script: ./gradlew spotbugs --continue
artifacts:
paths:
- "benchmarks/*/build/reports/spotbugs/*.html"
- "theodolite-benchmarks/*/build/reports/spotbugs/*.html"
when: on_failure
expire_in: 1 day
......@@ -114,10 +114,10 @@ spotbugs-benchmarks:
- if: "$CR_HOST && $CR_ORG && $CR_USER && $CR_PW && $IMAGE_NAME && $JAVA_PROJECT_NAME && $CI_COMMIT_TAG"
when: always
- changes:
- benchmarks/*
- benchmarks/$JAVA_PROJECT_NAME/**/*
- benchmarks/application-kafkastreams-commons/**/*
- benchmarks/workload-generator-commons/**/*
- theodolite-benchmarks/*
- theodolite-benchmarks/$JAVA_PROJECT_NAME/**/*
- theodolite-benchmarks/application-kafkastreams-commons/**/*
- theodolite-benchmarks/workload-generator-commons/**/*
if: "$CR_HOST && $CR_ORG && $CR_USER && $CR_PW && $IMAGE_NAME && $JAVA_PROJECT_NAME"
when: always
- if: "$CR_HOST && $CR_ORG && $CR_USER && $CR_PW && $IMAGE_NAME && $JAVA_PROJECT_NAME"
......@@ -176,7 +176,7 @@ deploy-uc4-load-generator:
# Theodolite Framework
.theodolite:
image: openjdk:11-jdk
image: ghcr.io/graalvm/graalvm-ce:java11-21.0.0.2
tags:
- exec-docker
variables:
......@@ -189,23 +189,33 @@ deploy-uc4-load-generator:
- cd theodolite-quarkus
- export GRADLE_USER_HOME=`pwd`/.gradle
build-theodolite:
build-theodolite-jvm:
stage: build
extends: .theodolite
# script: ./gradlew --build-cache assemble -Dquarkus.package.type=native
script: ./gradlew --build-cache assemble
artifacts:
paths:
- "theodolite-quarkus/build/lib/*"
- "theodolite-quarkus/build/*-runner.jar"
# - "theodolite-quarkus/build/*-runner" # For native image
expire_in: 1 day
build-theodolite-native:
stage: build
extends: .theodolite
script:
- gu install native-image # TODO move to image
- ./gradlew --build-cache assemble -Dquarkus.package.type=native
artifacts:
paths:
- "theodolite-quarkus/build/*-runner"
expire_in: 1 day
test-theodolite:
stage: test
extends: .theodolite
needs:
- build-theodolite
- build-theodolite-jvm
- build-theodolite-native
script: ./gradlew test --stacktrace
# Disabled for now
......@@ -213,7 +223,7 @@ test-theodolite:
stage: check
extends: .theodolite
needs:
- build-theodolite
- build-theodolite-jvm
- test-theodolite
script: ./gradlew ktlintCheck --continue
......@@ -222,7 +232,7 @@ test-theodolite:
stage: check
extends: .theodolite
needs:
- build-theodolite
- build-theodolite-jvm
- test-theodolite
script: ./gradlew detekt --continue
......@@ -232,12 +242,12 @@ deploy-theodolite:
- .theodolite
- .dind
needs:
- build-theodolite
- build-theodolite-native
- test-theodolite
script:
- DOCKER_TAG_NAME=$(echo $CI_COMMIT_REF_SLUG- | sed 's/^master-$//')
#- docker build -f src/main/docker/Dockerfile.native -t theodolite .
- docker build -f src/main/docker/Dockerfile.jvm -t theodolite .
- docker build -f src/main/docker/Dockerfile.native -t theodolite .
#- docker build -f src/main/docker/Dockerfile.jvm -t theodolite .
- "[ ! $CI_COMMIT_TAG ] && docker tag theodolite $CR_HOST/$CR_ORG/theodolite:${DOCKER_TAG_NAME}latest"
- "[ ! $CI_COMMIT_TAG ] && docker tag theodolite $CR_HOST/$CR_ORG/theodolite:$DOCKER_TAG_NAME$CI_COMMIT_SHORT_SHA"
- "[ $CI_COMMIT_TAG ] && docker tag theodolite $CR_HOST/$CR_ORG/theodolite:$CI_COMMIT_TAG"
......@@ -254,3 +264,30 @@ deploy-theodolite:
- if: "$CR_HOST && $CR_ORG && $CR_USER && $CR_PW"
when: manual
allow_failure: true
# Theodolite Random Scheduler
deploy-random-scheduler:
stage: deploy
extends:
- .dind
script:
- DOCKER_TAG_NAME=$(echo $CI_COMMIT_REF_SLUG- | sed 's/^master-$//')
- docker build --pull -t theodolite-random-scheduler execution/infrastructure/random-scheduler
- "[ ! $CI_COMMIT_TAG ] && docker tag theodolite-random-scheduler $CR_HOST/$CR_ORG/theodolite-random-scheduler:${DOCKER_TAG_NAME}latest"
- "[ $CI_COMMIT_TAG ] && docker tag theodolite-random-scheduler $CR_HOST/$CR_ORG/theodolite-random-scheduler:$CI_COMMIT_TAG"
- echo $CR_PW | docker login $CR_HOST -u $CR_USER --password-stdin
- docker push $CR_HOST/$CR_ORG/theodolite-random-scheduler
- docker logout
rules:
- if: "$CR_HOST && $CR_ORG && $CR_USER && $CR_PW && $CI_COMMIT_TAG"
when: always
- changes:
- execution/infrastructure/random-scheduler/**/*
if: "$CR_HOST && $CR_ORG && $CR_USER && $CR_PW"
when: always
- if: "$CR_HOST && $CR_ORG && $CR_USER && $CR_PW"
when: manual
allow_failure: true
\ No newline at end of file
FROM alpine:3.12
RUN apk update && apk add bash curl jq
RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl \
&& chmod +x ./kubectl \
&& mv ./kubectl /usr/local/bin/kubectl
ADD schedule.sh /bin/schedule
CMD /bin/schedule
# Theodolite Random Scheduler
This directory contains the Theodolite Random Scheduler that schedules pods on random nodes.
## Build and Push
Run the following commands
- `docker build -t theodolite-random-scheduler .`
- `docker tag theodolite-random-scheduler <user>/theodolite-random-scheduler`
- `docker push <user>/theodolite-random-scheduler`
## Deployment
Deploy the `deployment.yaml` file into Kubernetes. Note, that the `TARGET_NAMESPACE` environment variable specifies the operating namespace of the random scheduler.
apiVersion: apps/v1
kind: Deployment
metadata:
name: random-scheduler
labels:
app: random-scheduler
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
app: random-scheduler
template:
metadata:
labels:
app: random-scheduler
spec:
serviceAccount: random-scheduler
containers:
- name: random-scheduler
image: ghcr.io/cau-se/theodolite-random-scheduler:latest
imagePullPolicy: Always
env:
- name: TARGET_NAMESPACE
value: default
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: kube-system
name: random-scheduler
labels:
app: random-scheduler
component: random-scheduler
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: random-scheduler
subjects:
- kind: ServiceAccount
name: random-scheduler
namespace: kube-system
roleRef:
kind: ClusterRole
apiGroup: rbac.authorization.k8s.io
name: system:kube-scheduler
\ No newline at end of file
#!/bin/bash
# use kubectl in proxy mode in order to allow curl requesting the k8's api server
kubectl proxy --port 8080 &
echo "Target Namespace: $TARGET_NAMESPACE"
while true;
do
for PODNAME in $(kubectl get pods -n $TARGET_NAMESPACE -o json | jq '.items[] | select(.spec.schedulerName == "random-scheduler") | select(.spec.nodeName == null) | .metadata.name' | tr -d '"');
do
NODES=($(kubectl get nodes -o json | jq '.items[].metadata.name' | tr -d '"'))
NUMNODES=${#NODES[@]}
CHOSEN=${NODES[$[$RANDOM % $NUMNODES]]}
curl --header "Content-Type:application/json" --request POST --data '{"apiVersion":"v1", "kind": "Binding", "metadata": {"name": "'$PODNAME'"}, "target": {"apiVersion": "v1", "kind": "Node", "name": "'$CHOSEN'"}}' localhost:8080/api/v1/namespaces/$TARGET_NAMESPACE/pods/$PODNAME/binding/
echo "Assigned $PODNAME to $CHOSEN"
done
sleep 1
done
\ No newline at end of file
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY ./app /app
\ No newline at end of file
# Lag Trend SLO Evaluator
## Execution
For development:
```sh
uvicorn main:app --reload
```
Build the docker image:
```sh
docker build . -t theodolite-evaluator
```
Run the Docker image:
```sh
docker run -p 80:80 theodolite-evaluator
```
## Configuration
You can set the `HOST` and the `PORT` (and a lot of more parameters) via environment variables. Default is `0.0.0.0:80`.
For more information see [here](https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker#advanced-usage).
from fastapi import FastAPI,Request
import trend_slope_computer as trend_slope_computer
import logging
import os
import pandas as pd
import json
import sys
app = FastAPI()
logging.basicConfig(stream=sys.stdout,
format="%(asctime)s %(levelname)s %(name)s: %(message)s")
logger = logging.getLogger("API")
if os.getenv('LOG_LEVEL') == 'INFO':
logger.setLevel(logging.INFO)
elif os.getenv('LOG_LEVEL') == 'WARNING':
logger.setLevel(logging.WARNING)
elif os.getenv('LOG_LEVEL') == 'DEBUG':
logger.setLevel((logging.DEBUG))
def execute(results, threshold, warmup):
d = []
for result in results:
group = result['metric']['group']
for value in result['values']:
d.append({'group': group, 'timestamp': int(
value[0]), 'value': int(value[1]) if value[1] != 'NaN' else 0})
df = pd.DataFrame(d)
logger.info(df)
try:
trend_slope = trend_slope_computer.compute(df, warmup)
except Exception as e:
err_msg = 'Computing trend slope failed'
logger.exception(err_msg)
logger.error('Mark this subexperiment as not successful and continue benchmark')
return False
logger.info("Trend Slope: %s", trend_slope)
return trend_slope < threshold
@app.post("/evaluate-slope",response_model=bool)
async def evaluate_slope(request: Request):
data = json.loads(await request.body())
return execute(data['total_lag'], data['threshold'], data['warmup'])
logger.info("Slope evaluator is online")
\ No newline at end of file
from sklearn.linear_model import LinearRegression
import pandas as pd
import os
def compute(x, warmup_sec):
input = x
input['sec_start'] = input.loc[0:, 'timestamp'] - input.iloc[0]['timestamp']
regress = input.loc[input['sec_start'] >= warmup_sec] # Warm-Up
X = regress.iloc[:, 2].values.reshape(-1, 1) # values converts it into a numpy array
Y = regress.iloc[:, 3].values.reshape(-1, 1) # -1 means that calculate the dimension of rows, but have 1 column
linear_regressor = LinearRegression() # create object for the class
linear_regressor.fit(X, Y) # perform linear regression
Y_pred = linear_regressor.predict(X) # make predictions
trend_slope = linear_regressor.coef_[0][0]
return trend_slope
fastapi==0.55.1
scikit-learn==0.20.3
pandas==1.0.3
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment