From cc452afdc9fb9001139b0480ffe246efd3105e98 Mon Sep 17 00:00:00 2001 From: Nithin Shekar Kuruba Date: Mon, 30 Dec 2024 10:36:28 -0800 Subject: [PATCH] fix: build benchmark image for sso --- .../publish-image-keycloak-benchmark.yml | 63 ++++ .../bin/initialize-benchmark-entities.sh | 141 --------- benchmark-load-testing/bin/kc-chaos.sh | 43 --- benchmark-load-testing/bin/kc-failover.sh | 138 --------- .../bin/kc-rolling-restart.sh | 44 --- benchmark-load-testing/bin/kcb.sh | 273 ------------------ benchmark-load-testing/conf/README.adoc | 3 - docker/keycloak/Dockerfile-26 | 2 - docker/keycloak/Dockerfile-26-perf | 35 +++ localdev/macs/Dockerfile | 9 +- 10 files changed, 104 insertions(+), 647 deletions(-) create mode 100644 .github/workflows/publish-image-keycloak-benchmark.yml delete mode 100755 benchmark-load-testing/bin/initialize-benchmark-entities.sh delete mode 100755 benchmark-load-testing/bin/kc-chaos.sh delete mode 100755 benchmark-load-testing/bin/kc-failover.sh delete mode 100755 benchmark-load-testing/bin/kc-rolling-restart.sh delete mode 100755 benchmark-load-testing/bin/kcb.sh delete mode 100755 benchmark-load-testing/conf/README.adoc create mode 100644 docker/keycloak/Dockerfile-26-perf diff --git a/.github/workflows/publish-image-keycloak-benchmark.yml b/.github/workflows/publish-image-keycloak-benchmark.yml new file mode 100644 index 00000000..0fb22706 --- /dev/null +++ b/.github/workflows/publish-image-keycloak-benchmark.yml @@ -0,0 +1,63 @@ +name: Create and publish Keycloak Docker image - Dev + +on: + workflow_dispatch: + +env: + GITHUB_REGISTRY: ghcr.io + REDHAT_REGISTRY: registry.redhat.io + IMAGE_NAME: bcgov/sso-benchmark + +jobs: + build-and-push-image: + runs-on: ubuntu-20.04 + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Log in to the GitHub Container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.GITHUB_REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Log in to the REDHAT Container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REDHAT_REGISTRY }} + username: ${{ secrets.REDHAT_USERNAME }} + password: ${{ secrets.REDHAT_PASSWORD }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Cache Docker layers + uses: actions/cache@v4 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-buildx- + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: docker/keycloak + push: true + tags: ${{ env.GITHUB_REGISTRY }}/${{env.IMAGE_NAME}}:dev + file: docker/keycloak/Dockerfile-26-perf + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache-new + + # Temp fix + # https://github.com/docker/build-push-action/issues/252 + # https://github.com/moby/buildkit/issues/1896 + - name: Move cache + run: | + rm -rf /tmp/.buildx-cache + mv /tmp/.buildx-cache-new /tmp/.buildx-cache diff --git a/benchmark-load-testing/bin/initialize-benchmark-entities.sh b/benchmark-load-testing/bin/initialize-benchmark-entities.sh deleted file mode 100755 index 833b06bb..00000000 --- a/benchmark-load-testing/bin/initialize-benchmark-entities.sh +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/env bash -set -e -set -o pipefail -# set -x - -#Functions -function usage { - echo "Setup of test clients for the benchmark test with a pre-defined secret" - echo "Usage: $(basename $0) -k KEYCLOAK_HOME -r REALM_NAME -c CLIENT_ID [-d]" 2>&1 - echo "-k keycloak home path ex: /home/opt/keycloak-18.0.0 : default value KEYCLOAK_HOME env variable" - echo "-d delete the client and realm before re-creating them: default value is false" - echo "-r realm : default value test-realm" - echo "-c service account enabled client name : default value gatling" - echo "-d delete the client and realm : default value is false" - echo "-u user : default username user-0. The user's password will always be the username plus the suffix -password, ex: for user-0 this would be user-0-password" - exit 1 -} - -function set_kcb_in_path { - echo -e "Setting up kcadm.sh in PATH\n" - export PATH=$PATH:$KEYCLOAK_HOME/bin -} - -function create_realm { - if kcadm.sh get realms/${REALM_NAME} | grep -q ${REALM_NAME}; then - echo -e "INFO: Skipping Realm creation as realm exists\n" - else - echo -e "INFO: Creating Realm with realm id: ${REALM_NAME}" - kcadm.sh create realms -s realm=$REALM_NAME -s enabled=true -o > /dev/null - fi -} - -function create_service_enabled_client_assign_roles { - CID=$(kcadm.sh create clients -r $REALM_NAME -i -f - < /dev/null - echo -e "Successfully Deleted the Client and Realm\n" - fi -} - -#main() -#setting default values -OPTIND=1 -REALM_NAME=test-realm -CLIENT_ID=gatling -DELETE_ENTITIES='false' -USER_NAME=user-0 - -while getopts "k:r:u:c:d" arg; do - case $arg in - k) KEYCLOAK_HOME="$OPTARG"; - ;; - r) REALM_NAME="$OPTARG"; - ;; - c) CLIENT_ID="$OPTARG"; - ;; - d) DELETE_ENTITIES=true; - ;; - u) USER_NAME="$OPTARG"; - ;; - \?) echo "ERROR: Invalid option: -${OPTARG}" >&2 - usage - ;; - esac -done - -#Handle missing opt args -if (( ${OPTIND} == 1 )) -then - echo -e "ERROR: No Options Specified\n" - usage -fi -shift $(( OPTIND -1 )) - -#Setup the KCB client tool in the system PATH -set_kcb_in_path - -#Create or Re-Create Client and Realm -if ${DELETE_ENTITIES}; then - echo "INFO: deleting the Client and Realm" - delete_entities -else - echo "WARN: not deleting the Client and Realm" -fi - -create_realm -create_service_enabled_client_assign_roles -create_oidc_client -create_user diff --git a/benchmark-load-testing/bin/kc-chaos.sh b/benchmark-load-testing/bin/kc-chaos.sh deleted file mode 100755 index 62b0c120..00000000 --- a/benchmark-load-testing/bin/kc-chaos.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env bash -# Use this for simulating failures of pods when testing Keycloak's capabilities to recover. -set -e - -: ${INITIAL_DELAY_SECS:=30} -: ${CHAOS_DELAY_SECS:=10} -: ${PROJECT:="runner-keycloak"} - -LOGS_DIR=$1 - -echo -e "\033[0;31mINFO:$(date '+%F-%T-%Z') Entering Chaos mode, with an initial delay of $INITIAL_DELAY_SECS seconds\033[0m" -sleep $INITIAL_DELAY_SECS -echo -e "\033[0;31mINFO:$(date '+%F-%T-%Z') Running Chaos scenario - Delete random Keycloak pod\033[0m" - -ATTEMPT=0 -while true; do - ATTEMPT=$[ATTEMPT + 1] - RANDOM_KC_POD=$(kubectl \ - -n "${PROJECT}" \ - -o 'jsonpath={.items[*].metadata.name}' \ - get pods -l app=keycloak | \ - tr " " "\n" | \ - shuf | \ - head -n 1) - - kubectl get pods -n "${PROJECT}" -l app=keycloak -o wide - kubectl logs -f -n "${PROJECT}" "${RANDOM_KC_POD}" > "$LOGS_DIR/${ATTEMPT}-${RANDOM_KC_POD}.log" 2>&1 & - kubectl describe -n "${PROJECT}" pod "${RANDOM_KC_POD}" > "$LOGS_DIR/${ATTEMPT}-${RANDOM_KC_POD}-complete-resource.log" 2>&1 - kubectl top -n "${PROJECT}" pod -l app=keycloak --sum=true > "$LOGS_DIR/${ATTEMPT}-top.log" 2>&1 - echo -e "\033[0;31mINFO:$(date '+%F-%T-%Z') Killing Pod '${RANDOM_KC_POD}' and waiting for ${CHAOS_DELAY_SECS} seconds\033[0m" - kubectl delete pod -n "${PROJECT}" "${RANDOM_KC_POD}" --grace-period=1 - - START=$(date +%s) - - kubectl wait --for=condition=Available --timeout=600s deployments.apps/keycloak-operator -n "${PROJECT}" || true - kubectl wait --for=condition=Ready --timeout=600s keycloaks.k8s.keycloak.org/keycloak -n "${PROJECT}" || true - - END=$(date +%s) - DIFF=$(( END - START )) - - echo -e "\033[0;31mINFO:$(date '+%F-%T-%Z') Keycloak pod ${RANDOM_KC_POD} took ${DIFF} seconds to recover\033[0m" - sleep "${CHAOS_DELAY_SECS}" -done diff --git a/benchmark-load-testing/bin/kc-failover.sh b/benchmark-load-testing/bin/kc-failover.sh deleted file mode 100755 index 39721bf1..00000000 --- a/benchmark-load-testing/bin/kc-failover.sh +++ /dev/null @@ -1,138 +0,0 @@ -#!/usr/bin/env bash -# Script simulating different xsite failover scenarios -set -e - -if [[ "$RUNNER_DEBUG" == "1" ]]; then - set -x -fi - -function activeClusterDown() { - DOMAIN=$1 - CLIENT_IPS=$(dig +short client.${DOMAIN} | sort) - PRIMARY_IPS=$(dig +short primary.${DOMAIN} | sort) - BACKUP_IPS=$(dig +short backup.${DOMAIN} | sort) - - [[ "${CLIENT_IPS}" == "${BACKUP_IPS}" && "${CLIENT_IPS}" != "${PRIMARY_IPS}" ]] - return -} - -function scaleDownResource() { - kubectl -n $1 scale --replicas=0 $2 - kubectl -n $1 rollout status --watch --timeout=600s $2 -} - -# Removes the Keycloak aws-health-route so that Route53 will eventually failover -function killHealthRoute() { - kubectl -n ${PROJECT} delete route aws-health-route || true -} - -# Remove all Keycloak routes so that Route53 will failover from the active to the passive cluster and the old DNS ips will fail -function killKeycloakRoutes() { - scaleDownResource ${PROJECT} deployment/keycloak-operator - kubectl -n ${PROJECT} delete ingress keycloak-ingress || true - killHealthRoute -} - -# Delete the Keycloak + Infinispan pods to simulate cluster crash -function killKeycloakCluster() { - scaleDownResource openshift-operators deployment/infinispan-operator-controller-manager - scaleDownResource ${PROJECT} deployment/keycloak-operator - kubectl -n ${PROJECT} delete pods --all --force --grace-period=0 - kubectl -n ${PROJECT} delete statefulset --all -} - -# Delete the Infinispan GossipRouter -function killGossipRouter() { - scaleDownResource openshift-operators deployment/infinispan-operator-controller-manager - kubectl -n ${PROJECT} delete pods -l app=infinispan-router-pod --force --grace-period=0 - kubectl -n ${PROJECT} delete deployment/infinispan-router || true -} - -# Scale Infinispan and Keycloak Operators so that the original cluster is recreated -function reviveKeycloakCluster() { - echo -e "\033[0;31mINFO:$(date '+%F-%T-%Z') Running Recovery scenario - ${RECOVERY_MODE}\033[0m" - cat << EOF | kubectl -n ${PROJECT} apply -f - - apiVersion: route.openshift.io/v1 - kind: Route - metadata: - name: aws-health-route - spec: - host: "$1.${DOMAIN}" - port: - targetPort: https - tls: - insecureEdgeTerminationPolicy: Redirect - termination: passthrough - to: - kind: Service - name: keycloak-service -EOF - kubectl -n openshift-operators scale --replicas=1 deployment/infinispan-operator-controller-manager - kubectl -n ${PROJECT} scale --replicas=1 deployment/keycloak-operator - kubectl -n ${PROJECT} rollout status --watch --timeout=600s statefulset/infinispan - kubectl -n ${PROJECT} rollout status --watch --timeout=600s statefulset/keycloak - exit -} - -function waitForFailover() { - START=$(date +%s) - until activeClusterDown ${DOMAIN} - do - sleep 0.1 - done - END=$(date +%s) - DIFF=$(( END - START )) - - echo -e "\033[0;31mINFO:$(date '+%F-%T-%Z') Route53 took ${DIFF} seconds to failover\033[0m" -} - -function clusterFailover() { - killKeycloakCluster -} - -: ${PROJECT:="runner-keycloak"} -: ${FAILOVER_DELAY:=60} - -PROJECT=${PROJECT:-"runner-keycloak"} - -if [ -z "${RECOVERY_MODE}" ] && [ -z "${FAILOVER_MODE}" ]; then - echo "RECOVERY_MODE or FAILOVER_MODE env must be defined" - exit 1 -fi - -if [ -z "${DOMAIN}" ]; then - echo "DOMAIN env must be defined" - exit 1 -fi - -if [ -n "${RECOVERY_MODE}" ]; then - if [ "${RECOVERY_MODE^^}" == "ACTIVE" ]; then - reviveKeycloakCluster primary - elif [ "${RECOVERY_MODE^^}" == "PASSIVE" ]; then - reviveKeycloakCluster backup - else - echo "Unknown RECOVERY_MODE=${RECOVERY_MODE}" - exit 1 - fi -fi - -echo -e "\033[0;31mINFO:$(date '+%F-%T-%Z') Entering Failover mode, with an initial delay of ${FAILOVER_DELAY} seconds\033[0m" -sleep ${FAILOVER_DELAY} -echo -e "\033[0;31mINFO:$(date '+%F-%T-%Z') Running Failover scenario - ${FAILOVER_MODE}\033[0m" - -CLIENT_IPS=$(dig +short client.${DOMAIN} | sort) -PRIMARY_IPS=$(dig +short primary.${DOMAIN} | sort) -BACKUP_IPS=$(dig +short backup.${DOMAIN} | sort) - -if [ "${FAILOVER_MODE^^}" == "HEALTH_PROBE" ]; then - killHealthRoute -elif [ "${FAILOVER_MODE^^}" == "KEYCLOAK_ROUTES" ]; then - killKeycloakRoutes -elif [ "${FAILOVER_MODE^^}" == "CLUSTER_FAIL" ]; then - killKeycloakCluster -elif [ "${FAILOVER_MODE^^}" == "GOSSIP_ROUTER_FAIL" ]; then - killGossipRouter - exit -fi - -waitForFailover diff --git a/benchmark-load-testing/bin/kc-rolling-restart.sh b/benchmark-load-testing/bin/kc-rolling-restart.sh deleted file mode 100755 index f1c9a53c..00000000 --- a/benchmark-load-testing/bin/kc-rolling-restart.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env bash -# Use this for deleting all Keycloak or Infinispan pods in sequence. -set -e - -if [[ "$RUNNER_DEBUG" == "1" ]]; then - set -x -fi - -: ${PROJECT:="runner-keycloak"} - -# Ensure POD_LABEL is set -if [[ -z "${POD_LABEL}" ]]; then - echo "POD_LABEL is not set. Please export POD_LABEL before running the script." - exit 1 -fi - -echo -e "\033[0;31mINFO:$(date '+%F-%T-%Z') Deleting all pods with label '${POD_LABEL}' in sequence\033[0m" - -ALL_PODS=$(kubectl -n "${PROJECT}" -o 'jsonpath={.items[*].metadata.name}' get pods -l app="${POD_LABEL}" | tr " " "\n") - -ATTEMPT=0 -for POD in $ALL_PODS; do - ATTEMPT=$((ATTEMPT + 1)) - kubectl get pods -n "${PROJECT}" -l app="${POD_LABEL}" - echo -e "\033[0;31mINFO:$(date '+%F-%T-%Z') Killing Pod '${POD}'\033[0m" - kubectl delete pod -n "${PROJECT}" "${POD}" - - START=$(date +%s) - - if [[ "$POD_LABEL" == "keycloak" ]]; then - kubectl wait --for=condition=Available --timeout=120s deployments.apps/keycloak-operator -n "${PROJECT}" || true - kubectl wait --for=condition=Ready --timeout=120s keycloaks.k8s.keycloak.org/keycloak -n "${PROJECT}" || true - elif [[ "$POD_LABEL" == "infinispan-pod" ]]; then - kubectl wait --for condition=WellFormed --timeout=120s infinispans.infinispan.org -n "${PROJECT}" infinispan || true - fi - - END=$(date +%s) - DIFF=$(( END - START )) - - echo -e "\033[0;31mINFO:$(date '+%F-%T-%Z') ${POD} pod took ${DIFF} seconds to recover\033[0m" -done - -kubectl get pods -n "${PROJECT}" -l app="${POD_LABEL}" -echo -e "\033[0;31mINFO:$(date '+%F-%T-%Z') All ${POD_LABEL} pods have been restarted.\033[0m" diff --git a/benchmark-load-testing/bin/kcb.sh b/benchmark-load-testing/bin/kcb.sh deleted file mode 100755 index 01cdfc09..00000000 --- a/benchmark-load-testing/bin/kcb.sh +++ /dev/null @@ -1,273 +0,0 @@ -#!/usr/bin/env bash - -if [[ "$RUNNER_DEBUG" == "1" ]]; then - set -x -fi - -case "$(uname)" in - CYGWIN*) - CFILE=$(cygpath "$0") - RESOLVED_NAME=$(readlink -f "$CFILE") - ;; - Darwin*) - RESOLVED_NAME=$(readlink "$0") - ;; - FreeBSD) - RESOLVED_NAME=$(readlink -f "$0") - ;; - Linux) - RESOLVED_NAME=$(readlink -f "$0") - ;; -esac - -if [ "x$RESOLVED_NAME" = "x" ]; then - RESOLVED_NAME="$0" -fi - -GREP="grep" -DIRNAME=$(dirname "$RESOLVED_NAME") - -# Default values -JAVA_OPTS="-server" -JAVA_OPTS="${JAVA_OPTS} -Xmx4G -XX:+HeapDumpOnOutOfMemoryError" - -DEBUG_MODE="${DEBUG:-false}" -DEBUG_PORT="${DEBUG_PORT:-8787}" - -CHAOS_MODE="${CHAOS_MODE:-false}" - -CONFIG_ARGS=() -SERVER_OPTS=() - -SCENARIO="keycloak.scenario.authentication.ClientSecret" - -INCREMENT=32 -MODE="single-run" - -WORKLOAD_UNIT="users-per-sec" -CURRENT_WORKLOAD=1 - -MEASUREMENT=30 - -while [ "$#" -gt 0 ] -do - case "$1" in - --debug) - DEBUG_MODE=true - if [ -n "$2" ] && [ "$2" = "${2//-}" ]; then - DEBUG_PORT=$2 - shift - fi - ;; - --debug=*) - DEBUG_MODE=true - DEBUG_PORT=${1#*=} - ;; - --scenario=*) - SCENARIO=${1#*=} - ;; - --concurrent-users=*) - WORKLOAD_UNIT=concurrent-users - CURRENT_WORKLOAD=${1#*=} - ;; - --users-per-sec=*) - WORKLOAD_UNIT=users-per-sec - CURRENT_WORKLOAD=${1#*=} - ;; - --measurement=*) - MEASUREMENT=${1#*=} - ;; - --increment=*) - MODE=incremental - INCREMENT=${1#*=} - ;; - --chaos=*) - CHAOS_MODE=true - CHAOS_TIMEOUT=${1#*=} - ;; - --) - shift - break - ;; - *) - if [[ $1 = --* || ! $1 =~ ^-D.* ]]; then - CONFIG_ARGS+=("-D${1:2}") - else - SERVER_OPTS+=("$1") - fi - ;; - esac - shift -done - -# Set debug settings if not already set -if [ "$DEBUG_MODE" = "true" ]; then - DEBUG_OPT=$(echo "$JAVA_OPTS" | $GREP "\-agentlib:jdwp") - if [ "x$DEBUG_OPT" = "x" ]; then - JAVA_OPTS="$JAVA_OPTS -agentlib:jdwp=transport=dt_socket,address=$DEBUG_PORT,server=y,suspend=y" - else - echo "DEBUG: Debug already enabled in JAVA_OPTS, ignoring --debug argument." - fi -fi - -CLASSPATH_OPTS="$DIRNAME/../lib/*" - -declare -A RESULT_CACHE - -rewrite_output() { - sed -u 's|Please open the following file: |Please open the following file://|g' < /dev/stdin -} - -run_benchmark_with_workload() { - if [[ -v RESULT_CACHE[$2] ]]; then - echo "INFO: Keycloak benchmark was already running for $1=$2 with result ${RESULT_CACHE[$2]}." - return "${RESULT_CACHE[$2]}" - fi - local OUTPUT_DIR="${4:-"$DIRNAME/../results/"}" - echo "INFO: Running benchmark with $1=$2, result output will be available in: $OUTPUT_DIR" - mkdir -p "$OUTPUT_DIR" - GRAFANA_FROM_DATE_UNIX_MS=$(date +%s%3N) - DATE_START_UNIX=$(date +%s) - DATE_START_ISO=$(date --iso-8601=seconds) - DATE_START_ISO_COMPRESSED=$(date '+%Y%m%d-%H%M%S') - if [ "$MODE" = "incremental" ]; then - java $JAVA_OPTS "${SERVER_OPTS[@]}" "${CONFIG_ARGS[@]}" "-D$1=$2" "-Dmeasurement=${3:-30}" -cp $CLASSPATH_OPTS io.gatling.app.Gatling -rf "$OUTPUT_DIR" -s $SCENARIO > "$OUTPUT_DIR/gatling.log" 2>&1 - else - java $JAVA_OPTS "${SERVER_OPTS[@]}" "${CONFIG_ARGS[@]}" "-D$1=$2" "-Dmeasurement=${3:-30}" -cp $CLASSPATH_OPTS io.gatling.app.Gatling -rf "$OUTPUT_DIR" -s $SCENARIO | rewrite_output 2>&1 | tee "$OUTPUT_DIR/gatling.log" - fi - EXIT_RESULT=$? - # don't include URLs or password information into the configuration recorded - CONFIG_ARGS_CLEAN=() - for index in "${!CONFIG_ARGS[@]}" ; do [[ "${CONFIG_ARGS[$index]}" =~ .*(url|pass).* ]] || CONFIG_ARGS_CLEAN+=(${CONFIG_ARGS[$index]}) ; done - OUTPUT_FOLDER=$OUTPUT_DIR/$(ls $OUTPUT_DIR -Art | grep -- -20 | tail -1) - DATE_END_UNIX=$(date +%s) - DATE_END_ISO=$(date --iso-8601=seconds) - GRAFANA_TO_DATE_UNIX_MS=$(date +%s%3N) - SNAP_GRAFANA_TIME_WINDOW="from=${GRAFANA_FROM_DATE_UNIX_MS}&to=${GRAFANA_TO_DATE_UNIX_MS}" - jq '{ "grafana_output": { "stats": . } }' $OUTPUT_FOLDER/js/stats.json > $OUTPUT_FOLDER/result_grafana_stats.json - UUID=$(uuidgen) - jq '.' > $OUTPUT_FOLDER/result_grafana_inputs.json < ${OUTPUT_FOLDER}/result_sut.json - fi - jq -s add ${OUTPUT_FOLDER}/result_*.json > ${OUTPUT_FOLDER}/result-${DATE_START_ISO_COMPRESSED}-${UUID}.json - return ${EXIT_RESULT} -} - -if [ "$CHAOS_MODE" = "true" ]; then - echo "INFO: Running benchmark with chaos mode, logs output will be available in: $LOGS_DIR" - LOGS_DIR="$DIRNAME/../results/logs/" - - mkdir -p "$LOGS_DIR" - timeout "${CHAOS_TIMEOUT}" bash bin/kc-chaos.sh "${LOGS_DIR}" 2>&1 | tee "${LOGS_DIR}/kc-chaos.log" & -fi - -if [ "$MODE" = "incremental" ]; then - echo "INFO: Running benchmark in incremental mode." - MAX_ATTEMPTS=100 - ATTEMPT=0 - - trap printout SIGINT - printout() { - echo "" - echo "INFO: Finished with $WORKLOAD_UNIT=$CURRENT_WORKLOAD." - exit - } - - RESULT_ROOT_DIR="$DIRNAME/../results/$MODE-$(date '+%Y%m%d%H%M%S')" - mkdir -p $RESULT_ROOT_DIR - RESULT_ROOT_DIR=$(realpath ${RESULT_ROOT_DIR}) - - #Incremental run is expected to do a warm up run to setup the system for the subsequent Incremental runs, you can ignore this run's result. - echo "INFO: Running warm-up phase." - run_benchmark_with_workload "$WORKLOAD_UNIT" "$CURRENT_WORKLOAD" "$MEASUREMENT" "$RESULT_ROOT_DIR/$WORKLOAD_UNIT-$CURRENT_WORKLOAD-WARM-UP" - echo "INFO: Finished Warm-Up phase, for incremental run." - - while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do - # Check for invalid workload - if [ $CURRENT_WORKLOAD -lt 1 ]; then - echo "ERROR: Invalid state for $SCENARIO with $WORKLOAD_UNIT=$LAST_SUCCESSFUL_WORKLOAD." - exit 1 - fi - - ATTEMPT=$[ATTEMPT + 1] - - run_benchmark_with_workload "$WORKLOAD_UNIT" "$CURRENT_WORKLOAD" "$MEASUREMENT" "$RESULT_ROOT_DIR/$WORKLOAD_UNIT-$CURRENT_WORKLOAD" - - RESULT_CACHE[$CURRENT_WORKLOAD]=$? - - if [ ${RESULT_CACHE[$CURRENT_WORKLOAD]} -ne 0 ]; then - echo "INFO: Keycloak benchmark failed for $WORKLOAD_UNIT=$CURRENT_WORKLOAD" - LAST_SUCCESSFUL_WORKLOAD=$((CURRENT_WORKLOAD - INCREMENT)) - if [ $((RESULT_CACHE[$LAST_SUCCESSFUL_WORKLOAD])) -ne 0 ]; then - echo "ERROR: Invalid state. Last successful workload $LAST_SUCCESSFUL_WORKLOAD was not successful." - exit 1 - fi - - echo "INFO: Last Successful workload for scenario $SCENARIO is $WORKLOAD_UNIT=$LAST_SUCCESSFUL_WORKLOAD." - if [ $INCREMENT -eq 1 ]; then - ln -s $RESULT_ROOT_DIR/$WORKLOAD_UNIT-$LAST_SUCCESSFUL_WORKLOAD $RESULT_ROOT_DIR/last-successful - if [[ "${GITHUB_OUTPUT}" != "" ]]; then - OUTPUT_FOLDER=$RESULT_ROOT_DIR/last-successful/$(ls $RESULT_ROOT_DIR/last-successful -Art | grep -- -20 | tail -1) - echo "kcb_result=$OUTPUT_FOLDER/result-*.json" >> "${GITHUB_OUTPUT}" - fi - echo "INFO: Reached the limit for scenario $SCENARIO with $WORKLOAD_UNIT=$LAST_SUCCESSFUL_WORKLOAD." - exit - fi - - # Reset workload to last successful value and decrease increment - CURRENT_WORKLOAD=$((CURRENT_WORKLOAD - INCREMENT)) - INCREMENT=$((INCREMENT / 2)) - fi - - CURRENT_WORKLOAD=$((CURRENT_WORKLOAD + INCREMENT)) - done - - if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then - echo "INFO: Reached maximum attempts and all attempts succeeded." - fi - -else - echo "INFO: Running benchmark in single-run mode." - run_benchmark_with_workload $WORKLOAD_UNIT $CURRENT_WORKLOAD $MEASUREMENT - if [[ "${GITHUB_OUTPUT}" != "" ]]; then - OUTPUT_FOLDER=$DIRNAME/../results/$(ls $DIRNAME/../results -Art | grep -- -20 | tail -1) - OUTPUT_FOLDER=$(realpath ${OUTPUT_FOLDER}) - echo "kcb_result=$OUTPUT_FOLDER/result-*.json" >> "${GITHUB_OUTPUT}" - fi - exit -fi - -if [ "$CHAOS_MODE" = "true" ]; then - : ${PROJECT:="runner-keycloak"} - echo "INFO: Collecting logs at the end of the Chaos benchmark run" - PODS=$(kubectl -n "${PROJECT}" -o 'jsonpath={.items[*].metadata.name}' get pods -l app=keycloak | tr " " "\n") - for POD in $PODS; do - kubectl logs -n "${PROJECT}" "${POD}" > "$LOGS_DIR/End-of-run-${POD}.log" 2>&1 - kubectl describe -n "${PROJECT}" pod "${POD}" > "$LOGS_DIR/End-of-run-${POD}-complete-resource.log" 2>&1 - done - kubectl top -n "${PROJECT}" pod -l app=keycloak --sum=true > "$LOGS_DIR/End-of-run-top.log" 2>&1 - kubectl get pods -n "${PROJECT}" -l app=keycloak -o wide -fi diff --git a/benchmark-load-testing/conf/README.adoc b/benchmark-load-testing/conf/README.adoc deleted file mode 100755 index 3f768f4e..00000000 --- a/benchmark-load-testing/conf/README.adoc +++ /dev/null @@ -1,3 +0,0 @@ -= Gatling configuration - -Use files in this directory to configure Gatling diff --git a/docker/keycloak/Dockerfile-26 b/docker/keycloak/Dockerfile-26 index bfb0d63a..f2582566 100644 --- a/docker/keycloak/Dockerfile-26 +++ b/docker/keycloak/Dockerfile-26 @@ -13,8 +13,6 @@ ENV KC_METRICS_ENABLED=true # Configure a database vendor ENV KC_DB=postgres -COPY ./dataset-providers/keycloak-benchmark-dataset-0.15-SNAPSHOT.jar /opt/keycloak/providers - COPY --from=extensions-builder /tmp/services/target/bcgov-services-1.0.0.jar /opt/keycloak/providers/ WORKDIR /opt/keycloak diff --git a/docker/keycloak/Dockerfile-26-perf b/docker/keycloak/Dockerfile-26-perf new file mode 100644 index 00000000..21237966 --- /dev/null +++ b/docker/keycloak/Dockerfile-26-perf @@ -0,0 +1,35 @@ +FROM maven:3.9.9-eclipse-temurin-21 AS extensions-builder + +COPY ./extensions-26 /tmp/ +WORKDIR /tmp/ +RUN mvn -B clean package --file pom.xml + +FROM registry.redhat.io/rhbk/keycloak-rhel9:26.0-6 AS builder + +# Enable health and metrics support +ENV KC_HEALTH_ENABLED=true +ENV KC_METRICS_ENABLED=true + +# Configure a database vendor +ENV KC_DB=postgres + +# un-comment when dataset required for loadtests +COPY ./dataset-providers/keycloak-benchmark-dataset-0.15-SNAPSHOT.jar /opt/keycloak/providers + +COPY --from=extensions-builder /tmp/services/target/bcgov-services-1.0.0.jar /opt/keycloak/providers/ + +WORKDIR /opt/keycloak + +# copy the theme directory to `/opt/keycloak/themes/` for now, but we can consider to archive to be deployed later. +COPY ./extensions-26/themes/src/main/resources/theme /opt/keycloak/themes + +COPY ./configuration/26/keycloak.conf /opt/keycloak/conf + +COPY ./configuration/26/quarkus.properties /opt/keycloak/conf + +COPY ./configuration/26/keycloak-default-user-profile.json /tmp + +RUN /opt/keycloak/bin/kc.sh build + +# change these values to point to a running postgres instance +ENTRYPOINT ["/opt/keycloak/bin/kc.sh"] diff --git a/localdev/macs/Dockerfile b/localdev/macs/Dockerfile index c189702a..8c1bbdee 100644 --- a/localdev/macs/Dockerfile +++ b/localdev/macs/Dockerfile @@ -4,18 +4,21 @@ COPY ./docker/keycloak/extensions-26 /tmp/ WORKDIR /tmp/ RUN mvn -B clean package --file pom.xml -Dmaven.test.skip=true -# built using https://github.com/keycloak/keycloak-containers/blob/main/server/Dockerfile - -FROM keycloak:26.0.5 +# Built using quarkus/container/Dockerfile from https://github.com/keycloak/keycloak +FROM keycloak:26.0.6 AS builder +# Enable health and metrics support ENV KC_HEALTH_ENABLED=true ENV KC_METRICS_ENABLED=true + +# Configure a database vendor ENV KC_DB=postgres COPY --from=extensions-builder /tmp/services/target/bcgov-services-1.0.0.jar /opt/keycloak/providers/ WORKDIR /opt/keycloak +# copy the theme directory to `/opt/keycloak/themes/` for now, but we can consider to archive to be deployed later. COPY ./docker/keycloak/extensions-26/themes/src/main/resources/theme /opt/keycloak/themes/ COPY ./docker/keycloak/configuration/26/quarkus.properties /opt/keycloak/conf