- anvil-load-test-report.md - claude_communication_flow.md - incus-crowdsec-architecture.md - incus-meilisearch-manual.md - kitty-setup-guide.md - OpenAppSec_WAF_Operations_Guide.md - openappsec-setup-20250817.md - xray-proxy-guide.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
9.7 KiB
9.7 KiB
Anvil 부하테스트 및 성능 최적화 보고서
작성일: 2026-01-10 환경: Incus jp1 → k8s (k3s) → anvil namespace
Part 1. 핵심 요약
1. 아키텍처
┌─────────────────────────────────────────┐
│ k8s (k3s, max-pods=200) │
│ │
[Client] ──▶ Cloudflare ─┼─▶ Traefik (x3) │
(권장) │ │ │
│ ▼ │
│ Nginx (x2~15, HPA) │
│ │ │
│ ▼ │
│ PHP-FPM (x5~30, HPA) ─▶ Redis │
│ │ (Session) │
│ ▼ │
│ ProxySQL (Cache 256MB) │
│ │ │
└───────┼─────────────────────────────────┘
│
┌────────────┴────────────┐
▼ ▼
┌─────────────┐ ┌─────────────┐
│ MariaDB-1 │ │ MariaDB-2 │
│ (Primary) │──Repl───▶ │ (Replica) │
└─────────────┘ └─────────────┘
2. 최종 성능 결과
2.1 Gnuboard5 (실제 애플리케이션)
| 항목 | Origin Only | + Cloudflare (예상) |
|---|---|---|
| 최대 RPS | 505.9 | 2,000+ |
| 성공률 | 100% | 100% |
| 평균 응답 | 390ms | ~50ms (캐시 HIT) |
2.2 simple-db.php (단순 쿼리)
| 항목 | 값 |
|---|---|
| 최대 RPS | 3,466 |
| 성공률 | 100% |
| 평균 응답 | 56ms |
2.3 예상 동시 접속자
| 시나리오 | Gnuboard5 |
|---|---|
| Origin Only | ~1,700명 |
| Cloudflare 70% 캐시 | ~5,600명 |
| Cloudflare 80% 캐시 | ~8,500명 |
3. 최적화 적용 현황
| 영역 | 최적화 | 효과 | 상태 |
|---|---|---|---|
| ProxySQL | Query Cache 256MB | DB 부하 99% 감소 | ✅ |
| ProxySQL | Read Replica 활용 | +21% RPS | ✅ |
| PHP | OPcache 256MB | PHP 컴파일 캐시 | ✅ |
| PHP | Redis 세션 | 세션 공유/속도 | ✅ |
| HPA | minReplicas 설정 | Cold Start 방지 | ✅ |
| MariaDB | Buffer Pool 512MB | 99.998% 히트율 | ✅ |
| CDN | Cloudflare | +300% 예상 | ⏳ 권장 |
4. 핵심 설정값
4.1 HPA 설정
| Deployment | Min | Max | CPU Target |
|---|---|---|---|
| nginx | 2 | 15 | 70% |
| php-fpm | 5 | 30 | 70% |
4.2 리소스 설정
| 구성요소 | 설정 | 값 |
|---|---|---|
| MariaDB | max_connections | 500 |
| ProxySQL | Query Cache | 256MB, TTL 5초 |
| ProxySQL | Read Replica | hostgroup 1 |
| PHP | OPcache | 256MB, 20K files |
| PHP | Session | Redis |
| k3s | max-pods | 200 |
4.3 업로드 제한
| 구성요소 | 값 |
|---|---|
| Nginx | 100MB |
| PHP | 100MB |
5. 운영 체크리스트
필수 확인 사항
- HPA minReplicas 설정 확인 (nginx: 2, php-fpm: 5)
- ProxySQL Read Replica 설정 확인 (hostgroup 1)
- ProxySQL PVC 마운트 확인 (설정 영구 저장)
- OPcache 활성화 확인
- Redis 세션 연결 확인
- Cloudflare 적용 (권장)
모니터링 명령어
# k9s 실행
k9s
# HPA 상태
kubectl get hpa -n anvil
# Pod 리소스
kubectl top pods -n anvil
# ProxySQL 캐시 상태
kubectl exec -n anvil deploy/proxysql -- mysql -h127.0.0.1 -P6032 -uadmin -padmin \
-e "SELECT * FROM stats.stats_mysql_global WHERE Variable_Name LIKE '%Query_Cache%';"
6. 변경 이력
| 일시 | 변경 내용 | 효과 |
|---|---|---|
| 2026-01-09 | MariaDB max_connections 151→500 | 연결 여유 확보 |
| 2026-01-09 | nginx/php-fpm CPU 2코어 | 처리량 증가 |
| 2026-01-09 | ProxySQL Query Cache 256MB | +17% RPS |
| 2026-01-09 | k3s max-pods 200 | Pod 확장성 |
| 2026-01-09 | OPcache 최적화 | PHP 성능 향상 |
| 2026-01-09 | HPA minReplicas 설정 | +6% RPS |
| 2026-01-09 | ProxySQL Read Replica | +21% RPS |
| 2026-01-09 | Real IP 설정 | 클라이언트 IP 추적 |
| 2026-01-09 | 파일 업로드 100MB | 대용량 파일 지원 |
| 2026-01-10 | 최종 문서 정리 | - |
Part 2. 상세 설정 (참고)
A. ProxySQL 설정
Query Cache 설정
-- ProxySQL Admin (포트 6032) 접속
SET mysql-query_cache_size_MB = 256;
LOAD MYSQL VARIABLES TO RUNTIME;
SAVE MYSQL VARIABLES TO DISK;
-- SELECT 쿼리 캐시 + Read Replica 라우팅
INSERT INTO mysql_query_rules
(rule_id, active, match_digest, cache_ttl, destination_hostgroup, apply)
VALUES
(100, 1, '^SELECT', 5000, 1, 1);
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;
Hostgroup 구성
| Hostgroup | 서버 | 용도 |
|---|---|---|
| 0 | Primary (10.253.101.133) | Write |
| 1 | Primary + Replica | Read (캐시 + 부하분산) |
캐시 동작 흐름
요청 ──▶ ProxySQL
│
├─ Cache HIT (99.5%) ──▶ 즉시 응답 (0.1ms)
│
└─ Cache MISS (0.5%) ──▶ MariaDB (Primary/Replica)
│
└──▶ 캐시 저장 ──▶ 응답
B. PHP 설정
OPcache (opcache.ini)
opcache.enable=1
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0
opcache.revalidate_freq=0
opcache.fast_shutdown=1
opcache.interned_strings_buffer=16
세션 (session.ini)
session.save_handler = redis
session.save_path = "tcp://redis:6379"
업로드 (upload.ini)
upload_max_filesize = 100M
post_max_size = 100M
max_file_uploads = 20
max_execution_time = 300
max_input_time = 300
C. Nginx 설정
nginx.conf
worker_processes auto;
events {
worker_connections 1024;
use epoll;
multi_accept on;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
# Real IP
set_real_ip_from 0.0.0.0/0;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
# Gzip
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript;
}
default.conf (주요 부분)
upstream php-upstream {
server php-fpm:9000;
keepalive 32;
}
server {
client_max_body_size 100m;
location ~ \.php$ {
fastcgi_pass php-upstream;
fastcgi_keep_conn on;
fastcgi_buffer_size 32k;
fastcgi_buffers 16 16k;
}
}
D. Traefik Real IP 설정
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: traefik
namespace: kube-system
spec:
valuesContent: |-
additionalArguments:
- "--entryPoints.web.forwardedHeaders.insecure=true"
- "--entryPoints.websecure.forwardedHeaders.insecure=true"
E. HPA 설정
Cold Start 방지
kubectl patch hpa nginx-hpa -n anvil -p '{"spec":{"minReplicas":2}}'
kubectl patch hpa php-fpm-hpa -n anvil -p '{"spec":{"minReplicas":5}}'
F. k3s 설정
max-pods 증가
# /etc/rancher/k3s/config.yaml
kubelet-arg:
- "max-pods=200"
G. MariaDB 상태 (참고)
| 지표 | 값 | 평가 |
|---|---|---|
| Buffer Pool Size | 512MB | 적정 |
| Buffer Pool Hit Rate | 99.998% | 최상 |
| max_connections | 500 | 적정 |
| Slow Queries | 0 | 최상 |
H. Cloudflare 설정 가이드 (권장)
Cache Rules 설정
Rule 1: 정적 파일
If: File extension = css, js, jpg, png, gif, ico, woff2
Then: Cache (Edge TTL: 1 month)
Rule 2: 게시판 페이지 (비로그인)
If: URI contains "/gb5/" AND Cookie NOT contains "ck_mb_id"
Then: Cache (Edge TTL: 5 minutes)
Rule 3: 관리자/글쓰기 제외
If: URI contains "/adm" OR "/bbs/write" OR Cookie contains "ck_mb_id"
Then: Bypass cache
예상 효과
| 캐시 히트율 | 유효 RPS |
|---|---|
| 50% | ~1,000 |
| 70% | ~1,700 |
| 80% | ~2,500 |
I. 성능 튜닝 히스토리
| 설정 | RPS | 성공률 | 비고 |
|---|---|---|---|
| 초기 상태 | ~150 | 93% | Cold Start |
| + CPU 2코어 | ~370 | 99% | - |
| + minReplicas | 419 | 99.98% | +6% |
| + Read Replica | 505.9 | 100% | +21% |
J. 부하 테스트 명령어
# Gnuboard5 테스트
hey -n 20000 -c 200 -t 20 -host "gnu.anvil.it.com" "http://10.253.103.124/gb5/"
# simple-db.php 테스트
hey -n 20000 -c 200 -t 20 -host "gnu.anvil.it.com" "http://10.253.103.124/simple-db.php"
# ProxySQL 캐시 히트율 확인
kubectl exec -n anvil deploy/proxysql -- mysql -h127.0.0.1 -P6032 -uadmin -padmin \
-e "SELECT * FROM stats.stats_mysql_global WHERE Variable_Name LIKE '%Query_Cache%';"
K. k9s 단축키
| 키 | 기능 |
|---|---|
:ns |
네임스페이스 선택 |
:pod |
Pod 목록 |
:hpa |
HPA 목록 |
l |
로그 보기 |
s |
Shell 접속 |
d |
Describe |
/ |
필터링 |