You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: Blog_part_1.md
+83-52
Original file line number
Diff line number
Diff line change
@@ -25,7 +25,7 @@ I've quoted Locust’s high level description below but you can visit [their](ht
25
25
26
26
Now that we have a rough idea of what Locust is, let's get it installed.
27
27
28
-
**NOTE: If you don’t want to install Locust locally, skip down to the Docker section towards the bottom of this guide.
28
+
**NOTE:** If you don’t want to install Locust locally, skip down to the Docker section towards the bottom of this guide.
29
29
30
30
## Install Locust
31
31
@@ -61,36 +61,37 @@ Now that we have Locust installed we can create and run a Locust script. But fir
61
61
62
62
## Test Server
63
63
64
-
I have created a repo we will build out as we go. Within that repo you will find an example_server program written in Go (compiled on OSX). You can directly grab that binary [here](https://github.com/RealKinetic/locust_k8s/blob/49b221e52484c6e0d165490a3dbbf1fe4d2f9dce/example_server) or clone the repo with the following command:`git clone git@github.com:RealKinetic/locust_k8s.git`
64
+
I created a repo we will use to build out the server and test scripts. Within that repo you will find an [example_server](https://github.com/RealKinetic/locust_k8s/blob/master/examples/golang/example_server.go) program written in Go. If you are on OSX, and you trust binaries from the internet, you can grab the binary [here](https://github.com/RealKinetic/locust_k8s/blob/master/example_server); otherwise clone the repo with the following command:
65
65
66
-
Here is the Go code behind the file. It is also included in the repo if you would like to make changes or do not trust running a binary from the Internet. To build the go file run: `$ go build example_server.go`
Once you have the binary or repo pulled down go to that directly:
69
+
To build the server, run:
69
70
70
-
$ cd locust_k8s
71
+
$ go build examples/golang/example_server.go
71
72
72
-
And run the following command to run the server:
73
+
And run the following command to start the server:
73
74
74
75
$ ./example_server
75
76
76
-
This server will sit on port `8080`. You can test it by visiting http://localhost:8080. You should see a page with:
77
+
This server will listen on port `8080`. You can test it by visiting [http://localhost:8080](http://localhost:8080/). You should see a page with:
77
78
78
-
Our example home page.
79
+
>Our example home page.
79
80
80
-
There are two other endpoints exposed by this example server.
81
+
There are two other endpoints exposed by our example server.
81
82
82
-
*`\login` which we will send a post request to and returns `Login. The server will output `Login Request` to stdout when this endpoint is hit.
83
-
*`\profile` which we will send a get request to and returns `Profile`. The server will output `Profile Request` to stdout when this endpoint is hit.
83
+
*[`/login`](http://localhost:8080/login) accepts `POST` requests and returns a plain text response "*Login.*". The server will output "`Login Request`" to stdout when this endpoint is hit.
84
+
*[`/profile`](http://localhost:8080/profile) accepts `GET` requests and returns "*Profile.*". The server will output "`Profile Request`" to stdout when this endpoint is hit.
84
85
85
-
Now that we have an example server to hit we can create the Locust file.
86
+
Now that we have an example server, we can create the Locust test file.
86
87
87
88
## Running Locust
88
89
89
90
For this example we can use the example provided by Locust in their [quick start documentation](http://docs.locust.io/en/latest/quickstart.html).
90
91
91
-
You can use the `locustfile.py` in our example repo or create said file.
92
+
You can use the `locustfile.py` in our example repo, or create the file yourself.
92
93
93
-
Here's the code that you will need in `locustfile.py`:
94
+
Your `locustfile.py` should contain the following:
94
95
95
96
from locust import HttpLocust, TaskSet, task
96
97
@@ -100,7 +101,9 @@ Here's the code that you will need in `locustfile.py`:
@@ -115,35 +118,46 @@ Here's the code that you will need in `locustfile.py`:
115
118
min_wait = 5000
116
119
max_wait = 9000
117
120
118
-
You can learn more about what this file does in the Locust documentation and quick start walkthrough (highly recommended).
121
+
The Locust documentation and [quick start documentation](http://docs.locust.io/en/latest/quickstart.html) provides an explanation of the contents. We highly recommend working through their docs to learn more.
119
122
120
123
Now that we have our locustfile we can do a test.
121
124
122
125
First ensure your example server is running:
123
126
124
127
$ ./example_server
125
128
126
-
Then we run Locust and give it our file.
129
+
Now, in a new terminal we will run Locust. We will pass it the name of our test file, `locustfile.py`, and tell it to run against our example server on port `8080` of `localhost`.
With Locust running we can open the web user interface at: [http://localhost:8089](http://localhost:8089).
129
134
130
-
We pass in the host of our example server which is running on port 8080 of localhost.
135
+
For this test, we will simulate 1 user and specify 1 for the hatch rate. Click the `Start swarming` button. You should now see something similar to the following in the terminal running example server:
131
136
132
-
With Locust running we can open the web user interface at: http://localhost:8089
137
+
2017/09/13 15:24:33 Login Request
138
+
2017/09/13 15:24:33 Profile Request
139
+
2017/09/13 15:24:40 Profile Request
140
+
2017/09/13 15:24:46 Index Request
141
+
2017/09/13 15:24:55 Index Request
142
+
2017/09/13 15:25:00 Index Request
143
+
2017/09/13 15:25:07 Profile Request
144
+
2017/09/13 15:25:12 Index Request
133
145
134
-
We can do a quick test by adding 1 user to simulate and 1 for a hatch rate. Then click the `Start swarming` button.
146
+
In the Locust UI you will see a list of the endpoints being hit. You will see the request counts incrementing for `/` and `/profile`. There should be no failures unless Locust is having issues connecting to your server.
135
147
136
-
You should now see messages being sent to the stdout of your example server. In the Locust UI you will see a list of the endpoints being hit. You will see the request counts incrementing for `/` and `/profile`. There should not be failures being logged unless Locust is having issues connecting to your server.
148
+

137
149
138
150
# Docker
139
151
140
-
We're going to build and run our [Docker](https://www.docker.com/) containers locally first so go ahead and install Docker for your environment based off the directions on the [Docker](https://www.docker.com/) website.
152
+
We're going to start by building and running our [containers](https://www.docker.com/what-container) locally using [Docker](https://www.docker.com/). Install Docker for your environment using the directions on the [Docker](https://www.docker.com/) website.
153
+
154
+
**NOTE:** Before continuing, you should stop the two servers from the previous sections using `ctrl-c` in each terminal window.
141
155
142
156
# Docker Environment
143
157
144
-
We will have two containers running in our scenario: our example server and Locust instance. To support our locust container’s communication with our example server we need to configure a custom Docker network. Thankfully this is a simple process.
158
+
We will run two containers: our service (our golang example server) and our Locust instance. To support our locust container’s communication with our example server we need to configure a custom Docker network. Thankfully this is a simple process.
145
159
146
-
The following command will create a custom Docker network named `locustnw`
160
+
The following command will create a custom Docker network named `locustnw`:
147
161
148
162
$ docker network create --driver bridge locustnw
149
163
@@ -174,43 +188,51 @@ This will use the `Dockerfile` we've create in the `examples/golang` directory w
174
188
# Build the example executable
175
189
RUN go build example_server.go
176
190
177
-
# Set script to be executable
191
+
# Set the server to be executable
178
192
RUN chmod 755 example_server
179
193
180
194
# Expose the required port (8080)
181
195
EXPOSE 8080
182
196
183
-
# Start Locust using LOCUS_OPTS environment variable
197
+
# Start our example service
184
198
ENTRYPOINT ["./example_server"]
185
199
186
-
The `-t` argument allows us to tag our container with a name. In this case we're tagging it `goexample`.
200
+
The `-t` argument tags our container with a name, `goexample`, in this case.
187
201
188
202
Now that we've created our container we can run it with the following:
189
203
190
-
$ docker run -it -p=8080:8080 --name=exampleserver --network=locustnw goexample
204
+
$ docker run -it -p=8080:8080 \
205
+
--name=exampleserver \
206
+
--network=locustnw \
207
+
goexample
191
208
192
-
- The `-p` flag exposes port 8080 within the container to the outside on the same port 8080. This is the port our example server is listenining on.
193
-
- The `--name` flag allows us to give a named identifier to the container. This allows us to reference this container by name as a host instead of by IP address. This will be critical when we run the locust container.
209
+
- The `-p` flag exposes the container's port 8080 on localhost as port 8080. This is the port our example server is listening on.
210
+
- The `--name` flag allows us to give a named identifier to the container. This allows us to reference this container by name as a host instead of by IP address. This will be critical when we run the Locust container.
194
211
- The `--network` argument tells Docker to use our custom network for this container.
195
212
196
-
Since we exposed and mapped port 8080, you can test that our server is working by visiting http://localhost:8080.
213
+
**NOTE:** If you get the following error, stop the `example_server` we started previously (or any other services on port 8080).
197
214
198
-
Once you've verified that our example server container is running we can now build and run our Locust container. FYI if you ran Locust locally earlier you can re-run the same tests again now. Just point at the container version of our example server with the following `locust -f locustfile.py --host=http://localhost:8080`.
215
+
docker: Error response from daemon: driver failed programming external connectivity on endpoint exampleserver (...): Error starting userland proxy: Bind for 0.0.0.0:8080 failed: port is already allocated.
216
+
217
+
218
+
Since we exposed and mapped port 8080, you can test that our server is working by visiting [http://localhost:8080](http://localhost:8080).
219
+
220
+
Once you've verified your example server container is running, you can now build and run your Locust container.
199
221
200
222
## Locust Container
201
223
202
224
Building and running our locust container is similar to the process we used for our example server. First we build the container image with the following:
203
225
204
226
$ docker build docker -t locust-tasks
205
227
206
-
This uses the `Dockerfile` in our `docker` directory. That file consists of:
228
+
This builds the `Dockerfile` located in our `docker` directory. That file consists of:
# Add the external tasks directory into /locust-tasks
214
236
RUN mkdir locust-tasks
215
237
ADD locust-tasks /locust-tasks
216
238
WORKDIR /locust-tasks
@@ -227,9 +249,9 @@ This uses the `Dockerfile` in our `docker` directory. That file consists of:
227
249
# Start Locust using LOCUS_OPTS environment variable
228
250
ENTRYPOINT ["./run.sh"]
229
251
230
-
A note: as you can see, this container doesn't run Locust directly but instead uses a `run.sh` file which lives in `docker/locust-tasks`. This file is important for part 2 of our tutorial, when we will run locust in a distributed mode.
252
+
A note: this container doesn't run Locust directly but instead uses a `run.sh` file which lives in `docker/locust-tasks`. This file is important for part 2 of our tutorial where we will run locust in a distributed mode.
231
253
232
-
We will discuss quickly one import part of that file. Looking at the contents of that file:
254
+
We will briefly discuss one import part of the `run.sh` file:
@@ -245,58 +267,67 @@ We will discuss quickly one import part of that file. Looking at the contents of
245
267
246
268
$LOCUST $LOCUS_OPTS
247
269
248
-
You see that we rely on an environment variable named `$TARGET_HOST`to be the host url passed into our locustfile. This is what will allow us to communicate across containers within our Docker network. Let's look at how we do that.
270
+
We rely on an environment variable named `$TARGET_HOST`being passed into our locustfile. This is key for us to communicate across containers within our Docker network.
249
271
250
-
With that container built we can run it with a similar command as our dev server.
272
+
With our container built, we can run it with a similar command as our example service.
251
273
252
-
$ docker run -it -p=8089:8089 -e "TARGET_HOST=http://exampleserver:8080" --network=locustnw locust-tasks:latest
274
+
$ docker run -it -p=8089:8089 \
275
+
-e "TARGET_HOST=http://exampleserver:8080" \
276
+
--network=locustnw locust-tasks:latest
253
277
254
-
Once again we're exposing a port but this time it's port `8089`, the default locust port. We pass the same network command to ensure this container also runs on our custom Docker network. However: one additional argument we pass in is `-e`. This is the argument for passing environment variables in to the Docker container. In this case we're passing in `http://exampleserver:8080` as the variable `TARGET_HOST`. So now we can see how the `$TARGET_HOST` environment variable in our `run.sh` script comes into play. We also see how the custom Docker network and named containers allows us to use `exampleserver` as the host name versus attempting to find the containers IP address and passing that in. This simplifies things a great deal.
278
+
Once again we're exposing a port but this time it's port `8089`, the default locust port. We pass the network name to ensure this container also runs on our custom `locustnw`network.
255
279
256
-
Now that we have our locust server running we can visit http://localhost:8089 in a browser on our local machine to run locust via a container hitting our dev server also running within a container.
280
+
We also pass an additional argument: `-e`. This argument sets environment variables inside the Docker container. In this case we're passing in `http://exampleserver:8080` as the variable `TARGET_HOST`. This is how the `$TARGET_HOST` environment variable needed by our `run.sh` script is set. We also see how the custom Docker network and named containers allow us to use `exampleserver` as the host name versus attempting to find the containers IP address and passing that in. This simplifies things a great deal.
281
+
282
+
Now that we have our locust server running we can visit [http://localhost:8089](http://localhost:8089) in a browser on our local machine. This connects to our container which will test against our example server, also running within a container.
257
283
258
284
$ open http://localhost:8089
259
285
260
286
# Deployment
261
287
262
-
We can obviously install Locust directly on any machine we'd like. Whether on bare metal, a VM, or in our case we're going to use [Docker](https://www.docker.com/) and [Google Container Engine (GKE)](https://www.docker.com/).
288
+
We can install Locust directly on any machine we'd like. Bare metal, a VM, or, in our case, we're going to install into a [Docker](https://www.docker.com/)container and deploy the container to [Google Container Engine (GKE)](https://cloud.google.com/container-engine/).
263
289
264
290
## Google Container Engine
265
291
266
292
### Prerequisites
267
293
268
294
* Google Cloud Platform account
269
295
* Install and setup [Google Cloud SDK](https://cloud.google.com/sdk/)
296
+
** Be sure to run `$ gcloud init` after installing `gcloud`.
270
297
271
298
**Note:** when installing the Google Cloud SDK you will need to enable the following additional components:
272
299
273
-
*`Compute Engine Command Line Interface`
274
-
*`kubectl`
300
+
*[`Compute Engine Command Line Interface`](https://cloud.google.com/compute/docs/gcloud-compute/)
Set an environment variable to the cloud project you will be using:
304
+
305
+
$ export $PROJECTID
275
306
276
-
Before continuing, you can also set your preferred zone and project:
307
+
Before continuing, you can also [set your preferred zone and project](https://cloud.google.com/container-engine/docs/quickstart#optional_run_this_tutorial_locally_with_gcloud):
277
308
278
309
$ gcloud config set compute/zone ZONE
279
-
$ gcloud config set project PROJECT-ID
310
+
$ gcloud config set project $PROJECTID
280
311
281
312
### Deploying our example container
282
313
283
-
You can use the directions directly from the [Google Container Engine Quickstart](https://cloud.google.com/container-engine/docs/quickstart)or follow what we have below.
314
+
We have summarized the key steps needed to deploy a container from the [Google Container Engine Quickstart](https://cloud.google.com/container-engine/docs/quickstart)below. If you would like a more thorough walkthrough, view the quickstart guide.
284
315
285
-
First up we're going to create a cluster on GKE for our container to run in:
Then we want to give a new tag to our example container that matches where we will be pushing it in the [Google Container Registry](https://cloud.google.com/container-registry/). The Google Container Registry is Google's hosted Docker Registry. You can use any Docker registry that you'd prefer.
290
321
291
-
$ docker tag goexample gcr.io/PROJECT-ID/goexample
322
+
$ docker tag goexample gcr.io/$PROJECTID/goexample
292
323
293
324
Now that we've tagged our image we can push it to the registry with the following:
$ kubectl run example-node --image=gcr.io/PROJECT-ID/goexample:latest --port=8080
330
+
$ kubectl run example-node --image=gcr.io/$PROJECTID/goexample:latest --port=8080
300
331
301
332
This is a similar command to our local Docker commands where we give it a name and expose a port. In this case however we're using `kubectl` which is the [Kubernetes Command Line Inteface](https://kubernetes.io/docs/user-guide/kubectl-overview/).
0 commit comments