From eeb41b38972be94a3ea8283ed1824cdb02350f4b Mon Sep 17 00:00:00 2001 From: Andrew Delph Date: Tue, 10 Oct 2023 10:21:02 -0400 Subject: [PATCH 01/19] push images --- deploy_k8.sh | 4 +++- deploy_operator.sh | 4 ++-- dev | 2 +- operator/BUILD.bazel | 2 +- operator/config/manager/kustomization.yaml | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/deploy_k8.sh b/deploy_k8.sh index e3b4a9d..1b92e22 100755 --- a/deploy_k8.sh +++ b/deploy_k8.sh @@ -3,15 +3,17 @@ # Exit on any error set -e +# eval $(minikube docker-env) + STATEFULSET_NAME="store" NAMESPACE="default" -eval $(minikube docker-env) TAG=$(date +%s) NEW_IMAGE=docker.io/andrew-delph/main:$TAG bazel run --execution_log_json_file=events.json //main:store_image docker tag docker.io/andrew-delph/main:store_image $NEW_IMAGE +docker push $NEW_IMAGE ROLL_OUT_FLAG=0 diff --git a/deploy_operator.sh b/deploy_operator.sh index 24efd3d..535676e 100755 --- a/deploy_operator.sh +++ b/deploy_operator.sh @@ -1,11 +1,11 @@ #!/bin/bash +# eval $(minikube docker-env) -eval $(minikube docker-env) TAG=$(date +%s) IMG=docker.io/andrew-delph/operator:$TAG -bazel run //operator:operator_image +bazel run //operator:image_push docker tag docker.io/andrew-delph/operator:operator_image $IMG (cd operator && make deploy IMG=$IMG) (cd operator && kustomize build config/rbac | kubectl apply -f - || true) diff --git a/dev b/dev index 38da7b4..d93fbf4 100755 --- a/dev +++ b/dev @@ -23,8 +23,8 @@ case $1 in ;; k8-r) kubectl delete -f ./operator/config/samples/ || true - ./deploy_k8.sh ./deploy_operator.sh + ./deploy_k8.sh kubectl apply -f ./resources/prom.yaml kubectl create configmap prometheus-config --from-file=prometheus.yml || true ;; diff --git a/operator/BUILD.bazel b/operator/BUILD.bazel index c585fd0..f321b78 100644 --- a/operator/BUILD.bazel +++ b/operator/BUILD.bazel @@ -58,7 +58,7 @@ container_image( container_push( name = "image_push", format = "Docker", - image = ":store_image", + image = ":operator_image", registry = "ghcr.io", repository = "andrew-delph/my-key-store", tag = "latest", diff --git a/operator/config/manager/kustomization.yaml b/operator/config/manager/kustomization.yaml index 283df5d..3bc9947 100644 --- a/operator/config/manager/kustomization.yaml +++ b/operator/config/manager/kustomization.yaml @@ -5,4 +5,4 @@ kind: Kustomization images: - name: controller newName: docker.io/andrew-delph/operator - newTag: "1696944159" + newTag: "1696947634" From 7bfd808bc9c4bf1223019f70911954a808a10b12 Mon Sep 17 00:00:00 2001 From: Andrew Delph Date: Tue, 10 Oct 2023 11:39:24 -0400 Subject: [PATCH 02/19] push images to github repo --- deploy_k8.sh | 6 ++---- deploy_operator.sh | 5 ++--- docker-compose.yaml | 4 ++-- main/BUILD.bazel | 2 +- operator/BUILD.bazel | 6 +++--- operator/PROJECT | 2 +- operator/config/manager/kustomization.yaml | 4 ++-- operator/config/manager/manager.yaml | 2 +- operator/config/samples/cache_v1alpha1_mykeystore.yaml | 2 +- resources/store.yaml | 2 +- 10 files changed, 16 insertions(+), 19 deletions(-) diff --git a/deploy_k8.sh b/deploy_k8.sh index 1b92e22..b3012ae 100755 --- a/deploy_k8.sh +++ b/deploy_k8.sh @@ -9,11 +9,9 @@ STATEFULSET_NAME="store" NAMESPACE="default" TAG=$(date +%s) -NEW_IMAGE=docker.io/andrew-delph/main:$TAG +NEW_IMAGE=ghcr.io/andrew-delph/main:$TAG -bazel run --execution_log_json_file=events.json //main:store_image -docker tag docker.io/andrew-delph/main:store_image $NEW_IMAGE -docker push $NEW_IMAGE +bazel run --execution_log_json_file=events.json //main:image_push -- -dst=$NEW_IMAGE ROLL_OUT_FLAG=0 diff --git a/deploy_operator.sh b/deploy_operator.sh index 535676e..1743c10 100755 --- a/deploy_operator.sh +++ b/deploy_operator.sh @@ -4,9 +4,8 @@ TAG=$(date +%s) -IMG=docker.io/andrew-delph/operator:$TAG -bazel run //operator:image_push -docker tag docker.io/andrew-delph/operator:operator_image $IMG +IMG=ghcr.io/andrew-delph/operator:$TAG +bazel run //operator:image_push -- -dst=$IMG (cd operator && make deploy IMG=$IMG) (cd operator && kustomize build config/rbac | kubectl apply -f - || true) diff --git a/docker-compose.yaml b/docker-compose.yaml index 463e37d..8551bf9 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -38,7 +38,7 @@ services: store: # hostname: store - image: docker.io/andrew-delph/main:store_image + image: ghcr.io/andrew-delph/main:store_image scale: 5 depends_on: # - zookeeper @@ -57,7 +57,7 @@ services: # store-profile: # # hostname: store # # scale: 1 - # image: docker.io/andrew-delph/main:store_image + # image: ghcr.io/andrew-delph/main:store_image # environment: # - PROFILE_SERVER=true # - BOOTSTRAP_TIMEOUT=1 diff --git a/main/BUILD.bazel b/main/BUILD.bazel index 26ae873..3acba78 100644 --- a/main/BUILD.bazel +++ b/main/BUILD.bazel @@ -92,7 +92,7 @@ container_image( }, files = ["//config:default-config"], ports = ["80"], - repository = "docker.io/andrew-delph", + repository = "ghcr.io/andrew-delph", tags = ["latest"], # repository = "gcr.io/$PROJECT_ID" # repository = "us-central1-docker.pkg.dev/builder-project/repo1/greeter_server", diff --git a/operator/BUILD.bazel b/operator/BUILD.bazel index f321b78..3ae0101 100644 --- a/operator/BUILD.bazel +++ b/operator/BUILD.bazel @@ -26,7 +26,7 @@ go_binary( name = "operator", embed = [":go_default_library"], env = { - # "MYKEYSTORE_IMAGE": "docker.io/andrew-delph/main:store_image", + # "MYKEYSTORE_IMAGE": "ghcr.io/andrew-delph/main:store_image", "MYKEYSTORE_IMAGE": "strm/helloworld-http:latest", }, visibility = ["//visibility:public"], @@ -51,7 +51,7 @@ container_image( # }, # files = ["//config:default-config"], ports = ["80"], - repository = "docker.io/andrew-delph", + repository = "ghcr.io/andrew-delph", tags = ["latest"], ) @@ -60,7 +60,7 @@ container_push( format = "Docker", image = ":operator_image", registry = "ghcr.io", - repository = "andrew-delph/my-key-store", + repository = "andrew-delph/operator", tag = "latest", ) diff --git a/operator/PROJECT b/operator/PROJECT index 38d1f20..25dafc2 100644 --- a/operator/PROJECT +++ b/operator/PROJECT @@ -12,7 +12,7 @@ plugins: group: cache kind: MyKeyStore options: - image: docker.io/andrew-delph/main:store_image + image: ghcr.io/andrew-delph/main:store_image version: v1alpha1 manifests.sdk.operatorframework.io/v2: {} scorecard.sdk.operatorframework.io/v2: {} diff --git a/operator/config/manager/kustomization.yaml b/operator/config/manager/kustomization.yaml index 3bc9947..e3df532 100644 --- a/operator/config/manager/kustomization.yaml +++ b/operator/config/manager/kustomization.yaml @@ -4,5 +4,5 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization images: - name: controller - newName: docker.io/andrew-delph/operator - newTag: "1696947634" + newName: ghcr.io/andrew-delph/operator + newTag: "1696952067" diff --git a/operator/config/manager/manager.yaml b/operator/config/manager/manager.yaml index a99afdd..4d7639e 100644 --- a/operator/config/manager/manager.yaml +++ b/operator/config/manager/manager.yaml @@ -72,7 +72,7 @@ spec: name: manager env: - name: MYKEYSTORE_IMAGE - value: docker.io/andrew-delph/main:store_image + value: ghcr.io/andrew-delph/main:store_image securityContext: allowPrivilegeEscalation: false capabilities: diff --git a/operator/config/samples/cache_v1alpha1_mykeystore.yaml b/operator/config/samples/cache_v1alpha1_mykeystore.yaml index 0a9b496..1ecc460 100644 --- a/operator/config/samples/cache_v1alpha1_mykeystore.yaml +++ b/operator/config/samples/cache_v1alpha1_mykeystore.yaml @@ -4,4 +4,4 @@ metadata: name: store spec: size: 5 - image: docker.io/andrew-delph/main:store_image + image: ghcr.io/andrew-delph/main:store_image diff --git a/resources/store.yaml b/resources/store.yaml index 461d236..54a959f 100644 --- a/resources/store.yaml +++ b/resources/store.yaml @@ -19,7 +19,7 @@ spec: app: store spec: containers: - - image: docker.io/andrew-delph/main:store_image + - image: ghcr.io/andrew-delph/main:store_image # imagePullPolicy: "Always" imagePullPolicy: Never name: store From cacdbfd791d000c6fc9384045653702d828b737c Mon Sep 17 00:00:00 2001 From: Andrew Delph Date: Tue, 10 Oct 2023 12:43:40 -0400 Subject: [PATCH 03/19] create ./e2e_k8.sh --- dev | 2 +- e2e_k8.sh | 26 ++++++++++++++++++++++ operator/config/manager/kustomization.yaml | 2 +- 3 files changed, 28 insertions(+), 2 deletions(-) create mode 100755 e2e_k8.sh diff --git a/dev b/dev index d93fbf4..b91fcfe 100755 --- a/dev +++ b/dev @@ -38,7 +38,7 @@ case $1 in tmux kill-session -t k8_dev ;; k8-e2e) - k6 run -e ADDRESS="192.168.49.2:30000" e2e/test.js + ./e2e_k8.sh ;; dc-e2e) k6 run e2e/test.js diff --git a/e2e_k8.sh b/e2e_k8.sh new file mode 100755 index 0000000..e8fefbe --- /dev/null +++ b/e2e_k8.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Define the service and namespace +SERVICE_NAME=store +NAMESPACE=default +LOCAL_PORT=8080 +REMOTE_PORT=8080 + +# Start kubectl port-forward in the background +kubectl port-forward -n $NAMESPACE svc/$SERVICE_NAME $LOCAL_PORT:$REMOTE_PORT & +# Get the PID of kubectl port-forward +PORT_FORWARD_PID=$! + +# Function to kill the port-forward process when the script exits +function cleanup { + echo "Cleaning up..." + kill -9 $PORT_FORWARD_PID +} +trap cleanup EXIT + +# Wait for the connection to be open +echo "Waiting for port-forward to be ready..." +sleep 5 + +# Run your k6 script +k6 run e2e/test.js \ No newline at end of file diff --git a/operator/config/manager/kustomization.yaml b/operator/config/manager/kustomization.yaml index e3df532..0f86b99 100644 --- a/operator/config/manager/kustomization.yaml +++ b/operator/config/manager/kustomization.yaml @@ -5,4 +5,4 @@ kind: Kustomization images: - name: controller newName: ghcr.io/andrew-delph/operator - newTag: "1696952067" + newTag: "1696955381" From 04f7e0e5c31ae67f848f31a285fd9af0188c1eea Mon Sep 17 00:00:00 2001 From: Andrew Delph Date: Tue, 10 Oct 2023 12:48:53 -0400 Subject: [PATCH 04/19] update e2e script --- e2e/test.js | 2 +- e2e_k8.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e/test.js b/e2e/test.js index 1a35dcf..19dbd1e 100644 --- a/e2e/test.js +++ b/e2e/test.js @@ -23,7 +23,7 @@ export let options = { // How long the test lasts duration: "2h", // How many iterations per timeUnit - rate: 10, + rate: 25, // Start `rate` iterations per second timeUnit: "1s", // Pre-allocate VUs diff --git a/e2e_k8.sh b/e2e_k8.sh index e8fefbe..47f1ae6 100755 --- a/e2e_k8.sh +++ b/e2e_k8.sh @@ -7,7 +7,7 @@ LOCAL_PORT=8080 REMOTE_PORT=8080 # Start kubectl port-forward in the background -kubectl port-forward -n $NAMESPACE svc/$SERVICE_NAME $LOCAL_PORT:$REMOTE_PORT & +kubectl port-forward -n $NAMESPACE svc/$SERVICE_NAME $LOCAL_PORT:$REMOTE_PORT > /dev/null & # Get the PID of kubectl port-forward PORT_FORWARD_PID=$! From f6af70ca2f69646da79f83dd1063b093a6dc4eb0 Mon Sep 17 00:00:00 2001 From: Andrew Delph Date: Tue, 10 Oct 2023 12:50:43 -0400 Subject: [PATCH 05/19] mod test.js --- e2e/test.js | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/e2e/test.js b/e2e/test.js index 19dbd1e..3010d97 100644 --- a/e2e/test.js +++ b/e2e/test.js @@ -18,31 +18,31 @@ export let options = { // duration: "2h", // exec: "default", // }, - constant_arrival: { - executor: "constant-arrival-rate", - // How long the test lasts - duration: "2h", - // How many iterations per timeUnit - rate: 25, - // Start `rate` iterations per second - timeUnit: "1s", - // Pre-allocate VUs - preAllocatedVUs: 400, - maxVUs: 2000, - }, - // ramping_arrival: { - // executor: "ramping-arrival-rate", - // startRate: 50, - // stages: [ - // { target: 75, duration: "2m" }, - // { target: 100, duration: "1h" }, - // ], + // constant_arrival: { + // executor: "constant-arrival-rate", + // // How long the test lasts + // duration: "2h", + // // How many iterations per timeUnit + // rate: 25, // // Start `rate` iterations per second // timeUnit: "1s", // // Pre-allocate VUs - // preAllocatedVUs: 50, - // maxVUs: 10000, + // preAllocatedVUs: 400, + // maxVUs: 2000, // }, + ramping_arrival: { + executor: "ramping-arrival-rate", + startRate: 50, + stages: [ + { target: 30, duration: "2m" }, + { target: 300, duration: "1h" }, + ], + // Start `rate` iterations per second + timeUnit: "1s", + // Pre-allocate VUs + preAllocatedVUs: 50, + maxVUs: 10000, + }, // epoch: { // executor: "constant-arrival-rate", // exec: "epoch", From 3717e0697d3e0164198ada85d36844ab6804bae6 Mon Sep 17 00:00:00 2001 From: Andrew Delph Date: Tue, 10 Oct 2023 12:58:35 -0400 Subject: [PATCH 06/19] e2e make run working --- e2e/Makefile | 16 ++++++---------- e2e/resources/k6-output-grafana-cloud.yaml | 6 +++--- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/e2e/Makefile b/e2e/Makefile index d1718fe..9e92eeb 100644 --- a/e2e/Makefile +++ b/e2e/Makefile @@ -8,10 +8,10 @@ init: curl https://raw.githubusercontent.com/grafana/k6-operator/main/bundle.yaml | kubectl apply -f - setup: - kubectl --context minikube create namespace k6 || echo "namespace already exists" - kubectl --context minikube delete configmap test-scripts --ignore-not-found -n k6 - kubectl --context minikube delete configmap prometheus-config --ignore-not-found -n k6 - kubectl --context minikube create configmap test-scripts \ + kubectl create namespace k6 || echo "namespace already exists" + kubectl delete configmap test-scripts --ignore-not-found -n k6 + kubectl delete configmap prometheus-config --ignore-not-found -n k6 + kubectl create configmap test-scripts \ --from-file=./test.js -n k6 run: @@ -21,14 +21,10 @@ run: logs: stern -n k6 .* -prod: - make setup - ./run-kube.sh resources/k6-output-grafana-cloud.yaml --external - watch: - watch -n 15 kubectl get pods -n k6 + watch -n 15 kubectl get pods -n k6 -n k6-operator-system delete: - kubectl --context minikube delete -f resources/k6-output-grafana-cloud.yaml -n k6 + kubectl delete -f resources/k6-output-grafana-cloud.yaml -n k6 # cd dependencies/k6-operator && make delete diff --git a/e2e/resources/k6-output-grafana-cloud.yaml b/e2e/resources/k6-output-grafana-cloud.yaml index c669cdc..6129991 100644 --- a/e2e/resources/k6-output-grafana-cloud.yaml +++ b/e2e/resources/k6-output-grafana-cloud.yaml @@ -24,12 +24,12 @@ spec: # requests: # memory: 200Mi env: - - name: K6_OUT - value: experimental-prometheus-rw + # - name: K6_OUT + # value: experimental-prometheus-rw - name: K6_PROMETHEUS_RW_TREND_STATS value: "avg,p(90),p(99),min,max" - name: ADDRESS - value: "store-external.default.svc.cluster.local:8080" + value: "store.default.svc.cluster.local:8080" - name: K6_PROMETHEUS_RW_SERVER_URL value: "http://prometheus-service.default:9090/api/v1/write" # - name: K6_LOG_FORMAT From f29a8a34c69e0a54a3c2b083ef768587c56dff7f Mon Sep 17 00:00:00 2001 From: Andrew Delph Date: Tue, 10 Oct 2023 14:34:55 -0400 Subject: [PATCH 07/19] modify e2e --- deploy_k8.sh | 1 - e2e/resources/k6-output-grafana-cloud.yaml | 4 +-- e2e/test.js | 42 +++++++++++----------- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/deploy_k8.sh b/deploy_k8.sh index b3012ae..92e5000 100755 --- a/deploy_k8.sh +++ b/deploy_k8.sh @@ -35,7 +35,6 @@ SECONDS=0 # Reset the SECONDS variable if [ $ROLL_OUT_FLAG -eq 0 ]; then echo "The 'rollout' flag is not set. Setting up." (cd operator && kustomize build config/crd | kubectl apply -f - || true) - bazel run //main:image_push kubectl apply -f ./operator/config/samples/ || true else echo "The 'rollout' flag is set." diff --git a/e2e/resources/k6-output-grafana-cloud.yaml b/e2e/resources/k6-output-grafana-cloud.yaml index 6129991..1fde631 100644 --- a/e2e/resources/k6-output-grafana-cloud.yaml +++ b/e2e/resources/k6-output-grafana-cloud.yaml @@ -24,8 +24,8 @@ spec: # requests: # memory: 200Mi env: - # - name: K6_OUT - # value: experimental-prometheus-rw + - name: K6_OUT + value: experimental-prometheus-rw - name: K6_PROMETHEUS_RW_TREND_STATS value: "avg,p(90),p(99),min,max" - name: ADDRESS diff --git a/e2e/test.js b/e2e/test.js index 3010d97..0da90d0 100644 --- a/e2e/test.js +++ b/e2e/test.js @@ -18,31 +18,31 @@ export let options = { // duration: "2h", // exec: "default", // }, - // constant_arrival: { - // executor: "constant-arrival-rate", - // // How long the test lasts - // duration: "2h", - // // How many iterations per timeUnit - // rate: 25, - // // Start `rate` iterations per second - // timeUnit: "1s", - // // Pre-allocate VUs - // preAllocatedVUs: 400, - // maxVUs: 2000, - // }, - ramping_arrival: { - executor: "ramping-arrival-rate", - startRate: 50, - stages: [ - { target: 30, duration: "2m" }, - { target: 300, duration: "1h" }, - ], + constant_arrival: { + executor: "constant-arrival-rate", + // How long the test lasts + duration: "2h", + // How many iterations per timeUnit + rate: 40, // Start `rate` iterations per second timeUnit: "1s", // Pre-allocate VUs - preAllocatedVUs: 50, - maxVUs: 10000, + preAllocatedVUs: 400, + maxVUs: 2000, }, + // ramping_arrival: { + // executor: "ramping-arrival-rate", + // startRate: 50, + // stages: [ + // { target: 30, duration: "2m" }, + // { target: 300, duration: "1h" }, + // ], + // // Start `rate` iterations per second + // timeUnit: "1s", + // // Pre-allocate VUs + // preAllocatedVUs: 50, + // maxVUs: 10000, + // }, // epoch: { // executor: "constant-arrival-rate", // exec: "epoch", From 873a737e17c9fc3eb1d329fc226c7ea749f4d704 Mon Sep 17 00:00:00 2001 From: Andrew Delph Date: Tue, 10 Oct 2023 14:36:38 -0400 Subject: [PATCH 08/19] modify test script --- e2e/test.js | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/e2e/test.js b/e2e/test.js index 0da90d0..a0cabdc 100644 --- a/e2e/test.js +++ b/e2e/test.js @@ -18,31 +18,31 @@ export let options = { // duration: "2h", // exec: "default", // }, - constant_arrival: { - executor: "constant-arrival-rate", - // How long the test lasts - duration: "2h", - // How many iterations per timeUnit - rate: 40, - // Start `rate` iterations per second - timeUnit: "1s", - // Pre-allocate VUs - preAllocatedVUs: 400, - maxVUs: 2000, - }, - // ramping_arrival: { - // executor: "ramping-arrival-rate", - // startRate: 50, - // stages: [ - // { target: 30, duration: "2m" }, - // { target: 300, duration: "1h" }, - // ], + // constant_arrival: { + // executor: "constant-arrival-rate", + // // How long the test lasts + // duration: "2h", + // // How many iterations per timeUnit + // rate: 40, // // Start `rate` iterations per second // timeUnit: "1s", // // Pre-allocate VUs - // preAllocatedVUs: 50, - // maxVUs: 10000, + // preAllocatedVUs: 400, + // maxVUs: 2000, // }, + ramping_arrival: { + executor: "ramping-arrival-rate", + startRate: 50, + stages: [ + { target: 30, duration: "2m" }, + { target: 300, duration: "1h" }, + ], + // Start `rate` iterations per second + timeUnit: "1s", + // Pre-allocate VUs + preAllocatedVUs: 50, + maxVUs: 10000, + }, // epoch: { // executor: "constant-arrival-rate", // exec: "epoch", From 7c6932229ef12c5444bff66f48e25a5bc857bd6d Mon Sep 17 00:00:00 2001 From: Andrew Delph Date: Tue, 10 Oct 2023 16:40:55 -0400 Subject: [PATCH 09/19] Monitoring (#12) * monitoring helm init * prep for remote cluster * metrics server * make watch * 100 rate --- .tmuxinator/tmuxinator-k8.yaml | 2 +- dev | 2 - e2e/Makefile | 13 +- e2e/create_dashboards.sh | 21 + e2e/dashboards/dashboard-tests.json | 1984 ++++++++++++++++++++ e2e/loki-stack.values.yaml | 190 ++ e2e/resources/k6-output-grafana-cloud.yaml | 4 +- e2e/test.js | 42 +- operator/config/manager/kustomization.yaml | 2 +- 9 files changed, 2230 insertions(+), 30 deletions(-) create mode 100755 e2e/create_dashboards.sh create mode 100644 e2e/dashboards/dashboard-tests.json create mode 100644 e2e/loki-stack.values.yaml diff --git a/.tmuxinator/tmuxinator-k8.yaml b/.tmuxinator/tmuxinator-k8.yaml index 2a878d0..566b166 100644 --- a/.tmuxinator/tmuxinator-k8.yaml +++ b/.tmuxinator/tmuxinator-k8.yaml @@ -1,5 +1,5 @@ name: k8_dev -on_project_first_start: ./dev k8-init +# on_project_first_start: ./dev k8-init on_project_exit: minikube delete windows: - editor: diff --git a/dev b/dev index b91fcfe..ebb9f02 100755 --- a/dev +++ b/dev @@ -25,8 +25,6 @@ case $1 in kubectl delete -f ./operator/config/samples/ || true ./deploy_operator.sh ./deploy_k8.sh - kubectl apply -f ./resources/prom.yaml - kubectl create configmap prometheus-config --from-file=prometheus.yml || true ;; k8-operator) ./deploy_operator.sh diff --git a/e2e/Makefile b/e2e/Makefile index 9e92eeb..e700e05 100644 --- a/e2e/Makefile +++ b/e2e/Makefile @@ -6,6 +6,7 @@ build: init: @echo "init" curl https://raw.githubusercontent.com/grafana/k6-operator/main/bundle.yaml | kubectl apply -f - + make monitoring setup: kubectl create namespace k6 || echo "namespace already exists" @@ -22,9 +23,15 @@ logs: stern -n k6 .* watch: - watch -n 15 kubectl get pods -n k6 -n k6-operator-system + watch kubectl get pods -n k6 delete: - kubectl delete -f resources/k6-output-grafana-cloud.yaml -n k6 - # cd dependencies/k6-operator && make delete + kubectl delete -f resources/k6-output-grafana-cloud.yaml -n k6 || true + helm uninstall loki --namespace=monitoring --wait || true +monitoring: + helm repo add grafana https://grafana.github.io/helm-charts + kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml --wait + kubectl create namespace monitoring --dry-run=client -o yaml | kubectl apply -f - + helm upgrade --install loki --namespace=monitoring grafana/loki-stack -f loki-stack.values.yaml + bash ./create_dashboards.sh diff --git a/e2e/create_dashboards.sh b/e2e/create_dashboards.sh new file mode 100755 index 0000000..3466cd5 --- /dev/null +++ b/e2e/create_dashboards.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# default dashboards: https://github.com/prometheus-community/helm-charts/tree/8f91606e01b85b9aa013ed472c5acb836c4e7ac8/charts/kube-prometheus-stack/templates/grafana/dashboards-1.14 + +# delete existing dashboards +kubectl delete configmap --selector custom_dashboard='1' -n monitoring + +# Set the directory path +dir_path="./dashboards" + +# Loop through all files in the directory +for file_path in $dir_path/*; do + file_name=$(basename "${file_path%.*}") + + # # Create the ConfigMap using the file contents and name as the ConfigMap name + kubectl create configmap "$file_name" --from-file="$file_path" -n monitoring + + # # Add labels to the ConfigMap + kubectl label configmap "$file_name" grafana_dashboard='1' custom_dashboard='1' -n monitoring + +done \ No newline at end of file diff --git a/e2e/dashboards/dashboard-tests.json b/e2e/dashboards/dashboard-tests.json new file mode 100644 index 0000000..96f2ff1 --- /dev/null +++ b/e2e/dashboards/dashboard-tests.json @@ -0,0 +1,1984 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Visualize k6 OSS results stored in Prometheus", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [ + { + "asDropdown": false, + "icon": "external link", + "includeVars": false, + "keepTime": false, + "tags": [], + "targetBlank": true, + "title": "Grafana k6 OSS Docs: Prometheus Remote Write", + "tooltip": "Open docs in a new tab", + "type": "link", + "url": "https://k6.io/docs/results-output/real-time/prometheus-remote-write/" + } + ], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "http_req_s_errors" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "red", + "mode": "fixed" + } + }, + { + "id": "custom.lineStyle", + "value": { + "dash": [10, 10], + "fill": "dash" + } + }, + { + "id": "custom.axisPlacement", + "value": "right" + }, + { + "id": "unit", + "value": "reqps" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "http_req_s" + }, + "properties": [ + { + "id": "unit", + "value": "reqps" + }, + { + "id": "custom.axisPlacement", + "value": "right" + }, + { + "id": "color", + "value": { + "fixedColor": "yellow", + "mode": "fixed" + } + }, + { + "id": "custom.lineStyle", + "value": { + "dash": [10, 10], + "fill": "dash" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "vus" + }, + "properties": [ + { + "id": "color", + "value": { + "mode": "fixed" + } + }, + { + "id": "unit", + "value": "VUs" + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "http_req_duration_[a-zA-Z0-9_]+" + }, + "properties": [ + { + "id": "unit", + "value": "s" + }, + { + "id": "custom.axisPlacement", + "value": "right" + }, + { + "id": "color", + "value": { + "fixedColor": "blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 10, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg(k6_vus{testid=~\"$testid\"})", + "instant": false, + "legendFormat": "vus", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg(k6_http_req_duration_$quantile_stat{testid=~\"$testid\"})", + "hide": false, + "instant": false, + "legendFormat": "http_req_duration_$quantile_stat", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(irate(k6_http_reqs_total{testid=~\"$testid\"}[$__rate_interval]))", + "hide": false, + "instant": false, + "legendFormat": "http_req_s", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg(round(k6_http_req_failed_rate{testid=~\"$testid\"}, 0.1)*100)", + "hide": true, + "instant": false, + "legendFormat": "http_req_failed", + "range": true, + "refId": "E" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(irate(k6_http_reqs_total{testid=~\"$testid\", expected_response=\"false\"}[$__rate_interval]))", + "hide": false, + "instant": false, + "legendFormat": "http_req_s_errors", + "range": true, + "refId": "D" + } + ], + "title": "Performance Overview", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 11 + }, + "id": 1, + "panels": [], + "title": "Performance Overview", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 12 + }, + "id": 4, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.1.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(k6_http_reqs_total{testid=~\"$testid\"})", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "HTTP requests", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "red", + "mode": "fixed" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 6, + "y": 12 + }, + "id": 22, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.1.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(k6_http_reqs_total{testid=~\"$testid\", expected_response=\"false\"})", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "HTTP request failures", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 12, + "y": 12 + }, + "id": 20, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.1.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(irate(k6_http_reqs_total{testid=~\"$testid\"}[$__rate_interval]))", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Peak RPS", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Select a different Stat to change the query", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 18, + "y": 12 + }, + "id": 21, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.1.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg(k6_http_req_duration_$quantile_stat{testid=~\"$testid\"})", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "HTTP Request Duration", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 15 + }, + "id": 8, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg(irate(k6_data_sent_total{testid=~\"$testid\"}[$__rate_interval]))", + "instant": false, + "legendFormat": "data_sent", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "avg(irate(k6_data_received_total{testid=~\"$testid\"}[$__rate_interval]))", + "hide": false, + "instant": false, + "legendFormat": "data_received", + "range": true, + "refId": "B" + } + ], + "title": "Transfer Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "s" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "dropped_iterations" + }, + "properties": [ + { + "id": "unit", + "value": "none" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 15 + }, + "id": 9, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg(k6_iteration_duration_$quantile_stat{testid=~\"$testid\"})", + "instant": false, + "legendFormat": "iteration_duration_$quantile_stat", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "avg(k6_dropped_iterations_total{testid=~\"$testid\"})", + "hide": false, + "instant": false, + "legendFormat": "dropped_iterations", + "range": true, + "refId": "B" + } + ], + "title": "Iterations", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 23 + }, + "id": 16, + "panels": [], + "title": "HTTP", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Select a different Stat to change the query\n\nHTTP-specific built-in metrics", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "s" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "http_req_duration_[a-zA-Z0-9_]+" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 24 + }, + "id": 14, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg(k6_http_req_blocked_$quantile_stat{testid=~\"$testid\"})", + "hide": false, + "instant": false, + "legendFormat": "http_req_blocked_$quantile_stat", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg(k6_http_req_tls_handshaking_$quantile_stat{testid=~\"$testid\"})", + "hide": false, + "instant": false, + "legendFormat": "http_req_tls_handshaking_$quantile_stat", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg(k6_http_req_sending_$quantile_stat{testid=~\"$testid\"})", + "hide": false, + "instant": false, + "legendFormat": "http_req_sending_$quantile_stat", + "range": true, + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg(k6_http_req_waiting_$quantile_stat{testid=~\"$testid\"})", + "hide": false, + "instant": false, + "legendFormat": "http_req_waiting_$quantile_stat", + "range": true, + "refId": "E" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg(k6_http_req_receiving_$quantile_stat{testid=~\"$testid\"})", + "hide": false, + "instant": false, + "legendFormat": "http_req_receiving_$quantile_stat", + "range": true, + "refId": "F" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg(k6_http_req_duration_$quantile_stat{testid=~\"$testid\"})", + "hide": false, + "instant": false, + "legendFormat": "http_req_duration_$quantile_stat", + "range": true, + "refId": "A" + } + ], + "title": "HTTP Latency Timings", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Select a different Stat to change the query", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMin": 0, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "s" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "errors_http_req_duration_[a-zA-Z0-9_]+" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "red", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "success_http_req_duration_[a-zA-Z0-9_]+" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "green", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "http_req_duration_[a-zA-Z0-9_]+" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "yellow", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "http_req_duration_[a-zA-Z0-9_]+" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 24 + }, + "id": 15, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg(k6_http_req_duration_$quantile_stat{testid=~\"$testid\"})", + "hide": false, + "instant": false, + "legendFormat": "http_req_duration_$quantile_stat", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg(k6_http_req_duration_$quantile_stat{testid=~\"$testid\", expected_response=\"true\"})", + "instant": false, + "legendFormat": "success_http_req_duration_$quantile_stat", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg(k6_http_req_duration_$quantile_stat{testid=~\"$testid\", expected_response=\"false\"})", + "hide": false, + "instant": false, + "legendFormat": "errors_http_req_duration_$quantile_stat", + "range": true, + "refId": "B" + } + ], + "title": "HTTP Latency Stats", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMin": 0, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "reqps" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "http_req_s_errors" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "red", + "mode": "fixed" + } + }, + { + "id": "custom.lineStyle", + "value": { + "dash": [10, 10], + "fill": "dash" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "http_req_s" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "yellow", + "mode": "fixed" + } + }, + { + "id": "custom.lineStyle", + "value": { + "dash": [10, 10], + "fill": "dash" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "http_req_s_success" + }, + "properties": [ + { + "id": "custom.lineStyle", + "value": { + "dash": [10, 10], + "fill": "dash" + } + }, + { + "id": "color", + "value": { + "fixedColor": "green", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 24 + }, + "id": 18, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(irate(k6_http_reqs_total{testid=~\"$testid\"}[$__rate_interval]))", + "instant": false, + "legendFormat": "http_req_s", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(irate(k6_http_reqs_total{testid=~\"$testid\", expected_response=\"false\"}[$__rate_interval]))", + "hide": false, + "instant": false, + "legendFormat": "http_req_s_errors", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(irate(k6_http_reqs_total{testid=~\"$testid\", expected_response=\"true\"}[$__rate_interval]))", + "hide": false, + "instant": false, + "legendFormat": "http_req_s_success", + "range": true, + "refId": "C" + } + ], + "title": "HTTP Request Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "min/max/p95/p99 depends on the available Quantile Stats", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "name" + }, + "properties": [ + { + "id": "filterable", + "value": false + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "method" + }, + "properties": [ + { + "id": "filterable", + "value": false + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "status" + }, + "properties": [ + { + "id": "filterable", + "value": false + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "min" + }, + "properties": [ + { + "id": "unit", + "value": "s" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "max" + }, + "properties": [ + { + "id": "unit", + "value": "s" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "p95" + }, + "properties": [ + { + "id": "unit", + "value": "s" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "p99" + }, + "properties": [ + { + "id": "unit", + "value": "s" + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 32 + }, + "id": 17, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "enablePagination": true, + "fields": "", + "reducer": ["sum"], + "show": false + }, + "frameIndex": 2, + "showHeader": true + }, + "pluginVersion": "10.1.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg by(name, method, status) (k6_http_req_duration_min{testid=~\"$testid\"})", + "format": "table", + "hide": false, + "instant": false, + "legendFormat": "min", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg by(name, method, status) (k6_http_req_duration_max{testid=~\"$testid\"})", + "format": "table", + "hide": false, + "instant": false, + "legendFormat": "max", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg by(name, method, status) (k6_http_req_duration_p95{testid=~\"$testid\"})", + "format": "table", + "hide": false, + "instant": false, + "legendFormat": "p95", + "range": true, + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg by(name, method, status) (k6_http_req_duration_p99{testid=~\"$testid\"})", + "format": "table", + "hide": false, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "E" + } + ], + "title": "Requests by URL", + "transformations": [ + { + "id": "merge", + "options": {} + }, + { + "id": "groupBy", + "options": { + "fields": { + "Value #B": { + "aggregations": ["min"], + "operation": "aggregate" + }, + "Value #C": { + "aggregations": ["max"], + "operation": "aggregate" + }, + "Value #D": { + "aggregations": ["mean"], + "operation": "aggregate" + }, + "Value #E": { + "aggregations": ["mean"], + "operation": "aggregate" + }, + "method": { + "aggregations": [], + "operation": "groupby" + }, + "name": { + "aggregations": [], + "operation": "groupby" + }, + "status": { + "aggregations": [], + "operation": "groupby" + } + } + } + }, + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true + }, + "indexByName": { + "Time": 0, + "Value #B": 4, + "Value #C": 5, + "Value #D": 6, + "Value #E": 7, + "method": 2, + "name": 1, + "status": 3 + }, + "renameByName": { + "Value #B": "min", + "Value #B (min)": "min", + "Value #C": "max", + "Value #C (max)": "max", + "Value #D": "p95", + "Value #D (mean)": "p95", + "Value #E": "p99", + "Value #E (mean)": "p99" + } + } + } + ], + "type": "table" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 39 + }, + "id": 11, + "panels": [], + "title": "Checks", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Success Rate" + }, + "properties": [ + { + "id": "custom.hidden", + "value": false + }, + { + "id": "unit", + "value": "%" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value (mean)" + }, + "properties": [ + { + "id": "custom.hidden", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "check" + }, + "properties": [ + { + "id": "filterable", + "value": false + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 40 + }, + "id": 12, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "enablePagination": true, + "fields": "", + "reducer": ["sum"], + "show": false + }, + "frameIndex": 2, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Value (count)" + } + ] + }, + "pluginVersion": "10.1.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "round(k6_checks_rate{testid=~\"$testid\"}, 0.1)", + "format": "table", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Checks list", + "transformations": [ + { + "id": "labelsToFields", + "options": { + "keepLabels": ["__name__", "check"], + "mode": "columns" + } + }, + { + "id": "groupBy", + "options": { + "fields": { + "Value": { + "aggregations": ["mean"], + "operation": "aggregate" + }, + "check": { + "aggregations": [], + "operation": "groupby" + }, + "k6_checks_rate": { + "aggregations": ["sum", "count"], + "operation": "aggregate" + } + } + } + }, + { + "id": "calculateField", + "options": { + "alias": "Success Rate", + "binary": { + "left": "Value (mean)", + "operator": "*", + "reducer": "sum", + "right": "100" + }, + "mode": "binary", + "reduce": { + "reducer": "sum" + } + } + }, + { + "id": "convertFieldType", + "options": { + "conversions": [], + "fields": {} + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Filter by check name to query a particular check", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 100, + "axisSoftMin": 0, + "barAlignment": -1, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "%" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 40 + }, + "id": 13, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg(round(k6_checks_rate{testid=~\"$testid\"}, 0.1)*100)", + "instant": false, + "legendFormat": "k6_checks_rate", + "range": true, + "refId": "A" + } + ], + "title": "Checks Success Rate (aggregate individual checks)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 5, + "w": 24, + "x": 0, + "y": 48 + }, + "id": 23, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "### Visualize other k6 results \n\nAt the top of the dashboard, click `Add` and select `Visualization` from the dropdown menu. Choose the visualization type and input the PromQL queries for the `k6_` metric(s).\n\nAlternatively, click on the `Explore` icon on the menu bar and input the queries for the `k6_` metric(s). From `Explore`, you can add new Panels to this dashboard. \n\nNote that all k6 metrics are prefixed with the `k6_` namespace when sent to Prometheus.", + "mode": "markdown" + }, + "pluginVersion": "10.1.2", + "type": "text" + } + ], + "refresh": "", + "schemaVersion": 38, + "style": "dark", + "tags": ["prometheus", "k6"], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "prometheus", + "value": "P1809F7CD0C75ACF3" + }, + "description": "Choose a Prometheus Data Source", + "hide": 0, + "includeAll": false, + "label": "Prometheus DS", + "multi": false, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "selected": true, + "text": ["All"], + "value": ["$__all"] + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(testid)", + "description": "Filter by \"testid\" tag. Define it by tagging: k6 run --tag testid=xyz", + "hide": 0, + "includeAll": true, + "label": "Test ID", + "multi": true, + "name": "testid", + "options": [], + "query": { + "query": "label_values(testid)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "isNone": true, + "selected": false, + "text": "None", + "value": "" + }, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "metrics(k6_http_req_duration_)", + "description": "Statistic for Trend Metrics Queries. The available options depend on the values of the K6_PROMETHEUS_RW_TREND_STATS setting.", + "hide": 0, + "includeAll": false, + "label": "Trend Metrics Query", + "multi": false, + "name": "quantile_stat", + "options": [], + "query": { + "query": "metrics(k6_http_req_duration_)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "/http_req_duration_(min|max|count|sum|avg|med|p[0-9]+)/g", + "skipUrlSync": false, + "sort": 2, + "type": "query" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Adhoc filters are applied to all panels. To enable it, go to Dashboard Settings / Variables / adhoc_filter and select the target Prometheus data source.", + "filters": [], + "hide": 0, + "label": "AdhocFilter", + "name": "adhoc_filter", + "skipUrlSync": false, + "type": "adhoc" + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "k6 Prometheus", + "uid": "ccbb2351-2ae2-462f-ae0e-f2c893ad1028", + "version": 1, + "weekStart": "" +} diff --git a/e2e/loki-stack.values.yaml b/e2e/loki-stack.values.yaml new file mode 100644 index 0000000..16fbd4f --- /dev/null +++ b/e2e/loki-stack.values.yaml @@ -0,0 +1,190 @@ +test_pod: + enabled: true + image: bats/bats:v1.1.0 + pullPolicy: IfNotPresent + +grafana: + enabled: true + adminUser: admin + adminPassword: password + image: + tag: "" + nodeSelector: + vke.vultr.com/node-pool: main + service: + annotations: {} + appProtocol: "" + enabled: true + labels: {} + port: 80 + portName: service + targetPort: 3000 + nodePort: 30007 + type: NodePort + sidecar: + dashboards: + enabled: true + label: grafana_dashboard + labelValue: "1" + annotations: {} + multicluster: + global: + enabled: false + etcd: + enabled: false + provider: + foldersFromFilesStructure: true + updateIntervalSeconds: 30 + allowUiUpdates: false + datasources: + enabled: true + defaultDatasourceEnabled: true + isDefaultDatasource: true + uid: prometheus + annotations: {} + createPrometheusReplicasDatasources: false + label: grafana_datasource + labelValue: "1" + + exemplarTraceIdDestinations: {} + persistence: + enabled: false + existingClaim: storage-loki-0 + +prometheus: + enabled: true + server: + image: + tag: v2.42.0 + # priorityClassName: high-priority + service: + type: NodePort + nodePort: 30008 + + # global: + # scrape_interval: 3m + # extraArgs: + # log.level: debug + extraFlags: + - web.enable-lifecycle + - enable-feature=remote-write-receiver + # - storage.tsdb.max-block-duration=20m + # - storage.tsdb.min-block-duration=20m + # - storage.tsdb.retention.size=300MB + # - web.enable-remote-write-receiver + # - log.level=debug + # global: + # query_log_file: /prometheus/query.log + persistentVolume: + enabled: true + # existingClaim: "prometheus-pvc" + kubeStateMetrics: + enabled: false + alertmanager: + image: + tag: v0.25.0 + enabled: false + service: + type: NodePort + nodePort: 30009 + # priorityClassName: high-priority + persistentVolume: + enabled: false + configFromSecret: "loki-prometheus-alertmanager" + # alertmanagerFiles: + # alertmanager.yml: + # global: {} + # route: + # receiver: 'gmail-notifications' + # receivers: + # - name: 'gmail-notifications' + # email_configs: + # - to: example@gmail.ca + # from: example@gmail.com + # smarthost: smtp.gmail.com:587 + # auth_username: example@gmail.com + # auth_identity: example@gmail.com + # auth_password: example + # send_resolved: true + + # extraScrapeConfigs: | + # - job_name: rabbitmq + # scrape_interval: 3m + # scrape_timeout: 1m + # basic_auth: + # username: guest + # password: guest + # static_configs: + # - targets: + # - rabbitmq.default.svc.cluster.local:15692 + +loki: + enabled: true + isDefault: false + url: http://{{(include "loki.serviceName" .)}}:{{ .Values.loki.service.port }} + readinessProbe: + httpGet: + path: /ready + port: http-metrics + initialDelaySeconds: 45 + livenessProbe: + httpGet: + path: /ready + port: http-metrics + initialDelaySeconds: 45 + datasource: + jsonData: "{}" + uid: "" + persistence: + enabled: true + size: 40Gi + +promtail: + enabled: true + # priorityClassName: high-priority + config: + serverPort: 3101 + clients: + - url: http://{{ .Release.Name }}:3100/loki/api/v1/push + snippets: + # addScrapeJobLabel: true + # extraLimitsConfig: | + # readline_rate: 1000 + # readline_burst: 2000 + # readline_rate_enabled: true + extraRelabelConfigs: + # keep all kubernetes labels + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + - source_labels: [serving_knative_dev_service] + regex: "(.+)" + target_label: "app" + pipelineStages: + - drop: + source: "namespace" + expression: "(kube-public|kube-system)" + # - drop: + # older_than: 1h + # drop_counter_reason: 'line_too_old' + - cri: + - docker: + - json: + expressions: + level: level + - static_labels: + level: unknown + # - labels: + # level: stream + - labels: + level: + - output: + source: msg + +# proxy is currently only used by loki test pod +# Note: If http_proxy/https_proxy are set, then no_proxy should include the +# loki service name, so that tests are able to communicate with the loki +# service. +proxy: + http_proxy: "" + https_proxy: "" + no_proxy: "" diff --git a/e2e/resources/k6-output-grafana-cloud.yaml b/e2e/resources/k6-output-grafana-cloud.yaml index 1fde631..5ed6859 100644 --- a/e2e/resources/k6-output-grafana-cloud.yaml +++ b/e2e/resources/k6-output-grafana-cloud.yaml @@ -9,7 +9,7 @@ kind: K6 metadata: name: k6-output-grafana-cloud spec: - parallelism: 1 + parallelism: 3 script: configMap: # Remember...we created the 'test-scripts' ConfigMap with the available scripts inside. @@ -31,7 +31,7 @@ spec: - name: ADDRESS value: "store.default.svc.cluster.local:8080" - name: K6_PROMETHEUS_RW_SERVER_URL - value: "http://prometheus-service.default:9090/api/v1/write" + value: "http://loki-prometheus-server.monitoring:80/api/v1/write" # - name: K6_LOG_FORMAT # value: json # envFrom: diff --git a/e2e/test.js b/e2e/test.js index a0cabdc..3067f38 100644 --- a/e2e/test.js +++ b/e2e/test.js @@ -18,31 +18,31 @@ export let options = { // duration: "2h", // exec: "default", // }, - // constant_arrival: { - // executor: "constant-arrival-rate", - // // How long the test lasts - // duration: "2h", - // // How many iterations per timeUnit - // rate: 40, - // // Start `rate` iterations per second - // timeUnit: "1s", - // // Pre-allocate VUs - // preAllocatedVUs: 400, - // maxVUs: 2000, - // }, - ramping_arrival: { - executor: "ramping-arrival-rate", - startRate: 50, - stages: [ - { target: 30, duration: "2m" }, - { target: 300, duration: "1h" }, - ], + constant_arrival: { + executor: "constant-arrival-rate", + // How long the test lasts + duration: "2h", + // How many iterations per timeUnit + rate: 100, // Start `rate` iterations per second timeUnit: "1s", // Pre-allocate VUs - preAllocatedVUs: 50, - maxVUs: 10000, + preAllocatedVUs: 400, + maxVUs: 2000, }, + // ramping_arrival: { + // executor: "ramping-arrival-rate", + // startRate: 50, + // stages: [ + // { target: 30, duration: "2m" }, + // { target: 300, duration: "1h" }, + // ], + // // Start `rate` iterations per second + // timeUnit: "1s", + // // Pre-allocate VUs + // preAllocatedVUs: 50, + // maxVUs: 10000, + // }, // epoch: { // executor: "constant-arrival-rate", // exec: "epoch", diff --git a/operator/config/manager/kustomization.yaml b/operator/config/manager/kustomization.yaml index 0f86b99..21d4c39 100644 --- a/operator/config/manager/kustomization.yaml +++ b/operator/config/manager/kustomization.yaml @@ -5,4 +5,4 @@ kind: Kustomization images: - name: controller newName: ghcr.io/andrew-delph/operator - newTag: "1696955381" + newTag: "1696969023" From e477f14c52fe75b24feb6e8e6210bf960cbc3374 Mon Sep 17 00:00:00 2001 From: Andrew Delph Date: Tue, 10 Oct 2023 16:42:36 -0400 Subject: [PATCH 10/19] make stop --- e2e/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/e2e/Makefile b/e2e/Makefile index e700e05..1678001 100644 --- a/e2e/Makefile +++ b/e2e/Makefile @@ -25,6 +25,9 @@ logs: watch: watch kubectl get pods -n k6 +stop: + kubectl delete -f resources/k6-output-grafana-cloud.yaml -n k6 || true + delete: kubectl delete -f resources/k6-output-grafana-cloud.yaml -n k6 || true helm uninstall loki --namespace=monitoring --wait || true From e4ec8ca962059bb8d3e79c3ebee477ad49015245 Mon Sep 17 00:00:00 2001 From: Andrew Delph Date: Wed, 11 Oct 2023 18:16:07 -0400 Subject: [PATCH 11/19] docs.md --- docs.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 docs.md diff --git a/docs.md b/docs.md new file mode 100644 index 0000000..b8ed98c --- /dev/null +++ b/docs.md @@ -0,0 +1,35 @@ +- summary +- layout + - hasring + - partitions + - epoch buckets + - indexs + lsm +- gossip + - client discovery + - non operator member management +- consensus + - epochs + - members + temp members +- hashring + - current members + - temp members +- replication + - on epoch + - on cluster change +- read/write quorum +- external/internal endpoints +- protobufs +- indexes +- storage + - indexdb + - badgerdb +- operator + - code rollout + - scale cluster +- development environment + - docker-compose + - minikube +- benchmarks +- future improvements + - scan query +- tradeoffs From 3dd3e28d1e7c8cbee812325ca514a86d5837231d Mon Sep 17 00:00:00 2001 From: Andrew Delph Date: Thu, 12 Oct 2023 12:40:31 -0400 Subject: [PATCH 12/19] doc SAGA/2PC --- docs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs.md b/docs.md index b8ed98c..c85075d 100644 --- a/docs.md +++ b/docs.md @@ -32,4 +32,5 @@ - benchmarks - future improvements - scan query + - SAGA/2PC - tradeoffs From 5c8d8445493c1e23c2872bf5d9e8699cdfea4efb Mon Sep 17 00:00:00 2001 From: Andrew Delph Date: Thu, 12 Oct 2023 12:41:03 -0400 Subject: [PATCH 13/19] read repairs --- docs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs.md b/docs.md index c85075d..57c6997 100644 --- a/docs.md +++ b/docs.md @@ -33,4 +33,5 @@ - future improvements - scan query - SAGA/2PC + - read repairs - tradeoffs From f03761fe963fdaf0b77ae99e95dc551f6a7a67f1 Mon Sep 17 00:00:00 2001 From: Andrew Delph Date: Sat, 21 Oct 2023 16:50:12 -0400 Subject: [PATCH 14/19] test rate --- e2e/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/test.js b/e2e/test.js index 3067f38..4bc1bf8 100644 --- a/e2e/test.js +++ b/e2e/test.js @@ -23,7 +23,7 @@ export let options = { // How long the test lasts duration: "2h", // How many iterations per timeUnit - rate: 100, + rate: 10, // Start `rate` iterations per second timeUnit: "1s", // Pre-allocate VUs From 2dfff2a6c2022d812747061da05ad3d623609ccb Mon Sep 17 00:00:00 2001 From: Andrew Delph Date: Sat, 21 Oct 2023 17:00:39 -0400 Subject: [PATCH 15/19] change test --- e2e/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/test.js b/e2e/test.js index 4bc1bf8..0c6e7b8 100644 --- a/e2e/test.js +++ b/e2e/test.js @@ -166,7 +166,7 @@ export function remove() { } // options = { duration: "2h", vus: 1 }; -// options = { iterations: 1, vus: 1 }; +options = { iterations: 200, vus: 50 }; export default function () { const iterationNumber = exec.scenario.iterationInTest; From c680b9a87eaab81a6ddd04fa396182a9f329d92a Mon Sep 17 00:00:00 2001 From: Andrew Delph Date: Sat, 21 Oct 2023 17:02:54 -0400 Subject: [PATCH 16/19] change test only set --- e2e/test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/e2e/test.js b/e2e/test.js index 0c6e7b8..51bcf52 100644 --- a/e2e/test.js +++ b/e2e/test.js @@ -166,7 +166,7 @@ export function remove() { } // options = { duration: "2h", vus: 1 }; -options = { iterations: 200, vus: 50 }; +options = { iterations: 2000, vus: 100 }; export default function () { const iterationNumber = exec.scenario.iterationInTest; @@ -186,6 +186,7 @@ export default function () { check(setRes, { "set status is 200": (r) => r.status === 200, }); + return; if (setRes.status != 200) { console.error("SET REQUEST FAILED:", setRes.status, setRes.body); From 44770851faaf7bff4787c62081a5cd52ced5c03a Mon Sep 17 00:00:00 2001 From: Andrew Delph Date: Sat, 21 Oct 2023 17:05:03 -0400 Subject: [PATCH 17/19] bigger test --- e2e/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/test.js b/e2e/test.js index 51bcf52..b7e1c7c 100644 --- a/e2e/test.js +++ b/e2e/test.js @@ -166,7 +166,7 @@ export function remove() { } // options = { duration: "2h", vus: 1 }; -options = { iterations: 2000, vus: 100 }; +options = { iterations: 10000, vus: 500 }; export default function () { const iterationNumber = exec.scenario.iterationInTest; From 9439ed5d1eb528febdaf854544475214f0b7a775 Mon Sep 17 00:00:00 2001 From: Andrew Delph Date: Sat, 21 Oct 2023 17:10:29 -0400 Subject: [PATCH 18/19] add ThreadRequests option for workers --- config/config.go | 11 +- config/config_test.go | 1 + config/default-config.yaml | 3 +- config/test-config.yaml | 1 + main/manager.go | 556 +++++++++++++++++++------------------ 5 files changed, 292 insertions(+), 280 deletions(-) diff --git a/config/config.go b/config/config.go index dd6d404..0dc48c6 100644 --- a/config/config.go +++ b/config/config.go @@ -8,11 +8,12 @@ import ( ) type ManagerConfig struct { - WokersCount int `mapstructure:"WORKERS_COUNT"` - ReqChannelSize int `mapstructure:"REQ_CHANNEL_SIZE"` - ReplicaCount int `mapstructure:"REPLICA_COUNT"` - WriteQuorum int `mapstructure:"WRITE_QUORUM"` - ReadQuorum int `mapstructure:"READ_QUORUM"` + WokersCount int `mapstructure:"WORKERS_COUNT"` + ThreadRequests bool `mapstructure:"THREAD_REQUESTS"` + ReqChannelSize int `mapstructure:"REQ_CHANNEL_SIZE"` + ReplicaCount int `mapstructure:"REPLICA_COUNT"` + WriteQuorum int `mapstructure:"WRITE_QUORUM"` + ReadQuorum int `mapstructure:"READ_QUORUM"` SaveInterval int DefaultTimeout int `mapstructure:"DEFAULT_TIMEOUT"` PartitionCount int `mapstructure:"PARTITION_COUNT"` diff --git a/config/config_test.go b/config/config_test.go index dd01c71..3520165 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -62,6 +62,7 @@ func TestConfigOverwrite(t *testing.T) { assert.EqualValues(t, 99999, config.Manager.PartitionBuckets, "PartitionBuckets wrong value") assert.EqualValues(t, "/tmp/store/data", config.Manager.DataPath, "DataPath wrong value") assert.EqualValues(t, 991, config.Manager.PartitionConcurrency, "PartitionConcurrency wrong value") + assert.EqualValues(t, true, config.Manager.ThreadRequests, "ThreadRequests wrong value") // consensus config assert.EqualValues(t, 9, config.Consensus.EpochTime, "EpochTime wrong value") diff --git a/config/default-config.yaml b/config/default-config.yaml index 3caa524..d8c9c8c 100644 --- a/config/default-config.yaml +++ b/config/default-config.yaml @@ -4,7 +4,8 @@ manager: write_quorum: 2 default_timeout: 10 req_channel_size: 20 - workers_count: 100 + workers_count: 2 + thread_requests: true partition_count: 15 partition_concurrency: 10 partition_buckets: 1000 diff --git a/config/test-config.yaml b/config/test-config.yaml index 8c05ef0..1d123b7 100644 --- a/config/test-config.yaml +++ b/config/test-config.yaml @@ -6,6 +6,7 @@ manager: partition_buckets: 99999 partition_concurrency: 991 data_path: "/tmp/store/data" + thread_requests: true consensus: epoch_time: 9 data_path: "/tmp/store/raft" diff --git a/main/manager.go b/main/manager.go index 0bb44f7..9a5699b 100644 --- a/main/manager.go +++ b/main/manager.go @@ -188,7 +188,6 @@ func (m *Manager) startWorker(workerId int) { logrus.Debugf("starting worker %d", workerId) for { - workerLoop: select { case <-m.debugTick.C: // m.consensusCluster.Details() @@ -251,327 +250,336 @@ func (m *Manager) startWorker(workerId int) { logrus.Warn("Channel closed!") return } - switch task := data.(type) { + if m.config.Manager.ThreadRequests { + go m.handleTask(data) + } else { + m.handleTask(data) + } - case StopWorkerTask: - defer task.wg.Done() - return + } + } +} - case rpc.PartitionsHealthCheckTask: - // logrus.Warn("PartitionsHealthCheckTask") - err := m.consistencyController.IsHealthy() - task.ResCh <- err +func (m *Manager) handleTask(data interface{}) { + switch task := data.(type) { - case rpc.UpdateMembersTask: - var err error + case StopWorkerTask: + defer task.wg.Done() + return - if m.consensusCluster.Isleader() == false { - task.ResCh <- true - continue - } - if m.ring.CompareMembers(task.Members, task.TempMembers) == true { - // logrus.Warn("members already changed") - task.ResCh <- true - continue - } + case rpc.PartitionsHealthCheckTask: + // logrus.Warn("PartitionsHealthCheckTask") + err := m.consistencyController.IsHealthy() + task.ResCh <- err - err = m.consensusCluster.UpdateFsm(m.GetCurrentEpoch(), task.Members, task.TempMembers) - if err != nil { - logrus.Error("UpdateFsm err = %v", err) - task.ResCh <- err - continue - } + case rpc.UpdateMembersTask: + var err error - task.ResCh <- true + if m.consensusCluster.Isleader() == false { + task.ResCh <- true + return + } + if m.ring.CompareMembers(task.Members, task.TempMembers) == true { + // logrus.Warn("members already changed") + task.ResCh <- true + return + } - case rpc.UpdateEpochTask: - var err error + err = m.consensusCluster.UpdateFsm(m.GetCurrentEpoch(), task.Members, task.TempMembers) + if err != nil { + logrus.Error("UpdateFsm err = %v", err) + task.ResCh <- err + return + } - if m.consensusCluster.Isleader() == false { - task.ResCh <- true - continue - } + task.ResCh <- true - if m.LastEpochUpdateId == task.UpdateId { - task.ResCh <- true - continue - } + case rpc.UpdateEpochTask: + var err error - logrus.Warnf("UpdateEpochTask %s", task.UpdateId) + if m.consensusCluster.Isleader() == false { + task.ResCh <- true + return + } - err = m.consensusCluster.UpdateFsm(m.GetCurrentEpoch()+1, m.ring.GetMembersNames(false), m.ring.GetMembersNames(true)) - if err != nil { - logrus.Warnf("UpdateEpochTask UpdateMembers err = %v", err) - task.ResCh <- err - } + if m.LastEpochUpdateId == task.UpdateId { + task.ResCh <- true + return + } - err = m.consensusCluster.UpdateFsm(m.GetCurrentEpoch()+1, m.ring.GetMembersNames(false), m.ring.GetMembersNames(true)) - if err != nil { - logrus.Warnf("UpdateEpochTask UpdateMembers err = %v", err) - task.ResCh <- err - } + logrus.Warnf("UpdateEpochTask %s", task.UpdateId) - m.LastEpochUpdateId = task.UpdateId + err = m.consensusCluster.UpdateFsm(m.GetCurrentEpoch()+1, m.ring.GetMembersNames(false), m.ring.GetMembersNames(true)) + if err != nil { + logrus.Warnf("UpdateEpochTask UpdateMembers err = %v", err) + task.ResCh <- err + } - task.ResCh <- true + err = m.consensusCluster.UpdateFsm(m.GetCurrentEpoch()+1, m.ring.GetMembersNames(false), m.ring.GetMembersNames(true)) + if err != nil { + logrus.Warnf("UpdateEpochTask UpdateMembers err = %v", err) + task.ResCh <- err + } - case http.HealthTask: - err := m.consensusCluster.IsHealthy() - if err != nil { - logrus.Warnf("HealthTask err = %v", err) - task.ResCh <- err - continue - } + m.LastEpochUpdateId = task.UpdateId - task.ResCh <- true - case http.ReadyTask: - err := m.consensusCluster.IsHealthy() - if err != nil { - logrus.Debugf("IsHealthy err = %v", err) - task.ResCh <- err - continue - } + task.ResCh <- true - // err = m.ring.IsHealthy() - // if err != nil { - // logrus.Warnf("ring.IsHealthy err = %v", err) - // task.ResCh <- err - // continue - // } - - // err = m.consistencyController.IsBusy() - // if err != nil { - // logrus.Warnf("HealthTask err = %v", err) - // task.ResCh <- err - // continue - // } - - task.ResCh <- true - - case http.SetTask: - logrus.Debugf("worker SetTask: %+v", task) - members, err := m.SetRequest(task.Key, task.Value) - errorStr := "" - if err != nil { - errorStr = err.Error() - } - task.ResCh <- http.SetResponse{Error: errorStr, Members: members} - - case http.GetTask: - logrus.Debugf("worker GetTask: %+v", task) - value, failed_members, err := m.GetRequest(task.Key) - var valueStr string - if value != nil { - valueStr = value.Value - } - errorStr := "" - if err != nil { - errorStr = err.Error() - } - task.ResCh <- http.GetResponse{Value: valueStr, Error: errorStr, Failed_members: failed_members} - - case gossip.JoinTask: - // logrus.Warnf("worker JoinTask: %+v", task) - - err := m.consensusCluster.AddVoter(task.Name, task.IP) - if err != nil { - err = errors.Wrap(err, "gossip.JoinTask") - logrus.Error(err) - } else { - // logrus.Infof("AddVoter success") - } + case http.HealthTask: + err := m.consensusCluster.IsHealthy() + if err != nil { + logrus.Warnf("HealthTask err = %v", err) + task.ResCh <- err + return + } - _, rpcClient, err := m.rpcWrapper.CreateRpcClient(task.IP) - if err != nil { - err = errors.Wrap(err, "gossip.JoinTask") - logrus.Fatal(err) - continue - } - m.clientManager.AddClient(task.Name, rpcClient) + task.ResCh <- true + case http.ReadyTask: + err := m.consensusCluster.IsHealthy() + if err != nil { + logrus.Debugf("IsHealthy err = %v", err) + task.ResCh <- err + return + } - if m.config.Manager.Operator == false { - err = m.consensusCluster.UpdateFsm(m.GetCurrentEpoch(), m.gossipCluster.GetMembersNames(), m.gossipCluster.GetMembersNames()) - if err != nil { - logrus.Warnf("JoinTask UpdateMembers err = %v", err) - } - } + // err = m.ring.IsHealthy() + // if err != nil { + // logrus.Warnf("ring.IsHealthy err = %v", err) + // task.ResCh <- err + // continue + // } + + // err = m.consistencyController.IsBusy() + // if err != nil { + // logrus.Warnf("HealthTask err = %v", err) + // task.ResCh <- err + // continue + // } + + task.ResCh <- true + + case http.SetTask: + logrus.Debugf("worker SetTask: %+v", task) + members, err := m.SetRequest(task.Key, task.Value) + errorStr := "" + if err != nil { + errorStr = err.Error() + } + task.ResCh <- http.SetResponse{Error: errorStr, Members: members} + + case http.GetTask: + logrus.Debugf("worker GetTask: %+v", task) + value, failed_members, err := m.GetRequest(task.Key) + var valueStr string + if value != nil { + valueStr = value.Value + } + errorStr := "" + if err != nil { + errorStr = err.Error() + } + task.ResCh <- http.GetResponse{Value: valueStr, Error: errorStr, Failed_members: failed_members} - case gossip.LeaveTask: - // logrus.Warnf("worker LeaveTask: %+v", task) - m.clientManager.RemoveClient(task.Name) - m.consensusCluster.RemoveServer(task.Name) - if m.config.Manager.Operator == false { - err := m.consensusCluster.UpdateFsm(m.GetCurrentEpoch(), m.gossipCluster.GetMembersNames(), m.gossipCluster.GetMembersNames()) - if err != nil { - logrus.Warnf("JoinTask UpdateMembers err = %v", err) - } - } + case gossip.JoinTask: + // logrus.Warnf("worker JoinTask: %+v", task) - case consensus.FsmTask: - logrus.Warnf("FsmTask Epoch %v Members %v TempMembers %v", task.Epoch, len(task.Members), len(task.TempMembers)) - m.SetCurrentEpoch(task.Epoch) - m.consistencyController.PublishEpoch(task.Epoch) + err := m.consensusCluster.AddVoter(task.Name, task.IP) + if err != nil { + err = errors.Wrap(err, "gossip.JoinTask") + logrus.Error(err) + } else { + // logrus.Infof("AddVoter success") + } - m.ring.SetRingMembers(task.Members, task.TempMembers) - task.ResCh <- true + _, rpcClient, err := m.rpcWrapper.CreateRpcClient(task.IP) + if err != nil { + err = errors.Wrap(err, "gossip.JoinTask") + logrus.Fatal(err) + return + } + m.clientManager.AddClient(task.Name, rpcClient) - case rpc.SetValueTask: - logrus.Debugf("worker SetValueTask: %+v", task) + if m.config.Manager.Operator == false { + err = m.consensusCluster.UpdateFsm(m.GetCurrentEpoch(), m.gossipCluster.GetMembersNames(), m.gossipCluster.GetMembersNames()) + if err != nil { + logrus.Warnf("JoinTask UpdateMembers err = %v", err) + } + } - if task.Value.Epoch < m.GetCurrentEpoch()-1 { - task.ResCh <- errors.New("cannot set lagging epoch") - continue - } - err := m.SetValue(task.Value) - if err != nil { - logrus.Warnf("SetValue err = %v", err) - task.ResCh <- err - } else { - task.ResCh <- true - } + case gossip.LeaveTask: + // logrus.Warnf("worker LeaveTask: %+v", task) + m.clientManager.RemoveClient(task.Name) + m.consensusCluster.RemoveServer(task.Name) + if m.config.Manager.Operator == false { + err := m.consensusCluster.UpdateFsm(m.GetCurrentEpoch(), m.gossipCluster.GetMembersNames(), m.gossipCluster.GetMembersNames()) + if err != nil { + logrus.Warnf("JoinTask UpdateMembers err = %v", err) + } + } - case rpc.GetValueTask: - logrus.Debugf("worker GetValueTask: %+v", task) - // value, err := m.db.Get([]byte(task.Key)) - value, err := m.GetValue(task.Key) - if err == storage.KEY_NOT_FOUND { // TODO if the nodes partition is not up to date it should not count as response - task.ResCh <- nil - } else if err != nil { - task.ResCh <- err - } else { - task.ResCh <- value - } + case consensus.FsmTask: + logrus.Warnf("FsmTask Epoch %v Members %v TempMembers %v", task.Epoch, len(task.Members), len(task.TempMembers)) + m.SetCurrentEpoch(task.Epoch) + m.consistencyController.PublishEpoch(task.Epoch) - case rpc.StreamBucketsTask: // TODO test this is returning right values - logrus.Debugf("worker StreamBucketsTask: %+v", task) - var buckets []int32 = task.Buckets - if len(buckets) == 0 { - for i := 0; i < m.config.Manager.PartitionBuckets; i++ { - buckets = append(buckets, int32(i)) - } - } - for _, bucket := range buckets { - index1, err := BuildEpochIndex(int(task.PartitionId), uint64(bucket), task.LowerEpoch, "") - if err != nil { - logrus.Fatal(err) - continue - } - index2, err := BuildEpochIndex(int(task.PartitionId), uint64(bucket), task.UpperEpoch, "") - if err != nil { - logrus.Fatal(err) - continue - } - it := m.db.NewIterator( - []byte(index1), - []byte(index2), - false, - ) - for !it.IsDone() { - _, _, epoch, key, err := ParseEpochIndex(string(it.Key())) - if err != nil { - logrus.Fatal(err) - continue - } - timestamp, err := utils.DecodeBytesToInt64(it.Value()) - if err != nil { - logrus.Fatal(err) - continue - } - - task.ResCh <- &rpc.RpcValue{Key: key, Epoch: epoch, UnixTimestamp: timestamp} - it.Next() - } - it.Release() - } + m.ring.SetRingMembers(task.Members, task.TempMembers) + task.ResCh <- true - close(task.ResCh) + case rpc.SetValueTask: + logrus.Debugf("worker SetValueTask: %+v", task) - case VerifyPartitionEpochRequestTask: - logrus.Debugf("worker VerifyPartitionEpochRequestTask: %+v", task.PartitionId) - err := m.VerifyEpoch(task.PartitionId, task.Epoch) + if task.Value.Epoch < m.GetCurrentEpoch()-1 { + task.ResCh <- errors.New("cannot set lagging epoch") + return + } + err := m.SetValue(task.Value) + if err != nil { + logrus.Warnf("SetValue err = %v", err) + task.ResCh <- err + } else { + task.ResCh <- true + } - if err != nil { - task.ResCh <- err - } else { - task.ResCh <- VerifyPartitionEpochResponse{Valid: true} - } + case rpc.GetValueTask: + logrus.Debugf("worker GetValueTask: %+v", task) + // value, err := m.db.Get([]byte(task.Key)) + value, err := m.GetValue(task.Key) + if err == storage.KEY_NOT_FOUND { // TODO if the nodes partition is not up to date it should not count as response + task.ResCh <- nil + } else if err != nil { + task.ResCh <- err + } else { + task.ResCh <- value + } - case rpc.GetEpochTreeObjectTask: - logrus.Debugf("worker GetPartitionEpochObjectTask: %+v", task) - index, err := BuildEpochTreeObjectIndex(int(task.PartitionId), task.LowerEpoch) + case rpc.StreamBucketsTask: // TODO test this is returning right values + logrus.Debugf("worker StreamBucketsTask: %+v", task) + var buckets []int32 = task.Buckets + if len(buckets) == 0 { + for i := 0; i < m.config.Manager.PartitionBuckets; i++ { + buckets = append(buckets, int32(i)) + } + } + for _, bucket := range buckets { + index1, err := BuildEpochIndex(int(task.PartitionId), uint64(bucket), task.LowerEpoch, "") + if err != nil { + logrus.Fatal(err) + continue + } + index2, err := BuildEpochIndex(int(task.PartitionId), uint64(bucket), task.UpperEpoch, "") + if err != nil { + logrus.Fatal(err) + continue + } + it := m.db.NewIterator( + []byte(index1), + []byte(index2), + false, + ) + for !it.IsDone() { + _, _, epoch, key, err := ParseEpochIndex(string(it.Key())) if err != nil { - task.ResCh <- err + logrus.Fatal(err) continue } - - epochTreeObjectBytes, err := m.db.Get([]byte(index)) + timestamp, err := utils.DecodeBytesToInt64(it.Value()) if err != nil { - // logrus.Warnf("GetEpochTreeObjectTask err = %v index %v active: %v", err, index, m.consistencyController.IsPartitionActive(int(task.PartitionId))) - err = errors.Wrapf(err, "active: %v", m.consistencyController.IsPartitionActive(int(task.PartitionId))) - task.ResCh <- err + logrus.Fatal(err) continue } - epochTreeObject := &rpc.RpcEpochTreeObject{} - err = proto.Unmarshal(epochTreeObjectBytes, epochTreeObject) - if err != nil { - task.ResCh <- err - continue - } - task.ResCh <- epochTreeObject + task.ResCh <- &rpc.RpcValue{Key: key, Epoch: epoch, UnixTimestamp: timestamp} + it.Next() + } + it.Release() + } - case rpc.GetEpochTreeLastValidObjectTask: - logrus.Debugf("worker GetEpochTreeLastValidObjectTask: %+v", task) - epochTreeObjectLastValid, err := m.GetEpochTreeLastValid(task.PartitionId) - if err != nil { - task.ResCh <- err - } else if epochTreeObjectLastValid == nil { - task.ResCh <- errors.New("no valid EpochTreeObject for partition") - } else { - task.ResCh <- epochTreeObjectLastValid - } + close(task.ResCh) - case SyncPartitionTask: - logrus.Debugf("worker SyncPartitionTask: %+v", task.PartitionId) - epochTreeObjectLastValid, err := m.GetEpochTreeLastValid(task.PartitionId) - if err != nil { - task.ResCh <- errors.Wrap(err, "GetEpochTreeLastValid") - continue - } else if epochTreeObjectLastValid != nil && epochTreeObjectLastValid.LowerEpoch >= task.UpperEpoch { // TODO validate this is the correct compare - task.ResCh <- nil - continue - } + case VerifyPartitionEpochRequestTask: + logrus.Debugf("worker VerifyPartitionEpochRequestTask: %+v", task.PartitionId) + err := m.VerifyEpoch(task.PartitionId, task.Epoch) - lastValidEpoch := int64(0) - if epochTreeObjectLastValid != nil { - lastValidEpoch = epochTreeObjectLastValid.LowerEpoch - } + if err != nil { + task.ResCh <- err + } else { + task.ResCh <- VerifyPartitionEpochResponse{Valid: true} + } - logrus.Debugf("sync lastValidEpoch %d", lastValidEpoch) + case rpc.GetEpochTreeObjectTask: + logrus.Debugf("worker GetPartitionEpochObjectTask: %+v", task) + index, err := BuildEpochTreeObjectIndex(int(task.PartitionId), task.LowerEpoch) + if err != nil { + task.ResCh <- err + return + } - // find most healthy node - err = m.PoliteStreamRequest(int(task.PartitionId), lastValidEpoch, task.UpperEpoch+1, nil) + epochTreeObjectBytes, err := m.db.Get([]byte(index)) + if err != nil { + // logrus.Warnf("GetEpochTreeObjectTask err = %v index %v active: %v", err, index, m.consistencyController.IsPartitionActive(int(task.PartitionId))) + err = errors.Wrapf(err, "active: %v", m.consistencyController.IsPartitionActive(int(task.PartitionId))) + task.ResCh <- err + return + } - if err != nil { - logrus.Debug(err) - task.ResCh <- SyncPartitionResponse{Valid: false, LowerEpoch: lastValidEpoch, UpperEpoch: task.UpperEpoch + 1} - } else { - task.ResCh <- SyncPartitionResponse{Valid: true, LowerEpoch: lastValidEpoch, UpperEpoch: task.UpperEpoch + 1} - } + epochTreeObject := &rpc.RpcEpochTreeObject{} + err = proto.Unmarshal(epochTreeObjectBytes, epochTreeObject) + if err != nil { + task.ResCh <- err + return + } + task.ResCh <- epochTreeObject + + case rpc.GetEpochTreeLastValidObjectTask: + logrus.Debugf("worker GetEpochTreeLastValidObjectTask: %+v", task) + epochTreeObjectLastValid, err := m.GetEpochTreeLastValid(task.PartitionId) + if err != nil { + task.ResCh <- err + } else if epochTreeObjectLastValid == nil { + task.ResCh <- errors.New("no valid EpochTreeObject for partition") + } else { + task.ResCh <- epochTreeObjectLastValid + } + + case SyncPartitionTask: + logrus.Debugf("worker SyncPartitionTask: %+v", task.PartitionId) + epochTreeObjectLastValid, err := m.GetEpochTreeLastValid(task.PartitionId) + if err != nil { + task.ResCh <- errors.Wrap(err, "GetEpochTreeLastValid") + return + } else if epochTreeObjectLastValid != nil && epochTreeObjectLastValid.LowerEpoch >= task.UpperEpoch { // TODO validate this is the correct compare + task.ResCh <- nil + return + } - case hashring.RingUpdateTask: - // logrus.Warnf("worker MembersUpdateTask #%+v", len(task.Partitions)) + lastValidEpoch := int64(0) + if epochTreeObjectLastValid != nil { + lastValidEpoch = epochTreeObjectLastValid.LowerEpoch + } - currPartitions := utils.NewIntSet().From(task.Partitions) - m.consistencyController.HandleHashringChange(currPartitions) + logrus.Debugf("sync lastValidEpoch %d", lastValidEpoch) - task.ResCh <- true + // find most healthy node + err = m.PoliteStreamRequest(int(task.PartitionId), lastValidEpoch, task.UpperEpoch+1, nil) - default: - logrus.Panicf("worker unkown task type: %v", reflect.TypeOf(task)) - break workerLoop - } + if err != nil { + logrus.Debug(err) + task.ResCh <- SyncPartitionResponse{Valid: false, LowerEpoch: lastValidEpoch, UpperEpoch: task.UpperEpoch + 1} + } else { + task.ResCh <- SyncPartitionResponse{Valid: true, LowerEpoch: lastValidEpoch, UpperEpoch: task.UpperEpoch + 1} } + + case hashring.RingUpdateTask: + // logrus.Warnf("worker MembersUpdateTask #%+v", len(task.Partitions)) + + currPartitions := utils.NewIntSet().From(task.Partitions) + m.consistencyController.HandleHashringChange(currPartitions) + + task.ResCh <- true + + default: + logrus.Panicf("worker unkown task type: %v", reflect.TypeOf(task)) + } } From 55043603b413f1bd4200c89af9e906ee3a4f596d Mon Sep 17 00:00:00 2001 From: Andrew Delph Date: Sat, 21 Oct 2023 17:15:06 -0400 Subject: [PATCH 19/19] worker stops on StopWorkerTask --- main/manager.go | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/main/manager.go b/main/manager.go index 9a5699b..ed29686 100644 --- a/main/manager.go +++ b/main/manager.go @@ -250,10 +250,18 @@ func (m *Manager) startWorker(workerId int) { logrus.Warn("Channel closed!") return } - if m.config.Manager.ThreadRequests { - go m.handleTask(data) - } else { - m.handleTask(data) + switch task := data.(type) { + + case StopWorkerTask: + logrus.Warn("StopWorkerTask!") + defer task.wg.Done() + return + default: + if m.config.Manager.ThreadRequests { + go m.handleTask(data) + } else { + m.handleTask(data) + } } }