분산 뉴비를 위한 가이드(가 되고 싶은 포스팅)

공유기 포스팅 이후 지난 며칠간 정말 열심히 분산, 부하 시스템을 구축했습니다
https://ratatou2.tistory.com/278
공유기 브릿지 모드 설정하기 (feat. ipTIME & 삼성 공유기)
해보고 싶은게 (또) 생겼어요사실 예전부터 해보고 싶었던 것들인데 이번에 OCI도 뚫었고 해서 진짜 도전해보기로 한 [분산/부하/K8S] 세가지임 기왕하는거 제대로 하는게 더 재밌을 것 같아서 잠
ratatou2.tistory.com

공유기도 열심히 설치하고 방 한켠이 아주 난리가 났더랬죠
이걸 하게된 이유는 단순히 흥미로 시작 ㅎㅎ
그렇게 순서는 (1) 분산 시스템 구축 - (2) 부하 테스트 - (3) K8S 도전할 예정
과연 직접 분산 시스템을 구축해보고 K8S이 얼마나 편리한지를 체감 해보겠습니다
분산 시스템 구축 자체는 굉장히 단순해서 금방할 수 있음!
1. 목표

- 내 목표는 총 서버 4대를 사용할 것이고, 1대는 중계기(nginx), 나머지 3대는 App 서버로 사용할 것이다
- 지난 공유기 포스팅 때는 3대를 쓴다고 해놓고 오늘와서 4대를 쓰겠다는 이유는 중계기로 서버 한대를 온전히 써야하기 때문이다
- 중계 서버는 하이브리드(중계 + App 서버)로 두기 싫었고, 중계에만 온전한 성능을 쏟고자 했다
- App 서버를 돌리는 리소스로 인해 중계가 방해받지 않길 원했음
- 근데 이렇게 구상하니 App 서버가 두대뿐이라 3대는 써봐야지~ 싶어서 한대 더 늘렸다
- 서버들의 사양은 아래와 같다 (모두 우분투 22.04.5로 통일)

ps. 나중에 스트레스 테스트를 하며 배운 내용이지만, 중계기의 성능이 굉장히 중요하더라... ㅠ
2. 기본 서버 구조 띄우기
- 중계기는 nginx만, 나머지 3대의 App 서버는 간단한 Flask 앱을 띄워두었다
- 또한 nginx의 로드밸런싱 알고리즘은 기본 세팅(Round Robin)으로 뒀고, weight를 수정하는 등 다른 알고리즘으로 수정하진 않았음
- 나중에 튜닝하면서 weight를 수정하긴 했는데 이 부분은 부하 테스트 포스팅에서 이어가겠다
1) 각 서버들 IP 세팅
- 각 서버들의 IP들은 공유기에서 고정해뒀고 다음과 같다
# 중계기 - Mac Mini 2018
192.168.0.201
# 1번 App 서버 - SAMSUNG-Laptop-2015
192.168.0.202
# 2번 App 서버 - LG-Desktop-2015
192.168.0.203
# 3번 App 서버 - SAMSUNG-All-in-one-PC
192.168.0.204
2) App 서버 띄우기
아래 네 가지 파일을 같은 디렉토리에 만든다
(1) docker-compose.yml
# 템플릿
services:
app:
build: .
hostname: <각 PC 이름>
ports:
- "5000:5000"
# 예시
services:
app:
build: .
hostname: SAMSUNG-Laptop-2015
ports:
- "5000:5000"
(2) requirment.txt
flask
(3) Dockerfile
FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY app.py .
CMD ["python", "app.py"]
(4) app.py
from flask import Flask
import socket
app = Flask(__name__)
@app.route("/api/hello")
def hello():
return f"Hello from {socket.gethostname()}!\n"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
- 다 작성했으면 docker compose up -d로 컨테이너를 띄운다
- 이후엔 각 App 서버에서 아래 명령어로 정상적으로 응답이 오고 가는지 확인한다
curl http://localhost:5000/api/hello
3) 중계 서버 띄우기 (nginx)
- 나는 중계 서버에 nginx를 로컬에 직접 설치하여 진행하였다
- 어차피 중계로만 쓸 것이고, N100 서버에서 I/O 과부하로 터졌기 때문이다
- 뭔 말이냐면 Docker의 nginx가 host 모드가 아니라 생긴 문제였다
- 외부에서 요청이 오면 docker를 통해 받고, docker를 통해 내보내야 해서 같은 작업을 두배로 해야했고, 이것이 I/O의 과부하를 불러왔다
- 기존의 서비스들을 돌려두는게 있어서 N100의 nginx를 쉽게 host 모드로 돌릴 수 있는 것도 아니었음
- 이것이 주요 원인이 되어 기존 3대의 서버에서 4대로 늘린 것이다
- 그리고 후술할테지만, N100이 중계 서버로써 터진 이슈 때문에 찾아보니, 중계서버는 성능이 좋아야한다는 것이다
- 그래서 자연스레 현 서버들 중 가장 성능이 좋은 맥미니가 중계 서버를 하게 되었다
- 결국 아래는 중계 서버인 맥미니의 /etc/nginx/nginx.conf 파일 내용인 셈이다
user www-data;
worker_processes auto;
pid /run/nginx.pid;
events {
worker_connections 4096;
use epoll;
multi_accept on;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 0;
types_hash_max_size 2048;
server_tokens off;
# 로그 최소화
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log warn;
log_format upstreamlog '$remote_addr → $upstream_addr [$time_local] '
'"$request" $status $body_bytes_sent '
'in $request_time sec';
access_log /var/log/nginx/access.log upstreamlog;
upstream backend_pool {
server 192.168.0.202:5000; # LG_Desktop
server 192.168.0.203:5000; # Laptop
server 192.168.0.204:5000; # 500A2M
}
server {
listen 80;
server_name _;
location / {
proxy_pass http://backend_pool;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 연결/응답 제한
proxy_connect_timeout 4s; # 연결 안 되면 빠르게 failover
proxy_read_timeout 12s; # 느린 응답 방지
proxy_send_timeout 10s;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
}
}
}
- 이제 nginx 서비스를 시작해두면 된다
3. 테스트
- 잘 동작하는지 테스트해보자
- nginx를 띄워둔 '중계 서버'에서 아래 명령어를 실행하면 된다
- App 서버들이 잘 동작한다면 요청이 분배되는대로 각 서버의 host 이름이 반환될 것이다
# 템플릿
for i in {1..6}; do curl -s http://localhost:<포트번호>/<API 경로>; echo; done
# 예시
for i in {1..6}; do curl -s http://localhost:52837/api/hello; echo; done

- 잘된다!
- 별거 없게도 분산 구축 자체는 쉬웠다
- 진짜 어렵고 많은 시간을 쏟았던 것은 부하 테스트랑 튜닝...
- App 서버 3대가 요청의 처리 성능이 다름에도 round robin으로 분산이 되어있기 때문에 골고루 요청을 받는 형태이다
- 이 때, 수많은 요청이 한번에 들어오게 되면, 각 서버의 처리 속도에 따라 성능에 편차가 생기게 되고 이는 곧 불안정한 서비스로 이어진다
- 따라서 서버 3대의 성능과 사양에 따라 튜닝이 필요하며 이를 위해 정말 많은 테스트를 해야만 했다
- 글이 기니까! 다음 포스트에서 계속!
'Infra > DevOps' 카테고리의 다른 글
| 나만의 VPN 서버 만들기 (feat. 홈서버 + WireGuard) (4) | 2025.10.23 |
|---|---|
| 서버 부하 테스트 해보기 (feat. K6 스트레스 테스트 & 분산 구조 튜닝) (0) | 2025.10.23 |
| 서버 CPU 과부하 시 알림 보내기 (feat. Grafana 알림 설정 방법) (0) | 2025.10.13 |
| 오라클 클라우드(OCI) 퍼블릭 IP 적용 및 SSH 접속하기 (0) | 2025.10.04 |
| 오라클 클라우드(OCI) 서버 한방에 만들기 (feat. 인스턴스 생성) (0) | 2025.10.04 |