Rolling deployment를 위한 nginx 설정

Posted by yunki kim on October 3, 2022

  프로젝트를 진행하면서 무중단 배포를 적용하기 위해 이리저리 찾아보면서 Nginx를 활용해 로드밸런싱을 해야 한다는 것을 알게 되었다. 그리고 이번 프로젝트에 적용하기 가장 적합해 보이는 Rolling 배포 방식을 간단히 구현해 보았다. 현재 AWS EC2를 사용 중이기 때문에 Blue-green을 사용할 거면 인스턴스를 종료하고 시작하는 방법이 필요하다. 이 부분을 자동화시키고 싶어서 AWS 람다를 고려했으나 람다 권한이 없어서 적용하지 못했다. 결국 추가 인스턴스가 필요 없는 Rolling이 가장 적합하다 판단했다.

간단한 서버 세팅

  Nginx 설정이 중점이므로 express로 정말 간단한 서버 두대만 띄웠다. 코드는 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// server 1
const morgan = require("morgan");
const express = require('express');
 
const app = express();
 
app.use(morgan('dev'));
 
app.get("/", (req, res) => {
    res.send("server1");
});
 
app.listen(10003, () => {
    console.log("server1 start");
});
 
 
// server2
const morgan = require("morgan");
const express = require('express');
 
const app = express();
 
app.use(morgan('dev'));
 
app.get("/", (req, res) => {
    res.send("server2");
});
 
app.listen(10004, () => {
    console.log("server1 start");
});
cs

Nginx load balancing

  이제 nginx로 로드밸런싱을 설정해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# upstream 설정
upstream nodejs {
        # 로드밸런싱 알고리즘은 기본값인 라운드로빈 사용 
        server localhost:10003;
        server localhost:10004;
}
 
server {
        listen 80;
 
        location / {
                proxy_pass http://nodejs;
                proxy_http_version 1.1;
        }
}
cs

  위 설정을 /etc/nginx/sites-avaliable/ 에 allActive.conf라는 파일을 만들어 작성하자. 이제 다음과 같은 명령어를 이용해 설정을 적용하고 nginx를 재시작하자.

1
2
3
4
5
sudo rm /etc/nginx/sites-enabled/*
sudo ln -/etc/nginx/sites-available/allActive.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo nginx -s reload
sudo systemctl status nginx
cs

  이제 클라이언트에서 몇번 접속해보면 다음과 같은 로그가 서버에 남는 것을 볼 수 있다.

server 1 log
server 2 log

  라운드로빈은 요청을 순서대로 돌아가면서 서버에 배정하기 때문에 위와 같은 결과가 나온다.

Rolling Deployment를 위한 routing 변경

  이제 롤링 배포를 위해 특정 서버로 요청을 라우팅 하지 않게 설정을 해줘야 한다. 하지만 매번 수동으로 설정을 바꾸고, nginx 정상 시행 여부를 검증하고, nginx를 재시작하기에는 너무 많은 시간이 소요된다. 그래서 여러 설정을 미리 만들어 놓고 쉘 스크립트로 이 설정들을 갈아 끼우는 방식을 적용했다.

  우선 nginx에서 로드밸런싱의 대상이 되는 서버들 중 특정 서버로 가는 라우팅을 막고 싶다면 down 키워드를 사용하면 된다. 그리고 '/etc/nginx/sites-avaliable'라는 디렉터리에 원하는 설정들을 생성할 수 있다. '/etc/nginx/sites-avaliable'에 존재하는 설정 중 적용하길 원하는 설정이 있다면 '/etc/nginx/sites-enable'로 복사하면 된다. Nginx 기본 설정 파일인 nginx.conf가 '/etc/nginx/sites-enable'을 include 하고 있기 때문에 저 경로에 존재하는 설정을 nginx 불러와 사용한다.

1
2
3
4
5
6
7
8
# /etc/nginx/nginx.conf에 존재하는 설정
http {
    ...
 
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*.conf;
}
 
cs

  이제 모든 서버를 다 라우팅하는 설정인 allActive.conf, 첫 번째 서버로만 라우팅 시키는 server1 Active.conf, 두 번째 서버만 라우팅 시키는 server2 Active.conf를 '/etc/nginx/sites-avaliable'에 만들어 보자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# allActive.conf
upstream nodejs {
        server localhost:10003;
        server localhost:10004;
}
 
server {
        listen 80;
 
        location / {
                proxy_pass http://nodejs;
                proxy_http_version 1.1;
        }
}
 
# server1Active.conf
upstream nodejs {
        server localhost:10003;
        server localhost:10004 down;
}
 
server {
        listen 80;
 
        location / {
                proxy_pass http://nodejs;
                proxy_http_version 1.1;
        }
}
 
# server2Active.conf
upstream nodejs {
        server localhost:10003 down;
        server localhost:10004;
}
 
server {
        listen 80;
 
        location / {
                proxy_pass http://nodejs;
                proxy_http_version 1.1;
        }
}
cs

  이제 이 설정들을 원하는 대로 갈아 끼울 수 있게 쉘 스크립트를 만들자.

1
2
3
4
5
6
7
8
# allActive.sh
# 첫 번째 서버, 두 번째 서버 중 하나만 라우팅 시키는 쉘스크립트도 아래와 동일한다
# 두 번째 줄에서 allActive.conf를 알맞은 설정파일로 바꾸기만 하면 된다.
sudo rm /etc/nginx/sites-enabled/*
sudo ln -/etc/nginx/sites-available/allActive.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo nginx -s reload
sudo systemctl status nignx
cs

적용해보기

  이제 작성한 쉘스크립트와 설정이 잘 적용되는지 확인해보자. 첫 번째 서버로만 라우팅 시키기 위해 server1.conf를 적용해보자.

스크립트 실행

 

첫 번째 서버 로그
두 번쨰 서버 로그