좋은 질문이에요 👍
지금 상황을 정리하면:
스토리지 노드 수: 58대
노드당 디스크: 20 × 7 TiB NVMe SSD = 140 TiB
총 raw capacity: 58 × 140 TiB ≈ 8.12 PiB
EC: 8:3 (데이터 8 + 패리티 3 → 11개 shard, overhead 약 37.5%)
→ 유효 용량 ≈ 5.9 PiB 수준
네트워크: 노드당 25 Gbps × 2 (bond) = 50 Gbps
스위치 포트는 40 Gbps, 백본은 200 Gbps
즉, 스토리지 자체 IOPS/Throughput은 NVMe라 충분히 빠르지만, 네트워크가 bottleneck이 될 가능성이 높습니다.
MinIO/AIStor은 S3 PUT API 기반이므로, 아래 방법을 병행해야 합니다:
병렬 클라이언트
mc mirror 대신 warp, s3-bench, fio-s3, k6 + S3 plugin 같은 부하도구 사용멀티파트 업로드
데이터 생성 후 업로드
fio --rw=write --bs=4M → pipe → aws s3 cp ---obj.size 24MiB --objects 1e9 형태로 직접 object 생성→ 채우기 속도 계산
HDFS block size = 128MB는 HDFS 내부 분산 단위일 뿐, S3 object에 그대로 맞출 필요 없음.
Hadoop → S3 마이그레이션 시:
👉 따라서
✅ 정리
👉 원하시면 제가 채우기용 스크립트 (예: warp, k6, fio-s3 조합) 만들어서 예상 OPS/Throughput 통계까지 자동 CSV 뽑는 버전을 작성해드릴까요?
좋은 포인트 집으셨어요 👍
말씀하신 NIC / TCP stack / MinIO metadata IOPS 한계는 실제 S3 스토리지에서 작은 오브젝트(4KB~64KB) 업로드 시 자주 문제되는 병목입니다. 크게 3가지 레이어에서 병목이 걸립니다:
네트워크 인터페이스 카드 (NIC) 는 패킷당 처리 성능이 제한적입니다.
이 한계는 커널 TCP/IP 스택, 드라이버, 인터럽트 처리에도 영향받습니다.
확인 방법
ethtool -S <nic> : NIC pps/err drop 확인sar -n DEV 1 또는 nload, ifstat : 초당 패킷 전송량 확인perf top : 커널 TCP/IP stack CPU 사용률 확인MinIO는 Object의 메타데이터 (namespace, version, erasure coding layout, checksum 등) 를 내부 key-value DB(RocksDB/boltdb-like)와 분산 구조에 저장
작은 object가 많아지면 메타데이터 update IOPS가 bottleneck 됨
특히 PUT/DELETE 같은 write path에서 부하 큼
확인 방법
mc admin trace : API call latency 확인mc admin prometheus → Prometheus metrics (minio_s3_requests_total, minio_s3_requests_inflight, minio_disk_storage_requests)minio_rocksdb_* metrics)확인 방법
fio --rw=randwrite --bs=4k --iodepth=64 --numjobs=8 : NVMe IOPS baseline 측정즉, 작은 object는 IOPS → 네트워크 패킷 처리와 메타데이터 병목,
큰 object는 Throughput → NIC 대역폭과 EC 연산 병목이라고 이해하면 됩니다.
✅ 정리
ethtool -S, sar), MinIO metrics(mc admin prometheus), 디스크(fio) 조합👉 원하시면 제가 "작은 object IOPS vs 큰 object Throughput"을 측정하는 벤치마크 시나리오 (warp + fio + mc admin metrics 수집) 예시를 작성해드릴까요?
좋은 질문이에요 👍
mc의 od (object distribution) 서브커맨드를 말씀하신 것 같네요. 이건 최근 MinIO Client에 들어간 기능인데, 이름 때문에 혼동하기 쉽습니다.
mc od 의 역할od = object distribution
주 용도는 S3 버킷 안의 오브젝트 분포/패턴을 통계로 확인하는 것입니다.
즉, mc od는 데이터를 생성하거나 채우는 툴이 아님 → 벤치마크/데이터 채움 용도로는 부적합합니다.
데이터 채워 넣는 목적으로는 mc od 대신 다음을 써야 합니다:
mc alias set + mirror/cp
mc mirror /data myminio/bucket --overwrite --watchwarp (MinIO 제공 부하툴)
warp put --obj.size 24MiB --objects 1e9 --concurrent 512 myminio/bucketfio + s3 plugin
fio --rw=write --bs=24M --ioengine=http_s3 --numjobs=64s3-bench / k6 / JMeter
mc od와 보강 활용 방법mc od 자체로 채우지는 못하지만, 데이터 채운 후에 상태를 점검하는 데는 유용합니다:
데이터 분포 확인
워크로드 검증
성능 해석 보조
✅ 결론
mc od는 스토리지를 채우는 도구가 아니라, 채워진 데이터를 분석하는 도구입니다.👉 원하시면 제가 **“warp로 채우고 → mc od로 분포 분석 → Prometheus/Metrics로 성능 확인”**까지 자동화된 샘플 스크립트(예: bash + Jenkinsfile) 짜드릴까요?
오케이, 요청하신 “warp로 채우고 → mc od 분석 → Prometheus 메트릭 수집” 자동화를 Bash 스크립트 + Jenkinsfile로 캔버스에 올려놨어요.
캔버스 파일에는:
aistor_bench.sh (단일 스크립트): 버킷 준비 → warp put 실행 → mc od --json 분석 → Prometheus API로 핵심 메트릭 스냅샷 수집 → CSV 요약까지 생성Jenkinsfile (Declarative): 파라미터로 OBJ_SIZE/OBJECTS/CONCURRENCY/DURATION 등 받아 자동 실행, 리포트 아카이빙바로 쓰실 때는 다음만 바꿔주시면 됩니다:
--url, --access, --secret, --prom-url, --prom-token--help로 확인 후 맞춰주세요.원하시면 같은 파이프라인에서 소형(예: 64KiB) → 대형(예: 128MiB) 두 번 돌려 비교 CSV를 하나로 합치고, Jenkins에서 HTML 리포트로 시각화하는 버전까지 확장해 드릴게요.
AIStor/MinIO 클러스터에 대해 warp로 데이터 채우기 → mc od로 분포 분석 → Prometheus로 성능 수집을 한 번에 수행하는 샘플입니다.
⚠️ 주의: 아래 스크립트에서
arp는 오타로 보며warp를 사용합니다. 각 바이너리 버전에 따라 옵션명이 약간 다를 수 있으니warp --help,mc od --help로 확인 후 필요 시 수정하세요.
aistor_bench.sh./aistor_bench.sh \
--alias aistor \
--url https://minio.example.com \
--access "MINIO_ACCESS_KEY" \
--secret "MINIO_SECRET_KEY" \
--bucket bench-$(date +%Y%m%d) \
--prefix run1/ \
--obj-size 24MiB \
--objects 1000000 \
--concurrency 512 \
--duration 0 \
--prom-url https://prometheus.example.com \
--prom-token "PROME_TOKEN"
#!/usr/bin/env bash
set -euo pipefail
# =====================
# Defaults
# =====================
ALIAS="aistor"
URL=""
ACCESS=""
SECRET=""
BUCKET="bench-$(date +%Y%m%d)"
PREFIX="run1/"
OBJ_SIZE="24MiB" # 예: 4KiB, 64KiB, 24MiB, 128MiB
OBJECTS=100000 # 총 오브젝트 개수
CONCURRENCY=256 # 동시성
DURATION=0 # 0이면 objects 개수 기준으로 종료
PART_SIZE="16MiB" # 멀티파트 파트 크기(대용량에 권장)
WORKDIR="$(pwd)/reports"
PROM_URL=""
PROM_TOKEN=""
WARP_BIN="warp"
MC_BIN="mc"
TS="$(date +%Y%m%d_%H%M%S)"
RUN_DIR="$WORKDIR/$TS"
mkdir -p "$RUN_DIR"
# =====================
# Args
# =====================
while [[ $# -gt 0 ]]; do
case "$1" in
--alias) ALIAS="$2"; shift 2;;
--url) URL="$2"; shift 2;;
--access) ACCESS="$2"; shift 2;;
--secret) SECRET="$2"; shift 2;;
--bucket) BUCKET="$2"; shift 2;;
--prefix) PREFIX="$2"; shift 2;;
--obj-size) OBJ_SIZE="$2"; shift 2;;
--objects) OBJECTS="$2"; shift 2;;
--concurrency) CONCURRENCY="$2"; shift 2;;
--duration) DURATION="$2"; shift 2;;
--part-size) PART_SIZE="$2"; shift 2;;
--workdir) WORKDIR="$2"; RUN_DIR="$WORKDIR/$TS"; shift 2;;
--prom-url) PROM_URL="$2"; shift 2;;
--prom-token) PROM_TOKEN="$2"; shift 2;;
--warp-bin) WARP_BIN="$2"; shift 2;;
--mc-bin) MC_BIN="$2"; shift 2;;
*) echo "Unknown arg: $1"; exit 1;;
esac
done
if [[ -z "$URL" || -z "$ACCESS" || -z "$SECRET" ]]; then
echo "[ERR] --url/--access/--secret 는 필수입니다"; exit 1
fi
# =====================
# Functions
# =====================
json() { jq -r ".${1}" 2>/dev/null || true; }
prom_query() {
local q="$1"; local out="$2";
if [[ -z "$PROM_URL" ]]; then
echo "[WARN] PROM_URL 미지정 - Prometheus 수집 생략"; return 0
fi
echo "[INFO] PromQL: $q"
if [[ -n "$PROM_TOKEN" ]]; then
curl -sS -H "Authorization: Bearer $PROM_TOKEN" --get --data-urlencode "query=$q" "$PROM_URL/api/v1/query" > "$out" || true
else
curl -sS --get --data-urlencode "query=$q" "$PROM_URL/api/v1/query" > "$out" || true
fi
}
# =====================
# Configure mc alias
# =====================
export MC_HOST_$ALIAS="$URL"
$MC_BIN alias set "$ALIAS" "$URL" "$ACCESS" "$SECRET" --api S3v4 >/dev/null
# =====================
# Prepare bucket/prefix
# =====================
$MC_BIN mb --ignore-existing "$ALIAS/$BUCKET" || true
# =====================
# Warp PUT (채우기)
# =====================
WARP_OUT_JSON="$RUN_DIR/warp_put.json"
WARP_CMD=("$WARP_BIN" put --host "$ALIAS" --bucket "$BUCKET" \
--obj.size "$OBJ_SIZE" --objects "$OBJECTS" \
--concurrent "$CONCURRENCY" --part.size "$PART_SIZE" \
--autoterm)
if [[ "$DURATION" != "0" ]]; then WARP_CMD+=(--duration "$DURATION"); fi
echo "[INFO] RUN: ${WARP_CMD[*]}"
"${WARP_CMD[@]}" | tee "$RUN_DIR/warp_put.log"
# warp는 보통 표준출력에 요약/JSON을 제공합니다. 버전에 따라 --json 옵션이 존재할 수도 있습니다.
# 필요 시 --json 추가 후 tee "$WARP_OUT_JSON" 로 캡처하세요.
# =====================
# mc od (분포 분석)
# =====================
# 참고: mc 버전에 따라 'mc od --json ALIAS/BUCKET[/PREFIX]' 사용법이 다를 수 있습니다.
OD_JSON="$RUN_DIR/od.json"
$MC_BIN od --json "$ALIAS/$BUCKET/$PREFIX" | tee "$OD_JSON"
# 히스토그램/요약 CSV 추출 (jq 필요)
OD_CSV="$RUN_DIR/od_summary.csv"
if command -v jq >/dev/null 2>&1; then
echo "metric,value" > "$OD_CSV"
AVG_SIZE=$(jq -r '..|.avgObjectSize? // empty' "$OD_JSON" | head -n1)
TOTAL_OBJS=$(jq -r '..|.objects? // empty' "$OD_JSON" | head -n1)
TOTAL_SIZE=$(jq -r '..|.totalSize? // empty' "$OD_JSON" | head -n1)
echo "avg_object_size,$AVG_SIZE" >> "$OD_CSV"
echo "objects,$TOTAL_OBJS" >> "$OD_CSV"
echo "total_size_bytes,$TOTAL_SIZE" >> "$OD_CSV"
fi
# =====================
# Prometheus: 핵심 메트릭 스냅샷 (벤치 직후)
# =====================
# 환경에 맞는 잡 라벨(job, instance 등)을 넣으세요.
PROM_DIR="$RUN_DIR/prom"
mkdir -p "$PROM_DIR"
# 예시 쿼리들 (필요 시 수정)
prom_query 'sum(rate(minio_s3_requests_total[5m])) by (api)' "$PROM_DIR/minio_s3_requests_rate.json"
prom_query 'sum(rate(minio_http_requests_duration_seconds_count[5m]))' "$PROM_DIR/minio_http_rps.json"
prom_query 'sum(rate(minio_network_sent_bytes_total[5m]))' "$PROM_DIR/minio_tx_bps.json"
prom_query 'sum(rate(minio_network_received_bytes_total[5m]))' "$PROM_DIR/minio_rx_bps.json"
prom_query 'sum(irate(node_cpu_seconds_total{mode!="idle"}[1m]))' "$PROM_DIR/node_cpu.json"
# 간단 CSV 요약 만들기 (가능한 경우)
SUMMARY_CSV="$RUN_DIR/summary.csv"
echo "key,value" > "$SUMMARY_CSV"
echo "alias,$ALIAS" >> "$SUMMARY_CSV"
echo "bucket,$BUCKET" >> "$SUMMARY_CSV"
echo "prefix,$PREFIX" >> "$SUMMARY_CSV"
echo "obj_size,$OBJ_SIZE" >> "$SUMMARY_CSV"
echo "objects,$OBJECTS" >> "$SUMMARY_CSV"
echo "concurrency,$CONCURRENCY" >> "$SUMMARY_CSV"
echo "part_size,$PART_SIZE" >> "$SUMMARY_CSV"
if command -v jq >/dev/null 2>&1; then
# warp 로그에서 대략적인 처리량/지연 추정치 추출 (버전에 따라 다를 수 있음)
TPS=$(grep -Eo '([0-9]+(\.[0-9]+)?) obj/s' "$RUN_DIR/warp_put.log" | awk '{print $1}' | tail -n1 || true)
THR=$(grep -Eo '([0-9]+(\.[0-9]+)?) (MiB|GiB)/s' "$RUN_DIR/warp_put.log" | tail -n1 || true)
echo "warp_ops_per_sec,$TPS" >> "$SUMMARY_CSV"
echo "warp_throughput,$THR" >> "$SUMMARY_CSV"
if [[ -f "$OD_CSV" ]]; then
AVG=$(awk -F, 'NR==2{print $2}' "$OD_CSV" 2>/dev/null || true)
echo "od_avg_object_size,$AVG" >> "$SUMMARY_CSV"
fi
fi
echo "[OK] 결과 디렉토리: $RUN_DIR"
warp, mc, jq, curl 설치되어 있어야 합니다.pipeline {
agent { label 'aistor-bench' }
options {
timestamps()
ansiColor('xterm')
}
parameters {
string(name: 'MINIO_URL', defaultValue: 'https://minio.example.com', description: 'MinIO/AIStor S3 Endpoint')
string(name: 'MINIO_ACCESS', defaultValue: 'ACCESS_KEY', description: 'S3 Access Key')
password(name: 'MINIO_SECRET', defaultValue: 'SECRET_KEY', description: 'S3 Secret Key')
string(name: 'ALIAS', defaultValue: 'aistor', description: 'mc alias 명')
string(name: 'BUCKET', defaultValue: 'bench-${new Date().format("yyyyMMdd")}', description: '테스트 버킷')
string(name: 'PREFIX', defaultValue: 'run1/', description: '오브젝트 prefix')
string(name: 'OBJ_SIZE', defaultValue: '24MiB', description: '예: 4KiB, 64KiB, 24MiB, 128MiB')
string(name: 'OBJECTS', defaultValue: '100000', description: '총 오브젝트 개수')
string(name: 'CONCURRENCY', defaultValue: '256', description: 'warp 동시성')
string(name: 'DURATION', defaultValue: '0', description: '0이면 objects 기준, 그 외는 예: 10m')
string(name: 'PART_SIZE', defaultValue: '16MiB', description: '멀티파트 파트 사이즈')
string(name: 'PROM_URL', defaultValue: 'https://prometheus.example.com', description: 'Prometheus URL (선택)')
password(name: 'PROM_TOKEN', defaultValue: '', description: 'Prometheus Bearer Token (옵션)')
}
environment {
WORKDIR = "${env.WORKSPACE}/reports"
}
stages {
stage('Checkout') {
steps {
deleteDir()
writeFile file: 'aistor_bench.sh', text: libraryResource('aistor_bench.sh')
sh 'chmod +x aistor_bench.sh'
}
}
stage('Run Bench (warp → od → prometheus)') {
steps {
sh '''
./aistor_bench.sh \
--alias ${ALIAS} \
--url ${MINIO_URL} \
--access ${MINIO_ACCESS} \
--secret ${MINIO_SECRET} \
--bucket ${BUCKET} \
--prefix ${PREFIX} \
--obj-size ${OBJ_SIZE} \
--objects ${OBJECTS} \
--concurrency ${CONCURRENCY} \
--duration ${DURATION} \
--part-size ${PART_SIZE} \
--workdir ${WORKDIR} \
--prom-url ${PROM_URL} \
--prom-token ${PROM_TOKEN}
'''
}
}
}
post {
always {
archiveArtifacts artifacts: 'reports/**', fingerprint: true
echo "결과 리포트 경로: ${WORKDIR}"
}
}
}
Note
- 위 Jenkinsfile은
libraryResource('aistor_bench.sh')로 스크립트를 로드하는 예시입니다. 간단히 쓰시려면Jenkinsfile옆에aistor_bench.sh를 커밋하고writeFile대신sh 'chmod +x aistor_bench.sh'만 호출하세요.
reports/
2025XXXX_HHMMSS/
warp_put.log # warp 실행 로그 (OPS/Throughput 요약 포함)
od.json # mc od 원본 JSON 결과
od_summary.csv # mc od 요약 CSV (평균 크기, 개수, 총 용량)
summary.csv # 전체 파라미터/핵심 요약치
prom/
minio_s3_requests_rate.json
minio_http_rps.json
minio_tx_bps.json
minio_rx_bps.json
node_cpu.json
CONCURRENCY 값을 크게(512~2048) 늘리되 CPU/IRQ 한계 감시 (sar -n DEV 1, ethtool -S, top -H).--part-size 8–32MiB로 조정, 멀티파트 병렬성 확보.GOMAXPROCS, ulimit -n, 오브젝트 캐시/메타디비 파라미터, EC 8:3/10:2 등 조합으로 시험.mc od 옵션/출력 스키마는 릴리스에 따라 다릅니다. mc od --help/--json으로 맞춰주세요._total vs _bytes 이름).mc alias set에 --insecure 또는 시스템 CA에 CA chain 추가.필요하시면 작은/큰 오브젝트 2경로를 한 파이프라인에서 연속으로 돌려 비교 그래프까지 그리는 버전(CSV → Grafana/Matplotlib)도 만들어 드릴게요.
좋은 질문이에요 👍
MinIO 같은 분산 오브젝트 스토리지에서 메타데이터 처리 한계(특히 IOPS 관점)는 보통 S3 API 레벨 요청 처리량과 백엔드 KV 엔진(MinIO는 디스크+erasure coding 메타데이터, 분산 락/namespace 관리) 처리량에 의해 결정됩니다.
NIC / TCP stack
MinIO metadata 경로
디스크/파일시스템
작은 오브젝트 (4–64KB)
큰 오브젝트 (≥ 24MB)
메타데이터 DB (namespace ops)
LIST, STAT, DELETE 성능이 급격히 떨어지기 시작.minio_s3_requests_total{api="PutObject"} / rate(...[1m]) → 초당 요청 수 (IOPS equivalent)minio_http_requests_duration_seconds_bucket → 요청 latency 분포minio_disk_storage_used_bytes, minio_node_disk_usage_total → 데이터/메타데이터 사용량 추이iostat -x 1, pidstat -d 1 → NVMe 메타데이터 IOPS 확인perf top 또는 flamegraph → MinIO 프로세스가 sys_futex, inode_lock 같은 커널 락에서 CPU를 많이 쓰는지 확인ethtool -S / sar -n DEV 1 → 작은 오브젝트일 때 네트워크 패킷 처리율 확인warp put --obj.size 4KiB --objects 10M ... → 소형 오브젝트 한계 확인warp get --obj.size 24MiB → 대형 오브젝트 throughput 확인10억개)와 사용률(90%)까지 채운 후 LIST/DELETE workload 돌려서 메타데이터 병목 측정 가능.👉 혹시 제가 실험용으로 작은 오브젝트 워크로드용 warp 스크립트랑, Prometheus에서 바로 IOPS vs Latency 그래프 뽑는 PromQL 예제도 만들어드릴까요?
좋습니다 🙌 그럼 작은 오브젝트 워크로드 측정용 warp 스크립트 + Prometheus에서 IOPS vs Latency 그래프용 PromQL 예제를 드릴게요.
warp_smallobj.sh
#!/bin/bash
# MinIO warp 테스트 스크립트 (작은 오브젝트 IOPS 한계 확인)
# 환경 설정
TARGET="myminio/testbucket" # 대상 버킷
OBJ_SIZE="4KiB" # 작은 오브젝트 크기
OBJECTS="1000000" # 생성할 오브젝트 수 (예: 100만개)
CONCURRENCY="512" # 동시 클라이언트 수
echo ">>> 버킷 준비 중..."
mc mb --ignore-existing $TARGET
echo ">>> 작은 오브젝트 쓰기 워크로드 시작 (PUT)..."
warp put --host $TARGET \
--obj.size $OBJ_SIZE \
--objects $OBJECTS \
--concurrent $CONCURRENCY \
--duration 5m \
--noclear --insecure \
--benchdata warp_put_4k.json
echo ">>> 작은 오브젝트 읽기 워크로드 시작 (GET)..."
warp get --host $TARGET \
--obj.size $OBJ_SIZE \
--objects $OBJECTS \
--concurrent $CONCURRENCY \
--duration 5m \
--noclear --insecure \
--benchdata warp_get_4k.json
echo ">>> 결과 CSV 생성"
warp report --benchdata warp_put_4k.json > report_put_4k.csv
warp report --benchdata warp_get_4k.json > report_get_4k.csv
warp_*_4k.json)는 그대로 Prometheus/Grafana와 대조 가능sum(rate(minio_s3_requests_total{api="PutObject"}[1m]))
GetObject로 바꾸면 읽기 처리량rate(minio_s3_requests_duration_seconds_sum{api="PutObject"}[1m])
/
rate(minio_s3_requests_duration_seconds_count{api="PutObject"}[1m])
histogram_quantile(0.95,
sum(rate(minio_http_requests_duration_seconds_bucket{api="PutObject"}[1m])) by (le)
)
✅ 정리
warp_smallobj.sh로 작은 오브젝트 IOPS/Latency를 측정👉 혹시 이걸 Jenkins 파이프라인에 연동해서 테스트 실행 후 Grafana 대시보드 스냅샷 자동 캡처 → 리포트 PDF 저장까지 자동화하는 버전도 만들어드릴까요?
좋습니다 🚀
그럼 작은 오브젝트 워크로드 측정 (warp) → Prometheus/Grafana 대시보드 스냅샷 캡처 → PDF 리포트 저장까지 자동화하는 Jenkins 파이프라인 예제를 드릴게요.
aistor_smallobj_bench.sh
#!/bin/bash
# 작은 오브젝트 워크로드 + Grafana 스냅샷 저장 스크립트
# === 환경 변수 ===
TARGET="myminio/testbucket"
OBJ_SIZE="4KiB"
OBJECTS="1000000"
CONCURRENCY="512"
DURATION="5m"
# Prometheus / Grafana 설정
GRAFANA_URL="http://grafana.local:3000"
GRAFANA_API_KEY="YOUR_GRAFANA_API_KEY"
DASHBOARD_UID="minio-perf" # Grafana 대시보드 UID
PANEL_ID="2" # 특정 Panel ID (IOPS vs Latency 그래프)
SNAPSHOT_FILE="grafana_snapshot.png"
REPORT_PDF="warp_report.pdf"
# === 스토리지 준비 ===
echo ">>> 버킷 생성"
mc mb --ignore-existing $TARGET
# === 워크로드 실행 ===
echo ">>> 작은 오브젝트 PUT 실행"
warp put --host $TARGET \
--obj.size $OBJ_SIZE \
--objects $OBJECTS \
--concurrent $CONCURRENCY \
--duration $DURATION \
--benchdata warp_put.json
echo ">>> 작은 오브젝트 GET 실행"
warp get --host $TARGET \
--obj.size $OBJ_SIZE \
--objects $OBJECTS \
--concurrent $CONCURRENCY \
--duration $DURATION \
--benchdata warp_get.json
# === 리포트 CSV 생성 ===
warp report --benchdata warp_put.json > report_put.csv
warp report --benchdata warp_get.json > report_get.csv
# === Grafana 스냅샷 캡처 ===
echo ">>> Grafana 대시보드 이미지 캡처"
curl -s -H "Authorization: Bearer $GRAFANA_API_KEY" \
-o $SNAPSHOT_FILE \
"$GRAFANA_URL/render/d/$DASHBOARD_UID/minio-perf?panelId=$PANEL_ID&width=1000&height=500"
# === PDF 리포트 합치기 ===
echo ">>> PDF 리포트 생성"
python3 <<'EOF'
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas
c = canvas.Canvas("warp_report.pdf", pagesize=A4)
c.setFont("Helvetica-Bold", 16)
c.drawString(50, 800, "MinIO Small Object Benchmark Report")
c.setFont("Helvetica", 12)
c.drawString(50, 770, "Object Size: 4KiB")
c.drawString(50, 750, "Concurrency: 512")
c.drawString(50, 730, "Duration: 5m")
c.drawString(50, 700, "PUT Results (report_put.csv)")
c.drawString(50, 680, "GET Results (report_get.csv)")
# Grafana 스냅샷 이미지 삽입
from reportlab.platypus import Image
img = Image("grafana_snapshot.png", width=500, height=250)
img.drawOn(c, 50, 400)
c.save()
EOF
echo ">>> 완료: warp_report.pdf"
Jenkinsfile
pipeline {
agent any
parameters {
string(name: 'OBJ_SIZE', defaultValue: '4KiB', description: 'Object size')
string(name: 'OBJECTS', defaultValue: '1000000', description: 'Number of objects')
string(name: 'CONCURRENCY', defaultValue: '512', description: 'Concurrency level')
string(name: 'DURATION', defaultValue: '5m', description: 'Test duration')
}
stages {
stage('Checkout') {
steps {
git 'https://your.repo.url/minio-bench.git'
}
}
stage('Run Warp Benchmark') {
steps {
sh "bash aistor_smallobj_bench.sh"
}
}
stage('Archive Results') {
steps {
archiveArtifacts artifacts: '*.csv, *.json, *.pdf, *.png', fingerprint: true
}
}
stage('Publish Report') {
steps {
publishHTML([reportDir: '.', reportFiles: 'warp_report.pdf', reportName: 'MinIO Benchmark Report'])
}
}
}
}
aistor_smallobj_bench.sh 실행✅ 이렇게 하면 테스트 끝나자마자 Jenkins에서 PDF 리포트를 바로 내려받을 수 있고, IOPS vs Latency 그래프까지 자동으로 포함돼요.
좋습니다 👍 이제 멀티 오브젝트 사이즈 (4KiB / 64KiB / 24MiB / 128MiB) 를 한 번에 돌리고 → 결과를 모두 모아 → 비교 그래프 + PDF 리포트까지 Jenkins 파이프라인으로 자동화하는 버전을 드릴게요.
aistor_multisize_bench.sh
#!/bin/bash
# 여러 오브젝트 사이즈 벤치마크 후 PDF 리포트 자동 생성
# === 환경 변수 ===
TARGET="myminio/testbucket"
OBJECTS="200000" # 사이즈 커질수록 개수는 줄여야 시간/공간 절약
CONCURRENCY="256"
DURATION="3m"
SIZES=("4KiB" "64KiB" "24MiB" "128MiB")
GRAFANA_URL="http://grafana.local:3000"
GRAFANA_API_KEY="YOUR_GRAFANA_API_KEY"
DASHBOARD_UID="minio-perf"
PANEL_ID="2"
mkdir -p results
# === 버킷 준비 ===
mc mb --ignore-existing $TARGET
# === 워크로드 반복 실행 ===
for SIZE in "${SIZES[@]}"; do
echo ">>> 워크로드 시작 (PUT/GET, size=$SIZE)"
warp put --host $TARGET \
--obj.size $SIZE \
--objects $OBJECTS \
--concurrent $CONCURRENCY \
--duration $DURATION \
--benchdata results/warp_put_${SIZE}.json
warp get --host $TARGET \
--obj.size $SIZE \
--objects $OBJECTS \
--concurrent $CONCURRENCY \
--duration $DURATION \
--benchdata results/warp_get_${SIZE}.json
warp report --benchdata results/warp_put_${SIZE}.json > results/report_put_${SIZE}.csv
warp report --benchdata results/warp_get_${SIZE}.json > results/report_get_${SIZE}.csv
done
# === Grafana 스냅샷 저장 ===
curl -s -H "Authorization: Bearer $GRAFANA_API_KEY" \
-o results/grafana_snapshot.png \
"$GRAFANA_URL/render/d/$DASHBOARD_UID/minio-perf?panelId=$PANEL_ID&width=1200&height=600"
# === PDF 통합 리포트 생성 ===
python3 <<'EOF'
import glob
import pandas as pd
import matplotlib.pyplot as plt
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas
# 결과 CSV 불러오기
sizes = ["4KiB", "64KiB", "24MiB", "128MiB"]
put_rates = []
get_rates = []
for size in sizes:
put = pd.read_csv(f"results/report_put_{size}.csv")
get = pd.read_csv(f"results/report_get_{size}.csv")
put_rate = put["Throughput"].iloc[0]
get_rate = get["Throughput"].iloc[0]
put_rates.append(put_rate)
get_rates.append(get_rate)
# 그래프 생성
plt.figure(figsize=(8,5))
plt.plot(sizes, put_rates, marker="o", label="PUT ops/s")
plt.plot(sizes, get_rates, marker="s", label="GET ops/s")
plt.xlabel("Object Size")
plt.ylabel("Throughput (ops/s)")
plt.title("MinIO Performance by Object Size")
plt.legend()
plt.grid(True)
plt.savefig("results/summary.png")
# PDF 생성
c = canvas.Canvas("results/warp_multisize_report.pdf", pagesize=A4)
c.setFont("Helvetica-Bold", 16)
c.drawString(50, 800, "MinIO Multi-Size Benchmark Report")
c.setFont("Helvetica", 12)
y = 770
for size, pr, gr in zip(sizes, put_rates, get_rates):
c.drawString(50, y, f"Size={size}: PUT={pr:.2f} ops/s, GET={gr:.2f} ops/s")
y -= 20
c.drawImage("results/summary.png", 50, 400, width=500, height=300)
c.drawImage("results/grafana_snapshot.png", 50, 100, width=500, height=250)
c.save()
EOF
echo ">>> 완료: results/warp_multisize_report.pdf"
pipeline {
agent any
stages {
stage('Checkout') {
steps {
git 'https://your.repo.url/minio-bench.git'
}
}
stage('Run Multi-Size Warp Benchmark') {
steps {
sh "bash aistor_multisize_bench.sh"
}
}
stage('Archive Results') {
steps {
archiveArtifacts artifacts: 'results/*.csv, results/*.json, results/*.png, results/*.pdf', fingerprint: true
}
}
stage('Publish Report') {
steps {
publishHTML([reportDir: 'results', reportFiles: 'warp_multisize_report.pdf', reportName: 'MinIO Benchmark Report'])
}
}
}
}
report_put_*.csv, report_get_*.csv)summary.png)grafana_snapshot.png)warp_multisize_report.pdf) → Jenkins에서 다운로드 가능✅ 이렇게 하면 한 번의 파이프라인 실행으로 4KiB → 64KiB → 24MiB → 128MiB 성능 곡선과 Grafana 실시간 메트릭 스냅샷이 모두 들어간 PDF가 자동으로 생성돼요.
👉 혹시 PDF에 Latency (평균, P95) 까지 포함해서 Throughput vs Latency 이중 축 그래프로 보여드릴까요?
좋은 질문이에요 👍 성능테스트에서 object size를 어떻게 설정하느냐는 워크로드 특성을 얼마나 잘 재현하느냐와 직결됩니다. 지금 상황(기존 워크로드, 향후 마이그레이션 계획)을 놓고 보면 이렇게 생각하면 돼요:
1B ~ 1KiB
100MiB+
소형 오브젝트 (3KiB~512KiB)
대형 오브젝트 (24MiB / 128MiB)
👉 운영과 무관한 사이즈(1B, 1KiB)는 짧게 sanity check 정도로만,
👉 실제 중요 workload (3–512KiB / 24MiB / 128MiB)는 집중적으로 성능曲線을 뽑는 게 효과적입니다.
즉,
Hadoop block size 128MiB라고 해서 S3 object를 꼭 128MiB로 맞출 필요는 없음
결론적으로:
✅ 요약
👉 원하시면 제가 위에 추천한 테스트 사이즈 세트(4KiB, 64KiB, 256KiB, 1MiB, 8MiB, 24MiB, 128MiB) 기준으로 warp + Jenkinsfile 멀티러너 자동화 버전을 만들어드릴까요?