Ejecutando pruebas de JMeter en OpenShift usando Jenkins Pipeline

¡Hola a todos!

En este artículo quiero compartir uno de los métodos para ejecutar pruebas de rendimiento de JMeter en OpenShift utilizando Jenkins como herramienta de automatización. Primero realizaremos todas las acciones necesarias (creación ImageStreams, BuildConfig, Job y otros) manualmente. Después escribiremos el Jenkins Pipeline.

Como punto de partida debemos tener:

  1. un clúster de OpenShift (v3.11) en funcionamiento
  2. servidor de Jenkins con credenciales configuradas para trabajar en OpenShift
  3. archivo apache-jmeter-5.2.tgz

Como prueba utilizaremos una simple Solicitud HTTP en ya.ru en un solo hilo.

Creación de un proyecto en OpenShift

Comencemos creando un nuevo entorno. Crearemos perftest entorno con el comando:

$ oc new-project perftest --display-name="Pruebas de rendimiento" --description="Pruebas de rendimiento - JMeter"

Seremos redirigidos automáticamente al nuevo entorno creado perftest, verifiquemos que es así:

$ oc project
Usando el proyecto "perftest" en el servidor "https://127.0.0.1:8443".

Creación de Storage

Los informes de las pruebas se almacenarán en un espacio compartido para el servidor web y jmeter-metersu lugar — /jmeter/reports.

Es mejor crear el Storage ahora, porque los PODs dependerán de él jmeter-web y jmeter-master.

Encontrarás información más detallada sobre los storages en la documentación oficial Almacenamiento Persistente.

Crearemos archivos yaml para PV y 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

Crearemos PV y PVC en el entorno de OpenShift:

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

Verificamos el estado de 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

Así es como se verá en la GUI:

Ejecutando pruebas de JMeter en OpenShift usando Jenkins Pipeline

Creación de la imagen base de JMeter

Pasemos a la creación de ImageStream y BuildConfig.

Toda la información necesaria se puede encontrar en la documentación — Builds and Image Streams.

La estrategia de creación de imágenes utiliza Docker de una fuente local.

Crearemos una imagen base jmeter-base, que será la base para 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

Crearemos los objetos IS y BC:

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

Ahora construiremos la imagen base jmeter-base:

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

JMeter WEB

jmeter-web es un servidor Apache. Su función es proporcionar un directorio con los resultados de las pruebas para su visualización.

Preparado Dockerfile y el archivo de configuración httpd.conf. Para la directiva DocumentRoot se establece en /jmeter/reports, es decir, el directorio donde se almacenan los resultados de las pruebas.

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

Crearemos ImageStream y BuildConfig objetos:

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

Construimos la imagen de 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

Crearemos los objetos Servicio y DeploymentConfig:

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

Jmeter-master

Nos ocuparemos del despliegue del servidor web Apache.

Este es el Dockerfile jmeter-master‘a, basado en jmeter-base, que ejecutará pruebas y almacenará resultados en el almacenamiento.

Dockerfile

Dockerfile para jmeter-master, basado en 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 es un script que ejecuta JMeter y almacena los resultados en el directorio files.

En cada ejecución, el script elimina las pruebas anteriores, por lo que solo se puede trabajar con los datos más recientes. Pero esto no es un problema, ya que se puede modificar según tus necesidades.

#!/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

Crearemos IS y BC objetos:

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

Recopilando jmeter-master imagen:

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

Job

Jobse utilizan en OpenShiftpara ejecutar uno o varios PODy garantizar su finalización exitosa después de ejecutar el comando/script.

$ 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

Creando el objeto Job:

$ oc create -f job.yaml -n perftest

Comprobemos el estado del trabajo:

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

Para eliminar Job usaremos el comando:

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

Jenkins Pipeline

Ahora, automatización. Repasemos los pasos:

  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

A continuación, se presenta el pipeline, donde se realiza la clonación del repositorio, eliminación y creación de OpenShift Jobjobs.

#!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>INICIO - Pruebas de Rendimiento</strong><br /><br />Proyecto: Nombre del Proyecto<br />Entorno: PerfTest<br />Número de compilación: ${env.BUILD_NUMBER}<br />URL de compilación:   ${env.BUILD_URL}"
                }
            }
        }

        etapa('Git checkout') {
            pasos {
                ...
            }
        }

        etapa('Pruebas de Rendimiento') {
            pasos {
                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 "FALLIDA - Pruebas de Rendimiento"
                mail(to: 'username@srv.net', from: "jenkins@srv.net", subject: "FALLIDA - Pruebas de Rendimiento",mimeType: "text/html", body: "<strong>FALLIDA - Pruebas de Rendimiento</strong><br /><br />Proyecto: Nombre del Proyecto<br />Entorno: PerfTest<br />Número de compilación: ${env.BUILD_NUMBER}<br />URL de compilación: ${env.BUILD_URL}"
                }

            success {
                echo "EXITOSA - Pruebas de Rendimiento"
                mail(to: 'username@srv.net', from: "jenkins@srv.net", subject: "EXITOSA - Pruebas de Rendimiento",mimeType: "text/html", body: "<strong>EXITOSA - Pruebas de Rendimiento</strong><br /><br />Proyecto: Nombre del Proyecto<br />Entorno: PerfTest<br />Número de compilación: ${env.BUILD_NUMBER}<br />URL de compilación:   ${env.BUILD_URL}"
            }
        }

    }
}

Después de que el Pipeline se ejecute, recibirás una notificación en tu correo electrónico 'username@srv.net desde jenkins@srv.net.

Al seguir el enlace http://jmeter-web.127.0.0.1.nip.io/ veremos el directorio files, donde se almacenan los informes de pruebas:

Ejecutando pruebas de JMeter en OpenShift usando Jenkins Pipeline

El contenido del archivo 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

Conclusión

En este artículo se demostró una de las maneras de ejecutar pruebas de JMeter en un entorno de OpenShift. Se realizaron todos los pasos manualmente, después de lo cual se creó un Jenkins Pipeline para automatizar el proceso de ejecución de las pruebas.

Fuentes y documentación

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster