NGINX 쿡북 리뷰

Jeongmin Yeo (Ethan)·2023년 2월 18일
"한빛미디어 <나는 리뷰어다> 활동을 위해서 책을 제공받아 작성된 서평입니다."

NGINX 쿡북을 고른 이유는?

백엔드 개발자라면 nginx를 알고 있을 것이다. nginx는 웹 어플리케이션을 만들 때, 리버스 프록시, 로드 밸런서, API Gateway 등의 역할로 제일 앞단에 사용된다. 나는 Kubernetes 에서 어플리케이션을 사용자에게 노출할 때, ingress라는 오브젝트를 사용했는데, 이를 구현할 때 nginx를 많이 사용했었다. 큰 설정 없이 사용했지만, nginx가 제공하는 기능을 알면 도움이 될 것 같아서 이 책을 골랐다.

총평

NGINX의 다양한 기능을 소개한다. 대부분의 경우, 문제를 제시하고 해당 문제를 해결하기 위한 NGINX 설정 파일을 보여준다.

이 책은 번역서이지만 술술 읽히는 편이다. 그러나 몇몇 부분에서 잘못 설명된 부분이 있는 것 같다. 물론, 이는 제가 잘못 이해한 것일 수도 있습니다.

1) 12장에서는 고가용성을 다루며, Keepalived와 같은 도구를 사용하여 NGINX 서버의 가용성을 높이는 방법을 다룬다. 그러나 Keepalived가 백업 서버로 하트비트를 보낸다고 적혀 있는데 이게 아니라 NGINX 서버에 하트비트를 보내야 하지 않을까?

2) 15장에서는 성능 튜닝을 다루며, proxy_buffering 을 활성화하는 이유로 업스트림 서버의 응답을 메모리에 임시 파일에 기록되지 않도록 메모리에 버퍼링한다 라고 하는데 그러나 실제 레퍼런스에서는 임시 파일이 생성된다고 한다. 이 설명이 조금 다른 것 같다.

When buffering is enabled, nginx receives a response from the proxied server as soon as possible, saving it into the buffers set by the proxy_buffer_size and proxy_buffers directives. If the whole response does not fit into memory, a part of it can be saved to a temporary file on the disk. Writing to temporary files is controlled by the proxy_max_temp_file_size and proxy_temp_file_write_size directives.

NGINX Reference

Summary

아래는 책의 내용을 요약한 것인데 만약 관심 있는 내용이 있다면 책을 참고하시는 것도 좋을 것 같습니다.

chapter 1. 엔진엑스 기초

NGINX 설치하는 방법과 주요 설정 파일과 디렉토리에 대해서 다룬다. (로그 디렉토리 위치, NGINX 기본 설정 파일 등)

이 외에도 기본 HTTP 설정 파일을 소개하고, 설정을 바꿨을 때 무중단으로 reload 하는 방법에 대해서 가르켜준다.

chapter 2. 고성능 부하분산

HTTP, TCP, UDP 부하 분산을 제공하는 방법.

상태 유지가 필요한 어플리케이션에서 부하분산을 제공할 때 사용자 경험을 해치지 않는 법

부하분산 대상이 되는 업스트림 어플리케이션의 상태를 모니터링 하는 방법

부하분산 제공

  • HTTP, TCP, UDP
  • 부하분산 알고리즘 선택 (라운드로빈, least connection, least time, 제네릭 해시, 랜덤, IP 해시)
  • 슬로우 스타트 기능을 통해서 트래픽을 점진적으로 받도록 하기. 한번에 어플리케이션이 모든 트래픽을 받지 않도록하는 예열하는 기능이다.

상태 유지가 필요한 어플리케이션에서 부하분산을 제공할 때 사용자 경험을 해치지 않는 법

  • 스티키 쿠기 (특정 업스트림 서버로 요청을 전달하는 방법)
  • 스티키 런과 라우팅 (트래픽을 더 세밀하게 다뤄서 트래픽을 전송하는 방법)
  • 서버 유지보수가 필요하거나 서버를 종료해야 하는 상황에서 사용자 세션이 남아있는 엔진엑스 서버를 점진적으로 제외하기

부하분산 대상이 되는 업스트림 어플리케이션의 상태를 모니터링 하는 방법

  • HealthCheck 를 등록해서 수동적, 능동적으로 확인할 수 있다.

chapter 3. 트래픽 관리

트래픽 경로 설정과 제어 방법

사용자 요청을 특정 비율로 분기하거나, 사용자 위치 정보를 활용해서 흐름을 조절하고 요청 빈도, 연결수, 대역폭 등을 제한해서 트래픽을 제어하는 방법

  • A/B 테스트를 하고 싶을 경우에 쓸 수 있다.
  • GeoIP 모듈을 이용해서 특정 국가에서 들어오는 트래픽 차단
  • 프록시를 통해서 들어온 사용자의 요청에서 실제 IP 를 얻는 방법
  • 총 연결 수를 제한하는 방법
  • 서비스 리소스 부하를 막기 위해서 사용자에 대한 응답폭을 제한하는 방법

chapter 4. 대규모 확장 가능한 콘텐츠 캐싱

NGINX 를 이용한 콘텐츠 캐싱 제공 (CDN 처럼)

캐시와 관련된 여러가지 기능을 소개한다.

  • 콘텐츠를 캐시에 저장하고 캐시를 어디에 저장할 지.
  • 캐시를 생성중이라면 이후 캐시에 대한 요청은 업스트림 서버로 보내지 않기
  • 사용자마다 다른 동적인 페이지 같은 것들을 캐시하고 불러오는 방법
  • 캐시를 사용하지 않고 우회하는 방법
  • 사용자 환경 (i.e 웹브라우저) 에서 캐시하기
  • 캐시 컨텐츠를 무효화하기
  • 용량이 큰 파일을 작은 파일로 나눠서 캐시를 효율적으로 스트리밍 방식으로 전달하기.

chapter 5. 프로그래머빌리티와 자동화

프로그래머빌리티 (programmability) 란 프로그래밍을 통해서 상호작용하는 능력을 말한다.

여기서는 HTTP API 를 통해서 NGINX Plus (상용 버전. 오픈 소스 버전이 아님) 와 상호 작용하고 동적 제어 하는 방법을 다룬다. (업스트림 서버를 추가하거나 제거, 키 값 저장소를 통한 블랙리스트 추가 등)

NJS 모듈을 바탕으로 사용자 요청이나 응답 처리 시 엔진엑스에서 자바스크립트 실행하기

chapter 6. 인증

NGINX 레벨에서 인증을 해서 업스트림 서버에는 인증을 통과한 요청만 전달하도록 할 수 있다. 여기서는 NGINX 에서 제공하는 인증을 다룬다. NGINX 오픈 소스 버전에서는 HTTP 기본 인증과 하위 요청 인증이 있고, NGINX Plus 에서는 JWT 검증이 가능하다.

NGINX 하위 요청은 목적지 서버로 보내기 전에 내부 인증 서버로 보내서 요청을 처리하도록 하는 것이다.

추가로 NGINX Plus 에서는 OpenID 커넥트 SSO 를 통한 사용자 인증이 가능하다.

chapter 7. 보안 제어

NGINX 를 이용해서 어플리케이션의 보안을 제어하는 방법에 대해서 다룬다.

보안 제어 방법

  • IP 주소 기반 접근 제어가 있다. 접근이 되는 whitelist 를 허용하는 방식.

  • CORS 접근 허용

  • 클라이언트와 NGINX, NGINX 와 업스트림 서버의 통신에서 암호화 사용.

  • 비밀값을 사용해서 리소스 접근 보호

  • 어플리케이션에서 비밀값을 이용해 보안 링크 생성.

  • 특정 클라이언트에서만 적용되는 기간을 가진 제한 링크를 통해서 리소스 접근 보호

  • 사용 기간이 만료되면 파기되는 링크 생성하기

  • HTTP 요청을 HTTPS 로 리다이렉션

  • 폐쇄형 웹사이트를 위해서 모든 보안 검증을 통과해야 요청이 전송되도록

  • DDOS (Distributed Denial of Service) 공격 완화하기

chapter 8. HTTP/2

NGINX 에서 HTTP/2 를 이용하는 방법과 서버 푸쉬 방법 그리고 gRPC 를 이용하는 방법에 대해서 다룬다.

chapter 9. 정교한 스트리밍

NGINX 를 이용해서 MP4 (MPEG-4), FLV (Flash video) 파일을 스트리밍하는 방법에 대해서 다룬다.
NGINX Plus 는 HTTP 라이브 스트리밍 (HLS) 모듈을 이용해서 콘텐츠를 실시간으로 작게 나눠서 전송하는 방법, 이미 작게 쪼개진 미디어 파일을 전송하는 HTTP 동적 스트리밍 (HTTP Dynamic Streaming) 형식도 제공한다.

추가로 시청 경험을 해치지 않는 선에서 사용자가 미디어 콘텐츠를 내려받는 네트워크 대역폭을 제한할 수 있다.

chapter 11. 컨테이너와 마이크로서비스

NGINX 를 컨테이너 식으로 배포하는 방법과 이를 쿠버네티스와 openshift 에서 사용하는 방법

NGINX 를 API Gateway 로 사용해서 보안, 검증, 인증을 수행하고 요청을 적절한 서비스로 라우팅 하는 기능

이미 구성된 DNS 의 SRV 레코드를 활용해서 엔진엑스 플러스의 업스트림 서버를 설정하기

  • 이를 이용해서 서버가 추가되거나 제거되는 동적인 상황에 대응할 수 있다.

도커 허브에 등록된 공식 NGINX 이미지를 사용하기

여러 환경에서 동일한 컨테이너 이미지를 사용하도록 엔진엑스 설정에서 환경 변수를 사용하는 법

어플리케이션을 쿠버네티스 환경으로 배포하면서 인그레스 컨트롤러를 사용하는 법

프로메테우스로 모니터링 되는 환경에 NGINX 를 배포하고 통계를 확인하는 법

chapter 12. 고가용성

NGINX 에서 고가용성을 보장하는 방법

nginx-ha-keepalived 패키지를 이용해서 fail over 를 제공해서 고가용성을 보장하는 방법

DNS 서버에 NGINX IP 주소를 여러개 등록해서 부하를 분산하는 방법

  • 특정 NGINX 서버에 문제가 있다면 이 IP 를 지워줘야한다. AWS Route53 같은 걸 쓰면 이러한 기능을 제공해준다고 함.

NGINX Plus 설정 동기화하기

NGINX Plus 에서 고가용성 서버 간에 공유 메모리 영역 동기화하기

chapter 13. 고급 활동 모니터링

NGINX 를 사용하는 경우에 제공하는 모니터링 지표들에 대해서 알아보는 것. (사용자 요청, 업스트림 서버 풀, 캐시, 서버 상태 등)

NGINX 의 기본 모니터링 활성화하기

  • 활성 연결 수, 총 연결 수, 처리 된 연결 수, 요청에 대한 응답 수, 읽기 및 쓰기 작업 중인 연결 수, 대기 상태인 연결 수 등을 제공해준다.

NGINX Plus 에서 상세 지표 수집하기

  • 활성 연결 수, 가동 시간, 업스트림 서버 풀

NGINX Plux 에서 API 로 지표 수집하기

  • 서버에 대한 정보
  • 연결에 대한 정보
    • 총 연결 수
    • 활성화 연결 수
    • 드랍된 연결 수
    • idle 연결 수
  • 요청에 대한 통계
  • 특정 서버 존에 대한 통계
    • 1xx, 2xx, 3xx, 4xx, 5xx 응답 통계

chapter 14. 디버깅과 트러블 슈팅

유의미한 로그를 남기는 방법 (access.log 과 error.log)

중앙화된 로그 수집 시스템으로 로그를 넘기는 방법

접근 로그 남기기

  • 서버가 요청을 받은 시점의 로컬 시간
  • 사용자와 연결 맺은 IP 주소
  • realip_remote_addr 을 이용한 실제 클라이언트 IP 주소
  • 사용자 IP 에 대한 국가, 도시 정보

오류 로그 남기기

로그를 시스로그로 전달하기

  • 중앙화된 저장소로 모우기 위해서

NGINX 로그와 어플리케이션 로그를 연관짓는법

NGINX 오픈 트레이싱 셋업

  • 분산 서버 환경에서 성능과 트랜잭션 모니터링을 위해서

chapter 15. 성능 튜닝

클라이언트와의 연결을 유지해서 성능을 높이는 법 (keepalive 이용)

업스트림 서버와의 연결을 계속해서 유지해서 성능을 높이는 법 (keepalive 이용)

업스트림 서버의 응답이 메모리에 버퍼링 되도록 하기

  • 이걸 활성화하면 업스트림 서버로부터 응답을 가능한 빠르게 받을 수 있다.
  • 응답을 메모리에 버퍼링함으로써 네트워크 트래픽을 조절하는게 가능하다. 효율적인 데이터 전송이 가능함.
  • 큰 파일을 서버에서 보낼 때도 도움이 된다. 일부분만 가지고와서 보내는게 가능하니까. 메모리 측면에서. 필요하다면 임시 파일도 만든다고함.
  • Slow Client 의 경우에도 서버로 부터 응답을 빨리 받았으니까 응답을 되도록 빨리 준다. 즉 업스트림 서버에서 readTimeout 이 안날 수 있다.
  • 이 기능이 disable 되어있다면 클라이언트에게서 응답이 나가는 동안 업스트림 서버로부터 데이터를 읽는게 불가능하다. 동기식으로 처리되서.

접근 로그를 버퍼링해서 시스템 부하가 높을 때 워커 프로세스의 작업이 지연되거나 차단당하지 않도록 하기

  • 로그 데이터를 메모리에 버퍼링해서 최적화를 하는 것.

스파이크성 부하가 예상되거나 대량의 트래픽이 발생할 수 있는 경우에 운영체제가 더 많은 연결을 맺도록 튜닝해놓기.

  • 커널 옵션 중 net.core.somaxconn 이 있다. 커널이 연결을 큐잉할 수 있는 최대 값임. 512 보다 더 큰 값을 설정하고 nginx 의 listen 지시자의 backlog 매개변수에도 같은 값을 설정해야한다. 주로 튜닝 시점은 커널 로그에 명시적으로 값을 설정하라고 남겨질 때 하면 된다. nginx 자체가 워낙 연결 처리가 빨라서.

  • 시스템 성능 시 파일 디스크립터 (file descriptor) 설정을 늘려놓는 경우가 더 유용하다. 시스템 환경에서 연결이 맺어지면 이게 하나씩 생긴다. nginx 는 클라이언트와 업스트림 서버 둘을 연결하므로 두 개씩 생긴다. 대량의 연결을 처리하기 위해서 sys.fs.file.max 를 통해서 파일 디스크립터 개수를 늘려놓을 수 있다. 아니면 NGINX 가 시스템 사용자를 통해서 실행되는 경우에는 /etc/security/limits.conf 를 통해서 조정할 수 있다.

  • 마지막으로 더 많은 연결을 처리할 수 있도록 임시 포트를 활성화해야한다. 이 최대 개수는 net.ipv4.ip_local_port_range 값을 통해서 확인할 수 있다. 최솟값이 1024 이고 최대값이 65335 이면 문제 없다. 1024 가 TCP 포트 번호가 끝나는 지점, 65535 가 임시 포트가 끝나는 지점이다.

chapter 18. 실전 운영 팁

부피가 큰 설정 파일을 모듈화해서 관리하고, 설정 파일을 모울 땐 include 를 이용하기

NGINX 가 예상치 못하게 죽었거나 동작할 때 디버깅하는 방법

profile
좋은 습관을 가지고 싶은 평범한 개발자입니다.

0개의 댓글