[dragonfly] load-test

진웅·2025년 10월 30일

CNCF.DRAGONFLY

목록 보기
2/2

🎯 테스트 시나리오 개요

Phase 1: 초기 구성
├── iclhk8wk48 (테스트 그룹)
├── iclhk8wk49 (테스트 그룹)
├── iclhk8wk50 (테스트 그룹)
├── iclhk8wk51 (비교 그룹 - Dragonfly 없음)
├── iclhk8wk52 (비교 그룹 - Dragonfly 없음)
├── iclhk8wk53 (비교 그룹 - Dragonfly 없음)
└── iclhk8wk54 (비교 그룹 - Dragonfly 없음)

Phase 2: 성능 비교
├── 테스트 그룹 (48-50): Dragonfly P2P
└── 비교 그룹 (51-54): 직접 다운로드

Phase 3: 전체 확장 (검증 후)
└── 모든 노드에 Dragonfly 적용

📋 Phase 1: 초기 설정

1-1. 노드 라벨링

# 테스트 그룹 라벨 (48-50)
kubectl label node iclhk8wk48 dragonfly-test=enabled dragonfly-group=test
kubectl label node iclhk8wk49 dragonfly-test=enabled dragonfly-group=test
kubectl label node iclhk8wk50 dragonfly-test=enabled dragonfly-group=test

# 비교 그룹 라벨 (51-54)
kubectl label node iclhk8wk51 dragonfly-group=control
kubectl label node iclhk8wk52 dragonfly-group=control
kubectl label node iclhk8wk53 dragonfly-group=control
kubectl label node iclhk8wk54 dragonfly-group=control

# 확인
echo "=== 테스트 그룹 (Dragonfly 적용) ==="
kubectl get nodes -l dragonfly-test=enabled

echo "=== 비교 그룹 (Dragonfly 미적용) ==="
kubectl get nodes -l dragonfly-group=control

echo "=== 전체 노드 상태 ==="
kubectl get nodes -L dragonfly-test,dragonfly-group

1-2. Dragonfly Values 파일 (테스트용)

# dragonfly-test-values.yaml

# ==========================================
# Dragonfly 테스트 배포
# Chart: 1.4.15 (App: 2.3.3)
# 노드: iclhk8wk48-50 (3대)
# 폐쇄망: nexus.com
# ==========================================

global:
  # 폐쇄망 Private Registry
  imageRegistry: "nexus.com:15403"

# ==========================================
# Manager (소규모 테스트)
# ==========================================
manager:
  enable: true
  replicas: 1  # 테스트는 1개로
  
  image:
    repository: nexus.com:15403/dragonflyoss/manager
    tag: v2.3.3
    pullPolicy: IfNotPresent
  
  resources:
    requests:
      cpu: 500m
      memory: 1Gi
    limits:
      cpu: 1000m
      memory: 2Gi
  
  service:
    type: ClusterIP
    ports:
      - name: http
        port: 8080
        targetPort: 8080
      - name: grpc
        port: 65003
        targetPort: 65003
  
  # 메트릭 활성화
  metrics:
    enable: true
    port: 8000
    path: /metrics
    serviceMonitor:
      enable: true
      interval: 30s
      labels:
        release: prometheus

# ==========================================
# Scheduler (소규모 테스트)
# ==========================================
scheduler:
  enable: true
  replicas: 1  # 테스트는 1개로
  
  image:
    repository: nexus.com:15403/dragonflyoss/scheduler
    tag: v2.3.3
    pullPolicy: IfNotPresent
  
  resources:
    requests:
      cpu: 500m
      memory: 1Gi
    limits:
      cpu: 1000m
      memory: 2Gi
  
  service:
    type: ClusterIP
    ports:
      - name: http
        port: 8002
        targetPort: 8002
  
  # 메트릭 활성화
  metrics:
    enable: true
    port: 8000
    path: /metrics
    serviceMonitor:
      enable: true
      interval: 30s
      labels:
        release: prometheus
  
  config:
    scheduler:
      algorithm: default
      backSourceCount: 3
      filterParentLimit: 40
    manager:
      schedulerClusterID: 1

# ==========================================
# Seed Peer (소규모 테스트)
# ==========================================
seedClient:
  enable: true
  replicas: 2  # 테스트는 2개로 (3노드에 2개)
  
  image:
    repository: nexus.com:15403/dragonflyoss/client
    tag: v0.1.118
    pullPolicy: IfNotPresent
  
  resources:
    requests:
      cpu: 1000m
      memory: 2Gi
    limits:
      cpu: 2000m
      memory: 4Gi
  
  # Persistence 필수
  persistence:
    enable: true
    size: 50Gi  # 테스트는 작게
    storageClass: "local-path"  # 실제 StorageClass로 변경
    accessModes:
      - ReadWriteOnce
  
  # 메트릭 활성화
  metrics:
    enable: true
    port: 8000
    path: /metrics
    serviceMonitor:
      enable: true
      interval: 30s
      labels:
        release: prometheus
  
  config:
    seedPeer:
      enable: true
      type: "super"
      clusterID: 1
    
    proxy:
      # 폐쇄망 Registry
      registryMirror:
        addr: https://nexus.com:15403
      
      disableBackToSource: false  # Fallback 활성화
      
      # 보안 설정 (기존 인증서 사용)
      security:
        insecure: false
        cacert: "/etc/containerd/certs.d/nexus.com:15403/ca.crt"
        cert: "/etc/containerd/certs.d/nexus.com:15403/client.crt"
        key: "/etc/containerd/certs.d/nexus.com:15403/client.key"
    
    download:
      concurrentPieceCount: 10
      pieceDownloadTimeout: 60s
      rateLimit: 0
    
    upload:
      rateLimit: 0
      maxConcurrency: 100
    
    storage:
      dir: /var/lib/dragonfly
      taskExpireTime: 12h  # 테스트 기간
      diskGCThreshold: 85
      diskGCInterval: 30s
  
  # 기존 인증서 마운트
  volumeMounts:
    - name: containerd-certs
      mountPath: /etc/containerd/certs.d
      readOnly: true
  
  volumes:
    - name: containerd-certs
      hostPath:
        path: /etc/containerd/certs.d
        type: Directory
  
  # 분산 배치
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchExpressions:
              - key: app
                operator: In
                values:
                  - dragonfly-seed-client
          topologyKey: kubernetes.io/hostname

# ==========================================
# Client (테스트 노드만!) 🔥
# ==========================================
client:
  enable: true
  
  # 핵심: 테스트 노드만 선택!
  nodeSelector:
    dragonfly-test: enabled  # 48-50번만!
  
  image:
    repository: nexus.com:15403/dragonflyoss/client
    tag: v0.1.118
    pullPolicy: IfNotPresent
  
  resources:
    requests:
      cpu: 500m
      memory: 512Mi
    limits:
      cpu: 1000m
      memory: 1Gi
  
  # Persistence
  persistence:
    enable: true
    size: 20Gi  # 테스트는 작게
    storageClass: "local-path"
    accessModes:
      - ReadWriteOnce
  
  # 메트릭 활성화
  metrics:
    enable: true
    port: 8000
    path: /metrics
    serviceMonitor:
      enable: true
      interval: 30s
      labels:
        release: prometheus
  
  config:
    proxy:
      registryMirror:
        addr: https://nexus.com:15403
      
      listenAddress: "0.0.0.0:65001"
      
      disableBackToSource: false  # 필수!
      
      # 보안 설정
      security:
        insecure: false
        cacert: "/etc/containerd/certs.d/nexus.com:15403/ca.crt"
        cert: "/etc/containerd/certs.d/nexus.com:15403/client.crt"
        key: "/etc/containerd/certs.d/nexus.com:15403/client.key"
      
      # 여러 Registry 지원
      proxies:
        # Private Registry (메인)
        - regx: "nexus.com:15403/*"
          useHTTPS: true
          direct: true
        
        # Docker Hub (폐쇄망 미러)
        - regx: "docker.io/*"
          useHTTPS: true
          direct: true
        
        # 기타 Registry
        - regx: "gcr.io/*"
          useHTTPS: true
          direct: true
        - regx: "ghcr.io/*"
          useHTTPS: true
          direct: true
        - regx: "k8s.gcr.io/*"
          useHTTPS: true
          direct: true
        - regx: "quay.io/*"
          useHTTPS: true
          direct: true
        - regx: "registry.k8s.io/*"
          useHTTPS: true
          direct: true
    
    download:
      concurrentPieceCount: 10
      pieceDownloadTimeout: 30s
      downloadTimeout: 10m
      downloadRetryCount: 3
    
    storage:
      dir: /var/lib/dragonfly
      taskExpireTime: 6h
      diskGCThreshold: 90
      diskGCInterval: 15s
  
  # 인증서 마운트
  volumeMounts:
    - name: containerd-certs
      mountPath: /etc/containerd/certs.d
      readOnly: true
  
  volumes:
    - name: containerd-certs
      hostPath:
        path: /etc/containerd/certs.d
        type: Directory
  
  enableHost: true

# ==========================================
# dfinit (테스트 노드만!)
# ==========================================
dfinit:
  enable: true
  restartContainerRuntime: true
  
  # 핵심: 테스트 노드만!
  nodeSelector:
    dragonfly-test: enabled
  
  image:
    repository: nexus.com:15403/dragonflyoss/dfinit
    tag: v0.1.118
    pullPolicy: IfNotPresent
  
  config:
    containerRuntime:
      containerd:
        configPath: /etc/containerd/config.toml
        
        # 모든 Registry에 Dragonfly 적용
        registries:
          # Private Registry (메인)
          - hostNamespace: nexus.com:15403
            serverAddr: https://nexus.com:15403
            capabilities: ['pull', 'resolve']
          
          # Docker Hub
          - hostNamespace: docker.io
            serverAddr: https://registry-1.docker.io
            capabilities: ['pull', 'resolve']
          
          # GCR
          - hostNamespace: gcr.io
            serverAddr: https://gcr.io
            capabilities: ['pull', 'resolve']
          
          # GitHub CR
          - hostNamespace: ghcr.io
            serverAddr: https://ghcr.io
            capabilities: ['pull', 'resolve']
          
          # Kubernetes (old)
          - hostNamespace: k8s.gcr.io
            serverAddr: https://k8s.gcr.io
            capabilities: ['pull', 'resolve']
          
          # Quay
          - hostNamespace: quay.io
            serverAddr: https://quay.io
            capabilities: ['pull', 'resolve']
          
          # Kubernetes (new)
          - hostNamespace: registry.k8s.io
            serverAddr: https://registry.k8s.io
            capabilities: ['pull', 'resolve']

# ==========================================
# 외부 MySQL
# ==========================================
mysql:
  enable: false

externalMysql:
  migrate: true
  host: mysql.dragonfly-infra.svc.cluster.local
  port: 3306
  username: dragonfly
  password: "DragonflyPassword123!"
  database: dragonfly
  maxOpenConns: 50   # 테스트는 작게
  maxIdleConns: 10

# ==========================================
# 외부 Redis
# ==========================================
redis:
  enable: false

externalRedis:
  addrs:
    - redis.dragonfly-infra.svc.cluster.local:6379
  password: "RedisPassword123!"
  db: 0
  brokerDB: 1
  backendDB: 2

# ==========================================
# 보안
# ==========================================
securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  fsGroup: 1000

🚀 Phase 2: 설치 및 배포

2-1. 인프라 준비 (MySQL/Redis)

# 이미 구축되어 있다면 생략

# MySQL/Redis 배포
kubectl apply -f mysql-deployment.yaml
kubectl apply -f redis-deployment.yaml

# 확인
kubectl get pods -n dragonfly-infra

2-2. Dragonfly 설치

# install-dragonfly-test.sh
#!/bin/bash

set -e

echo "================================================"
echo "Dragonfly 테스트 배포"
echo "노드: iclhk8wk48-50 (3대)"
echo "================================================"

NAMESPACE="dragonfly-system"
RELEASE_NAME="dragonfly"
CHART_PATH="./dragonfly-1.4.15.tgz"
VALUES_FILE="./dragonfly-test-values.yaml"

# 1. Namespace 생성
echo "[1/5] Namespace 생성..."
kubectl create namespace ${NAMESPACE} --dry-run=client -o yaml | kubectl apply -f -

# 2. 노드 라벨 확인
echo "[2/5] 테스트 노드 확인..."
echo "=== 테스트 그룹 (Dragonfly 적용) ==="
kubectl get nodes -l dragonfly-test=enabled
echo ""
echo "=== 비교 그룹 (Dragonfly 미적용) ==="
kubectl get nodes -l dragonfly-group=control
echo ""

read -p "노드 라벨이 정확합니까? (yes/no): " CONFIRM
if [ "$CONFIRM" != "yes" ]; then
  echo "노드 라벨을 먼저 설정하세요."
  exit 1
fi

# 3. Helm 설치
echo "[3/5] Dragonfly 설치 중..."
helm install ${RELEASE_NAME} ${CHART_PATH} \
  --namespace ${NAMESPACE} \
  --values ${VALUES_FILE} \
  --wait \
  --timeout 10m

# 4. 배포 확인
echo "[4/5] 배포 상태 확인..."
kubectl get pods -n ${NAMESPACE} -o wide

# 5. Client가 3대만 배포되었는지 확인
echo "[5/5] Client Pod 확인..."
CLIENT_COUNT=$(kubectl get pods -n ${NAMESPACE} -l component=client --no-headers | wc -l)
echo "Client pods: ${CLIENT_COUNT}"

if [ "${CLIENT_COUNT}" -ne 3 ]; then
  echo "⚠️ 경고: Client pods가 3개가 아닙니다 (${CLIENT_COUNT}개)"
else
  echo "✅ Client pods 정상 (3개)"
fi

# Client가 테스트 노드에만 있는지 확인
echo ""
echo "=== Client Pod 배포 위치 ==="
kubectl get pods -n ${NAMESPACE} -l component=client -o wide

echo ""
echo "================================================"
echo "✅ Dragonfly 테스트 배포 완료!"
echo "================================================"
echo ""
echo "다음 단계:"
echo "1. 기능 테스트: ./test-functionality.sh"
echo "2. 성능 비교 테스트: ./test-comparison.sh"
echo "3. 모니터링: kubectl port-forward -n ${NAMESPACE} svc/dragonfly-manager 8080:8080"

2-3. 설치 실행

# 실행 권한
chmod +x install-dragonfly-test.sh

# 설치
./install-dragonfly-test.sh

# 예상 출력:
# [1/5] Namespace 생성...
# [2/5] 테스트 노드 확인...
# === 테스트 그룹 (Dragonfly 적용) ===
# NAME          STATUS   ROLES    AGE
# iclhk8wk48    Ready    <none>   10d
# iclhk8wk49    Ready    <none>   10d
# iclhk8wk50    Ready    <none>   10d
#
# === 비교 그룹 (Dragonfly 미적용) ===
# NAME          STATUS   ROLES    AGE
# iclhk8wk51    Ready    <none>   10d
# iclhk8wk52    Ready    <none>   10d
# iclhk8wk53    Ready    <none>   10d
# iclhk8wk54    Ready    <none>   10d

📊 Phase 3: 성능 비교 테스트

3-1. 비교 테스트 스크립트

# test-comparison.sh
#!/bin/bash

set -e

NAMESPACE="dragonfly-system"
TEST_IMAGE="nexus.com:15403/test-app:1gb"  # 큰 이미지 준비
ITERATIONS=5

echo "================================================"
echo "Dragonfly 성능 비교 테스트"
echo "================================================"
echo "테스트 그룹: iclhk8wk48-50 (Dragonfly)"
echo "비교 그룹: iclhk8wk51-54 (직접 다운로드)"
echo "이미지: ${TEST_IMAGE}"
echo "반복: ${ITERATIONS}회"
echo "================================================"

# 결과 파일
RESULT_FILE="comparison-results-$(date +%Y%m%d-%H%M%S).txt"

# ==========================================
# 1. 캐시 초기화
# ==========================================
echo ""
echo "[Step 1] 캐시 초기화..."

# Dragonfly 캐시 초기화 (테스트 그룹)
echo "Dragonfly 캐시 초기화 중..."
for pod in $(kubectl get pods -n ${NAMESPACE} -l component=client -o name); do
  kubectl exec -n ${NAMESPACE} ${pod} -- rm -rf /var/lib/dragonfly/storage/tasks/* 2>/dev/null || true
done

# Containerd 캐시 초기화 (모든 노드)
echo "Containerd 이미지 삭제 중..."
for node in iclhk8wk{48..54}; do
  ssh ${node} "crictl rmi ${TEST_IMAGE}" 2>/dev/null || true
done

echo "✅ 캐시 초기화 완료"
sleep 5

# ==========================================
# 2. 테스트 그룹 (Dragonfly) - Cold Start
# ==========================================
echo ""
echo "[Step 2] 테스트 그룹 - Cold Start (첫 다운로드)"
echo "---"

TEST_GROUP_COLD_TIMES=()

for i in $(seq 1 ${ITERATIONS}); do
  echo "Iteration ${i}/${ITERATIONS}..."
  
  START=$(date +%s)
  
  # 테스트 그룹 노드에 Pod 배포
  kubectl run test-cold-${i} --image=${TEST_IMAGE} \
    --overrides='{"spec":{"nodeSelector":{"dragonfly-test":"enabled"}}}' \
    2>/dev/null || true
  
  # Pod Ready 대기
  kubectl wait --for=condition=Ready pod/test-cold-${i} --timeout=600s 2>/dev/null || true
  
  END=$(date +%s)
  TIME=$((END - START))
  TEST_GROUP_COLD_TIMES+=($TIME)
  
  echo "  → 시간: ${TIME}초"
  
  # Pod 삭제
  kubectl delete pod test-cold-${i} --ignore-not-found=true
  
  sleep 5
done

# 평균 계산
TEST_COLD_AVG=$(echo "${TEST_GROUP_COLD_TIMES[@]}" | awk '{sum=0; for(i=1;i<=NF;i++){sum+=$i}; print sum/NF}')
echo ""
echo "테스트 그룹 Cold Start 평균: ${TEST_COLD_AVG}초"

# ==========================================
# 3. 비교 그룹 (직접) - Cold Start
# ==========================================
echo ""
echo "[Step 3] 비교 그룹 - Cold Start (첫 다운로드)"
echo "---"

CONTROL_GROUP_COLD_TIMES=()

# 캐시 초기화 (비교 그룹만)
for node in iclhk8wk{51..54}; do
  ssh ${node} "crictl rmi ${TEST_IMAGE}" 2>/dev/null || true
done
sleep 5

for i in $(seq 1 ${ITERATIONS}); do
  echo "Iteration ${i}/${ITERATIONS}..."
  
  START=$(date +%s)
  
  # 비교 그룹 노드에 Pod 배포
  kubectl run control-cold-${i} --image=${TEST_IMAGE} \
    --overrides='{"spec":{"nodeSelector":{"dragonfly-group":"control"}}}' \
    2>/dev/null || true
  
  # Pod Ready 대기
  kubectl wait --for=condition=Ready pod/control-cold-${i} --timeout=600s 2>/dev/null || true
  
  END=$(date +%s)
  TIME=$((END - START))
  CONTROL_GROUP_COLD_TIMES+=($TIME)
  
  echo "  → 시간: ${TIME}초"
  
  # Pod 삭제
  kubectl delete pod control-cold-${i} --ignore-not-found=true
  
  sleep 5
done

# 평균 계산
CONTROL_COLD_AVG=$(echo "${CONTROL_GROUP_COLD_TIMES[@]}" | awk '{sum=0; for(i=1;i<=NF;i++){sum+=$i}; print sum/NF}')
echo ""
echo "비교 그룹 Cold Start 평균: ${CONTROL_COLD_AVG}초"

# ==========================================
# 4. 테스트 그룹 - Cache Hit
# ==========================================
echo ""
echo "[Step 4] 테스트 그룹 - Cache Hit (캐시 사용)"
echo "---"

TEST_GROUP_CACHE_TIMES=()

for i in $(seq 1 ${ITERATIONS}); do
  echo "Iteration ${i}/${ITERATIONS}..."
  
  START=$(date +%s)
  
  kubectl run test-cache-${i} --image=${TEST_IMAGE} \
    --overrides='{"spec":{"nodeSelector":{"dragonfly-test":"enabled"}}}' \
    2>/dev/null || true
  
  kubectl wait --for=condition=Ready pod/test-cache-${i} --timeout=600s 2>/dev/null || true
  
  END=$(date +%s)
  TIME=$((END - START))
  TEST_GROUP_CACHE_TIMES+=($TIME)
  
  echo "  → 시간: ${TIME}초"
  
  kubectl delete pod test-cache-${i} --ignore-not-found=true
  
  sleep 3
done

TEST_CACHE_AVG=$(echo "${TEST_GROUP_CACHE_TIMES[@]}" | awk '{sum=0; for(i=1;i<=NF;i++){sum+=$i}; print sum/NF}')
echo ""
echo "테스트 그룹 Cache Hit 평균: ${TEST_CACHE_AVG}초"

# ==========================================
# 5. 결과 정리
# ==========================================
echo ""
echo "================================================"
echo "성능 비교 결과"
echo "================================================"

# 결과 저장
cat > ${RESULT_FILE} <<EOF
================================================
Dragonfly 성능 비교 테스트 결과
날짜: $(date)
================================================

테스트 설정:
- 테스트 그룹: iclhk8wk48-50 (Dragonfly)
- 비교 그룹: iclhk8wk51-54 (직접)
- 이미지: ${TEST_IMAGE}
- 반복 횟수: ${ITERATIONS}

Cold Start (첫 다운로드):
- 테스트 그룹: ${TEST_COLD_AVG}초
- 비교 그룹: ${CONTROL_COLD_AVG}초
- 차이: $(echo "scale=2; ${CONTROL_COLD_AVG} - ${TEST_COLD_AVG}" | bc)초
- 개선율: $(echo "scale=2; (${CONTROL_COLD_AVG} - ${TEST_COLD_AVG}) / ${CONTROL_COLD_AVG} * 100" | bc)%

Cache Hit (캐시 사용):
- 테스트 그룹: ${TEST_CACHE_AVG}초
- Speedup: $(echo "scale=2; ${TEST_COLD_AVG} / ${TEST_CACHE_AVG}" | bc)x

상세 데이터:
테스트 그룹 Cold: ${TEST_GROUP_COLD_TIMES[@]}
비교 그룹 Cold: ${CONTROL_GROUP_COLD_TIMES[@]}
테스트 그룹 Cache: ${TEST_GROUP_CACHE_TIMES[@]}
================================================
EOF

cat ${RESULT_FILE}

echo ""
echo "✅ 결과 저장: ${RESULT_FILE}"
echo ""
echo "다음 단계:"
echo "1. Prometheus 메트릭 확인"
echo "2. Grafana 대시보드 확인"
echo "3. 만족스러우면 전체 노드 확장"

3-2. 테스트 실행

# 실행 권한
chmod +x test-comparison.sh

# 테스트 실행
./test-comparison.sh

# 예상 소요 시간: 30-60분
# (이미지 크기와 네트워크 속도에 따라 다름)

3-3. 메트릭 확인

# Prometheus 메트릭 확인
kubectl port-forward -n dragonfly-system svc/dragonfly-manager 8080:8080 &

# 캐시 히트율
curl -s http://localhost:8080/metrics | grep cache_hit

# P2P 다운로드 비율
curl -s http://localhost:8080/metrics | grep download_piece | grep peer

# Scheduler Task 수
curl -s http://localhost:8080/metrics | grep scheduler_tasks

📈 Phase 4: 모니터링 및 분석

4-1. 실시간 모니터링 스크립트

# monitor-comparison.sh
#!/bin/bash

NAMESPACE="dragonfly-system"

echo "================================================"
echo "Dragonfly 실시간 모니터링"
echo "================================================"

while true; do
  clear
  echo "========== $(date) =========="
  echo ""
  
  # Pod 상태
  echo "=== Pod Status ==="
  kubectl get pods -n ${NAMESPACE}
  echo ""
  
  # 테스트 그룹 노드 리소스
  echo "=== 테스트 그룹 노드 (48-50) ==="
  kubectl top nodes | grep -E "(NAME|iclhk8wk(48|49|50))"
  echo ""
  
  # 비교 그룹 노드 리소스
  echo "=== 비교 그룹 노드 (51-54) ==="
  kubectl top nodes | grep -E "(NAME|iclhk8wk(51|52|53|54))"
  echo ""
  
  # Client 메트릭
  echo "=== Dragonfly Client 메트릭 ==="
  CLIENT_POD=$(kubectl get pods -n ${NAMESPACE} -l component=client -o name | head -1)
  if [ -n "${CLIENT_POD}" ]; then
    kubectl exec -n ${NAMESPACE} ${CLIENT_POD} -- curl -s http://localhost:8000/metrics 2>/dev/null | \
      grep -E "cache_hit|cache_miss|download_piece" | tail -5
  fi
  
  echo ""
  echo "새로고침: 10초마다 (Ctrl+C로 종료)"
  sleep 10
done
# 실행
chmod +x monitor-comparison.sh
./monitor-comparison.sh

4-2. 로그 확인

# 테스트 그룹 - Dragonfly Client 로그
kubectl logs -n dragonfly-system -l component=client --tail=100 -f

# 특정 노드의 Client 로그
CLIENT_POD=$(kubectl get pods -n dragonfly-system -l component=client -o wide | grep iclhk8wk48 | awk '{print $1}')
kubectl logs -n dragonfly-system ${CLIENT_POD} -f

# P2P 다운로드 확인
kubectl logs -n dragonfly-system -l component=client --tail=1000 | grep -i "download from peer"

# 캐시 히트 확인
kubectl logs -n dragonfly-system -l component=client --tail=1000 | grep -i "cache hit"

🎯 Phase 5: 전체 확장 (검증 완료 후)

5-1. 전체 배포용 Values

# dragonfly-production-values.yaml

# ==========================================
# 테스트 → 프로덕션 변경사항:
# 1. nodeSelector 제거 (전체 노드)
# 2. Replicas 증가
# 3. 리소스 증가
# 4. 스토리지 크기 증가
# ==========================================

# ... (이전과 동일) ...

# Client - nodeSelector 제거!
client:
  enable: true
  
  # nodeSelector 제거 → 모든 노드에 배포!
  # nodeSelector:
  #   dragonfly-test: enabled
  
  # ... (나머지 설정 동일) ...

# dfinit - nodeSelector 제거!
dfinit:
  enable: true
  
  # nodeSelector 제거 → 모든 노드 적용!
  # nodeSelector:
  #   dragonfly-test: enabled
  
  # ... (나머지 설정 동일) ...

5-2. 전체 확장 스크립트

# upgrade-to-production.sh
#!/bin/bash

set -e

NAMESPACE="dragonfly-system"
RELEASE_NAME="dragonfly"
CHART_PATH="./dragonfly-1.4.15.tgz"
VALUES_FILE="./dragonfly-production-values.yaml"

echo "================================================"
echo "Dragonfly 전체 노드 확장"
echo "테스트: iclhk8wk48-50 (3대)"
echo "  →  전체: iclhk8wk48-54 (7대)"
echo "================================================"

# 확인
read -p "테스트 결과가 만족스럽습니까? (yes/no): " CONFIRM
if [ "$CONFIRM" != "yes" ]; then
  echo "취소되었습니다."
  exit 1
fi

# 백업
echo "[1/4] 현재 설정 백업..."
helm get values ${RELEASE_NAME} -n ${NAMESPACE} > values-test-backup-$(date +%Y%m%d).yaml
echo "✅ 백업 완료"

# Helm Upgrade
echo "[2/4] Helm Upgrade 실행..."
helm upgrade ${RELEASE_NAME} ${CHART_PATH} \
  --namespace ${NAMESPACE} \
  --values ${VALUES_FILE} \
  --wait \
  --timeout 15m

# 확인
echo "[3/4] 배포 상태 확인..."
kubectl get pods -n ${NAMESPACE} -o wide

CLIENT_COUNT=$(kubectl get pods -n ${NAMESPACE} -l component=client --no-headers | wc -l)
echo ""
echo "Client pods: ${CLIENT_COUNT}"

if [ "${CLIENT_COUNT}" -ne 7 ]; then
  echo "⚠️ 경고: Client pods가 7개가 아닙니다 (${CLIENT_COUNT}개)"
else
  echo "✅ Client pods 정상 (7개)"
fi

# 노드별 Client 확인
echo "[4/4] 노드별 Client 배포 확인..."
echo ""
kubectl get pods -n ${NAMESPACE} -l component=client -o wide

echo ""
echo "================================================"
echo "✅ 전체 노드 확장 완료!"
echo "================================================"

📊 결과 정리 및 보고서

비교 보고서 템플릿

# Dragonfly 성능 비교 테스트 보고서

## 테스트 환경
- **날짜**: 2025-01-XX
- **Chart 버전**: 1.4.15
- **App 버전**: 2.3.3
- **Registry**: nexus.com:15403

## 노드 구성
| 그룹 | 노드 | Dragonfly | 용도 |
|------|------|-----------|------|
| 테스트 | iclhk8wk48-50 | ✅ | P2P 다운로드 |
| 비교 | iclhk8wk51-54 | ❌ | 직접 다운로드 |

## 성능 측정 결과

### Cold Start (첫 다운로드)
| 그룹 | 평균 시간 | 개선율 |
|------|----------|--------|
| 테스트 (Dragonfly) | XX초 | - |
| 비교 (직접) | YY초 | ZZ% |

### Cache Hit (캐시 사용)
- 테스트 그룹 평균: AA초
- Speedup: BBx

## 메트릭 분석

### 캐시 히트율
- 테스트 그룹: XX%
- 목표: >50%
- 상태: ✅ 달성 / ❌ 미달성

### P2P 다운로드 비율
- P2P 다운로드: XX%
- Registry 직접: YY%

### 네트워크 트래픽
- Registry 트래픽 감소: ZZ%

## 결론 및 권장사항

### 장점
- ✅ Cold Start 성능 개선
- ✅ 캐시 효율 확인
- ✅ Registry 부하 감소

### 문제점
- ⚠️ (문제가 있다면 기록)

### 권장사항
- [ ] 전체 노드 확장
- [ ] 추가 모니터링 기간 필요
- [ ] 설정 튜닝 필요

## 첨부
- 상세 로그: `comparison-results-YYYYMMDD.txt`
- 메트릭 스크린샷

🎯 체크리스트

Phase 1: 초기 설정

  • 노드 라벨링 (48-50: 테스트, 51-54: 비교)
  • MySQL/Redis 배포
  • Values 파일 준비
  • 이미지 Private Registry 업로드

Phase 2: 테스트 배포

  • Dragonfly 설치 (3대만)
  • Client가 테스트 노드에만 배포 확인
  • dfinit 실행 확인
  • 기본 동작 테스트

Phase 3: 성능 비교

  • 비교 테스트 스크립트 실행
  • Cold Start 비교
  • Cache Hit 측정
  • 결과 분석

Phase 4: 모니터링

  • Prometheus 메트릭 확인
  • 로그 분석
  • 리소스 사용량 비교
  • 보고서 작성

Phase 5: 전체 확장

  • 테스트 결과 검토
  • 승인 획득
  • 전체 노드로 확장
  • 최종 검증

🚨 롤백 계획

# 문제 발생 시 즉시 롤백

# 방법 1: Helm Rollback
helm rollback dragonfly -n dragonfly-system

# 방법 2: 테스트 설정으로 복구
helm upgrade dragonfly ./dragonfly-1.4.15.tgz \
  --namespace dragonfly-system \
  --values values-test-backup-YYYYMMDD.yaml

# 방법 3: 완전 제거
helm uninstall dragonfly -n dragonfly-system

# 노드 설정 복구 (필요시)
for node in iclhk8wk{48..50}; do
  ssh ${node} "sudo cp /etc/containerd/certs.d/*/hosts.toml.bak.* /etc/containerd/certs.d/*/hosts.toml"
  ssh ${node} "sudo systemctl restart containerd"
done

🎯 핵심 정리

테스트 구성:

  • 테스트 그룹 (48-50): Dragonfly P2P
  • 비교 그룹 (51-54): 직접 다운로드
  • 동일한 이미지로 성능 비교

성공 기준:

  • ✅ Cold Start 개선 >20%
  • ✅ 캐시 히트율 >50%
  • ✅ 에러 없음
  • ✅ 안정성 확인

확장 조건:

  • 1-2주 안정성 검증
  • 성능 목표 달성
  • 이해관계자 승인

이제 3대 테스트로 안전하게 검증 후, 전체 7대로 확장할 수 있습니다! 🚀

profile
bytebliss

0개의 댓글