Skip to content

Commit

Permalink
Run benchmarker containers without docker-compose
Browse files Browse the repository at this point in the history
We continue to use docker-compose, but it is now running
the infrastructure. Containers are launched from the rq
container via the docker Python library.

Broker benchmarking is now definitely not working.
  • Loading branch information
awelzel committed Sep 18, 2023
1 parent 759e533 commit aee83c0
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 125 deletions.
94 changes: 0 additions & 94 deletions ci-based/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,97 +98,3 @@ services:
- "-m"
- "http.server"
restart: always



zeek-base:
container_name: zeek
build:
context: .
dockerfile: Dockerfile
cap_add:
- SYS_NICE
security_opt:
- "seccomp:./zeek-seccomp.json"
environment:
- TMPFS_PATH=/mnt/data/tmpfs
- ZEEKCPUS=${ZEEKCPUS}
- ZEEKSEED=/benchmarker/random.seed
- ZEEKBIN=/zeek/install/bin/zeek
- DATA_FILE_NAME=${DATA_FILE_NAME:-}
- BENCH_COMMAND=${BENCH_COMMAND:-}
- BENCH_ARGS=${BENCH_ARGS:-}
volumes:
- test_data:/test_data:ro
# - ./scripts:/benchmarker/scripts:ro
tmpfs: /mnt/data/tmpfs
networks:
- zeek-internal
command: /benchmarker/scripts/run-zeek.sh

# Environment variables that need to be set in the host environment running docker-compose:
# - BUILD_FILE_PATH
# if remote: set to path where $BUILD_FILE_NAME is stored
# if local: set to install path of zeek
# - BUILD_FILE_NAME (if remote, set to blank if local)
# if remote: set to filename of tgz file with build
# if local: set to blank
# - DATA_FILE_NAME
zeek-remote:
extends: zeek-base
environment:
- IS_LOCAL=0
- BUILD_FILE_NAME=${BUILD_FILE_NAME}
volumes:
- ${BUILD_FILE_PATH}:/benchmarker/binaries:ro
- zeek_install_data:/zeek/install

zeek-local:
extends: zeek-base
environment:
- IS_LOCAL=1
- DATA_FILE_NAME=${DATA_FILE_NAME}
volumes:
- ${BUILD_FILE_PATH}:/benchmarker/zeek/install:ro

broker-base:
container_name: broker
build:
context: .
dockerfile: Dockerfile
cap_add:
- SYS_NICE
security_opt:
- "seccomp:./zeek-seccomp.json"
environment:
- TMPFS_PATH=/mnt/data/tmpfs
- DATA_FILE_NAME=${DATA_FILE_NAME}
volumes:
- broker_test_data:/test_data:ro
- ./scripts:/benchmarker/scripts:ro
tmpfs: /mnt/data/tmpfs
command: /benchmarker/scripts/run-broker.sh

# Environment variables that need to be set in the host environment running docker-compose:
# - BUILD_FILE_PATH
# if remote: set to path where $BUILD_FILE_NAME is stored
# if local: set to install path of broker
# - BUILD_FILE_NAME (if remote, set to blank if local)
# if remote: set to filename of tgz file with build
# if local: set to blank
# - DATA_FILE_NAME
broker-remote:
extends: broker-base
environment:
- IS_LOCAL=0
- BUILD_FILE_NAME=${BUILD_FILE_NAME}
volumes:
- ${BUILD_FILE_PATH}:/benchmarker/binaries:ro

broker-local:
extends: broker-base
environment:
- IS_LOCAL=1
- DATA_FILE_NAME=${DATA_FILE_NAME}
volumes:
- ${BUILD_FILE_PATH}:/benchmarker/broker/install:ro
2 changes: 0 additions & 2 deletions ci-based/scripts/tiny-benchmark.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
# prefixed with nice and taskset under timeout and that's it.
#
set -eux
echo ${ZEEKBIN}
echo ${ZEEKCPUS}
NICE_ADJUSTMENT=${NICE_ADJUSTMENT:--19}
KILL_TIMEOUT=${KILL_TIMEOUT:-300}

Expand Down
123 changes: 94 additions & 29 deletions ci-based/zeek_benchmarker/tasks.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import dataclasses
import errno
import hashlib
import json
import logging
import os
import os.path
import pathlib
import re
import shlex
import shutil
import subprocess
import typing

import docker
Expand Down Expand Up @@ -60,31 +60,83 @@ def get() -> "ContainerRunner":
def __init__(self, client: docker.client.DockerClient = None):
self._client = client or docker.from_env()

def build_env(self, job: "Job", **kwargs) -> Env:
env = {
"BUILD_FILE_PATH": job.job_dir,
"BUILD_FILE_NAME": job.build_filename,
**kwargs,
def runc(
self,
*,
image: str,
command: str,
env: Env,
seccomp_profile: dict[str, any], # contents of the seccomp profile
install_volume: str,
install_target: str,
timeout: float = None,
cap_add: typing.Optional[list[str]] = None,
tmpfs: typing.Optional[list[str]] = None,
network_disabled: bool = True,
):
"""
Run the given image for benchmarking, mounting
install_volume at install_target.
"""
# Don't modify the caller's env.
env = env.copy()

# Ensure the image exists locally.
self._client.images.get(image)

class Result(typing.NamedTuple):
returncode: int
stdout: bytes
stderr: bytes

cap_add = cap_add or ["SYS_NICE"]
default_tmpfs_path = "/mnt/data/tmpfs"
tmpfs = tmpfs or {
default_tmpfs_path: "",
}

return env
if not tmpfs:
env["TMPFS_PATH"] = default_tmpfs_path

def run(self, target: str, env: Env, timeout: float = None):
return subprocess.run(
[
"docker-compose",
"up",
"--no-log-prefix",
"--force-recreate",
target,
],
env=env,
# capture_output=True,
stdout=subprocess.PIPE,
check=False,
timeout=timeout,
mounts = [
docker.types.Mount(
type="volume",
source=install_volume,
target=install_target,
)
]

security_opt = [
f"seccomp={json.dumps(seccomp_profile)}",
]

container = self._client.containers.run(
image=image,
command=command,
detach=True,
cap_add=cap_add,
environment=env,
tmpfs=tmpfs,
mounts=mounts,
security_opt=security_opt,
network_disabled=network_disabled,
)

try:
wait = container.wait()
stdout_bytes = container.logs(stdout=True, stderr=False)
stderr_bytes = container.logs(stdout=False, stderr=True)
result = Result(wait.get("StatusCode", 99), stdout_bytes, stderr_bytes)
logger.debug(
"runc: returndcode=%s stdout=%s stderr=%s",
result.returncode,
result.stdout,
result.stderr,
)
return result
finally:
container.remove(force=True)

def unpack_build(
self,
build_path: pathlib.Path,
Expand Down Expand Up @@ -138,7 +190,7 @@ def unpack_build(
# If the spool directory is backed by a volume (when this code
# is running within docker-compose), need to use a volume mount
# because the paths within the container are meaningless to the
# docker daemon for bind-mounts.
# docker daemon running on the host for bind-mounts.
spool_volume = os.getenv("SPOOL_VOLUME")
if spool_volume:
source_mount = docker.types.Mount(
Expand Down Expand Up @@ -342,26 +394,38 @@ def run_zeek_test(self, t):
cr = ContainerRunner.get()
cfg = config.get()

extra_env = {
env = {
"BENCH_TEST_ID": t.test_id,
"ZEEKCPUS": cfg.zeek_cpus,
"ZEEKBIN": "/zeek/install/bin/zeek",
"ZEEKSEED": "/benchmarker/random.seed",
}

if t.bench_command and t.bench_args:
extra_env["BENCH_COMMAND"] = t.bench_command
extra_env["BENCH_ARGS"] = t.bench_args
env["BENCH_COMMAND"] = t.bench_command
env["BENCH_ARGS"] = t.bench_args

if t.pcap:
extra_env["DATA_FILE_NAME"] = t.pcap
env["DATA_FILE_NAME"] = t.pcap

env = ContainerRunner.get().build_env(self, **extra_env)
# TODO: Make configurable.
with open("./zeek-seccomp.json", "rb") as fp:
seccomp_profile = json.load(fp)

store = storage.get()
for i in range(1, t.runs + 1):
logger.debug("Running %s:%s (%d)", self.job_id, t.test_id, i)

try:
proc = cr.run("zeek-remote", env)
proc = cr.runc(
image="zeek-benchmarker-zeek-runner",
command="/benchmarker/scripts/run-zeek.sh",
env=env,
seccomp_profile=seccomp_profile,
install_volume=self.install_volume,
install_target="/zeek/install",
)

result = ZeekTestResult.parse_from(i, proc.stdout)
logger.info(
"Completed %s:%s (%d) result=%s", self.job_id, t.test_id, i, result
Expand All @@ -378,7 +442,6 @@ def run_zeek_test(self, t):
proc.stdout,
proc.stderr,
)
return

def _process(self):
cfg = config.get()
Expand Down Expand Up @@ -425,6 +488,8 @@ def _process(self):
import io
import sqlite3

raise NotImplementedError("XXX this needs a re-work")

cr = ContainerRunner.get()
env = cr.build_env(self)
proc = cr.run("broker-remote", env)
Expand Down

0 comments on commit aee83c0

Please sign in to comment.