NCONF="$ROOT$BASE/nginx/conf"
mkdir -p "$NCONF/conf.d" "$ROOT$BASE/nginx/logs" "$ROOT$BASE/nginx/cache"
APP="$NCONF/conf.d/app.conf"
cat > "$APP" <<EOF
upstream app_backend {
server 127.0.0.1:8080 weight=3 max_fails=2 fail_timeout=10s;
server 127.0.0.1:8081 weight=1 max_fails=2 fail_timeout=10s;
server 127.0.0.1:8082 backup;
server 127.0.0.1:8084 down;
keepalive 32;
}
upstream app_sticky {
ip_hash;
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
EOF== 1. 폴더 준비 ==
WORK/app/nginx/cache
WORK/app/nginx/conf
WORK/app/nginx/conf/conf.d
WORK/app/nginx/logs
== 2. upstream 다중 서버와 전체 설정 작성 ==
작성 완료: conf.d/app.conf$WORK 는 DRY_RUN=1 일 때만 붙는 임시 경로이고, 실제 서버에서는 $BASE 바로 아래에 씁니다.
grep -n '^\s*server 127' "$APP" | mask
grep -n 'ip_hash\|app_sticky' "$APP" | mask
grep -n 'log_format\|access_log\|upstream_addr\|upstream_response_time\|request_time' "$APP" | mask== 3. upstream 속성 확인 (weight·max_fails·fail_timeout·backup·down) ==
2: server 127.0.0.1:8080 weight=3 max_fails=2 fail_timeout=10s;
3: server 127.0.0.1:8081 weight=1 max_fails=2 fail_timeout=10s;
4: server 127.0.0.1:8082 backup;
5: server 127.0.0.1:8084 down;
11: server 127.0.0.1:8080;
12: server 127.0.0.1:8081;
== 4. 세션 고정(ip_hash) 확인 ==
9:upstream app_sticky {
10: ip_hash;
56: proxy_pass http://app_sticky/;
ip_hash 는 클라이언트 IP 로 서버를 고정합니다. 프록시·NAT 뒤라 IP 가 뭉치면 한 서버로 쏠립니다
== 5. 접근 로그 형식 확인 ==
15:log_format lb '$remote_addr - [$time_local] "$request" '
17: 'rt=$request_time urt=$upstream_response_time '
18: 'ua="$upstream_addr"';
33: access_log /app/nginx/logs/access.log lb;
이 로그 파일의 압축·삭제(백업)는 리눅스 운영 06 의 logrotate 로 자동화합니다번호는 app.conf 안 줄 번호입니다. 같은 파일 하나에 upstream·로그·server 블록이 함께 들어 있습니다.
awk 'BEGIN{o=0;c=0}
{o+=gsub(/{/,"{"); c+=gsub(/}/,"}")}
END{
if (o==c) printf " 중괄호 짝 검사 통과: 여는 %d 닫는 %d\n", o, c
else { printf " 중괄호 불일치: 여는 %d 닫는 %d\n", o, c; exit 1 }
}' "$APP"
run "$BASE/nginx/sbin/nginx" -t -c "$NCONF/nginx.conf"== 6. gzip 확인 ==
20:gzip on;
21:gzip_types text/plain text/css application/json application/javascript;
22:gzip_min_length 1024;
23:gzip_comp_level 5;
== 7. 캐시 설정 확인 (정적은 무조건, API 는 조건부) ==
27:proxy_cache_path /app/nginx/cache levels=1:2 keys_zone=app_cache:10m max_size=200m inactive=60m;
40: proxy_cache app_cache;
41: proxy_cache_valid 200 10m;
47: proxy_cache app_cache;
48: proxy_cache_valid 200 30s;
49: proxy_cache_bypass $http_x_no_cache;
/static/ 은 200 이면 10분 캐시, /api/ 는 30초만 캐시하고 X-No-Cache 헤더로 우회할 수 있습니다
== 8. rate limit 확인 ==
25:limit_req_zone $binary_remote_addr zone=applimit:10m rate=10r/s;
46: limit_req zone=applimit burst=20 nodelay;
== 9. 설정 검증 ==
중괄호 짝 검사 통과: 여는 8 닫는 8
[dry] /app/nginx/sbin/nginx -t -c WORK/app/nginx/conf/nginx.conf중괄호 짝 검사는 오타로 블록이 안 닫힌 실수를 nginx 를 띄우기 전에 잡아 줍니다.
sed -i 's/server 127.0.0.1:8080 weight=3 max_fails=2 fail_timeout=10s;/server 127.0.0.1:8080 down; # deploy 중/' "$APP"
run "$BASE/nginx/sbin/nginx" -t -c "$NCONF/nginx.conf"
run systemctl reload nginx
git -C "$CONF_DIR" add conf.d/app.conf
git -C "$CONF_DIR" diff --cached --quiet || git -C "$CONF_DIR" commit -q -m "app.conf: 로드밸런싱 설정 확정"== 10. 무중단 배포: 8080 배포를 위해 down 표시 ==
2: server 127.0.0.1:8080 down; # deploy 중
11: server 127.0.0.1:8080;
[dry] /app/nginx/sbin/nginx -t -c WORK/app/nginx/conf/nginx.conf
[dry] systemctl reload nginx
8081·8082 로만 요청이 가고 8080 은 통계에서 제외됩니다
== 11. 배포 완료 후 복구 ==
2: server 127.0.0.1:8080 weight=3 max_fails=2 fail_timeout=10s;
11: server 127.0.0.1:8080;
[dry] /app/nginx/sbin/nginx -t -c WORK/app/nginx/conf/nginx.conf
[dry] systemctl reload nginx
점검 페이지 전환 없이 upstream 만 바꿔 무중단으로 배포합니다(리눅스 운영 05 참조)
== 12. 설정 버전 관리(git) ==
02c12a0 app.conf: 로드밸런싱 설정 확정
/app/nginx/conf 를 git 으로 관리하면 교체 전 diff 로 무엇이 바뀌는지 검토할 수 있습니다
== 13. 문제 해결: 상태 코드별 로그 확인 ==
상태 코드 502 건수: 1
상태 코드 504 건수: 1
상태 코드 413 건수: 1
상태 코드 403 건수: 1
[dry] curl -sS -o /dev/null -w 연결 확인 상태코드: %{http_code}\n http://127.0.0.1/health커밋 해시는 작성자·날짜를 스크립트 안에서 고정했기 때문에 다시 실행해도 같은 값이 나옵니다.