이코에코(Eco²)/Eventual Consistency
이코에코(Eco²) Eventual Consistency #2: ext-authz 2500 VUs 부하 테스트
mango_fr
2025. 12. 30. 12:11
테스트 실행: Locust VUs 2500/ramp-ups: 250, Observability: Prometheus/Grafana, Locust
1. 테스트 환경
https://snapshots.raintank.io/dashboard/snapshot/JbEhJRXD1vCt77ZOfCxy9N72wXJ3ZyKj
Grafana
If you're seeing this Grafana has failed to load its application files 1. This could be caused by your reverse proxy settings. 2. If you host grafana under subpath make sure your grafana.ini root_url setting includes subpath. If not using a reverse proxy m
snapshots.raintank.io
항목
값
테스트 시간
2025-12-30 11:27:26 ~ 11:45:43 KST (18분)
테스트 도구
Locust (2,500 VU)
엔드포인트
/api/v1/authz/ping (Istio DirectResponse)
ext-authz Pods
2 → 4 (HPA auto-scale)
노드
k8s-api-auth (2 vCPU, 2GB)
테스트 구성:
┌─────────────────────────────────────────────────────────────────────────┐
│ Load Test Architecture │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ Locust (2,500 VU) │
│ │ │
│ │ HTTPS (Bearer Token) │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Istio Gateway │ │
│ └────────┬────────┘ │
│ │ │
│ │ gRPC (ext-authz) │
│ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ ext-authz Pod 1 │ ... │ ext-authz Pod 4 │ (HPA: 2→4) │
│ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │
│ │ Local Cache (O(1)) │ │
│ └───────────────────────┘ │
│ │
│ ✅ Redis 호출 없음 (100% 로컬 캐시) │
│ │
└─────────────────────────────────────────────────────────────────────────┘
2. 처리량 (Throughput)
2.1 RPS Summary
메트릭
값
소스
Locust RPS
~1,500 req/s
Locust UI
Prometheus Max RPS
1,477 req/s
sum(rate(ext_authz_requests_total[1m]))
Prometheus Avg RPS
798 req/s
18분 평균
2.2 RPS Timeline (Prometheus)
Time (KST) | RPS
---------------|--------
11:27:30 | 994
11:28:00 | 1,257
11:28:30 | 1,356
11:29:00 | 1,486 ← Peak
11:29:30 | 1,299
11:30:00 | 284 ← 노드 포화
... | 0 ← 잠시 중단
11:32:00 | 1,319
11:32:30 | 1,424
11:33:00 | 1,312
... | ~1,340 ← 안정화
11:41:30 | 1,143
11:42:00 | 324 ← 테스트 종료 시작
3. 레이턴시 분석
3.1 전체 요청 레이턴시 (ext-authz gRPC)
메트릭
Max
Avg
p99
275.5ms
157.4ms
Avg
24.4ms
16.5ms
3.2 컴포넌트별 레이턴시
컴포넌트
p99 Max
p99 Avg
비중
JWT Verify
7.2ms
6.5ms
~40%
Cache Lookup
2.3µs
2.2µs
~0.01%
gRPC/Network
~268ms
~150ms
~60%
3.3 레이턴시 분석
┌─────────────────────────────────────────────────────────────────────────┐
│ p99 Latency 분해 (max 275.5ms) │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ gRPC/Network: ~268ms (97.3%) │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ ┌───────┐ │
│ │JWT 7ms│ (2.6%) │
│ └───────┘ │
│ │ Cache: 2.3µs (0.0008%) │
│ │
│ ✅ 로컬 캐시로 인한 지연: 무시 가능 (< 3µs) │
│ ⚠️ 병목: Istio/gRPC 네트워크 오버헤드 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
4. 로컬 캐시 성능
4.1 캐시 메트릭
메트릭
값
설명
Cache Lookups
845,914
전체 조회 수
Cache Lookup p99
2.3µs
p99 레이턴시
Cache Hits
0
테스트 토큰은 블랙리스트 아님
Cache Misses
845,914
정상 토큰 (allow)
Cache Evictions
0
TTL 만료 없음
4.2 Redis 비교
항목
로컬 캐시
Redis
개선
p99 Latency
2.3µs
~2ms
870배
네트워크 호출
0
845,914
제거
5. 리소스 사용량
5.1 HPA Scaling
시간
Pods
CPU 상태
시작
2
정상
11:29
4
노드 포화 (100%)
종료
4
유지
5.2 노드 리소스
메트릭
값
Node
k8s-api-auth
CPU
2 vCPU (100% 도달)
Memory
2GB (86% 사용)
6. MQ 상태
메트릭
값
Connection Status
1 (Connected)
Events Received
0 (테스트 중 로그아웃 없음)
Events Failed
0
Reconnects
0
7. 결론
7.1 성능 요약
항목
결과
최대 RPS
1,477 req/s (Prometheus)
평균 RPS
798 req/s
p99 Latency
275.5ms (max)
캐시 p99
2.3µs
Redis 호출
0
7.2 병목 분석
1. 노드 CPU 포화 (2 vCPU, 100%)
└── ext-authz 4 pods가 노드 한계 도달
2. Istio/gRPC 네트워크 오버헤드 (~97% of latency)
└── ext-authz 자체 처리 시간 < 10ms
3. 로컬 캐시: 병목 아님 (2.3µs)
└── Redis 대비 870배 빠름
7.3 권장 사항
개선
예상 효과
노드 스케일아웃
RPS 노드수 배수로 증가
ext-authz 노드 분리
격리된 리소스 확보
Istio 튜닝
p99 레이턴시 감소
8. 테스트 명령어
8.1 Locust
# Web UI
TOKEN="<jwt>" locust -f locustfile_authz.py --host https://api.dev.growbin.app
# Headless
TOKEN="<jwt>" locust -f locustfile_authz.py --headless -u 2500 -r 250 -t 18m \
--host https://api.dev.growbin.app
8.2 Prometheus 쿼리
# RPS
sum(rate(ext_authz_requests_total[1m]))
# p99 Latency
histogram_quantile(0.99, sum(rate(ext_authz_request_duration_seconds_bucket[1m])) by (le)) * 1000
# Cache Lookup p99
histogram_quantile(0.99, sum(rate(ext_authz_blacklist_cache_lookup_duration_seconds_bucket[1m])) by (le)) * 1000000
# JWT Verify p99
histogram_quantile(0.99, sum(rate(ext_authz_jwt_verify_duration_seconds_bucket[1m])) by (le)) * 1000
9. References