ROSA Cluster - Scaling Benchmark #29
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: ROSA Cluster - Scaling Benchmark | |
on: | |
workflow_dispatch: | |
inputs: | |
clusterName: | |
description: 'Name of the cluster' | |
type: string | |
default: 'gh-keycloak' | |
region: | |
description: 'Name of the region where EC2 instances should be installed' | |
type: string | |
default: 'eu-west-1' | |
numberOfEntitiesInRealm: | |
description: 'Number of entities for the scenario in DB' | |
type: number | |
default: 100000 | |
maxWaitEntityCreation: | |
description: 'Maximum number of seconds to wait for creation of entities' | |
type: number | |
default: 900 | |
numberOfUsersPerSecond: | |
description: 'User logins per second' | |
type: number | |
default: 200 | |
numberOfClientsPerSecond: | |
description: 'Client credential grants per second' | |
type: number | |
default: 1000 | |
measurement: | |
description: 'Measurement period (seconds)' | |
type: number | |
default: 600 | |
skipCreateDeployment: | |
description: 'Skip creating Keycloak deployment' | |
type: boolean | |
default: false | |
skipCreateDataset: | |
description: 'Skip creating dataset' | |
type: boolean | |
default: false | |
skipDeleteProject: | |
description: 'Skip deleting project' | |
type: boolean | |
default: false | |
concurrency: cluster_${{ github.event.inputs.clusterName || format('gh-{0}', github.repository_owner) }} | |
env: | |
PROJECT_PREFIX: runner- # same as default | |
PROJECT: runner-keycloak | |
KC_CPU_REQUESTS: 6 | |
KC_INSTANCES: 3 | |
KC_DISABLE_STICKY_SESSION: true | |
KC_MEMORY_REQUESTS_MB: 4000 | |
KC_MEMORY_LIMITS_MB: 4000 | |
KC_HEAP_MAX_MB: 2048 | |
KC_DB_POOL_INITIAL_SIZE: 30 | |
KC_DB_POOL_MAX_SIZE: 30 | |
KC_DB_POOL_MIN_SIZE: 30 | |
ANSIBLE_CUSTOM_VARS_ARG: '-e @env_rosa_benchmark.yml' | |
jobs: | |
run: | |
name: Run Benchmark | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
- name: Setup ROSA CLI | |
uses: ./.github/actions/rosa-cli-setup | |
with: | |
aws-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
aws-default-region: ${{ vars.AWS_DEFAULT_REGION }} | |
rosa-token: ${{ secrets.ROSA_TOKEN }} | |
- name: Login to OpenShift cluster | |
uses: ./.github/actions/oc-keycloak-login | |
with: | |
clusterName: ${{ inputs.clusterName || format('gh-{0}', github.repository_owner) }} | |
- name: Set up JDK | |
uses: actions/setup-java@v3 | |
with: | |
distribution: 'temurin' | |
java-version: '17' | |
cache: 'maven' | |
- name: Cache Maven Wrapper | |
uses: actions/cache@v3 | |
with: | |
path: | | |
.mvn/wrapper/maven-wrapper.jar | |
key: ${{ runner.os }}-maven-wrapper-${{ hashFiles('**/maven-wrapper.properties') }} | |
restore-keys: | | |
${{ runner.os }}-maven-wrapper- | |
- name: Build with Maven | |
run: | | |
./mvnw -B clean package -DskipTests -pl benchmark | |
tar xfvz benchmark/target/keycloak-benchmark-*.tar.gz | |
mv keycloak-benchmark-* keycloak-benchmark | |
- name: Allow cluster to scale | |
if: ${{ !inputs.skipCreateDeployment }} | |
run: rosa edit machinepool -c ${{ inputs.clusterName }} --min-replicas 3 scaling | |
- name: Create Keycloak deployment | |
if: ${{ !inputs.skipCreateDeployment }} | |
uses: ./.github/actions/keycloak-create-deployment | |
with: | |
projectPrefix: ${{ env.PROJECT_PREFIX }} | |
disableStickySessions: ${{ !env.KC_DISABLE_STICKY_SESSION }} | |
replicas: ${{ env.KC_INSTANCES }} | |
podCpuRequests: ${{ env.KC_CPU_REQUESTS }} | |
podMemoryRequests: ${{ env.KC_MEMORY_REQUESTS_MB }} | |
podMemoryLimit: ${{ env.KC_MEMORY_LIMITS_MB }} | |
heapMaxSizeMB: ${{ env.KC_HEAP_MAX_MB }} | |
- name: Get URLs | |
uses: ./.github/actions/get-keycloak-url | |
with: | |
project: ${{ env.PROJECT }} | |
- name: Create Keycloak dataset with "${{ inputs.numberOfEntitiesInRealm }}" users and clients | |
if: ${{ !inputs.skipCreateDataset }} | |
uses: ./.github/actions/keycloak-create-dataset | |
with: | |
project: ${{ env.PROJECT }} | |
users: ${{ inputs.numberOfEntitiesInRealm }} | |
clients: 100 | |
clientsPerRealm: ${{ inputs.numberOfEntitiesInRealm }} | |
createClientForSpecificRealm: true | |
maxWaitEntityCreation: ${{ inputs.maxWaitEntityCreation }} | |
- name: Create AWS EC2 instances | |
id: create_aws_ec2_instances | |
uses: ./.github/actions/ec2-create-instances | |
with: | |
region: ${{ inputs.region }} | |
- name: Run Memory Usage Total Query Before Benchmark | |
uses: ./.github/actions/prometheus-run-queries | |
with: | |
project: ${{ env.PROJECT }} | |
runMemoryUsageTotal: true | |
output: memory_create_sessions | |
- name: Testing memory for creating sessions | |
id: kcb-authorization-code-1 | |
run: > | |
./benchmark.sh ${{ inputs.region }} | |
--scenario=keycloak.scenario.authentication.AuthorizationCode | |
--server-url=${{ env.KEYCLOAK_URL }} | |
--realm-name=realm-0 | |
--users-per-sec=${{ inputs.numberOfUsersPerSecond }} | |
--ramp-up=20 | |
--logout-percentage=0 | |
--measurement=${{ inputs.measurement }} | |
--users-per-realm=${{ inputs.numberOfEntitiesInRealm }} | |
--log-http-on-failure | |
--sla-error-percentage=0.001 | |
continue-on-error: true | |
working-directory: ansible | |
- name: Run Memory Usage Total Query After Benchmark | |
uses: ./.github/actions/prometheus-run-queries | |
with: | |
project: ${{ env.PROJECT }} | |
runMemoryUsageTotal: true | |
output: memory_create_sessions | |
- name: Calculate number of active sessions | |
id: active_sessions_count | |
env: | |
USERS_PER_SEC: ${{ inputs.numberOfUsersPerSecond }} | |
TIME_IN_SEC: ${{ inputs.measurement }} | |
run: echo "active_sessions=$(awk "BEGIN {print $USERS_PER_SEC*$TIME_IN_SEC; exit}")" >> $GITHUB_OUTPUT | |
- name: Calculate and Store Memory Usage Total For Active User Sessions | |
uses: ./.github/actions/prometheus-metrics-calc | |
with: | |
input: memory_create_sessions | |
performedTestName: 'Memory usage for sessions' | |
calculatedMetricName: 'Active sessions per 500 MB memory' #as a unit for memory calculation is chosen 500MB memory size to find out how much user sessions so much memory can handle. | |
criteriaValue: ${{ steps.active_sessions_count.outputs.active_sessions }} | |
isvCPU: false | |
isMemory: true | |
- name: Run CPU sec Util Query Before Benchmark | |
uses: ./.github/actions/prometheus-run-queries | |
with: | |
project: ${{ env.PROJECT }} | |
runCpuSecsUtil: true | |
output: user_logins_vCpu | |
- name: Testing CPU usage for user logins | |
id: kcb-authorization-code-2 | |
run: > | |
./benchmark.sh ${{ inputs.region }} | |
--scenario=keycloak.scenario.authentication.AuthorizationCode | |
--server-url=${{ env.KEYCLOAK_URL }} | |
--realm-name=realm-0 | |
--users-per-sec=${{ inputs.numberOfUsersPerSecond }} | |
--ramp-up=20 | |
--logout-percentage=100 | |
--measurement=${{ inputs.measurement }} | |
--users-per-realm=${{ inputs.numberOfEntitiesInRealm }} | |
--log-http-on-failure | |
--sla-error-percentage=0.001 | |
continue-on-error: true | |
working-directory: ansible | |
- name: Run CPU sec Util Query After Benchmark | |
uses: ./.github/actions/prometheus-run-queries | |
with: | |
project: ${{ env.PROJECT }} | |
runCpuSecsUtil: true | |
output: user_logins_vCpu | |
- name: Calculate and Store CPU sec Util For Ran Benchmark | |
uses: ./.github/actions/prometheus-metrics-calc | |
with: | |
input: user_logins_vCpu | |
performedTestName: 'CPU usage for user logins' | |
calculatedMetricName: 'User Logins per second per 1vCPU' | |
criteriaValue: ${{ inputs.numberOfUsersPerSecond }} | |
measurementInterval: ${{ inputs.measurement }} | |
isvCPU: true | |
isMemory: false | |
- name: Run CPU sec Util Query Before Benchmark | |
uses: ./.github/actions/prometheus-run-queries | |
with: | |
project: ${{ env.PROJECT }} | |
runCpuSecsUtil: true | |
output: client_credential_grants_vCpu | |
- name: Testing CPU usage for client credential grants | |
id: kcb-client-secret | |
run: > | |
./benchmark.sh ${{ inputs.region }} | |
--scenario=keycloak.scenario.authentication.ClientSecret | |
--server-url=${{ env.KEYCLOAK_URL }} | |
--realm-name=realm-0 | |
--users-per-sec=${{ inputs.numberOfClientsPerSecond }} | |
--ramp-up=20 | |
--measurement=${{ inputs.measurement }} | |
--users-per-realm=${{ inputs.numberOfEntitiesInRealm }} | |
--log-http-on-failure | |
--sla-error-percentage=0.001 | |
continue-on-error: true | |
working-directory: ansible | |
- name: Run CPU sec Util Query After Benchmark | |
uses: ./.github/actions/prometheus-run-queries | |
with: | |
project: ${{ env.PROJECT }} | |
runCpuSecsUtil: true | |
output: client_credential_grants_vCpu | |
- name: Calculate and Store CPU usage For Ran Benchmark | |
uses: ./.github/actions/prometheus-metrics-calc | |
with: | |
input: client_credential_grants_vCpu | |
performedTestName: 'CPU usage for client credential grants' | |
calculatedMetricName: 'Client Credential Grants per second per 1vCPU' | |
criteriaValue: ${{ inputs.numberOfClientsPerSecond }} | |
measurementInterval: ${{ inputs.measurement }} | |
isvCPU: true | |
isMemory: false | |
- name: Archive Gatling reports | |
if: ${{ always() }} | |
uses: actions/upload-artifact@v3 | |
with: | |
name: gatling-results | |
path: ansible/files/benchmark/*/results | |
retention-days: 5 | |
- name: Archive Summary | |
uses: actions/upload-artifact@v3 | |
with: | |
name: summary | |
path: ansible/files/benchmark/*/results/*/js/stats.json | |
retention-days: 5 | |
- name: Archive Calculated Metrics summary | |
uses: actions/upload-artifact@v3 | |
with: | |
name: Calculated environment conclusion | |
path: | | |
result-*.json | |
retention-days: 5 | |
- name: Delete EC2 instances | |
if: ${{ always() && steps.create_aws_ec2_instances.conclusion != 'skipped' }} | |
uses: ./.github/actions/ec2-delete-instances | |
with: | |
region: ${{ inputs.region }} | |
- name: Delete Keycloak deployment | |
if: ${{ (success() || failure()) && !inputs.skipDeleteProject }} | |
uses: ./.github/actions/keycloak-delete-deployment | |
with: | |
project: ${{ env.PROJECT }} | |
- name: Scale down the cluster | |
if: ${{ (success() || failure()) && !inputs.skipDeleteProject }} | |
run: rosa edit machinepool -c ${{ inputs.clusterName }} --min-replicas 0 scaling | |
archive: | |
name: Commit results to Git repository | |
runs-on: ubuntu-latest | |
permissions: | |
contents: write | |
actions: write | |
needs: | |
- run | |
steps: | |
- name: Checkout repository for results | |
uses: actions/checkout@v4 | |
with: | |
ref: 'result-data' | |
- uses: actions/download-artifact@v3 | |
with: | |
name: Calculated environment conclusion | |
- name: Commit result-summary | |
shell: bash | |
env: | |
GITHUB_OAUTH: ${{ secrets.GITHUB_TOKEN }} | |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
run: | | |
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
git config --global user.name "github-actions[bot]" | |
DATE_FOLDER=rosa_scalability/$(date +"%Y/%m/%d") | |
mkdir -p ${DATE_FOLDER} | |
mv *.json ${DATE_FOLDER} | |
git add . | |
git commit -m "generated" | |
git push | |
- name: Trigger data aggregation | |
if: github.repository == 'keycloak/keycloak-benchmark' | |
env: | |
GH_TOKEN: ${{ github.token }} | |
# manually trigger the run, as a push with a standard GitHub action token doesn't trigger any workflow run on GitHub | |
run: gh workflow run -R keycloak/keycloak-benchmark aggregate-results.yaml --ref result-data |