diff --git a/.github/workflows/install-and-run-spsh-loadtest.yml b/.github/workflows/install-and-run-spsh-loadtest.yml index cd91956..fa3b44b 100644 --- a/.github/workflows/install-and-run-spsh-loadtest.yml +++ b/.github/workflows/install-and-run-spsh-loadtest.yml @@ -1,10 +1,14 @@ --- -name: Install SPSH Loadtest Action +name: Install SPSH Loadtest Action -on: +on: workflow_call: inputs: - branch: + branch_code: + type: string + required: false + default: main + branch_img: type: string required: false default: main @@ -13,9 +17,13 @@ on: required: false default: "login" config: - type: string + type: string required: false default: "debug" + max_vus: + type: string + required: false + default: "10" scenario: type: string required: true @@ -23,7 +31,7 @@ on: execute: type: boolean required: true - default: true + default: false secrets: KUBECONFIG: @@ -64,15 +72,14 @@ jobs: fi rollout: - runs-on: 'ubuntu-latest' + runs-on: "ubuntu-latest" needs: branch_meta steps: - name: Checkout repo uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1 with: - repository: 'dBildungsplattform/schulportal-load-tests' - # change this ref to a branch to test changes - ref: "${{ inputs.branch }}" + repository: "dBildungsplattform/schulportal-load-tests" + ref: "${{ inputs.branch_code }}" - name: Install kubectl and Helm uses: azure/setup-kubectl@3e0aec4d80787158d308d7b364cb1b702e7feb7f #v4.0.0 @@ -83,23 +90,24 @@ jobs: echo "${{ secrets.KUBECONFIG }}" > /home/runner/.kube/config chmod 600 /home/runner/.kube/config - - name: Rollout schulportal-load-tests Helm Chart + - name: Rollout schulportal-load-tests Helm Chart run: | - helm upgrade --install \ - schulportal-load-tests \ - ./charts/schulportal-load-tests \ - --namespace spsh \ - --kubeconfig /home/runner/.kube/config \ - --set branch="${{ inputs.branch }}" \ - --set pattern="${{ inputs.pattern }}" \ - --set config="${{ inputs.config }}" \ - ${{ inputs.branch != 'main' && format('--set imageTag="{0}"', needs.branch_meta.outputs.ticket ) || '--set imageTag="latest"' }} \ - --wait + helm upgrade --install \ + schulportal-load-tests \ + ./charts/schulportal-load-tests \ + --namespace spsh \ + --kubeconfig /home/runner/.kube/config \ + --set branch="${{ inputs.branch_code }}" \ + --set pattern="${{ inputs.pattern }}" \ + --set config="${{ inputs.config }}" \ + --set max_vus="${{ inputs.max_vus }}" \ + ${{ inputs.branch_img != 'main' && format('--set imageTag="{0}"', needs.branch_meta.outputs.ticket ) || '--set imageTag="latest"' }} \ + --wait - name: Convert branch name to lowercase id: convert_branch run: | - LOWERCASE_BRANCH=$(echo "${{ inputs.branch }}" | tr '[:upper:]' '[:lower:]') + LOWERCASE_BRANCH=$(echo "${{ inputs.branch_code }}" | tr '[:upper:]' '[:lower:]') echo "Lowercase branch: $LOWERCASE_BRANCH" echo "::set-output name=lowercase_branch::$LOWERCASE_BRANCH" @@ -107,4 +115,3 @@ jobs: if: ${{ inputs.execute }} run: | kubectl create job --from=cronjob/loadtest-spsh-${{inputs.scenario}} ${{ inputs.scenario}}-${{steps.convert_branch.outputs.lowercase_branch}}-$(date +%d.%m.%Y-%H%M) -n spsh - # kubectl create job --from=cronjob/ -n diff --git a/.github/workflows/publish-image-on-push-to-branch.yml b/.github/workflows/publish-image-on-push-to-branch.yml index ee7a1b5..0a8ee98 100644 --- a/.github/workflows/publish-image-on-push-to-branch.yml +++ b/.github/workflows/publish-image-on-push-to-branch.yml @@ -1,9 +1,9 @@ -name: 'Publish image to GHCR on push to branch' +name: "Publish image to GHCR on push to branch" on: push: branches-ignore: - - 'main' + - "main" concurrency: group: schulportal-load-tests-${{ github.ref }} @@ -20,5 +20,5 @@ jobs: image_name: "schulportal-load-tests" run_trivy_scan: true image_tag_generation: "ticket_from_branch" - add_latest_tag: false - container_registry: "ghcr.io" \ No newline at end of file + add_latest_tag: false + container_registry: "ghcr.io" diff --git a/.github/workflows/publish-image-on-tag.yml b/.github/workflows/publish-image-on-tag.yml index 4cd8cd6..8adb02d 100644 --- a/.github/workflows/publish-image-on-tag.yml +++ b/.github/workflows/publish-image-on-tag.yml @@ -1,4 +1,4 @@ -name: 'Publish image to GHCR and Helm chart to GH pages on tag' +name: "Publish image to GHCR and Helm chart to GH pages on tag" on: push: @@ -21,4 +21,4 @@ jobs: run_trivy_scan: true image_tag_generation: "version_git_tag" add_latest_tag: true - container_registry: "ghcr.io" \ No newline at end of file + container_registry: "ghcr.io" diff --git a/.github/workflows/trigger-loadtest.yml b/.github/workflows/trigger-loadtest.yml index 49b6970..c4ff338 100644 --- a/.github/workflows/trigger-loadtest.yml +++ b/.github/workflows/trigger-loadtest.yml @@ -1,26 +1,36 @@ --- -name: Trigger Loadtest +name: Trigger Loadtest on: workflow_dispatch: inputs: - branch: - description: 'Branch to take tests and helm/cron setup from' + branch_code: + description: "Branch to take test code and helm/cron setup from" + required: false + type: string + default: main + branch_img: + description: "Branch to take Dockerfile/img from" required: false type: string default: main pattern: - description: 'sets PATTERN env var used as k6 input' + description: "sets PATTERN env var used as k6 input" required: false type: string default: "login" config: - description: 'sets CONFIG env var used as k6 input' + description: "sets CONFIG env var used as k6 input" required: false type: string default: "debug" + max_vus: + description: "sets the maximum number of virtual users" + required: false + type: string + default: "10" scenario: - description: 'name of test scenario defined in values.yaml' + description: "name of test scenario defined in values.yaml" type: string required: true default: dev-scenario @@ -28,7 +38,7 @@ on: description: "execute cronjob scenario after install" type: boolean required: true - default: true + default: false jobs: install_loadtest: @@ -38,12 +48,12 @@ jobs: contents: read uses: ./.github/workflows/install-and-run-spsh-loadtest.yml with: - branch: ${{ inputs.branch }} - pattern: ${{ inputs.pattern }} - config: ${{ inputs.config }} + branch_code: ${{ inputs.branch_code }} + branch_img: ${{ inputs.branch_img }} + pattern: ${{ inputs.pattern }} + config: ${{ inputs.config }} + max_vus: ${{ inputs.max_vus }} scenario: ${{ inputs.scenario }} execute: ${{ inputs.execute }} - secrets: + secrets: KUBECONFIG: ${{ secrets.KUBECONFIG }} - - \ No newline at end of file diff --git a/charts/schulportal-load-tests/templates/cronjob.yaml b/charts/schulportal-load-tests/templates/cronjob.yaml index c3db728..d464695 100644 --- a/charts/schulportal-load-tests/templates/cronjob.yaml +++ b/charts/schulportal-load-tests/templates/cronjob.yaml @@ -37,13 +37,15 @@ spec: value: {{ $job_options.kc_base }} - name: PATTERN value: {{ $.Values.pattern }} + - name: MAX_VUS + value: {{ $.Values.max_vus | quote }} command: ["sh", "-c", "git clone https://github.com/dBildungsplattform/schulportal-load-tests && cd schulportal-load-tests && git checkout {{ $.Values.branch }} && cp /data/json/users.json /home/k6/schulportal-load-tests/loadtest/data/users.json && chmod +x run.sh && - ./run.sh $SPSH_BASE $CONFIG $PATTERN $KC_BASE "] + ./run.sh $SPSH_BASE $CONFIG $PATTERN $MAX_VUS $KC_BASE "] volumeMounts: - name: secret-volume mountPath: /secrets diff --git a/charts/schulportal-load-tests/templates/spsh-loadtest-secret-json.yaml b/charts/schulportal-load-tests/templates/spsh-loadtest-secret-json.yaml index 855fae3..75d3452 100644 --- a/charts/schulportal-load-tests/templates/spsh-loadtest-secret-json.yaml +++ b/charts/schulportal-load-tests/templates/spsh-loadtest-secret-json.yaml @@ -3,7 +3,7 @@ kind: OnePasswordItem metadata: name: spsh-loadtest-secret-json namespace: spsh - labels: + labels: app.kubernetes.io/managed-by: helm spec: - itemPath: "vaults/spsh-dev-schulportal/items/spsh-loadtest-secret-json" \ No newline at end of file + itemPath: "vaults/spsh-dev-schulportal/items/spsh-loadtest-secret-json" diff --git a/charts/schulportal-load-tests/templates/spsh-loadtest-secret.yaml b/charts/schulportal-load-tests/templates/spsh-loadtest-secret.yaml index f28e012..fe29cfb 100644 --- a/charts/schulportal-load-tests/templates/spsh-loadtest-secret.yaml +++ b/charts/schulportal-load-tests/templates/spsh-loadtest-secret.yaml @@ -3,7 +3,7 @@ kind: OnePasswordItem metadata: name: spsh-loadtest-secret namespace: spsh - labels: + labels: app.kubernetes.io/managed-by: helm spec: - itemPath: "vaults/spsh-dev/items/spsh-loadtest-secret" \ No newline at end of file + itemPath: "vaults/spsh-dev/items/spsh-loadtest-secret" diff --git a/charts/schulportal-load-tests/values.yaml b/charts/schulportal-load-tests/values.yaml index b2fe49d..227c344 100644 --- a/charts/schulportal-load-tests/values.yaml +++ b/charts/schulportal-load-tests/values.yaml @@ -4,6 +4,7 @@ port: 5656 schedule: 0 8 * * * pattern: "dummy_pattern" config: "dummy_config" +max_vus: "10" cronjobs: dev-scenario: @@ -18,12 +19,10 @@ cronjobs: serviceName: hpa-scenario spsh_base: "https://dbp-1021.dev.spsh.dbildungsplattform.de" kc_base: "kc_base" - # jobsParallelism: not used yet but available? test it - # staging-scenario: - # serviceName: staging-scenario - # image: ghcr.io/dbildungsplattform/schulportal-load-tests:latest - # environment: spsh.staging.dbildungsplattform.de - # prod-scenario: + staging-scenario: + serviceName: staging-scenario + spsh_base: "https://spsh.staging.spsh.dbildungsplattform.de" + # prod-scenario: # serviceName: prod-scenario # image: ghcr.io/dbildungsplattform/schulportal-load-tests:latest # environment: spsh.dbildungsplattform.de diff --git a/loadtest/usecases/1_login.ts b/loadtest/usecases/1_login.ts index 3589270..6f81a69 100644 --- a/loadtest/usecases/1_login.ts +++ b/loadtest/usecases/1_login.ts @@ -12,7 +12,7 @@ const successfulLoginDuration = new Trend("successful_logins_duration", true); const users = getDefaultUserMix(); export const options = { - ...getDefaultOptions(users), + ...getDefaultOptions(), }; export default wrapTestFunction(main); diff --git a/loadtest/util/config.ts b/loadtest/util/config.ts index 0569ea2..d0f9782 100644 --- a/loadtest/util/config.ts +++ b/loadtest/util/config.ts @@ -1,6 +1,5 @@ -import { UserMix } from "./users.ts"; - const SPSH_BASE = __ENV["SPSH_BASE"]; +const MAX_VUS = Number.parseInt(__ENV["MAX_VUS"]); export enum CONFIG { SPIKE = "spike", @@ -17,11 +16,9 @@ export function getConfig(): CONFIG { throw Error(`Invalid value for config '${config}'`); } -export function getDefaultOptions(users?: UserMix) { +export function getDefaultOptions() { const config = getConfig(); - // Use this for real setup only; Traffic will be high - const maxVUs = users ? users.getTotalUserNumber() : 100; - // const maxVUs = 10; + const maxVUs = MAX_VUS ?? 10; switch (config) { case CONFIG.SPIKE: return { @@ -47,12 +44,12 @@ export function getDefaultOptions(users?: UserMix) { stages: [{ duration: "10m", target: 10 * maxVUs }], thresholds: { http_req_failed: [{ threshold: "rate<0.10", abortOnFail: true }], - http_req_duration: [{ threshold: "p(95)<2000", abortOnFail: true }], + http_req_duration: [{ threshold: "p(95)<5000", abortOnFail: true }], }, }; case CONFIG.DEBUG: return { - stages: [{ duration: "10s", target: 10 }], + stages: [{ duration: "1s", target: maxVUs }], }; } } diff --git a/loadtest/util/users.ts b/loadtest/util/users.ts index 11f20fc..f906ffb 100644 --- a/loadtest/util/users.ts +++ b/loadtest/util/users.ts @@ -142,12 +142,4 @@ export class UserMix { this.tracker.set(key, value); } } - - getTotalUserNumber() { - return this.maxUsers - ? this.maxUsers - : this.activeRoles.reduce((total, role) => { - return total + mapRoleToCount(role); - }, 0); - } } diff --git a/run.sh b/run.sh index 60935a3..99f22e3 100644 --- a/run.sh +++ b/run.sh @@ -1,8 +1,6 @@ SPSH_BASE=$1 CONFIG=$2 # stage configuration (spike, stress, breakpoint) -echo SPSH_BASE="$SPSH_BASE" CONFIG="$CONFIG" KC_BASE="$KC_BASE" - if [[ -z "$CONFIG" ]]; then echo "no config specified" return 1 @@ -12,7 +10,10 @@ if [[ -z "$PATTERN" ]]; then PATTERN="*" fi -KC_BASE=$4 # not needed yet +MAX_VUS=$4 +KC_BASE=$5 # not needed yet + +echo SPSH_BASE="$SPSH_BASE" CONFIG="$CONFIG" PATTERN="$PATTERN" MAX_VUS="$MAX_VUS" KC_BASE="$KC_BASE" IS_LOCAL=1 if [[ "$SPSH_BASE" =~ "localhost" ]]; then @@ -45,6 +46,6 @@ for uc in loadtest/usecases/*; do fi K6_PROMETHEUS_RW_SERVER_URL=http://application-kube-prometheu-prometheus.monitoring:9090/api/v1/write \ K6_PROMETHEUS_RW_TREND_STATS="p(99)","p(90)","p(50)",min,max,avg \ - k6 run $options -e SPSH_BASE="$SPSH_BASE" -e CONFIG="$CONFIG" -e KC_BASE="$KC_BASE" --tag hostname="$(hostname)" --tag usecase="$filename" --tag started="$(date -u +%s)" "$uc" + k6 run $options -e SPSH_BASE="$SPSH_BASE" -e CONFIG="$CONFIG" -e MAX_VUS="$MAX_VUS" -e KC_BASE="$KC_BASE" --tag hostname="$(hostname)" --tag usecase="$filename" --tag started="$(date -u +%s)" "$uc" fi done \ No newline at end of file