feat: test bench

pull/24376/head
Marco Neumann 2021-11-25 18:14:40 +01:00
parent 524dfa8ce2
commit f2f090bde7
13 changed files with 628 additions and 0 deletions

View File

@ -73,6 +73,7 @@ exclude = [
"massif.out.*",
"perf/",
"scripts/",
"test_bench/",
"test_fixtures/",
"tools/",
]

57
test_bench/README.md Normal file
View File

@ -0,0 +1,57 @@
# Test Bench
The test bench makes it easier to stage deployment scenarios to:
- experiment and test with novel multi-node architectures
- simulate workarounds beyond what is possible on developer machines
- test complex interplay between components
## Architecture
The test bench is meant to run in [Kubernetes]. To create different test setups or to customize a setup to a specific
cluster we use [Kustomize]. The [Kustomize] configs can be found in `k8s/`.
To glue IOx to [Kubernetes] we need some helper code which can be found under `glue/`.
## Getting Started
First you need to build an image with the glue code:
```console
$ cd glue
$ docker build -t iox-glue .
$ cd ..
```
Then push the image to some container registry which is accessible by your [Kubernetes] cluster:
```console
$ docker push some.registry.io/foo/iox-glue
```
Next we'll "kustomize" the test bench. You can use `k8s/overlays/demo` as a starting point. There you should at least
have a look at `images-patch.yml` to set the image with the glue code that you've just built. Then you can deploy the
whole thing:
```console
$ kubectl kustomize ./k8s/overlays/demo| kubectl apply -f -
```
Now IOx should be ready for experiments. You might just feed it with some data:
```console
$ # in another terminal:
$ kubectl port-forward service/iox-router-service 8080:8080 8082:8082
$ # in your main terminal:
$ cd ../iox_data_generator/
$ cargo run --release -- \
--spec schemas/cap-write.toml \
--continue \
--host 127.0.0.1:8080 \
--token arbitrary \
--org myorg \
--bucket mybucket
```
[Kustomize]: https://kustomize.io/
[Kubernetes]: https://kubernetes.io/

View File

@ -0,0 +1,14 @@
FROM alpine:latest
ENV CURL_FLAGS="--proto =https --tlsv1.2 -sSf" \
GRPCURL_VERSION="1.8.5"
RUN apk add --no-cache bash curl
RUN curl ${CURL_FLAGS} -Lo grpcurl.tar.gz https://github.com/fullstorydev/grpcurl/releases/download/v${GRPCURL_VERSION}/grpcurl_${GRPCURL_VERSION}_linux_x86_64.tar.gz \
&& tar xvf grpcurl.tar.gz \
&& mv grpcurl /bin
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

119
test_bench/glue/entrypoint.sh Executable file
View File

@ -0,0 +1,119 @@
#!/bin/bash
set -eu -o pipefail
# extract ordinal index from server ID
[[ $HOSTNAME =~ -([0-9]+)$ ]] || (echo "invalid hostname" && exit 1)
ordinal=${BASH_REMATCH[1]}
# calculate server ID
offset="${INFLUXDB_IOX_ID_OFFSET:-0}"
server_id=$((ordinal + offset))
echo "ServerID: $server_id"
# set server ID
while true; do
set +e
grpcurl -d "{\"id\": $server_id}" -allow-unknown-fields -plaintext "$INFLUXDB_IOX_GRPC_BIND_ADDR" influxdata.iox.deployment.v1.DeploymentService.UpdateServerId
status=$?
set -e
if [[ $status == 0 ]]; then
echo "server ID set"
break
else
echo "cannot set server ID yet, waiting..."
sleep 1
fi
done
# wait for rule/config updates
FINGERPRINT_DONE=/fingerprint.done
FINGERPRINT_STAGING=/fingerprint.staging
F_CURRENT=/current
while true; do
# create new fingerprint
rm -rf "$FINGERPRINT_STAGING"
mkdir "$FINGERPRINT_STAGING"
for cfg_file in /iox_config/*; do
# create backup of file so it doesn't change while we're working with it
cp "$cfg_file" "$F_CURRENT"
# determine type
if [[ $cfg_file == *"router"* ]]; then
type="router"
else
type="database"
fi
# compare hash
hash="$(sha256sum "$F_CURRENT" | sed -E 's/([a-f0-9]+).*/\1/g')"
in_sync=0
if [ -f "$FINGERPRINT_DONE/$hash.$type" ]; then
echo "$cfg_file: in-sync"
in_sync=1
else
echo "$cfg_file: out of sync"
# select create/update routing depending on the config type
if [[ $type == "database" ]]; then
echo "Create database..."
set +e
grpcurl -d @ < "$F_CURRENT" -allow-unknown-fields -plaintext "$INFLUXDB_IOX_GRPC_BIND_ADDR" influxdata.iox.management.v1.ManagementService.CreateDatabase
status=$?
set -e
if [[ $status == 0 ]]; then
echo "databse created"
in_sync=1
else
echo "cannot create database, try updating it..."
set +e
grpcurl -d @ < "$F_CURRENT" -allow-unknown-fields -plaintext "$INFLUXDB_IOX_GRPC_BIND_ADDR" influxdata.iox.management.v1.ManagementService.UpdateDatabase
status=$?
set -e
if [[ $status == 0 ]]; then
echo "database updated"
in_sync=1
else
echo "cannot update database"
fi
fi
else
echo "Update router..."
set +e
grpcurl -d @ < "$F_CURRENT" -allow-unknown-fields -plaintext "$INFLUXDB_IOX_GRPC_BIND_ADDR" influxdata.iox.router.v1.RouterService.UpdateRouter
status=$?
set -e
if [[ $status == 0 ]]; then
echo "router updated"
in_sync=1
else
echo "cannot update router"
fi
fi
fi
# store state
if [[ $in_sync == 1 ]]; then
cp "$F_CURRENT" "$FINGERPRINT_STAGING/$hash.$type"
fi
done
# TODO: delete resources that are no longer present, should be done by comparing the list of resources on the server VS the ones in config files by name
# store fingerprints for next round
rm -rf "$FINGERPRINT_DONE"
mkdir "$FINGERPRINT_DONE"
if [ -n "$(ls -A "$FINGERPRINT_STAGING")" ]; then
cp "$FINGERPRINT_STAGING"/* "$FINGERPRINT_DONE"/
fi
sleep 10
done

View File

@ -0,0 +1,29 @@
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: not-important
spec:
template:
spec:
containers:
- name: debug
image: nixery.dev/shell/findutils/gnugrep/gnutar/hexdump/less/mount/procps/curl/grpcurl/binutils/gdb/strace/rustc/linuxpackages.perf/perf-tools/gzip/zstd
command:
- /bin/bash
- -c
- --
args:
- while true; do sleep 30; done;
resources:
requests:
cpu: 1
memory: 1G
limits:
cpu: 1
memory: 2G
securityContext:
capabilities:
add:
- SYS_PTRACE
shareProcessNamespace: true

View File

@ -0,0 +1,15 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- minio.yml
- redpanda.yml
- router.yml
- query.yml
patches:
- path: debug-sidecar-patch.yml
target:
kind: StatefulSet
name: iox-.*

View File

@ -0,0 +1,69 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: minio-deployment
labels:
app: minio
spec:
replicas: 1
selector:
matchLabels:
app: minio
template:
metadata:
labels:
app: minio
spec:
containers:
- name: minio
image: minio/minio:RELEASE.2021-08-05T22-01-19Z
args:
- server
- --address=0.0.0.0:8080
- --console-address=0.0.0.0:8081
- /data
env:
- name: MINIO_ROOT_USER
value: minio
- name: MINIO_ROOT_PASSWORD
value: miniominio
- name: MINIO_PROMETHEUS_AUTH_TYPE
value: public
- name: MINIO_HTTP_TRACE
value: /dev/stdout
volumeMounts:
- name: data
mountPath: /data
initContainers:
- name: create-bucket
image: minio/minio:RELEASE.2021-08-05T22-01-19Z
command:
- /bin/sh
args:
- -c
- mkdir -p /data/iox
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: minio-service
spec:
selector:
app: minio
ports:
- name: s3
protocol: TCP
port: 8080
targetPort: 8080
- name: console
protocol: TCP
port: 8081
targetPort: 8081

View File

@ -0,0 +1,88 @@
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: iox-query-statefulset
spec:
selector:
matchLabels:
app: iox-query
serviceName: "iox-query"
replicas: 2
template:
metadata:
annotations:
kubectl.kubernetes.io/default-container: iox
labels:
app: iox-query
spec:
containers:
- name: iox
env:
- name: INFLUXDB_IOX_SERVER_MODE
value: database
- name: INFLUXDB_IOX_BIND_ADDR
value: 0.0.0.0:8080
- name: INFLUXDB_IOX_GRPC_BIND_ADDR
value: 0.0.0.0:8082
- name: LOG_FILTER
value: info
- name: RUST_BACKTRACE
value: "1"
- name: RUST_LOG
value: info
- name: INFLUXDB_IOX_OBJECT_STORE
value: s3
- name: INFLUXDB_IOX_BUCKET
value: iox
- name: AWS_ACCESS_KEY_ID
value: minio
- name: AWS_SECRET_ACCESS_KEY
value: miniominio
- name: AWS_ENDPOINT
value: http://minio-service:8080
resources:
requests:
cpu: 1
memory: 1G
limits:
cpu: 1
memory: 2G
- name: glue
env:
- name: INFLUXDB_IOX_ID_OFFSET
value: "1"
- name: INFLUXDB_IOX_GRPC_BIND_ADDR
value: 0.0.0.0:8082
resources:
requests:
cpu: 1
memory: 1G
limits:
cpu: 1
memory: 2G
volumeMounts:
- name: config
mountPath: /iox_config
volumes:
- name: config
configMap:
name: iox-query-configs
---
apiVersion: v1
kind: Service
metadata:
name: iox-query-service
spec:
selector:
app: iox-query
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
- name: grpc
protocol: TCP
port: 8082
targetPort: 8082

View File

@ -0,0 +1,45 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: redpanda-deployment
labels:
app: redpanda
spec:
replicas: 1
selector:
matchLabels:
app: redpanda
template:
metadata:
labels:
app: redpanda
spec:
containers:
- name: redpanda
image: vectorized/redpanda:v21.7.6
args:
- redpanda
- start
- --overprovisioned
- --smp=1
- --memory=128M
- --reserve-memory=0M
- --node-id=0
- --check=false
- --kafka-addr=CLIENT://0.0.0.0:9092,EXTERNAL://0.0.0.0:9093
- --advertise-kafka-addr=CLIENT://redpanda-service:9092,EXTERNAL://redpanda-service:9093
---
apiVersion: v1
kind: Service
metadata:
name: redpanda-service
spec:
selector:
app: redpanda
ports:
- name: kafka
protocol: TCP
port: 9093
targetPort: 9093

View File

@ -0,0 +1,78 @@
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: iox-router-statefulset
spec:
selector:
matchLabels:
app: iox-router
serviceName: "iox-router"
replicas: 2
template:
metadata:
annotations:
kubectl.kubernetes.io/default-container: iox
labels:
app: iox-router
spec:
containers:
- name: iox
env:
- name: INFLUXDB_IOX_SERVER_MODE
value: router
- name: INFLUXDB_IOX_BIND_ADDR
value: 0.0.0.0:8080
- name: INFLUXDB_IOX_GRPC_BIND_ADDR
value: 0.0.0.0:8082
- name: LOG_FILTER
value: info
- name: RUST_BACKTRACE
value: "1"
- name: RUST_LOG
value: info
resources:
requests:
cpu: 1
memory: 1G
limits:
cpu: 1
memory: 2G
- name: glue
env:
- name: INFLUXDB_IOX_ID_OFFSET
value: "1000"
- name: INFLUXDB_IOX_GRPC_BIND_ADDR
value: 0.0.0.0:8082
resources:
requests:
cpu: 1
memory: 1G
limits:
cpu: 1
memory: 2G
volumeMounts:
- name: config
mountPath: /iox_config
volumes:
- name: config
configMap:
name: iox-router-configs
---
apiVersion: v1
kind: Service
metadata:
name: iox-router-service
spec:
selector:
app: iox-router
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
- name: grpc
protocol: TCP
port: 8082
targetPort: 8082

View File

@ -0,0 +1,85 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: iox-router-configs
data:
router-1: |
{
"router": {
"name": "myorg_mybucket",
"write_sharder": {
"specific_targets": [
{
"matcher": {
"table_name_regex": ".*"
},
"shard": 1
}
],
"hash_ring": null
},
"write_sinks": {
"1": {
"sinks": [
{
"write_buffer": {
"direction": "DIRECTION_WRITE",
"type": "kafka",
"connection": "redpanda-service:9093",
"connection_config": {},
"creation_config": {
"n_sequencers": 1,
"options": {}
}
},
"ignore_errors": false
}
]
}
},
"query_sinks": null
}
}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: iox-query-configs
data:
database-1: |
{
"rules": {
"name": "myorg_mybucket",
"partition_template": {
"parts": [
{"time": "%Y-%m-%d %H:00:00"}
]
},
"lifecycle_rules": {
"buffer_size_soft": 1073741824,
"buffer_size_hard": 2147483648,
"worker_backoff_millis": 100,
"max_active_compactions": 1,
"persist": true,
"persist_row_threshold": 10000000,
"catalog_transactions_until_checkpoint": 100,
"late_arrive_window_seconds": 300,
"persist_age_threshold_seconds": 1800,
"mub_row_threshold": 100000
},
"routing_config": {"sink": {"kafka": {}}},
"worker_cleanup_avg_sleep": "500s",
"write_buffer_connection": {
"direction": "DIRECTION_READ",
"type": "kafka",
"connection": "redpanda-service:9093",
"connection_config": {},
"creation_config": {
"n_sequencers": 1,
"options": {}
}
}
}
}

View File

@ -0,0 +1,15 @@
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: not-important
spec:
template:
spec:
containers:
- name: iox
image: quay.io/influxdb/iox:main
imagePullPolicy: Always
- name: glue
image: europe-west3-docker.pkg.dev/influxdata-fusion/mneumann-repository-docker-1/iox-glue
imagePullPolicy: Always

View File

@ -0,0 +1,13 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
- configs.yml
patches:
- path: images-patch.yml
target:
kind: StatefulSet
name: iox-.*