Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.
Anpassung des Container-Images
Tester-Image laden
Diese Lösung verwendet ein öffentliches Amazon Elastic Container Registry (Amazon ECR) -Image-Repository, das von AWS verwaltet wird, um das Image zu speichern, das für die Ausführung der konfigurierten Tests verwendet wird. Wenn Sie das Container-Image anpassen möchten, können Sie das Image neu erstellen und in ein ECR-Image-Repository in Ihrem eigenen AWS-Konto übertragen.
Wenn Sie diese Lösung anpassen möchten, können Sie das Standard-Container-Image verwenden oder diesen Container nach Ihren Bedürfnissen bearbeiten. Wenn Sie die Lösung anpassen, verwenden Sie das folgende Codebeispiel, um die Umgebungsvariablen zu deklarieren, bevor Sie Ihre benutzerdefinierte Lösung erstellen.
#!/bin/bash export REGION=aws-region-code # the AWS region to launch the solution (e.g. us-east-1) export BUCKET_PREFIX=my-bucket-name # prefix of the bucket name without the region code export BUCKET_NAME=$BUCKET_PREFIX-$REGION # full bucket name where the code will reside export SOLUTION_NAME=my-solution-name export VERSION=my-version # version number for the customized code export PUBLIC_ECR_REGISTRY=public.ecr.aws/awssolutions/distributed-load-testing-on-aws-load-tester # replace with the container registry and image if you want to use a different container image export PUBLIC_ECR_TAG=v3.1.0 # replace with the container image tag if you want to use a different container image
Wenn Sie das Container-Image anpassen möchten, können Sie es entweder in einem privaten Image-Repository oder in einem öffentlichen Image-Repository in Ihrem AWS-Konto hosten. Die Image-Ressourcen befinden sich im deployment/ecr/distributed-load-testing-on-aws-load-tester Verzeichnis, das sich in der Codebasis befindet.
Sie können das Image erstellen und an das Host-Ziel übertragen.
-
Informationen zu privaten Amazon ECR-Repositorys und -Images finden Sie unter Private Amazon ECR-Repositorys und private Images im Amazon ECR-Benutzerhandbuch.
-
Informationen zu öffentlichen Amazon ECR-Repositorys und -Images finden Sie unter Öffentliche Amazon ECR-Repositorys und öffentliche Images im Amazon ECR Public User Guide.
Sobald Sie Ihr eigenes Image erstellt haben, können Sie die folgenden Umgebungsvariablen deklarieren, bevor Sie Ihre maßgeschneiderte Lösung erstellen.
#!/bin/bash export PUBLIC_ECR_REGISTRY=YOUR_ECR_REGISTRY_URI # e.g. YOUR_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/YOUR_IMAGE_NAME export PUBLIC_ECR_TAG=YOUR_ECR_TAG # e.g. latest, v3.4.0
Das folgende Beispiel zeigt die Containerdatei.
FROM public.ecr.aws/amazonlinux/amazonlinux:2023-minimal RUN dnf update -y && \ dnf install -y python3.11 python3.11-pip java-21-amazon-corretto bc procps jq findutils unzip && \ dnf clean all ENV PIP_INSTALL="pip3.11 install --no-cache-dir" # install bzt RUN $PIP_INSTALL --upgrade bzt awscli setuptools==78.1.1 h11 urllib3==2.2.2 && \ $PIP_INSTALL --upgrade bzt COPY ./.bzt-rc /root/.bzt-rc RUN chmod 755 /root/.bzt-rc # install bzt tools RUN bzt -install-tools -o modules.install-checker.exclude=selenium,gatling,tsung,siege,ab,k6,external-results-loader,locust,junit,testng,rspec,mocha,nunit,xunit,wdio,robot,newman RUN rm -rf /root/.bzt/selenium-taurus RUN mkdir /bzt-configs /tmp/artifacts ADD ./load-test.sh /bzt-configs/ ADD ./*.jar /bzt-configs/ ADD ./*.py /bzt-configs/ RUN chmod 755 /bzt-configs/load-test.sh RUN chmod 755 /bzt-configs/ecslistener.py RUN chmod 755 /bzt-configs/ecscontroller.py RUN chmod 755 /bzt-configs/jar_updater.py RUN python3.11 /bzt-configs/jar_updater.py # Remove jar files from /tmp RUN rm -rf /tmp/jmeter-plugins-manager-1* && \ rm -rf /usr/local/lib/python3.11/site-packages/setuptools-65.5.0.dist-info && \ rm -rf /usr/local/lib/python3.11/site-packages/urllib3-1.26.17.dist-info # Add settings file to capture the output logs from bzt cli RUN mkdir -p /etc/bzt.d && echo '{"settings": {"artifacts-dir": "/tmp/artifacts"}}' > /etc/bzt.d/90-artifacts-dir.json WORKDIR /bzt-configs ENTRYPOINT ["./load-test.sh"]
Zusätzlich zu einer Container-Datei enthält das Verzeichnis das folgende Bash-Skript, das die Testkonfiguration von Amazon S3 herunterlädt, bevor das Taurus/Blazemeter Programm ausgeführt wird.
#!/bin/bash # set a uuid for the results xml file name in S3 UUID=$(cat /proc/sys/kernel/random/uuid) pypid=0 echo "S3_BUCKET:: ${S3_BUCKET}" echo "TEST_ID:: ${TEST_ID}" echo "TEST_TYPE:: ${TEST_TYPE}" echo "FILE_TYPE:: ${FILE_TYPE}" echo "PREFIX:: ${PREFIX}" echo "UUID:: ${UUID}" echo "LIVE_DATA_ENABLED:: ${LIVE_DATA_ENABLED}" echo "MAIN_STACK_REGION:: ${MAIN_STACK_REGION}" cat /proc/self/cgroup TASK_ID=$(grep -oE '[a-f0-9]{32}' /proc/self/cgroup | head -n 1) echo $TASK_ID sigterm_handler() { if [ $pypid -ne 0 ]; then echo "container received SIGTERM." kill -15 $pypid wait $pypid exit 143 #128 + 15 fi } trap 'sigterm_handler' SIGTERM echo "Download test scenario" aws s3 cp s3://$S3_BUCKET/test-scenarios/$TEST_ID-$AWS_REGION.json test.json --region $MAIN_STACK_REGION # Set the default log file values to jmeter LOG_FILE="jmeter.log" OUT_FILE="jmeter.out" ERR_FILE="jmeter.err" KPI_EXT="jtl" # download JMeter jmx file if [ "$TEST_TYPE" != "simple" ]; then # setting the log file values to the test type LOG_FILE="${TEST_TYPE}.log" OUT_FILE="${TEST_TYPE}.out" ERR_FILE="${TEST_TYPE}.err" # set variables based on TEST_TYPE if [ "$TEST_TYPE" == "jmeter" ]; then EXT="jmx" TYPE_NAME="JMeter" # Copy *.jar to JMeter library path. See the Taurus JMeter path: https://gettaurus.org/docs/JMeter/ JMETER_LIB_PATH=`find ~/.bzt/jmeter-taurus -type d -name "lib"` echo "cp $PWD/*.jar $JMETER_LIB_PATH" cp $PWD/*.jar $JMETER_LIB_PATH elif [ "$TEST_TYPE" == "k6" ]; then curl --output /tmp/artifacts/k6.rpm https://dl.k6.io/rpm/x86_64/k6-v0.58.0-amd64.rpm rpm -ivh /tmp/artifacts/k6.rpm dnf install -y k6 rm -rf /tmp/artifacts/k6.rpm EXT="js" KPI_EXT="csv" TYPE_NAME="K6" elif [ "$TEST_TYPE" == "locust" ]; then EXT="py" TYPE_NAME="Locust" fi if [ "$FILE_TYPE" != "zip" ]; then aws s3 cp s3://$S3_BUCKET/public/test-scenarios/$TEST_TYPE/$TEST_ID.$EXT ./ --region $MAIN_STACK_REGION else aws s3 cp s3://$S3_BUCKET/public/test-scenarios/$TEST_TYPE/$TEST_ID.zip ./ --region $MAIN_STACK_REGION unzip $TEST_ID.zip echo "UNZIPPED" ls -l # If zip and locust, make sure to pick locustfile if [ "$TEST_TYPE" != "locust" ]; then TEST_SCRIPT=$(find . -name "*.${EXT}" | head -n 1) else TEST_SCRIPT=$(find . -name "locustfile.py" | head -n 1) fi # only looks for the first test script file. TEST_SCRIPT=`find . -name "*.${EXT}" | head -n 1` echo $TEST_SCRIPT if [ -z "$TEST_SCRIPT" ]; then echo "There is no test script (.${EXT}) in the zip file." exit 1 fi sed -i -e "s|$TEST_ID.$EXT|$TEST_SCRIPT|g" test.json # copy bundled plugin jars to jmeter extension folder to make them available to jmeter BUNDLED_PLUGIN_DIR=`find $PWD -type d -name "plugins" | head -n 1` # attempt to copy only if a /plugins folder is present in upload if [ -z "$BUNDLED_PLUGIN_DIR" ]; then echo "skipping plugin installation (no /plugins folder in upload)" else # ensure the jmeter extensions folder exists JMETER_EXT_PATH=`find ~/.bzt/jmeter-taurus -type d -name "ext"` if [ -z "$JMETER_EXT_PATH" ]; then # fail fast - if plugins bundled they will be needed for the tests echo "jmeter extension path (~/.bzt/jmeter-taurus/**/ext) not found - cannot install bundled plugins" exit 1 fi cp -v $BUNDLED_PLUGIN_DIR/*.jar $JMETER_EXT_PATH fi fi fi #Download python script if [ -z "$IPNETWORK" ]; then python3.11 -u $SCRIPT $TIMEOUT & pypid=$! wait $pypid pypid=0 else aws s3 cp s3://$S3_BUCKET/Container_IPs/${TEST_ID}_IPHOSTS_${AWS_REGION}.txt ./ --region $MAIN_STACK_REGION export IPHOSTS=$(cat ${TEST_ID}_IPHOSTS_${AWS_REGION}.txt) python3.11 -u $SCRIPT $IPNETWORK $IPHOSTS fi echo "Running test" stdbuf -i0 -o0 -e0 bzt test.json -o modules.console.disable=true | stdbuf -i0 -o0 -e0 tee -a result.tmp | sed -u -e "s|^|$TEST_ID $LIVE_DATA_ENABLED |" CALCULATED_DURATION=`cat result.tmp | grep -m1 "Test duration" | awk -F ' ' '{ print $5 }' | awk -F ':' '{ print ($1 * 3600) + ($2 * 60) + $3 }'` # upload custom results to S3 if any # every file goes under $TEST_ID/$PREFIX/$UUID to distinguish the result correctly if [ "$TEST_TYPE" != "simple" ]; then if [ "$FILE_TYPE" != "zip" ]; then cat $TEST_ID.$EXT | grep filename > results.txt else cat $TEST_SCRIPT | grep filename > results.txt fi if [ -f results.txt ]; then sed -i -e 's/<stringProp name="filename">//g' results.txt sed -i -e 's/<\/stringProp>//g' results.txt sed -i -e 's/ //g' results.txt echo "Files to upload as results" cat results.txt files=(`cat results.txt`) extensions=() for f in "${files[@]}"; do ext="${f##*.}" if [[ ! " ${extensions[@]} " =~ " ${ext} " ]]; then extensions+=("$ext") fi done # Find all files in the current folder with the same extensions all_files=() for ext in "${extensions[@]}"; do for f in *."$ext"; do all_files+=("$f") done done for f in "${all_files[@]}"; do p="s3://$S3_BUCKET/results/$TEST_ID/${TYPE_NAME}_Result/$PREFIX/$UUID/$f" if [[ $f = /* ]]; then p="s3://$S3_BUCKET/results/$TEST_ID/${TYPE_NAME}_Result/$PREFIX/$UUID$f" fi echo "Uploading $p" aws s3 cp $f $p --region $MAIN_STACK_REGION done fi fi if [ -f /tmp/artifacts/results.xml ]; then # Insert the Task ID at the same level as <FinalStatus> curl -s $ECS_CONTAINER_METADATA_URI_V4/task Task_CPU=$(curl -s $ECS_CONTAINER_METADATA_URI_V4/task | jq '.Limits.CPU') Task_Memory=$(curl -s $ECS_CONTAINER_METADATA_URI_V4/task | jq '.Limits.Memory') START_TIME=$(curl -s "$ECS_CONTAINER_METADATA_URI_V4/task" | jq -r '.Containers[0].StartedAt') # Convert start time to seconds since epoch START_TIME_EPOCH=$(date -d "$START_TIME" +%s) # Calculate elapsed time in seconds CURRENT_TIME_EPOCH=$(date +%s) ECS_DURATION=$((CURRENT_TIME_EPOCH - START_TIME_EPOCH)) sed -i.bak 's/<\/FinalStatus>/<TaskId>'"$TASK_ID"'<\/TaskId><\/FinalStatus>/' /tmp/artifacts/results.xml sed -i 's/<\/FinalStatus>/<TaskCPU>'"$Task_CPU"'<\/TaskCPU><\/FinalStatus>/' /tmp/artifacts/results.xml sed -i 's/<\/FinalStatus>/<TaskMemory>'"$Task_Memory"'<\/TaskMemory><\/FinalStatus>/' /tmp/artifacts/results.xml sed -i 's/<\/FinalStatus>/<ECSDuration>'"$ECS_DURATION"'<\/ECSDuration><\/FinalStatus>/' /tmp/artifacts/results.xml echo "Validating Test Duration" TEST_DURATION=$(grep -E '<TestDuration>[0-9]+.[0-9]+</TestDuration>' /tmp/artifacts/results.xml | sed -e 's/<TestDuration>//' | sed -e 's/<\/TestDuration>//') if (( $(echo "$TEST_DURATION > $CALCULATED_DURATION" | bc -l) )); then echo "Updating test duration: $CALCULATED_DURATION s" sed -i.bak.td 's/<TestDuration>[0-9]*\.[0-9]*<\/TestDuration>/<TestDuration>'"$CALCULATED_DURATION"'<\/TestDuration>/' /tmp/artifacts/results.xml fi if [ "$TEST_TYPE" == "simple" ]; then TEST_TYPE="jmeter" fi echo "Uploading results, bzt log, and JMeter log, out, and err files" aws s3 cp /tmp/artifacts/results.xml s3://$S3_BUCKET/results/${TEST_ID}/${PREFIX}-${UUID}-${AWS_REGION}.xml --region $MAIN_STACK_REGION aws s3 cp /tmp/artifacts/bzt.log s3://$S3_BUCKET/results/${TEST_ID}/bzt-${PREFIX}-${UUID}-${AWS_REGION}.log --region $MAIN_STACK_REGION aws s3 cp /tmp/artifacts/$LOG_FILE s3://$S3_BUCKET/results/${TEST_ID}/${TEST_TYPE}-${PREFIX}-${UUID}-${AWS_REGION}.log --region $MAIN_STACK_REGION aws s3 cp /tmp/artifacts/$OUT_FILE s3://$S3_BUCKET/results/${TEST_ID}/${TEST_TYPE}-${PREFIX}-${UUID}-${AWS_REGION}.out --region $MAIN_STACK_REGION aws s3 cp /tmp/artifacts/$ERR_FILE s3://$S3_BUCKET/results/${TEST_ID}/${TEST_TYPE}-${PREFIX}-${UUID}-${AWS_REGION}.err --region $MAIN_STACK_REGION aws s3 cp /tmp/artifacts/kpi.${KPI_EXT} s3://$S3_BUCKET/results/${TEST_ID}/kpi-${PREFIX}-${UUID}-${AWS_REGION}.${KPI_EXT} --region $MAIN_STACK_REGION else echo "An error occurred while the test was running." fi
Neben dem Dockerfileecslistener.py Skript aus, während die Leader-Task das ecscontroller.py Skript ausführt. Das ecslistener.py Skript erstellt einen Socket auf Port 50000 und wartet auf eine Nachricht. Das ecscontroller.py Skript stellt eine Verbindung zum Socket her und sendet die Starttestnachricht an die Worker-Aufgaben, sodass sie gleichzeitig starten können.
Bild der Webkonsole (nur ALB + ECS Fargate-Vorlage)
Die ALB + ECS Fargate-Vorlage führt die Webkonsole als Container auf ECS Fargate aus. Standardmäßig ruft die Lösung das Web-Konsolen-Image aus einem öffentlichen Amazon ECR-Repository ab, das von AWS verwaltet wird.
In Umgebungen, in denen der Zugriff auf öffentliche Container-Registries eingeschränkt ist (z. B. VPCs ohne Internetzugang oder Konten mit ECR-Richtlinien für den öffentlichen Zugriff), müssen Sie das öffentliche Image in ein privates Amazon ECR-Repository spiegeln und den privaten Image-URI im Parameter Image URI der Web-Konsole angeben. CloudFormation Sie können diesen Ansatz auch verwenden, um das Web-Konsolen-Image an Ihre Bedürfnisse anzupassen.
Spiegeln Sie das öffentliche Image in ein privates ECR-Repository
Um das Bild der Webkonsole in ein privates ECR-Repository zu spiegeln:
-
Authentifizieren Sie sich bei der öffentlichen ECR-Registrierung:
$ aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws -
Rufen Sie das Bild der öffentlichen Webkonsole ab:
$ docker pull public.ecr.aws/aws-solutions/distributed-load-testing-on-aws-web-console:<version> -
Erstellen Sie ein privates ECR-Repository in Ihrem Konto (falls noch keines vorhanden ist):
$ aws ecr create-repository --repository-name <your-repo-name> --region <region> 2>/dev/null || true -
Authentifizieren Sie sich bei Ihrer privaten ECR-Registrierung:
$ aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin <account-id>.dkr.ecr.<region>.amazonaws.com -
Taggen Sie das Bild und übertragen Sie es in Ihr privates Repository:
$ docker tag public.ecr.aws/aws-solutions/distributed-load-testing-on-aws-web-console:<version> \ <account-id>.dkr.ecr.<region>.amazonaws.com/<your-repo-name>:<version> $ docker push <account-id>.dkr.ecr.<region>.amazonaws.com/<your-repo-name>:<version> -
Geben Sie beim Starten des ALB + ECS Fargate-Stacks den privaten Image-URI in den Image-URI-Parameter der Web-Konsole ein:
<account-id>.dkr.ecr.<region>.amazonaws.com/<your-repo-name>:<version>
Passen Sie das Bild der Webkonsole an
Sie können das Bild der Webkonsole auch anpassen. Die Bildressourcen befinden sich im deployment/ecr/distributed-load-testing-on-aws-web-console Verzeichnis, das sich im GitHub Repository
Der Webkonsolen-Container verwendet Nginx, um die statische Webanwendung bereitzustellen. Beim Start lädt das Entrypoint-Skript die Web-Konsolen-Assets von Amazon S3 herunter und extrahiert sie in den Nginx-Dokumentenstamm.
Das folgende Beispiel zeigt die Containerdatei.
FROM public.ecr.aws/nginx/nginx:alpine # Install AWS CLI for S3 operations RUN apk upgrade --no-cache zlib libpng && \ apk add --no-cache aws-cli # Copy nginx configuration COPY nginx.conf /etc/nginx/nginx.conf # Copy entrypoint script COPY entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh EXPOSE 80 ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
Das Entrypoint-Skript lädt die Webkonsolen-Assets von S3 herunter und startet Nginx.
#!/bin/sh set -e S3_URI="s3://${S3_BUCKET}/${S3_KEY}" echo "[$(date -Iseconds)] Downloading from $S3_URI" # AWS CLI has built-in retry with exponential backoff (standard mode) AWS_MAX_ATTEMPTS=5 aws s3 cp "$S3_URI" /tmp/web-app.zip echo "[$(date -Iseconds)] Download successful" # Extract and cleanup unzip -o /tmp/web-app.zip -d /usr/share/nginx/html/ rm -f /tmp/web-app.zip # Start Nginx exec nginx -g 'daemon off;'
Die Nginx-Konfiguration dient der Einzelseitenanwendung (SPA) mit Unterstützung für die Integritätsprüfung von ALB, GZIP-Komprimierung, statischem Asset-Caching und Sicherheitsheadern.
events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; gzip on; gzip_types text/plain text/css application/json application/javascript text/xml application/xml; server { listen 80; root /usr/share/nginx/html; index index.html; # Health check endpoint for ALB location /healthz { return 200 'OK'; } # SPA routing location / { try_files $uri $uri/ /index.html; } # Cache static assets for 1 year location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ { expires 1y; add_header Cache-Control "public, immutable"; } # No cache for index.html (SPA entry point) location = /index.html { add_header Cache-Control "no-cache, no-store, must-revalidate"; } # No cache for runtime config location = /aws-exports.json { add_header Cache-Control "no-store, no-cache, must-revalidate"; } # Security headers add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; } }
Weitere Informationen finden Sie unter Pushing a Docker Image to an Amazon ECR Private Repository im Amazon ECR User Guide.