Ausführen von JMeter-Tests in OpenShift unter Verwendung von Jenkins Pipeline

Hallo zusammen!

In diesem Artikel möchte ich einen der Wege teilen, um Leistungstests mit JMeter in OpenShift unter Verwendung von Jenkins als Automatisierung zu starten. Zunächst werden wir alle notwendigen Schritte (Erstellung ImageStreams, BuildConfig, Job und weitere) manuell durchführen. Danach schreiben wir eine Jenkins-Pipeline.

Als Ausgangspunkt sollten wir haben:

  1. ein funktionierendes OpenShift (v3.11) Cluster
  2. Jenkins-Server mit konfigurierten Anmeldeinformationen für die Arbeit in OpenShift
  3. Datei apache-jmeter-5.2.tgz

Als Tests wird eine einfache HTTP-Anfrage auf ya.ru in einem Thread.

Projekt in OpenShift erstellen

Wir beginnen mit der Erstellung einer neuen Umgebung. Wir erstellen perftest Umgebung mit dem Befehl:

$ oc new-project perftest --display-name="Performance Tests" --description="Performance Tests - JMeter"

Wir werden automatisch in die gerade erstellte Umgebung weitergeleitet perftest, wir überprüfen, dass dem so ist:

$ oc project
Using project "perftest" on server "https://127.0.0.1:8443".

Speicher erstellen

Die Testberichte werden an einem gemeinsamen Ort für den Webserver und jmeter-metergespeichert — /jmeter/reports.

Es ist besser, den Speicher jetzt zu erstellen, da darauf die PODs basieren werden jmeter-web und jmeter-master.

Detaillierte Informationen zu Speichern finden Sie in der offiziellen Dokumentation Persistent Storage.

Wir erstellen yaml-Dateien für PV und PVC.

pv.yaml

$ tee pv.yaml<<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: jmeter-reports
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  glusterfs:
    endpoints: glusterfs-cluster
    path: /jmeter/reports
    readOnly: false
  persistentVolumeReclaimPolicy: Retain
EOF

pvc.yaml

$ tee pvc.yaml<<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: jmeter-reports
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
EOF

für das Init-System SystemD: PV und PVC in der OpenShift-Umgebung:

$ oc create -f pv.yaml -n perftest
$ oc create -f pvc.yaml -n perftest

Wir überprüfen den Status für PVC:

$ oc get pvc -n perftest
NAME             STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS        AGE
jmeter-reports   Bound     pvc-b0e5f152-db4b-11ea-a497-566f75280024   10Gi       RWX            glusterfs-storage   8m

So wird es im GUI aussehen:

Ausführen von JMeter-Tests in OpenShift unter Verwendung von Jenkins Pipeline

Basis-Image von JMeter erstellen

Kommen wir zur Erstellung von ImageStream und BuildConfig.

Alle notwendigen Informationen finden Sie in der Dokumentation — Builds and Image Streams.

Als Strategie zum Erstellen von Images wird verwendet Docker aus einer lokalen Quelle.

Wir erstellen das Basis-Image jmeter-base, das die Grundlage für jmeter-master.

Dockerfile

FROM openjdk:8u212-jdk

ARG JMETER_VER="5.2"
ENV JMETER_HOME /jmeter/apache-jmeter-$JMETER_VER
ENV PATH $JMETER_HOME/bin:$PATH

RUN mkdir -p /jmeter/results 
    && mkdir /jmeter/tests

WORKDIR /jmeter

COPY apache-jmeter-$JMETER_VER.tgz .

RUN tar -xzf $JMETER_HOME.tgz 
    && rm $JMETER_HOME.tgz 
    && ls -la

RUN sed -i s/#server.rmi.ssl.disable=false/server.rmi.ssl.disable=true/ $JMETER_HOME/bin/jmeter.properties

EXPOSE 60000

is.yaml

$ tee is.yaml<<EOF
apiVersion: v1
kind: ImageStream
metadata:
  labels:
    build: jmeter-base
  name: jmeter-base
EOF

bc.yaml

$ tee bc.yaml<<EOF
apiVersion: v1
kind: BuildConfig
metadata:
  name: jmeter-base
spec:
  failedBuildsHistoryLimit: 5
  nodeSelector: null
  output:
    to:
      kind: ImageStreamTag
      name: 'jmeter-base:latest'
  postCommit: {}
  resources: {}
  runPolicy: Serial
  source:
    binary: {}
    type: Binary
  strategy:
    dockerStrategy:
      from:
        kind: ImageStreamTag
        name: 'openjdk:8u212-jdk'
    type: Docker
  successfulBuildsHistoryLimit: 5
EOF

Lass uns Objekte erstellen IS und BC:

$ oc create -f is.yaml -n perftest
$ oc create -f bc.yaml -n perftest

Jetzt erstellen wir das Basis-Image jmeter-base:

$ oc start-build jmeter-base -n perftest --from-dir=. --follow

JMeter WEB

jmeter-web das ist der Apache-Webserver. Seine Aufgabe ist es, ein Verzeichnis mit den Testergebnissen zur Ansicht bereitzustellen.

Vorbereitet Dockerfile und die Konfigurationsdatei httpd.conf. Für die Direktive DocumentRoot ist der Wert /jmeter/reports, d.h. das Verzeichnis, in dem die Testergebnisse gespeichert werden.

Dockerfile

$ tee Dockerfile<<EOF
FROM httpd:2.4

COPY httpd.conf /usr/local/apache2/conf/httpd.conf
RUN chmod -R 777 /usr/local/apache2/logs

EXPOSE 8080

CMD ["httpd", "-D", "FOREGROUND"]
EOF

is.yaml

$ tee is.yaml<<EOF
apiVersion: v1
kind: ImageStream
metadata:
  generation: 1
  labels:
    build: jmeter-web
  name: jmeter-web
EOF

bc.yaml

$ tee bc.yaml<<EOF
apiVersion: v1
kind: BuildConfig
metadata:
  name: jmeter-web
spec:
  failedBuildsHistoryLimit: 5
  nodeSelector: null
  output:
    to:
      kind: ImageStreamTag
      name: 'jmeter-web:latest'
  runPolicy: Serial
  source:
    binary: {}
    type: Binary
  strategy:
    dockerStrategy:
      from:
        kind: ImageStreamTag
        name: 'httpd:2.4'
    type: Docker
  successfulBuildsHistoryLimit: 5
EOF

für das Init-System SystemD: ImageStream und BuildConfig Objekte:

$ oc create -f is.yaml -n perftest
$ oc create -f bc.yaml -n perftest

Wir bauen das Image aus Dockerfile:

$ oc start-build jmeter-web -n perftest --from-dir=. --follow

dc.yaml

$ tee dc.yaml<<EOF
apiVersion: apps.openshift.io/v1
kind: DeploymentConfig
metadata:
  name: jmeter-web
spec:
  replicas: 1
  template:
    metadata:
      labels:
        name: jmeter-web
    spec:
      containers:
        - image: 172.30.1.1:5000/perftest/jmeter-web
          name: jmeter-web
          volumeMounts:
            - mountPath: /jmeter/reports
              name: jmeter-reports
          ports:
            - containerPort: 80
              protocol: TCP
            - containerPort: 8080
              protocol: TCP
      volumes:
        - name: jmeter-reports
          persistentVolumeClaim:
            claimName: jmeter-reports
EOF

sc.yaml

$ tee sc.yaml<<EOF
apiVersion: v1
kind: Service
metadata:
  labels:
    app: jmeter-web
  name: jmeter-web
spec:
  ports:
    - name: 8080-tcp
      port: 8080
      protocol: TCP
      targetPort: 8080
  selector:
    deploymentconfig: jmeter-web
  sessionAffinity: None
  type: ClusterIP
EOF

Lass uns Objekte erstellen Service und DeploymentConfig:

$ oc create -f sc.yaml -n perftest
$ oc create -f dc.yaml -n perftest

Jmeter-master

Lass uns mit dem Deployment des Apache-Webservers beginnen.

Das ist der Dockerfile jmeter-master‘a, basierend auf jmeter-base, der Tests ausführt und die Ergebnisse im Speicher speichert.

Dockerfile

Dockerfile für jmeter-master, basierend auf jmeter-base.

FROM jmeter-base

ARG JMETER_VER="5.2"
ENV JMETER_HOME /jmeter/apache-jmeter-$JMETER_VER
ENV PATH $JMETER_HOME/bin:$PATH

WORKDIR /jmeter
COPY run.sh /jmeter/
COPY tests/*.jmx /jmeter/tests/
RUN chmod +x /jmeter/run.sh

ENTRYPOINT ["/bin/bash"]
CMD ["/jmeter/run.sh"]

run.sh

run.sh das ist ein Skript, das JMeter startet und die Ergebnisse im Verzeichnis speichert. files.

Bei jedem Start löscht das Skript die vorherigen Tests, sodass man nur mit den neuesten Daten arbeiten kann. Das ist jedoch kein Problem, da man es an die eigenen Bedürfnisse anpassen kann.

#!/bin/bash

set -e

if [ -d "/jmeter/reports/files" ]
then
    echo "Directory /jmeter/reports/files exist - OK"
else
    echo "Creating /jmeter/reports/files directory"
    mkdir /jmeter/reports/files
fi

if [ -d "/jmeter/reports/dashboards" ]
then
    echo "Directory /jmeter/reports/dashboards exist"
else
    echo "Creating /jmeter/reports/dashboards directory"
    mkdir /jmeter/reports/dashboards
fi

echo "*** JMeter START Tests ***"

for item in $(ls -1 /jmeter/tests | grep jmx)
do
    echo "*** Removing dashboard directory for $item"
    rm -rdf /jmeter/reports/dashboards/${item}*

    echo "*** Removing tests directory for $item"
    rm -rdf /jmeter/reports/files/${item}*

    echo "*** Testing a $item file ***"
    jmeter -n -t /jmeter/tests/${item} -l /jmeter/reports/files/${item}-report.jtl -e -o /jmeter/reports/dashboards/${item}-dash
done

is.yaml

$ tee is.yaml<<EOF
apiVersion: image.openshift.io/v1
kind: ImageStream
metadata:
  generation: 1
  labels:
    build: jmeter-master
  name: jmeter-master
EOF

bc.yaml

$ tee bc.yaml<<EOF
apiVersion: build.openshift.io/v1
kind: BuildConfig
metadata:
  name: jmeter-master
spec:
  failedBuildsHistoryLimit: 5
  nodeSelector: null
  output:
    to:
      kind: ImageStreamTag
      name: 'jmeter-master:latest'
  runPolicy: Serial
  source:
    binary: {}
    type: Binary
  strategy:
    dockerStrategy:
      from:
        kind: ImageStreamTag
        name: 'jmeter-base:latest'
    type: Docker
  successfulBuildsHistoryLimit: 5
EOF

für das Init-System SystemD: IS und BC Objekte:

$ oc create -f is.yaml -n perftest
$ oc create -f bc.yaml -n perftest

Erstellen jmeter-master Abbild:

$ oc start-build jmeter-master -n perftest --from-dir=. --follow

Job

Jobwerden in OpenShifte verwendet, um einen oder mehrere PODauszuführen und deren erfolgreichen Abschluss nach der Ausführung des Befehls/Skripts zu garantieren.

$ tee job.yaml<<EOF
apiVersion: batch/v1
kind: Job
metadata:
  name: jmeter-master
  labels:
    jobName: jmeter-master
spec:
  completions: 1
  parallelism: 1
  template:
    metadata:
      name: jmeter-master
      labels:
        jobName: jmeter-master
    spec:
      containers:
        - name: jmeter-master
          image: 172.30.1.1:5000/perftest/jmeter-master:latest
          volumeMounts:
            - mountPath: /jmeter/reports
              name: jmeter-reports
          imagePullPolicy: Always
      volumes:
        - name: jmeter-reports
          persistentVolumeClaim:
            claimName: jmeter-reports
      restartPolicy: Never
      terminationGracePeriodSeconds: 30
EOF

Objekt erstellen Job:

$ oc create -f job.yaml -n perftest

Prüfen wir den Status des Jobs:

$ oc get jobs -n perftest
NAME            DESIRED   SUCCESSFUL   AGE
jmeter-master   1         1            5m

Um zu löschen, Job verwenden wir den Befehl:

$ oc delete jobs/jmeter-master -n perftest --ignore-not-found=true

Jenkins Pipeline

Nun zur Automatisierung. Lassen Sie uns die Schritte noch einmal durchgehen:

  1. git clone
  2. oc whoami -t
  3. oc start-build ...
  4. oc delete jobs/jmeter-master
  5. oc create -f job.yaml -n perftest

Im Folgenden finden Sie die Pipeline, die das Klonen des Repositories, das Löschen und Erstellen von OpenShift durchführt. Job‘s.

#!groovy

pipeline {

    agent any

    stages {

        stage('Start Notifications') {
            steps {
                echo "Sending Email Notification"
            }
            post {
                always {
                    echo "STARTED - Performance Tests"
                    mail(to: 'username@srv.net', from: "jenkins@srv.net", subject: "START - Performance Tests",mimeType: "text/html", body: "<strong>START - Leistungstests</strong><br /><br />Projekt: Name des Projekts<br />Umgebung: PerfTest<br />Build-Nummer: ${env.BUILD_NUMBER}<br />Build-URL:   ${env.BUILD_URL}"
                }
            }
        }

        stage('Git checkout') {
            steps {
                ...
            }
        }

        stage('Leistungstests') {
            steps {
                script {
                    sh '''
                        OC_CMD1="oc login -u=username -p=PASS -n=perftest 
                        --server=https://...:8443"

                        $OC_CMD1

                        OC_TOKEN=`oc whoami -t`

                        OC_CMD2="oc --token=$OC_TOKEN --server=https://...:8443 
                        start-build jmeter-master -n=perftest --from-dir=./master 
                        --follow=true"

                        OC_CMD3="oc --token=$OC_TOKEN --server=https://...:8443 
                        delete jobs/jmeter-master -n=perftest --ignore-not-found=true"

                        OC_CMD4="oc--token=$OC_TOKEN --server=https://...:8443 
                        create -f ./master/job.yaml -n=perftest"

                        $OC_CMD2
                        $OC_CMD3
                        $OC_CMD4
                    '''
                }
            }
        }

        post {
            failure {
                echo "FEHLGESCHLAGEN - Leistungstests"
                mail(to: 'username@srv.net', from: "jenkins@srv.net", subject: "FEHLGESCHLAGEN - Leistungstests",mimeType: "text/html", body: "<strong>FEHLGESCHLAGEN - Leistungstests</strong><br /><br />Projekt: Name des Projekts<br />Umgebung: PerfTest<br />Build-Nummer: ${env.BUILD_NUMBER}<br />Build-URL: ${env.BUILD_URL}"
                }

            success {
                echo "ERFOLGREICH - Leistungstests"
                mail(to: 'username@srv.net', from: "jenkins@srv.net", subject: "ERFOLGREICH - Leistungstests",mimeType: "text/html", body: "<strong>ERFOLGREICH - Leistungstests</strong><br /><br />Projekt: Name des Projekts<br />Umgebung: PerfTest<br />Build-Nummer: ${env.BUILD_NUMBER}<br />Build-URL:   ${env.BUILD_URL}"
            }
        }

    }
}

Nach der Ausführung der Pipeline erhalten wir eine Benachrichtigung per E-Mail 'username@srv.net ab jenkins@srv.net.

Wenn Sie dem Link folgen, http://jmeter-web.127.0.0.1.nip.io/ sehen wir das Verzeichnis, filesin dem die Testberichte gespeichert sind:

Ausführen von JMeter-Tests in OpenShift unter Verwendung von Jenkins Pipeline

Inhalt der Datei ya.HTTP.Request.jmx-report.jtk:

timeStamp,elapsed,label,responseCode,responseMessage,threadName,dataType,success,failureMessage,bytes,sentBytes,grpThreads,allThreads,URL,Latency,IdleTime,Connect
1597311456443,569,Yandex - HTTP Request,200,Ok,Thread Group 1-1,text,true,,59449,220,1,1,https://ya.ru/,145,0,57
1597311456443,147,Yandex - HTTP Request-0,302,Found,Thread Group 1-1,,true,,478,110,1,1,http://ya.ru/,145,0,57
1597311456592,420,Yandex - HTTP Request-1,200,Ok,Thread Group 1-1,text,true,,58971,110,1,1,https://ya.ru/,370,0,259

Fazit

In diesem Artikel wurde eine der Möglichkeiten demonstriert, JMeter-Tests in einer OpenShift-Umgebung auszuführen. Wir haben alle Schritte manuell durchgeführt und anschließend eine Jenkins-Pipeline erstellt, um den Prozess der Testausführung zu automatisieren.

Quellen und Dokumentation

Quelle: habr.com

60GB SSD 8Gb DDR4