@terascope/scripts 2.25.0 → 2.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/helpers/config.d.ts.map +1 -1
- package/dist/src/helpers/config.js +75 -0
- package/dist/src/helpers/config.js.map +1 -1
- package/dist/src/helpers/helm.js +8 -1
- package/dist/src/helpers/helm.js.map +1 -1
- package/dist/src/helpers/images/index.js +3 -3
- package/dist/src/helpers/images/index.js.map +1 -1
- package/dist/src/helpers/test-runner/services.d.ts +1 -0
- package/dist/src/helpers/test-runner/services.d.ts.map +1 -1
- package/dist/src/helpers/test-runner/services.js +278 -5
- package/dist/src/helpers/test-runner/services.js.map +1 -1
- package/dist/src/helpers/test-runner/utils.d.ts.map +1 -1
- package/dist/src/helpers/test-runner/utils.js +9 -0
- package/dist/src/helpers/test-runner/utils.js.map +1 -1
- package/docker/ceph/.env.example +28 -0
- package/docker/ceph/README.md +111 -0
- package/docker/ceph/docker-compose.yml +104 -0
- package/docker/ceph/scripts/common.sh +78 -0
- package/docker/ceph/scripts/mgr.sh +21 -0
- package/docker/ceph/scripts/mon.sh +131 -0
- package/docker/ceph/scripts/osd.sh +48 -0
- package/docker/ceph/scripts/rgw.sh +29 -0
- package/docker/ceph/scripts/setup.sh +55 -0
- package/package.json +4 -3
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Ceph test service
|
|
2
|
+
|
|
3
|
+
A single-node Ceph cluster (1 mon, 1 mgr, 1 OSD, 1 RGW) providing an
|
|
4
|
+
S3-compatible endpoint for tests. The OSD is a BlueStore store on a sparse file,
|
|
5
|
+
so there are no loop devices, no `--privileged`, and nothing touching the host's
|
|
6
|
+
disks.
|
|
7
|
+
|
|
8
|
+
## Under `ts-scripts test`
|
|
9
|
+
|
|
10
|
+
The `opensearch` suite runs Ceph. Any other package opts in by setting
|
|
11
|
+
`TEST_CEPH='true'` in its `test` script.
|
|
12
|
+
|
|
13
|
+
`ensureCeph()` (`src/helpers/test-runner/services.ts`) generates the `.env` file
|
|
14
|
+
in this directory from `src/helpers/config.ts`, runs `up -d`, waits for the
|
|
15
|
+
`setup` script to exit 0, and runs `down -v` on teardown. Tests read
|
|
16
|
+
`CEPH_HOST`, `CEPH_ACCESS_KEY`, and `CEPH_SECRET_KEY` from the environment.
|
|
17
|
+
|
|
18
|
+
It also generates `docker-compose.osds.yml`, an override holding an `osd1`,
|
|
19
|
+
`osd2`... service per `CEPH_OSD_COUNT`, each cloned from the `osd0` block, and
|
|
20
|
+
runs compose with both files. `CEPH_OSD_COUNT=1` (the default) deletes the
|
|
21
|
+
override and runs the base file alone, so there is nothing to generate for the
|
|
22
|
+
common case. Edit `osd0` to change what every OSD gets.
|
|
23
|
+
|
|
24
|
+
**No bucket is pre-created.** The stack gives you an S3 user; every test makes
|
|
25
|
+
whatever buckets it needs and cleans them up.
|
|
26
|
+
|
|
27
|
+
Every `CEPH_*` key in `config.ts` is overridable by an env var of the same name,
|
|
28
|
+
except `CEPH_HOST` and `CEPH_PROTOCOL`, which are derived — set `CEPH_HOSTNAME`
|
|
29
|
+
and `CEPH_PORT` instead.
|
|
30
|
+
|
|
31
|
+
## Standalone
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
cp .env.example .env
|
|
35
|
+
docker compose up -d
|
|
36
|
+
docker compose run --rm toolbox # a shell with ceph / radosgw-admin / rados
|
|
37
|
+
docker compose down -v
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Use **path-style** S3 addressing — virtual-host style needs wildcard DNS.
|
|
41
|
+
|
|
42
|
+
## How addressing works
|
|
43
|
+
|
|
44
|
+
Nothing here pins an IP or a subnet. `mon.sh` reads the monitor's own address
|
|
45
|
+
off its interface at runtime, writes it into `ceph.conf` and the monmap, and
|
|
46
|
+
every other daemon finds the monitor through that shared `ceph.conf`. Docker is
|
|
47
|
+
therefore free to allocate whatever range is available, and this stack can never
|
|
48
|
+
collide with an existing network.
|
|
49
|
+
|
|
50
|
+
If docker hands out a different address on a later `up`, `mon.sh` notices that
|
|
51
|
+
the stored monmap disagrees, rewrites it in place (preserving the fsid and map
|
|
52
|
+
epoch) and carries on.
|
|
53
|
+
|
|
54
|
+
The one case this does not cover is the docker daemon reassigning addresses
|
|
55
|
+
underneath containers that keep running — the monitor recovers, but an OSD that
|
|
56
|
+
was never restarted will still be pointed at the old address. Restart the stack.
|
|
57
|
+
|
|
58
|
+
## Things to be aware of when using this docker compose
|
|
59
|
+
|
|
60
|
+
**`down` without `-v` keeps the cluster.** The named volumes hold the fsid,
|
|
61
|
+
keyrings, monmap, and OSD stores, and every script is idempotent, so a plain
|
|
62
|
+
`down`/`up` deliberately reuses the existing cluster. A config that gets applied at
|
|
63
|
+
creation time, like `osd_pool_default_size` set by `OSD_COUNT`, will not change
|
|
64
|
+
until you `down -v`.
|
|
65
|
+
|
|
66
|
+
**Changing `OSD_COUNT` requires `down -v`.** `osd.sh` skips provisioning when it
|
|
67
|
+
finds a `ready` marker, so going 3→1 on existing volumes leaves osd.1 and osd.2
|
|
68
|
+
in the osdmap with no daemons behind them — degraded forever. Under
|
|
69
|
+
`ts-scripts test` that is covered: `ensureCeph()` runs `down -v` before every
|
|
70
|
+
`up`.
|
|
71
|
+
|
|
72
|
+
**The count is structural in the YAML.** `rgw.sh` blocks until `OSD_COUNT` OSDs
|
|
73
|
+
are up, and compose can't template a service, so the service blocks have to
|
|
74
|
+
exist. `ts-scripts test` generates them (see above); standalone, add matching
|
|
75
|
+
`osd1`, `osd2`... blocks yourself. Each OSD provisions itself, so such a block
|
|
76
|
+
is a copy of `osd0` with a different `OSD_ID` and `hostname`.
|
|
77
|
+
|
|
78
|
+
**No `container_name:` keys.** Container names are globally unique in Docker, so
|
|
79
|
+
hardcoding them would stop two stacks coexisting even under different project
|
|
80
|
+
names. Containers are `<project>-<service>-1`, and in-network addressing uses
|
|
81
|
+
the compose service name (`rgw`, `mon`).
|
|
82
|
+
|
|
83
|
+
**Export `CEPH_*`, never the container-side names.** Compose's precedence is
|
|
84
|
+
`environment:` > shell env (for `${VAR}` interpolation only) > `env_file`, and
|
|
85
|
+
the scripts inside the containers read their values from `env_file` — so a
|
|
86
|
+
shell export reaches interpolation but not the containers.
|
|
87
|
+
|
|
88
|
+
Under `ts-scripts test` that is already handled: the `CEPH_*` vars go through
|
|
89
|
+
`config.ts`, which writes both sides of the `.env` file, so `CEPH_PORT=9000
|
|
90
|
+
ts-scripts test` publishes *and* binds 9000. Exporting the container-side name
|
|
91
|
+
is what breaks — `.env` is regenerated on every run, so `RGW_PORT=9000` is
|
|
92
|
+
overwritten in the file while your shell value still wins for interpolation,
|
|
93
|
+
publishing one port while RGW listens on another.
|
|
94
|
+
|
|
95
|
+
Standalone, there is no generator, so change the `.env` file rather than your
|
|
96
|
+
shell.
|
|
97
|
+
|
|
98
|
+
**Readiness is `setup` exiting, not the containers starting.** `up -d` already
|
|
99
|
+
blocks on the `depends_on` chain, so it returns with the cluster healthy and RGW
|
|
100
|
+
serving; the only thing still outstanding is `setup`, which creates the S3 user.
|
|
101
|
+
`up --wait` doesn't cover it — `setup` has no healthcheck and nothing depends on
|
|
102
|
+
it, so `--wait` only requires that it started — and `docker compose wait setup`
|
|
103
|
+
errors with "no containers for project" once that container has exited. Use
|
|
104
|
+
`docker compose ps -a setup` instead, which keeps listing it after it exits.
|
|
105
|
+
|
|
106
|
+
## Planned Improvements
|
|
107
|
+
|
|
108
|
+
TLS on the RGW endpoint. `rgw.sh` starts a plain beast frontend; beast supports
|
|
109
|
+
`ssl_port=`/`ssl_certificate=`, but it needs a cert minted for the hostname
|
|
110
|
+
clients actually connect on. MinIO still covers the encrypted e2e target until
|
|
111
|
+
then.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Default project name for standalone `docker compose up`. ts-scripts overrides
|
|
2
|
+
# it with COMPOSE_PROJECT_NAME, which takes precedence over this key.
|
|
3
|
+
name: ceph
|
|
4
|
+
|
|
5
|
+
# A single-node Ceph cluster (1 mon, 1 mgr, 1 OSD, 1 RGW) for local testing.
|
|
6
|
+
# The OSD is a BlueStore store on a sparse file, so no loop devices, no
|
|
7
|
+
# privileged containers, and nothing touching the host's disks.
|
|
8
|
+
#
|
|
9
|
+
# Under `ts-scripts test` the .env file used is generated from
|
|
10
|
+
# packages/scripts/src/helpers/config.ts -- see ensureCeph() in
|
|
11
|
+
# src/helpers/test-runner/services.ts. Edits to it are overwritten on every run.
|
|
12
|
+
# Standalone: `cp .env.example .env` first.
|
|
13
|
+
|
|
14
|
+
x-ceph: &ceph
|
|
15
|
+
image: ${CEPH_IMAGE:-quay.io/ceph/ceph:v19.2.6}
|
|
16
|
+
env_file: .env
|
|
17
|
+
volumes:
|
|
18
|
+
- ./scripts:/scripts:ro
|
|
19
|
+
- ceph-etc:/etc/ceph
|
|
20
|
+
- ceph-lib:/var/lib/ceph
|
|
21
|
+
networks: [ceph]
|
|
22
|
+
# Ceph daemons want a decent number of threads/fds.
|
|
23
|
+
ulimits:
|
|
24
|
+
nofile: 65536
|
|
25
|
+
nproc: 65536
|
|
26
|
+
|
|
27
|
+
services:
|
|
28
|
+
# Also creates the cluster on first run: fsid, ceph.conf, keyrings, monmap.
|
|
29
|
+
mon:
|
|
30
|
+
<<: *ceph
|
|
31
|
+
hostname: ceph-mon
|
|
32
|
+
command: ["bash", "/scripts/mon.sh"]
|
|
33
|
+
healthcheck:
|
|
34
|
+
test: ["CMD", "ceph", "--connect-timeout", "5", "quorum_status"]
|
|
35
|
+
interval: 5s
|
|
36
|
+
timeout: 10s
|
|
37
|
+
retries: 30
|
|
38
|
+
start_period: 10s
|
|
39
|
+
restart: unless-stopped
|
|
40
|
+
|
|
41
|
+
mgr:
|
|
42
|
+
<<: *ceph
|
|
43
|
+
hostname: ceph-mgr
|
|
44
|
+
command: ["bash", "/scripts/mgr.sh"]
|
|
45
|
+
depends_on:
|
|
46
|
+
mon:
|
|
47
|
+
condition: service_healthy
|
|
48
|
+
restart: unless-stopped
|
|
49
|
+
|
|
50
|
+
# Provisions its own BlueStore store on first run. Under `ts-scripts test`
|
|
51
|
+
# this block is the template CEPH_OSD_COUNT > 1 clones into osd1, osd2... in
|
|
52
|
+
# the generated docker-compose.osds.yml override. Standalone, copy it by
|
|
53
|
+
# hand, bump OSD_ID, and raise OSD_COUNT in the env file.
|
|
54
|
+
osd0:
|
|
55
|
+
<<: *ceph
|
|
56
|
+
hostname: ceph-osd0
|
|
57
|
+
command: ["bash", "/scripts/osd.sh"]
|
|
58
|
+
environment:
|
|
59
|
+
OSD_ID: 0
|
|
60
|
+
depends_on:
|
|
61
|
+
mon:
|
|
62
|
+
condition: service_healthy
|
|
63
|
+
restart: unless-stopped
|
|
64
|
+
|
|
65
|
+
rgw:
|
|
66
|
+
<<: *ceph
|
|
67
|
+
hostname: ceph-rgw
|
|
68
|
+
command: ["bash", "/scripts/rgw.sh"]
|
|
69
|
+
ports:
|
|
70
|
+
# Same port inside and out, so RGW never hands back an unreachable URL.
|
|
71
|
+
- "${RGW_PORT:-8000}:${RGW_PORT:-8000}"
|
|
72
|
+
depends_on:
|
|
73
|
+
osd0: {condition: service_started}
|
|
74
|
+
healthcheck:
|
|
75
|
+
test: ["CMD-SHELL", "curl -fsS -o /dev/null http://localhost:${RGW_PORT:-8000}/"]
|
|
76
|
+
interval: 5s
|
|
77
|
+
timeout: 5s
|
|
78
|
+
retries: 40
|
|
79
|
+
start_period: 20s
|
|
80
|
+
restart: unless-stopped
|
|
81
|
+
|
|
82
|
+
setup:
|
|
83
|
+
<<: *ceph
|
|
84
|
+
command: ["bash", "/scripts/setup.sh"]
|
|
85
|
+
depends_on:
|
|
86
|
+
rgw:
|
|
87
|
+
condition: service_healthy
|
|
88
|
+
restart: "no"
|
|
89
|
+
|
|
90
|
+
# ---- opt-in: `docker compose run --rm toolbox` for a ceph/radosgw-admin shell
|
|
91
|
+
toolbox:
|
|
92
|
+
<<: *ceph
|
|
93
|
+
profiles: [tools]
|
|
94
|
+
command: ["bash"]
|
|
95
|
+
stdin_open: true
|
|
96
|
+
tty: true
|
|
97
|
+
restart: "no"
|
|
98
|
+
|
|
99
|
+
volumes:
|
|
100
|
+
ceph-etc:
|
|
101
|
+
ceph-lib:
|
|
102
|
+
|
|
103
|
+
networks:
|
|
104
|
+
ceph:
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Shared helpers for the Ceph role scripts.
|
|
3
|
+
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
CEPH_CONF=/etc/ceph/ceph.conf
|
|
7
|
+
|
|
8
|
+
log() { echo "[$(date -u '+%H:%M:%S')] [${ROLE:-ceph}] $*" >&2; }
|
|
9
|
+
|
|
10
|
+
die() { log "FATAL: $*"; exit 1; }
|
|
11
|
+
|
|
12
|
+
# This container's own IPv4 address on the docker network, read at runtime.
|
|
13
|
+
own_addr() {
|
|
14
|
+
local addr
|
|
15
|
+
addr=$(hostname -i | tr ' ' '\n' | grep -v ':' | head -1)
|
|
16
|
+
[ -n "$addr" ] || die "could not determine this container's IPv4 address"
|
|
17
|
+
echo "$addr"
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
# Block until the monitor has written the shared ceph.conf.
|
|
21
|
+
wait_for_conf() {
|
|
22
|
+
local tries=${1:-120}
|
|
23
|
+
while [ ! -s "$CEPH_CONF" ]; do
|
|
24
|
+
tries=$((tries - 1))
|
|
25
|
+
[ "$tries" -le 0 ] && die "timed out waiting for $CEPH_CONF"
|
|
26
|
+
sleep 1
|
|
27
|
+
done
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
# Block until the monitor forms a quorum and answers.
|
|
31
|
+
wait_for_mon() {
|
|
32
|
+
local tries=${1:-120}
|
|
33
|
+
log "waiting for monitor quorum ..."
|
|
34
|
+
until ceph --connect-timeout 5 quorum_status >/dev/null 2>&1; do
|
|
35
|
+
tries=$((tries - 1))
|
|
36
|
+
[ "$tries" -le 0 ] && die "timed out waiting for monitor quorum"
|
|
37
|
+
sleep 2
|
|
38
|
+
done
|
|
39
|
+
log "monitor quorum reached"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
# Block until at least $1 OSDs report "up".
|
|
43
|
+
wait_for_osds() {
|
|
44
|
+
local want=$1 tries=${2:-180} up=0
|
|
45
|
+
log "waiting for $want OSD(s) to come up ..."
|
|
46
|
+
while :; do
|
|
47
|
+
up=$(ceph osd stat -f json 2>/dev/null \
|
|
48
|
+
| python3 -c 'import sys,json; print(json.load(sys.stdin)["num_up_osds"])' 2>/dev/null || echo 0)
|
|
49
|
+
[ "$up" -ge "$want" ] && break
|
|
50
|
+
tries=$((tries - 1))
|
|
51
|
+
[ "$tries" -le 0 ] && die "timed out waiting for OSDs (only $up/$want up)"
|
|
52
|
+
sleep 2
|
|
53
|
+
done
|
|
54
|
+
log "$up OSD(s) up"
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
# Block until the cluster reports HEALTH_OK (HEALTH_WARN is tolerated after a
|
|
58
|
+
# grace period -- a fresh cluster warns while PGs are still peering).
|
|
59
|
+
wait_for_health() {
|
|
60
|
+
local tries=${1:-120} status=""
|
|
61
|
+
log "waiting for cluster health ..."
|
|
62
|
+
while :; do
|
|
63
|
+
status=$(ceph health 2>/dev/null | awk '{print $1}' || true)
|
|
64
|
+
[ "$status" = "HEALTH_OK" ] && break
|
|
65
|
+
tries=$((tries - 1))
|
|
66
|
+
if [ "$tries" -le 0 ]; then
|
|
67
|
+
log "cluster is $status, continuing anyway:"
|
|
68
|
+
ceph -s >&2 || true
|
|
69
|
+
return 0
|
|
70
|
+
fi
|
|
71
|
+
sleep 2
|
|
72
|
+
done
|
|
73
|
+
log "cluster is HEALTH_OK"
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
fix_perms() {
|
|
77
|
+
chown -R ceph:ceph "$@" 2>/dev/null || true
|
|
78
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
ROLE=mgr
|
|
3
|
+
source /scripts/common.sh
|
|
4
|
+
|
|
5
|
+
MGR_ID=${MGR_ID:-x}
|
|
6
|
+
MGR_DATA=/var/lib/ceph/mgr/ceph-${MGR_ID}
|
|
7
|
+
|
|
8
|
+
wait_for_conf
|
|
9
|
+
wait_for_mon
|
|
10
|
+
|
|
11
|
+
mkdir -p "$MGR_DATA"
|
|
12
|
+
if [ ! -s "${MGR_DATA}/keyring" ]; then
|
|
13
|
+
log "creating keyring for mgr.${MGR_ID}"
|
|
14
|
+
ceph auth get-or-create "mgr.${MGR_ID}" \
|
|
15
|
+
mon 'allow profile mgr' osd 'allow *' mds 'allow *' \
|
|
16
|
+
-o "${MGR_DATA}/keyring"
|
|
17
|
+
fi
|
|
18
|
+
fix_perms "$MGR_DATA"
|
|
19
|
+
|
|
20
|
+
log "starting ceph-mgr id=${MGR_ID}"
|
|
21
|
+
exec ceph-mgr -f -i "$MGR_ID" --setuser ceph --setgroup ceph
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Creates the cluster on first run -- fsid, ceph.conf, keyrings, monmap, and the
|
|
3
|
+
# monitor's data store -- and then runs the monitor.
|
|
4
|
+
ROLE=mon
|
|
5
|
+
source /scripts/common.sh
|
|
6
|
+
|
|
7
|
+
MON_ID=${MON_ID:-mon0}
|
|
8
|
+
MON_DATA=/var/lib/ceph/mon/ceph-${MON_ID}
|
|
9
|
+
MON_ADDR=$(own_addr)
|
|
10
|
+
|
|
11
|
+
# Replicate only as widely as there are OSDs to replicate across. With one OSD
|
|
12
|
+
# and size=2 every PG sits active+undersized+degraded forever: writes still
|
|
13
|
+
# succeed via min_size=1, but the cluster never reaches HEALTH_OK.
|
|
14
|
+
OSD_COUNT=${OSD_COUNT:-1}
|
|
15
|
+
POOL_SIZE=$(( OSD_COUNT >= 2 ? 2 : 1 ))
|
|
16
|
+
|
|
17
|
+
mkdir -p /etc/ceph /var/lib/ceph/mon /var/lib/ceph/bootstrap-osd /var/lib/ceph/mgr
|
|
18
|
+
|
|
19
|
+
# Keep the fsid across restarts; only mint one for a genuinely new cluster.
|
|
20
|
+
FSID=$(awk '/^fsid/ {print $3}' "$CEPH_CONF" 2>/dev/null || true)
|
|
21
|
+
if [ -z "$FSID" ]; then
|
|
22
|
+
FSID=$(uuidgen)
|
|
23
|
+
log "creating new cluster, fsid=${FSID}"
|
|
24
|
+
else
|
|
25
|
+
log "reusing existing cluster, fsid=${FSID}"
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
# ceph.conf is entirely generated, so rewrite it on every start rather than
|
|
29
|
+
# patching it. That is what keeps mon_host correct when docker hands out a
|
|
30
|
+
# different address after a `down` that kept the volumes.
|
|
31
|
+
cat > "$CEPH_CONF" <<EOF
|
|
32
|
+
# Generated by scripts/mon.sh -- single-node Ceph for local testing.
|
|
33
|
+
# Rewritten on every monitor start. Not a production configuration.
|
|
34
|
+
[global]
|
|
35
|
+
fsid = ${FSID}
|
|
36
|
+
mon_initial_members = ${MON_ID}
|
|
37
|
+
mon_host = [v2:${MON_ADDR}:3300,v1:${MON_ADDR}:6789]
|
|
38
|
+
|
|
39
|
+
# Deliberately no public_network/cluster_network: these containers have a single
|
|
40
|
+
# interface, so Ceph binds to the right address on its own, and hardcoding a
|
|
41
|
+
# range here would put back the pinned-subnet problem this layout removes.
|
|
42
|
+
|
|
43
|
+
auth_cluster_required = cephx
|
|
44
|
+
auth_service_required = cephx
|
|
45
|
+
auth_client_required = cephx
|
|
46
|
+
|
|
47
|
+
# One host: replicate across OSDs rather than across hosts.
|
|
48
|
+
osd_crush_chooseleaf_type = 0
|
|
49
|
+
osd_pool_default_size = ${POOL_SIZE}
|
|
50
|
+
osd_pool_default_min_size = 1
|
|
51
|
+
# Deliberately no osd_pool_default_pg_num/pgp_num here: the autoscaler starts
|
|
52
|
+
# new pools at pg_num=1, and a pinned pgp_num above that makes every librados
|
|
53
|
+
# pool_create (i.e. every pool RGW creates for itself) fail with ERANGE.
|
|
54
|
+
|
|
55
|
+
# Cache ceiling per OSD. Only approached under sustained write load -- idle RSS
|
|
56
|
+
# is well under 100 MiB. Keeps a heavy test from ballooning inside Docker's VM.
|
|
57
|
+
osd_memory_target = 939524096
|
|
58
|
+
|
|
59
|
+
# Log to stderr so "docker compose logs" actually shows something. The upstream
|
|
60
|
+
# images default to journald, which no one is running inside these containers.
|
|
61
|
+
log_to_stderr = true
|
|
62
|
+
err_to_stderr = true
|
|
63
|
+
log_to_file = false
|
|
64
|
+
log_to_journald = false
|
|
65
|
+
mon_cluster_log_to_stderr = true
|
|
66
|
+
mon_cluster_log_to_file = false
|
|
67
|
+
mon_cluster_log_to_journald = false
|
|
68
|
+
|
|
69
|
+
# Warnings that are noise on a disposable single-node cluster.
|
|
70
|
+
mon_warn_on_insecure_global_id_reclaim = false
|
|
71
|
+
mon_warn_on_insecure_global_id_reclaim_allowed = false
|
|
72
|
+
mon_warn_on_pool_no_redundancy = false
|
|
73
|
+
auth_allow_insecure_global_id_reclaim = true
|
|
74
|
+
mon_data_avail_warn = 2
|
|
75
|
+
mon_data_avail_crit = 1
|
|
76
|
+
|
|
77
|
+
[mon]
|
|
78
|
+
mon_allow_pool_delete = true
|
|
79
|
+
|
|
80
|
+
[osd]
|
|
81
|
+
osd_max_pg_per_osd_hard_ratio = 10
|
|
82
|
+
EOF
|
|
83
|
+
|
|
84
|
+
if [ ! -f "${MON_DATA}/keyring" ]; then
|
|
85
|
+
log "bootstrapping monitor at ${MON_ADDR}"
|
|
86
|
+
|
|
87
|
+
# Monitor keyring.
|
|
88
|
+
ceph-authtool --create-keyring /tmp/ceph.mon.keyring \
|
|
89
|
+
--gen-key -n mon. --cap mon 'allow *'
|
|
90
|
+
|
|
91
|
+
# Admin keyring -- this is what the toolbox and every script authenticates as.
|
|
92
|
+
ceph-authtool --create-keyring /etc/ceph/ceph.client.admin.keyring \
|
|
93
|
+
--gen-key -n client.admin \
|
|
94
|
+
--cap mon 'allow *' --cap osd 'allow *' --cap mds 'allow *' --cap mgr 'allow *'
|
|
95
|
+
|
|
96
|
+
# OSD bootstrap keyring.
|
|
97
|
+
ceph-authtool --create-keyring /var/lib/ceph/bootstrap-osd/ceph.keyring \
|
|
98
|
+
--gen-key -n client.bootstrap-osd \
|
|
99
|
+
--cap mon 'profile bootstrap-osd' --cap mgr 'allow r'
|
|
100
|
+
|
|
101
|
+
ceph-authtool /tmp/ceph.mon.keyring --import-keyring /etc/ceph/ceph.client.admin.keyring
|
|
102
|
+
ceph-authtool /tmp/ceph.mon.keyring --import-keyring /var/lib/ceph/bootstrap-osd/ceph.keyring
|
|
103
|
+
|
|
104
|
+
monmaptool --create \
|
|
105
|
+
--addv "${MON_ID}" "[v2:${MON_ADDR}:3300,v1:${MON_ADDR}:6789]" \
|
|
106
|
+
--fsid "${FSID}" /tmp/monmap
|
|
107
|
+
|
|
108
|
+
mkdir -p "$MON_DATA"
|
|
109
|
+
ceph-mon --mkfs -i "$MON_ID" --monmap /tmp/monmap --keyring /tmp/ceph.mon.keyring
|
|
110
|
+
else
|
|
111
|
+
# The store already holds a monmap naming whatever address this container had
|
|
112
|
+
# last time. Reconcile it before starting, or the monitor fails to bind.
|
|
113
|
+
# Modify the stored map rather than creating a fresh one so the fsid and the
|
|
114
|
+
# map epoch survive.
|
|
115
|
+
ceph-mon -i "$MON_ID" --extract-monmap /tmp/monmap >/dev/null 2>&1 \
|
|
116
|
+
|| die "could not read the existing monmap from ${MON_DATA}"
|
|
117
|
+
|
|
118
|
+
if monmaptool --print /tmp/monmap 2>/dev/null | grep -q "v1:${MON_ADDR}:6789"; then
|
|
119
|
+
log "monmap already lists ${MON_ADDR}"
|
|
120
|
+
else
|
|
121
|
+
log "monitor address changed, rewriting monmap to ${MON_ADDR}"
|
|
122
|
+
monmaptool --rm "$MON_ID" /tmp/monmap >/dev/null
|
|
123
|
+
monmaptool --addv "${MON_ID}" "[v2:${MON_ADDR}:3300,v1:${MON_ADDR}:6789]" /tmp/monmap >/dev/null
|
|
124
|
+
ceph-mon -i "$MON_ID" --inject-monmap /tmp/monmap
|
|
125
|
+
fi
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
fix_perms /etc/ceph /var/lib/ceph
|
|
129
|
+
|
|
130
|
+
log "starting ceph-mon id=${MON_ID} at ${MON_ADDR}"
|
|
131
|
+
exec ceph-mon -f -i "$MON_ID" --setuser ceph --setgroup ceph
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Registers this OSD with the monitor and lays down its BlueStore store on a
|
|
3
|
+
# sparse file, then runs it. Idempotent: a store that is already provisioned is
|
|
4
|
+
# reused as-is.
|
|
5
|
+
#
|
|
6
|
+
# Each OSD provisions itself rather than sharing a single osd-init container, so
|
|
7
|
+
# adding a second OSD is a copy of the osd0 service block with a different
|
|
8
|
+
# OSD_ID and nothing else has to change.
|
|
9
|
+
ROLE=osd.${OSD_ID:-?}
|
|
10
|
+
source /scripts/common.sh
|
|
11
|
+
|
|
12
|
+
OSD_ID=${OSD_ID:?OSD_ID must be set}
|
|
13
|
+
OSD_SIZE=${OSD_SIZE:-10G}
|
|
14
|
+
OSD_DATA=/var/lib/ceph/osd/ceph-${OSD_ID}
|
|
15
|
+
|
|
16
|
+
wait_for_conf
|
|
17
|
+
wait_for_mon
|
|
18
|
+
|
|
19
|
+
if [ ! -f "${OSD_DATA}/ready" ]; then
|
|
20
|
+
# A half-built store from an interrupted run would confuse --mkfs.
|
|
21
|
+
rm -rf "$OSD_DATA"
|
|
22
|
+
mkdir -p "$OSD_DATA"
|
|
23
|
+
|
|
24
|
+
uuid=$(uuidgen)
|
|
25
|
+
secret=$(ceph-authtool --gen-print-key)
|
|
26
|
+
|
|
27
|
+
log "registering osd.${OSD_ID} (uuid ${uuid})"
|
|
28
|
+
assigned=$(echo "{\"cephx_secret\": \"${secret}\"}" \
|
|
29
|
+
| ceph osd new "$uuid" "$OSD_ID" -i - -n client.admin)
|
|
30
|
+
[ "$assigned" = "$OSD_ID" ] || die "monitor assigned osd.${assigned}, expected osd.${OSD_ID}"
|
|
31
|
+
|
|
32
|
+
log "creating ${OSD_SIZE} sparse BlueStore device for osd.${OSD_ID}"
|
|
33
|
+
truncate -s "$OSD_SIZE" "${OSD_DATA}/block"
|
|
34
|
+
|
|
35
|
+
ceph-authtool --create-keyring "${OSD_DATA}/keyring" \
|
|
36
|
+
--name "osd.${OSD_ID}" --add-key "$secret"
|
|
37
|
+
|
|
38
|
+
fix_perms "$OSD_DATA"
|
|
39
|
+
ceph-osd -i "$OSD_ID" --mkfs --osd-uuid "$uuid" --setuser ceph --setgroup ceph
|
|
40
|
+
|
|
41
|
+
touch "${OSD_DATA}/ready"
|
|
42
|
+
log "osd.${OSD_ID} provisioned"
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
fix_perms /etc/ceph "$OSD_DATA"
|
|
46
|
+
|
|
47
|
+
log "starting ceph-osd id=${OSD_ID}"
|
|
48
|
+
exec ceph-osd -f -i "$OSD_ID" --setuser ceph --setgroup ceph
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
ROLE=rgw
|
|
3
|
+
source /scripts/common.sh
|
|
4
|
+
|
|
5
|
+
RGW_ID=${RGW_ID:-test}
|
|
6
|
+
RGW_PORT=${RGW_PORT:-8000}
|
|
7
|
+
OSD_COUNT=${OSD_COUNT:-1}
|
|
8
|
+
NAME="client.rgw.${RGW_ID}"
|
|
9
|
+
KEYRING="/etc/ceph/ceph.${NAME}.keyring"
|
|
10
|
+
|
|
11
|
+
wait_for_conf
|
|
12
|
+
wait_for_mon
|
|
13
|
+
# RGW creates its pools on startup, which needs OSDs to actually accept writes.
|
|
14
|
+
wait_for_osds "$OSD_COUNT"
|
|
15
|
+
|
|
16
|
+
if [ ! -s "$KEYRING" ]; then
|
|
17
|
+
log "creating keyring for ${NAME}"
|
|
18
|
+
ceph auth get-or-create "$NAME" \
|
|
19
|
+
mon 'allow rw' osd 'allow rwx' mgr 'allow rw' \
|
|
20
|
+
-o "$KEYRING"
|
|
21
|
+
fi
|
|
22
|
+
fix_perms "$KEYRING"
|
|
23
|
+
|
|
24
|
+
log "starting radosgw ${NAME} on port ${RGW_PORT}"
|
|
25
|
+
exec radosgw -f -n "$NAME" -k "$KEYRING" \
|
|
26
|
+
--setuser ceph --setgroup ceph \
|
|
27
|
+
--rgw-frontends="beast port=${RGW_PORT}" \
|
|
28
|
+
--rgw-run-sync-thread=false \
|
|
29
|
+
--rgw-relaxed-s3-bucket-names=true
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Creates the S3 user.
|
|
3
|
+
|
|
4
|
+
ROLE=setup
|
|
5
|
+
source /scripts/common.sh
|
|
6
|
+
|
|
7
|
+
S3_USER=${S3_USER:-test}
|
|
8
|
+
S3_ACCESS_KEY=${S3_ACCESS_KEY:?}
|
|
9
|
+
S3_SECRET_KEY=${S3_SECRET_KEY:?}
|
|
10
|
+
RGW_PORT=${RGW_PORT:-8000}
|
|
11
|
+
# The compose service name, not a container_name
|
|
12
|
+
export S3_ENDPOINT=${S3_ENDPOINT:-http://rgw:${RGW_PORT}}
|
|
13
|
+
export S3_ACCESS_KEY S3_SECRET_KEY
|
|
14
|
+
|
|
15
|
+
wait_for_conf
|
|
16
|
+
wait_for_mon
|
|
17
|
+
|
|
18
|
+
log "waiting for the RGW endpoint at ${S3_ENDPOINT} ..."
|
|
19
|
+
tries=90
|
|
20
|
+
until curl -fsS -o /dev/null "${S3_ENDPOINT}"; do
|
|
21
|
+
tries=$((tries - 1))
|
|
22
|
+
[ "$tries" -le 0 ] && die "RGW never became reachable"
|
|
23
|
+
sleep 2
|
|
24
|
+
done
|
|
25
|
+
|
|
26
|
+
if radosgw-admin user info --uid="$S3_USER" >/dev/null 2>&1; then
|
|
27
|
+
log "S3 user '${S3_USER}' already exists"
|
|
28
|
+
else
|
|
29
|
+
log "creating S3 user '${S3_USER}'"
|
|
30
|
+
radosgw-admin user create \
|
|
31
|
+
--uid="$S3_USER" \
|
|
32
|
+
--display-name="Local test user" \
|
|
33
|
+
--access-key="$S3_ACCESS_KEY" \
|
|
34
|
+
--secret-key="$S3_SECRET_KEY" >/dev/null
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
wait_for_health 60
|
|
38
|
+
|
|
39
|
+
cat >&2 <<EOF
|
|
40
|
+
|
|
41
|
+
------------------------------------------------------------------
|
|
42
|
+
Ceph is up. S3 endpoint ready.
|
|
43
|
+
|
|
44
|
+
Endpoint (from host) http://localhost:${RGW_PORT}
|
|
45
|
+
Endpoint (in-network) http://rgw:${RGW_PORT}
|
|
46
|
+
Region us-east-1
|
|
47
|
+
Access key ${S3_ACCESS_KEY}
|
|
48
|
+
Secret key ${S3_SECRET_KEY}
|
|
49
|
+
|
|
50
|
+
Use path-style addressing; virtual-host style needs DNS wildcards.
|
|
51
|
+
------------------------------------------------------------------
|
|
52
|
+
|
|
53
|
+
EOF
|
|
54
|
+
|
|
55
|
+
ceph -s >&2
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@terascope/scripts",
|
|
3
3
|
"displayName": "Scripts",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.26.0",
|
|
5
5
|
"description": "A collection of terascope monorepo scripts",
|
|
6
6
|
"homepage": "https://github.com/terascope/teraslice/tree/master/packages/scripts#readme",
|
|
7
7
|
"bugs": {
|
|
@@ -45,7 +45,8 @@
|
|
|
45
45
|
"typedoc-plugin-markdown": "~4.13.0",
|
|
46
46
|
"yaml": "~2.9.0",
|
|
47
47
|
"yargs": "~18.1.0",
|
|
48
|
-
"@terascope/core-utils": "~2.
|
|
48
|
+
"@terascope/core-utils": "~2.18.0",
|
|
49
|
+
"@terascope/docker-compose-js": "~2.2.0"
|
|
49
50
|
},
|
|
50
51
|
"devDependencies": {
|
|
51
52
|
"@jest/globals": "^30.4.1",
|
|
@@ -59,7 +60,7 @@
|
|
|
59
60
|
"@types/yargs": "~17.0.35",
|
|
60
61
|
"jest-extended": "~7.0.0",
|
|
61
62
|
"typescript": "~6.0.3",
|
|
62
|
-
"@terascope/types": "~2.
|
|
63
|
+
"@terascope/types": "~2.17.0"
|
|
63
64
|
},
|
|
64
65
|
"peerDependencies": {
|
|
65
66
|
"typescript": "~6.0.3"
|