- 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>
407 lines
9.7 KiB
Markdown
407 lines
9.7 KiB
Markdown
# 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 적용 (권장)
|
|
|
|
### 모니터링 명령어
|
|
|
|
```bash
|
|
# 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 설정
|
|
|
|
```sql
|
|
-- 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)
|
|
|
|
```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)
|
|
|
|
```ini
|
|
session.save_handler = redis
|
|
session.save_path = "tcp://redis:6379"
|
|
```
|
|
|
|
### 업로드 (upload.ini)
|
|
|
|
```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
|
|
|
|
```nginx
|
|
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 (주요 부분)
|
|
|
|
```nginx
|
|
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 설정
|
|
|
|
```yaml
|
|
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 방지
|
|
|
|
```bash
|
|
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 증가
|
|
|
|
```bash
|
|
# /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. 부하 테스트 명령어
|
|
|
|
```bash
|
|
# 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 |
|
|
| `/` | 필터링 |
|