Skip to content

nginx load balancing

์„œ๋ฏผ์ • edited this page Nov 23, 2021 · 2 revisions

ํ•ด๋‹น ๊ธ€์€ ๋ธ”๋กœ๊ทธ์—๋„ ์ž‘์„ฑํ•ด๋‘์—ˆ์Šต๋‹ˆ๋‹ค.

image ์šฐ์„  ์›ํ•˜๋Š” ๊ตฌ์กฐ๋Š” ์œ„์™€ ๊ฐ™์œผ๋ฉฐ, ํ๋ฆ„์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • nginx๋Š” proxy์—ญํ• ์„ ํ•˜๋ฉฐ, ๋ณ„๋„์˜ ์ธ์Šคํ„ด์Šค๋กœ ๊ตฌ์„ฑํ•œ๋‹ค.
  • WAS๋Š” Spring Application์ด๋ฉฐ, ์ด ๋‘ ๋Œ€๋กœ ๊ตฌ์„ฑํ•œ๋‹ค.
  • ๋‘ ๋Œ€์˜ WAS๋Š” ํ•˜๋‚˜์˜ Database๋ฅผ ๋ฐ”๋ผ๋ณธ๋‹ค.
  • ํด๋ผ์ด์–ธํŠธ๋Š” ์ •ํ•ด์ง„ ๋„๋ฉ”์ธ์œผ๋กœ ์ ‘์†ํ•˜๋ฉด, nginx์—์„œ round-robin ๋ฐฉ์‹์œผ๋กœ ์ ์ ˆํ•œ WAS๋กœ ์š”์ฒญ์„ ๋ถ„๋ฐฐํ•˜๋ฉฐ, ๊ฐ WAS๋Š” ๋™์ผํ•œ DB๋ฅผ ๋ฐ”๋ผ๋ณด๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์‘๋‹ตํ•  ์ˆ˜ ์žˆ๋‹ค. ์‚ฌ์‹ค ๋„ˆ๋ฌด ๊ฐ„๋‹จํ•ด์„œ ๊ธ€๋กœ ์“ฐ๊ธฐ๋„ ๋ญฃํ•˜์ง€๋งŒ.. ๋‚˜์ค‘์„ ์œ„ํ•ด!

WAS ๊ตฌ์ถ•ํ•˜๊ธฐ

Spring Application์„ ๋„์šธ EC2 ์ธ์Šคํ„ด์Šค๋ฅผ ํ•˜๋‚˜ ์ƒ์„ฑํ•œ๋‹ค.

์ƒ์„ฑ๋œ EC2์— ์ ‘์†ํ•œ ๋’ค, ์Šคํ”„๋ง์„ ๋„์šธ ์ˆ˜ ์žˆ๋Š” ํ™˜๊ฒฝ์„ค์ •์„ ํ•œ๋‹ค.

sudo apt update
sudo apt install default-jre
sudo apt install default-jdk

์ดํ›„, ์†Œ์Šค์ฝ”๋“œ๋ฅผ github์—์„œ ํด๋ก ํ•œ๋‹ค.

git clone -b {branch๋ช…} --single-branch {๋ ˆํฌ์ง€ํ† ๋ฆฌ ์ฃผ์†Œ}

// ์„œ๋ธŒ๋ชจ๋“ˆ์ด ํฌํ•จ๋˜์–ด์žˆ์œผ๋ฉฐ ๋ ˆํฌ์ง€ํ† ๋ฆฌ๊ฐ€ ๋ฐ”๋ผ๋ณด๊ณ  ์žˆ๋Š” ์„œ๋ธŒ๋ชจ๋“ˆ์„ ๊ฐ€์ ธ์˜ฌ ๊ฒฝ์šฐ
git clone -b {branch๋ช…} --single-branch {๋ ˆํฌ์ง€ํ† ๋ฆฌ ์ฃผ์†Œ} --recurse-submodules

// ์„œ๋ธŒ๋ชจ๋“ˆ์ด ํฌํ•จ๋˜์–ด์žˆ์œผ๋ฉฐ ์ตœ์‹ ์˜ ์„œ๋ธŒ๋ชจ๋“ˆ์„ ๊ฐ€์ ธ์˜ฌ ๊ฒฝ์šฐ
git clone -b {branch๋ช…} --single-branch {๋ ˆํฌ์ง€ํ† ๋ฆฌ ์ฃผ์†Œ} --remote-submodules

ํด๋ก ํ•œ ๋ ˆํฌ์ง€ํ† ๋ฆฌ์—์„œ build.gradle์ด ์žˆ๋Š” ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์ด๋™ํ•œ ๋’ค ์†Œ์Šค์ฝ”๋“œ ๋ฐฐํฌ, ๋นŒ๋“œ๋ฅผ ์ง„ํ–‰ํ•œ ๋’ค ์‹คํ–‰ํ•œ๋‹ค.

./gradlew clean build

cd build/libs
java -jar -Dspring.profiles.active={activeProfile} *.jar &

์ด ๊ณผ์ •์„ ๋‘ ๊ฐœ์˜ ์ธ์Šคํ„ด์Šค์—์„œ ๊ฐ๊ฐ ์ง„ํ–‰ํ•œ๋‹ค.

์ดํ›„ pull request ๋ฐ push์— ๋”ฐ๋ผ ์ž๋™์œผ๋กœ ๋นŒ๋“œ ๋ฐ ์‹คํ–‰์ด ์ง„ํ–‰๋˜๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” jenkins์— ์—ฐ๋™ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

ps -ef | grep java

์œ„ ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด java -jar .. ์ด ํ”„๋กœ์„ธ์Šค๋กœ์„œ ์‹คํ–‰๋˜๊ณ  ์žˆ๋Š”์ง€๋ฅผ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ๋นŒ๋“œ๋Š” ๋์ง€๋งŒ ์‹คํ–‰์ด ์•ˆ๋ ์ˆ˜๋„..

nginx์— ๋กœ๋“œ๋ฐธ๋Ÿฐ์‹ฑ ์„ค์ •ํ•˜๊ธฐ

๋‘ ๋Œ€์˜ WAS๋ฅผ ๋ชจ๋‘ ๋„์› ๋‹ค๋ฉด, nginx ์—ญํ• ์„ ๋‹ด๋‹นํ•  ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ๋‹ค๋ฉด, ๋จผ์ € ๋„์ปค๋ฅผ ์„ค์น˜ํ•œ๋‹ค.

sudo apt-get update && \
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common && \
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - && \
sudo apt-key fingerprint 0EBFCD88 && \
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" && \
sudo apt-get update && \
sudo apt-get install -y docker-ce && \
sudo usermod -aG docker ubuntu && \
sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && \
sudo chmod +x /usr/local/bin/docker-compose && \
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

๋‚ด๊ฐ€ ์ง„ํ–‰ํ•  nginx๋Š” ๋„์ปค์—์„œ ์„ค์น˜ํ•˜๋ฉฐ, ์šฐ์•„ํ•œ ํ…Œํฌ์ฝ”์Šค์—์„œ ์ œ๊ณตํ•ด์ฃผ๋Š” docker image๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ๋‚˜์ค‘์— ์„œ๋ฒ„์— ์ง์ ‘ nginx๋ฅผ ์„ค์น˜ํ•ด์„œ ํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์‹œ๋„ํ•ด๋ณด์•„์•ผ๊ฒ ๋‹ค.

์•„๋ฌด์ชผ๋ก ๋„์ปค๊ฐ€ ์„ค์น˜๋˜์—ˆ๋‹ค๋ฉด, ์ด์ œ http://๋‚ด๋„๋ฉ”์ธ.ํ•œ๊ตญ ์— ์ ‘์†ํ•ด์„œ ์‚ฌ์šฉํ•  ๋ฌด๋ฃŒ ๋„๋ฉ”์ธ์„ ์ƒ์„ฑํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  TLS ์„ค์ •์„ ์ง„ํ–‰ํ•œ๋‹ค.

TLS ์„ค์ •

์„œ๋ฒ„์˜ ๋ณด์•ˆ๊ณผ ๋ณ„๊ฐœ๋กœ ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ๊ฐ„ ํ†ต์‹ ์ƒ์˜ ์•”ํ˜ธํ™”๊ฐ€ ํ•„์š”ํ•˜๊ธฐ์— TLS๋ฅผ ์„ค์ •ํ•ด์ค€๋‹ค. ํ‰๋ฌธ์œผ๋กœ ํ†ต์‹ ํ•  ๊ฒฝ์šฐ, ํŒจํ‚ท์„ ์Šค๋‹ˆํ•‘ํ•  ์ˆ˜ ์žˆ๋‹ค.

letsencrypt๋ฅผ ํ†ตํ•ด ๋ฌด๋ฃŒ๋กœ TLS ์ธ์ฆ์„œ๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์ž.

docker run -it --rm --name certbot \
  -v '/etc/letsencrypt:/etc/letsencrypt' \
  -v '/var/lib/letsencrypt:/var/lib/letsencrypt' \
  certbot/certbot certonly -d '[๋„๋ฉ”์ธ ์ฃผ์†Œ]' --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory

์œ„ ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด ์ธ์ฆ์„œ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ค‘, Please deploy a DNS TXT record under the name ์ด๋ผ๋Š” ๋ฌธ๊ตฌ๊ฐ€ ๋‚˜์˜ค๋ฉด ๋‹ค์Œ์„ ์ง„ํ–‰ํ•œ๋‹ค.

image TXT๋Š” ๋‚ด๋„๋ฉ”์ธ.ํ•œ๊ตญ์˜ ๋„๋ฉ”์ธ ์„ค์ •์—์„œ ์ง„ํ–‰ํ•˜๋Š” ๊ฒƒ์ด๋ฉฐ, ๋‚ด๋„๋ฉ”์ธ.ํ•œ๊ตญ์—์„œ ์ž…๋ ฅ์„ ๋ชจ๋‘ ๋งˆ์น˜๊ณ  ์ €์žฅํ•œ ๋’ค ์•ฝ 5์ดˆ์ •๋„ ๊ธฐ๋‹ค๋ฆฐ ๋‹ค์Œ letsencrypt ์„ค์ •์„ ์™„๋ฃŒํ•ด์ฃผ๋ฉด ์ •์ƒ์ ์œผ๋กœ ์™„๋ฃŒ๋œ๋‹ค.

์ƒ์„ฑํ•œ ์ธ์ฆ์„œ๋ฅผ ํ˜„์žฌ ๊ฒฝ๋กœ๋กœ ์ด๋™ํ•œ๋‹ค.

sudo cp /etc/letsencrypt/live/[๋„๋ฉ”์ธ์ฃผ์†Œ]/fullchain.pem ./
sudo cp /etc/letsencrypt/live/[๋„๋ฉ”์ธ์ฃผ์†Œ]/privkey.pem ./

vi Dockerfile ์ด๋ผ๋Š” ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด Dockerfile์„ ์ƒ์„ฑํ•˜๊ณ , ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•œ๋‹ค.

// Dockerfile
FROM nginx

COPY nginx.conf /etc/nginx/nginx.conf 
COPY fullchain.pem /etc/letsencrypt/live/[๋„๋ฉ”์ธ์ฃผ์†Œ]/fullchain.pem
COPY privkey.pem /etc/letsencrypt/live/[๋„๋ฉ”์ธ์ฃผ์†Œ]/privkey.pem

๊ฐ™์€ ๋””๋ ‰ํ† ๋ฆฌ์—์„œ vi nginx.conf ํŒŒ์ผ์„ ์ƒ์„ฑํ•œ ๋’ค, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•œ๋‹ค.

events {}

http {       
  # ์ƒ์„ฑํ•œ ๋‘ ๋Œ€์˜ WAS private IP๋ฅผ upstream app ์•„๋ž˜์— ์ž‘์„ฑํ•œ๋‹ค.
  upstream app {
    server {WAS private IP}:{ํฌํŠธ๋ฒˆํ˜ธ};
    server {WAS private IP}:{ํฌํŠธ๋ฒˆํ˜ธ};
  }
  
  # Redirect all traffic to HTTPS
  server {
    listen 80;
    return 301 https://$host$request_uri;
  }

  server {
    listen 443 ssl;  
    ssl_certificate /etc/letsencrypt/live/[๋„๋ฉ”์ธ์ฃผ์†Œ]/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/[๋„๋ฉ”์ธ์ฃผ์†Œ]/privkey.pem;

    # Disable SSL
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

    # ํ†ต์‹ ๊ณผ์ •์—์„œ ์‚ฌ์šฉํ•  ์•”ํ˜ธํ™” ์•Œ๊ณ ๋ฆฌ์ฆ˜
    ssl_prefer_server_ciphers on;
    ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;

    # Enable HSTS
    # client์˜ browser์—๊ฒŒ http๋กœ ์–ด๋– ํ•œ ๊ฒƒ๋„ load ํ•˜์ง€ ๋ง๋ผ๊ณ  ๊ทœ์ œํ•ฉ๋‹ˆ๋‹ค.
    # ์ด๋ฅผ ํ†ตํ•ด http์—์„œ https๋กœ redirect ๋˜๋Š” request๋ฅผ minimize ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    add_header Strict-Transport-Security "max-age=31536000" always;

    # SSL sessions
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;      

    location / {
      proxy_pass http://app;    
    }
  }
}

nginx๊ฐ€ ์—ฌ๋Ÿฌ ์„œ๋ฒ„์— ๋ถ„๋ฐฐํ•ด์ฃผ๋ฏ€๋กœ upstream ์„œ๋ฒ„์— ์ž‘์„ฑํ•œ๋‹ค. ๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ์€ ์š”์ฒญ์„ ๊ณ ๋ฃจ ๋ถ„๋ฐฐํ•ด์„œ ์„œ๋ฒ„๋กœ ๋„˜๊ฒจ์ฃผ๋Š”๋ฐ, ์ด ๋•Œ ์–ด๋–ป๊ฒŒ ๋ถ„๋ฐฐํ•  ์ง€ ๊ทœ์น™์„ ์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

์ง€๊ธˆ ์œ„ nginx.conf์ฒ˜๋Ÿผ ์•„๋ฌด ๊ทœ์น™๋„ upstream์— ์ ์ง€ ์•Š๊ณ  server ip๋งŒ ์ž‘์„ฑํ•œ๋‹ค๋ฉด default์ธ round-robin ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•˜๊ฒŒ ๋œ๋‹ค.

upstream app {
    ip_hash;
    server {WAS private IP}:{ํฌํŠธ๋ฒˆํ˜ธ};
    server {WAS private IP}:{ํฌํŠธ๋ฒˆํ˜ธ};
  }

ip_hash๋ฅผ ์ ์–ด์ฃผ๊ฒŒ ๋˜๋ฉด, ip๋ฅผ ํ•ด์‹œ๊ฐ’์œผ๋กœ ๋‚˜๋ˆ ์ฃผ๊ฒŒ ๋œ๋‹ค. ์ด๋ ‡๊ฒŒ ๋ถ„๋ฐฐํ•˜๊ฒŒ ๋˜๋ฉด ํ•œ๋ฒˆ ์ ‘์†ํ–ˆ๋˜ ip๋Š” ๊ฐ™์€ ํ•ด์‹œ๊ฐ’์„ ๊ฐ€์ง€๋ฏ€๋กœ ๋งค๋ฒˆ ๋™์ผํ•œ ์„œ๋ฒ„์—๊ฒŒ ์š”์ฒญ์„ ๋ณด๋‚ด๊ฒŒ ๋œ๋‹ค. ์„ธ์…˜์œผ๋กœ ๋ฌด์–ธ๊ฐ€๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ ์ด ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค. (์•ฝ๊ฐ„์˜ ๋‡Œํ”ผ์…œ)

์ด ์™ธ์—๋„ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

  • round-robin(default)
  • hash - hash <ํ‚ค> ํ˜•ํƒœ๋กœ ์ž‘์„ฑํ•˜๋ฉฐ ํ•ด์‹œํ•œ ๊ฐ’์œผ๋กœ ๋ถ„๋ฐฐํ•œ๋‹ค. ex)hash $remote_addr (= ์ด๋Š” ip_hash์™€ ๊ฐ™๋‹ค)
  • ip_hash - ์•„์ดํ”ผ๋ฅผ ํ•ด์‹ฑํ•ด ์š”์ฒญ์„ ๋ถ„๋ฐฐํ•œ๋‹ค.
  • random
  • least_conn - ์—ฐ๊ฒฐ์ˆ˜๊ฐ€ ๊ฐ€์žฅ ์ ์€ ์„œ๋ฒ„์— ๊ฐ€์ค‘์น˜๋ฅผ ๊ณ ๋ คํ•ด์„œ ๋ถ„๋ฐฐ
  • least_time - ์—ฐ๊ฒฐ์ˆ˜๊ฐ€ ๊ฐ€์žฅ ์ ์œผ๋ฉด์„œ ํ‰๊ท  ์‘๋‹ต์‹œ๊ฐ„์ด ๊ฐ€์žฅ ์ ์€ ์ชฝ์„ ์„ ํƒํ•ด์„œ ๋ถ„๋ฐฐ ์ž์„ธํ•œ ๋‚ด์šฉ์€ nginx-stream-upstream-module ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•˜๋˜ ์ค‘ ๊ฐ€์ค‘์น˜๋ผ๋Š” ๋ง์ด ๋‚˜์™”๋Š”๋ฐ ํŠน์ • ์„œ๋ฒ„์— 2๋ฐฐ์˜ ๊ฐ€์ค‘์น˜๋ฅผ ์ฃผ๊ณ  ์‹ถ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•˜๋ฉด ๋œ๋‹ค.

upstream app {
    server {WAS private IP}:{ํฌํŠธ๋ฒˆํ˜ธ} weight=2;
    server {WAS private IP}:{ํฌํŠธ๋ฒˆํ˜ธ};
  }

์œ„์™€ ๊ฐ™์ด ์ž‘์„ฑํ•˜๋ฉด ๊ทœ์น™์€ ๋ผ์šด๋“œ ๋กœ๋นˆ์œผ๋กœ ์œ ์ง€ํ•˜๋˜ ์ฒซ๋ฒˆ์งธ ์„œ๋ฒ„๋ฅผ 2๋ฐฐ ๋” ๋งŽ์ด ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค.

nginx์˜ configuration์„ ํ†ตํ•ด ๋กœ๋“œ๋ฐธ๋Ÿฐ์‹ฑ ์„ค์ •์„ ๋ชจ๋‘ ๋งˆ์ณค์œผ๋‹ˆ, ๋„์ปค ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋„์šฐ๋ฉด ์ •์ƒ์ ์œผ๋กœ ๋กœ๋“œ๋ฐธ๋Ÿฐ์‹ฑ์ด ๊ฐ€๋Šฅํ•ด์ง„๋‹ค.

docker build -t nextstep/reverse-proxy:0.0.2 .
docker run -d -p 80:80 -p 443:443 --name proxy nextstep/reverse-proxy:0.0.2

๋—

๋ณด๊ณ  ๋˜ ๋ณด๊ณ  (๋ณด๋˜๋ณด)


Documents ๐Ÿ“ƒ


ํŒ€ ๊ทœ์น™ ๐Ÿค

Code Convention

๊ธฐ์ˆ  ๊ณต์œ  ๐Ÿธ


๋ฐ์ผ๋ฆฌ ๋ฏธํŒ… ๋ฐ ํšŒ์˜๋ก ๐Ÿณ

2์ฐจ ~ 4์ฐจ ํšŒ์˜ ๋ฐ ๋ฐ์ผ๋ฆฌ ๋ฏธํŒ…์€ ๋””์Šค์ฝ”๋“œ์—์„œ ์ง„ํ–‰๋˜์–ด ์ด์Šˆ๋กœ ๋ฐ˜์˜๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ดํ›„ ํšŒ์˜ ๋ฐ ๋ฐ์ผ๋ฆฌ ๋ฏธํŒ…์€ ๋””์Šค์ฝ”๋“œ์—์„œ ์ง„ํ–‰๋˜์–ด ์ด์Šˆ๋กœ ๋ฐ˜์˜๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Clone this wiki locally