Git Product home page Git Product logo

gosbench's Introduction

Gosbench

Gosbench is the Golang reimplementation of Cosbench. It is a distributed S3 performance benchmark tool with Prometheus exporter leveraging the official Golang AWS SDK

Usage

Gosbench consists of two parts:

  • Server: Coordinates Workers and general test queue
  • Workers: Actually connect to S3 and perform reading, writing, deleting and listing of objects

INFO: -d activates debug logging, -t activates trace logging

Running a test

  1. Build the server: go install github.com/mulbc/gosbench/server
  2. Run the server, specifying a config file: server -c path/to/config.yaml - you can find an example config in the example folder
  3. The server will open port 2000 for workers to connect to - make sure this port is not blocked by your firewall!
  4. Build the worker: go install github.com/mulbc/gosbench/worker
  5. Run the worker, specifying the server connection details: worker -s 192.168.1.1:2000
  6. The worker will immediately connect to the server and will start to get to work. The worker opens port 8888 for the Prometheus exporter. Please make sure this port is allowed in your firewall and that you added the worker to the Prometheus config.

Prometheus configuration

Make sure your prometheus configuration looks similar to this:

global:
  scrape_interval:     15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
scrape_configs:
  - job_name: 'prometheus'
    static_configs:
    - targets:
        - localhost:9090

  - job_name: 'gosbench'
    scrape_interval: 1s
    static_configs:
      - targets:
        - WORKER1.example.com:8888
        - WORKER2.example.com:8888

To reload the configuration, you can either send a SIGHUP to your prometheus server or just restart it ;) Afterwards ensure that you have your Gosbench workers listed at http://your.prometheus.server.example.com:9090/targets

It is expected that the workers are in state DOWN most of the time... they are only scrapeable during a test run.

It is Best Practice to run the Prometheus Node Exporter on all hosts as well, to gather common system metrics during the tests. This will help you in identifying bottlenecks. Please consult the Node Exporter manuals on how to install and configure it on your platform.

Evaluating a test

During a test, Prometheus will scrape the performance data continuously from the workers. You can visualize this data in Grafana. To get an overview of what the provided data looks like, check out the example scrape.

There is also an example Grafana dashboard that you can import and use. The Dashboard has some basic overview of the most common stats that people are interested in:

Gosbench Dashboard in action

Docker

There are now Docker container images available for easy consumption:

docker pull quay.io/mulbc/goroom-server
docker pull quay.io/mulbc/goroom-worker

In the k8s folder you will find example files to deploy Gosbench on Openshift and Kubernetes. Be sure to modify the ConfigMaps in gosbench.yaml to use your S3 endpoint credentials.

Reading pre-existing files from buckets

Due to popular demand, reading pre-existing files have been added. You activate this special mode by setting existing_read_weight to something higher than 0.

There are some important things to consider though ;)

Just like with other operations, the bucket_prefix value will be evaluated to determine the bucket name to search for pre-existing objects.

Example: This is an excerpt of your config:

    objects:
      size_min: 5
      size_max: 100
      part_size: 0
      # distribution: constant, random, sequential
      size_distribution: random
      unit: KB
      number_min: 10
      number_max: 100
      # distribution: constant, random, sequential
      number_distribution: constant
    buckets:
      number_min: 2
      number_max: 10
      # distribution: constant, random, sequential
      number_distribution: constant
    bucket_prefix: myBucket-

Note: Due to the constant distribution, we will only consider the _min values.

This will cause each workers to search for pre-existing files in the buckets myBucket-0 and myBucket-1 and read 10 objects from these buckets. If there are less than 10 objects in any of these buckets, some objects will be read multiple times. The object size given in your config will be ignored when reading pre-existing files.

Cosbench vs Gosbench benchmark comparision

When a new tool is presented, it’s essential to compare it to existing tools for accuracy. For this reason, we ran a comparision between Cosbench and Gosbench. Both benchmarks were tasked to do a 100% write test and 100% read test on 4KB, 16KB, 256KB, 1MB, 4MB objects for 60 seconds each. The tests were to run on one RGW using S3 protocol in ceph storage clusteri, also run in the test configuration in parallel. Figure below show writing and reading, respectively. From these charts, it’s apparent that the performance metrics for all objects are similar for both tools.

Latency

Bandwidth

Contributing

  • Be aware that this repo uses pre-commit hooks - install them via pre-commit install
  • We are using Go modules in this repository - read up on it here
  • Check out the open TODOs for hints on what to work on

Known issues

  • Workers will error out when the config's min value is larger than the max value (even for a constant distribution)

gosbench's People

Contributors

microyahoo avatar mulbc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

gosbench's Issues

Image requested in deployment is private

Describe the bug

Deployment in yaml cannot continue due to quay.io/mulbc/goroom being a private image

To Reproduce

  1. Apply yaml in cluster
  2. Pod cannot start due to private goroom-app image

Expected behavior

Expected pod to start based on publicly accessible image

Screenshots

image

Environment (please complete the following information):

  • OS: MacOS Monterey

IsTruncated not checked after ListObjects

Describe the bug
IsTruncated not checked after ListObjects.

To Reproduce
Steps to reproduce the behavior:
ListObjects may be Truncated when too many objects.

result, err := service.ListObjects(&s3.ListObjectsInput{

result.IsTruncated should be checked

Expected behavior
List all objects rather than truncated

Add notification “found worker 1 of N”

When workers connect to the server, add a message that says how many workers are left until we can start with the current test.
Currently the server just silently waits until enough workers have connected. This can be confusing for new users.

Make the server port an argument

Add an argument to the server to specify the listening port. That way one can have multiple servers running in parallel on one server.

object is wrong for fuc EvaluateDistribution

Describe the bug
When config objects number_distribution: sequential and number_min: 1, only 1 object writes many times

To Reproduce
Steps to reproduce the behavior:
Only fill 1 op when number_distribution is sequential from number_min value 1

for object := uint64(0); object < objectCount; object++ {

Expected behavior
Obj name should increment from number_min to number_max

Func common.EvaluateDistribution shouldn't means bucketCount and bucket should not start from uint64(0).
fillWorkqueue to fill works in the test in advance and then workUntilTimeout seems logically inaccurate

panic: reflect: reflect.Value.SetInt using unaddressable value [recovered] with stop_with_runtime parameter

Describe the bug
When setting the parameter stop_with_runtime with a value, it give a error

To Reproduce
Steps to reproduce the behavior:

  1. Config a yaml with the value: "stop_with_runtime: 900s" for example
  2. Start server with yaml
  3. See error
    [root@server bin]# ./server -c /root/s3-config2.yaml
    panic: reflect: reflect.Value.SetInt using unaddressable value [recovered]
    panic: reflect: reflect.Value.SetInt using unaddressable value [recovered]
    panic: reflect: reflect.Value.SetInt using unaddressable value

goroutine 1 [running]:
gopkg.in/yaml%2ev3.handleErr(0xc0000dfd28)
/root/go/pkg/mod/gopkg.in/[email protected]/yaml.go:294 +0x6d
panic({0x552cc0, 0xc000094fc0})
/usr/lib/golang/src/runtime/panic.go:838 +0x207
gopkg.in/yaml%2ev3.handleErr(0xc0000ded90)
/root/go/pkg/mod/gopkg.in/[email protected]/yaml.go:294 +0x6d
panic({0x552cc0, 0xc000094fc0})
/usr/lib/golang/src/runtime/panic.go:838 +0x207
reflect.flag.mustBeAssignableSlow(0x40bee7?)
/usr/lib/golang/src/reflect/value.go:262 +0x85
reflect.flag.mustBeAssignable(...)
/usr/lib/golang/src/reflect/value.go:249
reflect.Value.SetInt({0x56cfa0?, 0x67bdc0?, 0x1?}, 0xd18c2e2800)
/usr/lib/golang/src/reflect/value.go:2163 +0x48
gopkg.in/yaml%2ev3.(*decoder).scalar(0x56cfa0?, 0xc0000f8a00, {0x56cfa0?, 0x67bdc0?, 0x0?})
/root/go/pkg/mod/gopkg.in/[email protected]/decode.go:647 +0xa54
gopkg.in/yaml%2ev3.(*decoder).unmarshal(0xc0000bd650, 0xc0000f8a00, {0x56cfa0?, 0x67bdc0?, 0x0?})
/root/go/pkg/mod/gopkg.in/[email protected]/decode.go:505 +0x385
gopkg.in/yaml%2ev3.(*decoder).callObsoleteUnmarshaler.func1({0x56cfa0?, 0x67bdc0?})
/root/go/pkg/mod/gopkg.in/[email protected]/decode.go:378 +0x125
github.com/mulbc/gosbench/common.(*Duration).UnmarshalYAML(0xc0000e4420, 0xc0000be160)
/root/go/pkg/mod/github.com/mulbc/[email protected]/common/configFile.go:246 +0x39
gopkg.in/yaml%2ev3.(*decoder).callObsoleteUnmarshaler(0xc0000bd650, 0xc0000f8a00, {0x7f06c85eb838, 0xc0000e4420})
/root/go/pkg/mod/gopkg.in/[email protected]/decode.go:376 +0xa7
gopkg.in/yaml%2ev3.(*decoder).prepare(0x559d80?, 0xc0000e4420?, {0x559d80?, 0xc0000e4420?, 0xc000094cc0?})
/root/go/pkg/mod/gopkg.in/[email protected]/decode.go:424 +0x228
gopkg.in/yaml%2ev3.(*decoder).unmarshal(0xc0000bd650, 0xc0000f8a00, {0x559d80?, 0xc0000e4420?, 0xc0000df008?})
/root/go/pkg/mod/gopkg.in/[email protected]/decode.go:499 +0x255
gopkg.in/yaml%2ev3.(*decoder).mappingStruct(0xc0000bd650, 0xc0000b4e60, {0x575920?, 0xc0000e4360?, 0xc0000df270?})
/root/go/pkg/mod/gopkg.in/[email protected]/decode.go:932 +0xd1b
gopkg.in/yaml%2ev3.(*decoder).mapping(0xc0000bd650, 0xc0000b4e60, {0x575920?, 0xc0000e4360?, 0x7f06c85e17e8?})
/root/go/pkg/mod/gopkg.in/[email protected]/decode.go:783 +0xbe
gopkg.in/yaml%2ev3.(*decoder).unmarshal(0xc0000bd650, 0xc0000b4e60, {0x54c880?, 0xc0000a80d0?, 0xc0000a2120?})
/root/go/pkg/mod/gopkg.in/[email protected]/decode.go:507 +0x3a5
gopkg.in/yaml%2ev3.(*decoder).sequence(0x54f8a0?, 0xc0000b4dc0, {0x54f8a0?, 0xc0000c0260?, 0xc000094a30?})
/root/go/pkg/mod/gopkg.in/[email protected]/decode.go:750 +0x26f
gopkg.in/yaml%2ev3.(*decoder).unmarshal(0xc0000bd650, 0xc0000b4dc0, {0x54f8a0?, 0xc0000c0260?, 0x0?})
/root/go/pkg/mod/gopkg.in/[email protected]/decode.go:509 +0x34f
gopkg.in/yaml%2ev3.(*decoder).mappingStruct(0xc0000bd650, 0xc0000b45a0, {0x566680?, 0xc0000c0240?, 0xc0000df958?})
/root/go/pkg/mod/gopkg.in/[email protected]/decode.go:932 +0xd1b
gopkg.in/yaml%2ev3.(*decoder).mapping(0xc0000bd650, 0xc0000b45a0, {0x566680?, 0xc0000c0240?, 0x0?})
/root/go/pkg/mod/gopkg.in/[email protected]/decode.go:783 +0xbe
gopkg.in/yaml%2ev3.(*decoder).unmarshal(0xc0000bd650, 0xc0000b45a0, {0x566680?, 0xc0000c0240?, 0xc0000dfc60?})
/root/go/pkg/mod/gopkg.in/[email protected]/decode.go:507 +0x3a5
gopkg.in/yaml%2ev3.(*decoder).document(0x566680?, 0xc0000c0240?, {0x566680?, 0xc0000c0240?, 0xc000086400?})
/root/go/pkg/mod/gopkg.in/[email protected]/decode.go:524 +0x5d
gopkg.in/yaml%2ev3.(*decoder).unmarshal(0xc0000bd650, 0xc0000b4500, {0x566680?, 0xc0000c0240?, 0xc0000dfcf0?})
/root/go/pkg/mod/gopkg.in/[email protected]/decode.go:495 +0x415
gopkg.in/yaml%2ev3.unmarshal({0xc0000e8000, 0x31b, 0x31c}, {0x54c8c0?, 0xc0000c0240}, 0x40?)
/root/go/pkg/mod/gopkg.in/[email protected]/yaml.go:167 +0x406
gopkg.in/yaml%2ev3.Unmarshal(...)
/root/go/pkg/mod/gopkg.in/[email protected]/yaml.go:89
main.loadConfigFromFile({0xc0000e8000, 0x31b, 0x31c})
/root/go/pkg/mod/github.com/mulbc/[email protected]/server/main.go:56 +0x1f5
main.main()
/root/go/pkg/mod/github.com/mulbc/[email protected]/server/main.go:77 +0xb1

Config

s3_config:

  • access_key: **************
    secret_key: khNE=****************
    region: eu-central-1
    endpoint: ****************

tests:

  • name: read test
    read_weight: 100
    existing_read_weight: 0
    write_weight: 0
    delete_weight: 0
    list_weight: 0
    objects:
    size_min: 1
    size_max: 100000
    part_size: 0
    size_distribution: random
    unit: KB
    number_min: 10
    number_max: 10
    number_distribution: constant
    buckets:
    number_min: 1
    number_max: 10
    number_distribution: constant
    bucket_prefix: 1255gosbenchobject_
    prefix: obj
    stop_with_runtime: 900s
    stop_with_ops:
    workers: 2
    workers_share_buckets: True
    parallel_clients: 3
    clean_after: True
    ...

Without 900s as value, the server works

Environment (please complete the following information):

  • OS: Red Hat Enterprise Linux release 8.7 (Ootpa)
  • Golang version go version go1.18.9 linux/amd64
  • No firewall

Implement workers_share_buckets

Implement the config option workers_share_buckets.
This should remove the workerID prefix for buckets when accessing them as a worker in the tests.

Preparations finished - waiting on server to start work

Hi! Thanks for the tool, I faced an issue after creating buckets worker stuck with this message:

INFO[2020-10-19T10:39:47+03:00] Preparations finished - waiting on server to start work

What can be wrong? Is it a config file problem probably?
Here is config file: https://gist.github.com/ushacow/6459dfb1d578f5079e5c0a579d011930

UPD: Actually gosbench created objects now, but I cannot see metrics, there is a just blank page in ip:8888/metrics page
UPD2: I can see metrics, but they almost all equal to 0

grafana error

how can i deal with it?
image

grafana compose.yml

  grafana:
   image: grafana/grafana
   ports:
     - 13000:3000
   volumes:
     - ./grafana/:/etc/grafana/provisioning/
     - /home/trz/hdd/monitor/grafana_data:/var/lib/grafana
       #environment:
     #- GF_INSTALL_PLUGINS=camptocamp-prometheus-alertmanager-datasource
   links:
     - prometheus:prometheus
     - alertmanager:alertmanager
   restart: always

ServiceAccount name differentiates, causes error when applying yaml

Working with Natale to debug these errors, this happened on his cluster, but I just reran on mine and didn't experience anything. Keeping here for now, will retry later.

Describe the bug

Due to a ServiceAccount name difference in the generated yaml, causes an error when applying yaml file.

To Reproduce
Steps to reproduce the behavior:

  1. Apply generated yaml file in OpenShift cluster
  2. Error due to mismatch of ServiceAccount name

Expected behavior

Expected to apply yaml file and workshop begin to start

Screenshots
If applicable, add screenshots to help explain your problem.

Environment (please complete the following information):

  • OS: Mac
  • OpenShift 4.11.7

Additional context
Here's the specific difference that caused the error:

###
# Code generated by goroom.blum.coffee
# This can be used directly with "oc apply -f" or "kubectl apply -f"
#   to deploy a goroom environment
###

apiVersion: v1
kind: Namespace
metadata:
  name: default
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: gosbench-role <--
  namespace: default
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: gosbench-role-binding
subjects:
  - kind: ServiceAccount
    name: gosbench-role
    namespace: default
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: Service
metadata:
  name: goroom-app
  namespace: default
  labels:
    app: goroom-app
spec:
  # type: NodePort
  ports:
    - port: 8080
      name: goroom-app
  selector:
    app: goroom-app
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: goroom-app
  namespace: default
  labels:
    app: goroom-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: goroom-app
  template:
    metadata:
      labels:
        app: goroom-app
    spec:
      serviceAccountName: k8s-101-role <--
...

Add tests that read existing data from a bucket

A couple of people asked me to add a test type that would read pre-existing data from a bucket instead of running through the prepare step.

With this, we would potentially take the bucket_prefix as full bucket name, assume workers_share_buckets is True and in the prepare step scan for already existing files, then add them to the job queue.

Additionally I would add a existing_read_weight to the config that would weight the amount of reading existing files in the bucket. This way a mix of reading pre-existinng writes, listing & writing would still be possible...

Can't curl yaml file needed for oc/kubectl

Describe the bug

Initial curl command to download the yaml file isn't downloading to local directory

To Reproduce
Steps to reproduce the behavior:

  1. Used example curl command from web app: curl --fail 'http://goroom.blum.coffee/ocp?gitSource=https://github.com/red-hat-storage/ocs-training.git&gitBranch=master&namespace=default'
  2. Refreshed directory to see if new .yaml file appears, no file does

Expected behavior

Expected to see new yaml file based on parameters

Screenshots

Screen Shot 2022-11-24 at 10 29 07 PM

Environment (please complete the following information):

  • OS: MacOS Monterry

Add job names

Is your feature request related to a problem? Please describe.
For Grafana Annotations and for logging I want to name tests so that I can easily reference them

Describe the solution you'd like
Add name field to the array of tests

Worker ends in FATAL after all tests are done

When the server has processed all tests, it closes down. The clients always try to reconnect, but now the server is unreachable and the workers fail with an error message.
Solution: Add a signal for the workers, letting them know not to reconnect, but to shut down as well.

Bucket Deletion Failing

I'm consistently receiving this message as my test runs end:

Error during bucket deleting - ignoring error="BatchedDeleteIncomplete: some objects have failed to be deleted.\ncaused by: failed to perform batch operation on \"\" to \"\":\nNoSuchBucket: The specified bucket does not exist\n\tstatus code: 404, request id: 167E6C0CDDE87D15, host id: "

Not really sure why. Sometimes the bucket does remain on my storage system (when that error is repeated 10 times), other times there are fewer than 10 of those entries and the bucket is gone.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.