Skip to content

Commit

Permalink
Hello, distributed loadtesting
Browse files Browse the repository at this point in the history
  • Loading branch information
joakimhew committed Jun 21, 2018
0 parents commit 63e2c80
Show file tree
Hide file tree
Showing 18 changed files with 578 additions and 0 deletions.
Binary file added .DS_Store
Binary file not shown.
118 changes: 118 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
src/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/

# Virtualenv
# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
.Python
[Bb]in
[Ii]nclude
[Ll]ib
[Ll]ib64
[Ll]ocal
[Ss]cripts
pyvenv.cfg
.venv
pip-selfcheck.json
Binary file added .vs/slnx.sqlite
Binary file not shown.
116 changes: 116 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/bin/locust"
},
{
"name": "Python: Attach",
"type": "python",
"request": "attach",
"localRoot": "${workspaceFolder}",
"remoteRoot": "${workspaceFolder}",
"port": 3000,
"secret": "my_secret",
"host": "localhost"
},
{
"name": "Python: Terminal (integrated)",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
},
{
"name": "Python: Terminal (external)",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "externalTerminal"
},
{
"name": "Python: Django",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/manage.py",
"args": [
"runserver",
"--noreload",
"--nothreading"
],
"debugOptions": [
"RedirectOutput",
"Django"
]
},
{
"name": "Python: Flask (0.11.x or later)",
"type": "python",
"request": "launch",
"module": "flask",
"env": {
"FLASK_APP": "app.py"
},
"args": [
"run",
"--no-debugger",
"--no-reload"
]
},
{
"name": "Python: Module",
"type": "python",
"request": "launch",
"module": "module.name"
},
{
"name": "Python: Pyramid",
"type": "python",
"request": "launch",
"args": [
"${workspaceFolder}/development.ini"
],
"debugOptions": [
"RedirectOutput",
"Pyramid"
]
},
{
"name": "Python: Watson",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/console.py",
"args": [
"dev",
"runserver",
"--noreload=True"
]
},
{
"name": "Python: All debug Options",
"type": "python",
"request": "launch",
"pythonPath": "${config:python.pythonPath}",
"program": "${file}",
"module": "module.name",
"env": {
"VAR1": "1",
"VAR2": "2"
},
"envFile": "${workspaceFolder}/.env",
"args": [
"arg1",
"arg2"
],
"debugOptions": [
"RedirectOutput"
]
}
]
}
88 changes: 88 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
Distributed load testing using kubernetes and locust
======================

The repository contains everything needed to run a distributed load testing environment in kubernetes using a locust master and locust slaves.


## Table of contents
1. [Project structure](#project-structure)
2. [Prerequisites](#prerequisites)
3. [Running](#running)
4. [Architecture](#architecture)

### Project structure

.
├── .vscode # launch.json and tasks.json needed to debug the tasks.py in vsc
├── docker-image # The shared docker image for locust masters and slaves
│ ├── locust-tasks # Python source code
| | ├── requirements.txt # Python dependencies for tasks.py
| | ├── tasks.py # Locust tasks
| ├── run.sh # Shell script to determine if the docker containers should be master or slave
│ ├── Dockerfile # Dockerfile
├── loadtest-chart # Helm chart
| ├── templates # Helm templates
| | ├── _helpers.tpl # Helm helpers
| | ├── locust-master-deployment.yaml # Kubernetes deployment configuration for locust master
| | ├── locust-master-service.yaml # Kubernetes service configuration for locust master
| | ├── locust-slave-deployment.yaml # Kubernetes deployment configuration for locust slaves
| ├── Chart.yaml # Chart definition
| ├── values.yaml # Chart definition
└── ...
___

### Prerequisites

| Product | Version | Link |
| :------------------|:-----------------------------|:--------------------------------------------------------|
| Python | 2.7.15 | [Windows][Python-Windows], [MacOS][Python-macOS] |
| Docker | 18.03.0-ce (23751) | [Windows][Docker-Windows], [MacOS][Docker-macOS] |
| kubectl | 2.0.0 | [Windows][kubectl-Windows], [MacOS][kubectl-MacOS] |
| Minikube | 0.27.0 | [Windows][Minikube], [MacOS][Minikube] |
| helm | 2.9.1 | [Windows][helm-Windows] [MacOS][helm-macOS] |


### Running

#### Preparing the local kubernetes cluster
Start a local kubernetes cluster with minikube by running the following command `minikube start`

Confirm that everything is OK by running `minikube status` it should return something like:

```
minikube: Running
cluster: Running
kubectl: Correctly Configured: pointing to minikube-vm at 192.168.99.100
```

Now that we have minikube running we are going to want to point our docker environment to the one running on the cluster. Do this with the command `eval $(minikube docker-env)`. You can unset the environment at any time by running `eval $(docker-machine env --unset)`.

Confirm that the docker environment is correct by running `docker images`. You should see a list of related kubernetes images like k8s.gcr.io.

Now we're ready to install tiller onto our local kubernetes cluster. Tiller will make sure that we can use helm to install, update and delete our charts. The easiest way to do this is to simply run `helm init`.

#### Building the docker image
In the root of the repo, run `docker build docker-image -t locust-tasks:latest`

#### Installing the helm charts
Now that we have the docker image built and registered in the minikube docker registry. We can get our deployments and services for locust into our kubernetes cluster. Simply run `helm install loadtest-chart --name locust`.

#### Confirm the installation and access locust dashboard
To confirm that locust is running in our cluster. Run `minikube service list`. You should find locust-loadtest-chart-master with 3 URL's. Go to the first one and you should now see the locust load testing frontpage.

![locust][locust]


### Architecture

[Python-Windows]: https://www.python.org/downloads/windows/
[Python-MacOS]: https://www.python.org/downloads/mac-osx/
[Docker-Windows]: https://docs.docker.com/docker-for-windows/install/#download-docker-for-windows
[Docker-MacOS]: https://docs.docker.com/docker-for-windows/install/#download-docker-for-windows
[kubectl-Windows]: https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-with-chocolatey-on-windows
[kubectl-MacOS]: https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-with-homebrew-on-macos
[Minikube]: https://kubernetes.io/docs/tasks/tools/install-minikube/
[helm-Windows]: https://docs.helm.sh/using_helm/#from-chocolatey-windows
[helm-macOS]: https://docs.helm.sh/using_helm/#from-homebrew-macos

[locust]: images/locust.png
Binary file added docker-image/.DS_Store
Binary file not shown.
17 changes: 17 additions & 0 deletions docker-image/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
FROM python:2.7

ADD locust-tasks /locust-tasks
ADD certs /certs
ADD run.sh .

# Install the required dependencies via pip
RUN pip install -r /locust-tasks/requirements.txt

# Expose the required Locust ports
EXPOSE 5557 5558 8089

# Set script to be executable
RUN chmod 755 run.sh

# Start Locust using LOCUS_OPTS environment variable
ENTRYPOINT ["bash", "./run.sh"]
29 changes: 29 additions & 0 deletions docker-image/locust-tasks/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
astroid==1.6.5
backports.functools-lru-cache==1.5
beautifulsoup4==4.6.0
certifi==2018.4.16
chardet==3.0.4
click==6.7
configparser==3.5.0
enum34==1.1.6
Flask==1.0.2
futures==3.2.0
gevent==1.3.3
greenlet==0.4.13
idna==2.7
isort==4.3.4
itsdangerous==0.24
Jinja2==2.10
lazy-object-proxy==1.3.1
-e git://github.com/locustio/locust.git@61b43c7df442d6829b4c1bf9fba176cad9a2347c#egg=locustio
MarkupSafe==1.0
mccabe==0.6.1
msgpack-python==0.5.6
pylint==1.9.2
pyzmq==17.0.0
requests==2.19.1
singledispatch==3.4.0.3
six==1.11.0
urllib3==1.23
Werkzeug==0.14.1
wrapt==1.10.11
11 changes: 11 additions & 0 deletions docker-image/locust-tasks/tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from locust import HttpLocust, TaskSet, task

class UserBehavior(TaskSet):
@task(4)
def testTask(self):
self.client.get("/")

class WebsiteUser(HttpLocust):
task_set = UserBehavior
min_wait = 1000
max_wait = 2000
Loading

0 comments on commit 63e2c80

Please sign in to comment.