Nginx로 AWS ELB 대체하기

몇달 전 기존에 쓰고 있던 AWS EC2(t2.micro) 인스턴스 2개를 비용 문제로 예약 인스턴스로 바꿨다. 그런데 비용을 좀 아끼자고 결정한 일이 오히려 비용을 몇배로 키웠다. 

예약 인스턴스를 구매하고 ELB 사용하면서 비용이 더 증가했다.

처음엔 예약 인스턴스 기간이 제대로 설정이 안됐나 싶었지만 상세 내역을 보니 문제는 바로 ELB 였다. AWS에서 이녀석을 어떻게 구현했는지 모르겠지만 ELB 한대당 t2.micro 서버 한대와 맞먹는 요금이 나오는걸로 봐서는 ELB를 EC2 위에 올려서 서비스하는건가? 하는 생각도 든다.

ELB는 왜 썼나?

비용 문제를 제외하면 라우터(Route53)와 도커 컨테이너 사이에 로드발란서(ELB)를 두고 포트를 맵핑하는 방법은 정말 간편하다. 특히 SSL 인증서를 ELB에 넣는 것도 클릭 몇번이면 다 해결되지 이걸 안써야할 이유를 못찾을 정도 였는데… 이제서야 그 이유를 찾은것 같다. 쉬운 만큼 비싸다! 그럼 각설하고 ELB 대신에 nginx 를 설정해보자.

ELB를 대신할 nginx 의 위치

도커가 설치된 호스트 서버를 최전방에 위치시키면 출처를 알 수 없는 수많은 트래픽을 받아야하기 때문에 최대한 ELB 뒤에 숨기고 싶었으나 이제는 선택의 여지가 없다. 그래도 EC2 서버 자체가 털리지 않도록 AWS 보안 그룹 설정에서 80과 443 포트만 와이드 오픈으로 열어두자. 

어찌됐든 도커가 설치된 EC2 서버에 nginx를 설치해야되는데, 이 녀석을 도커 컨테이너로 띄울지 EC2 서버에 직접 서비스로 올릴지는 잠깐 고민했다. ELB를 대신할 nginx의 역할은 부하 분산의 목적보다는 한 서버위에 여러 컨테이너로 올려지는 서비스에 포트를 바인딩하기 위한 멀티 호스팅이 주 목적이기 때문에 그냥 EC2 서버에 직접 올리기로 했다.

nginx를 설치하고 멀티 호스팅 설정은 /etc/nginx/conf.d/ 폴더 하위에 호스트 별로 설정을 추가한다. 먼저 이 블로그는 도커 컨테이너의 8888번 포트와 맵핑되어 있다. 

## /etc/nginx/conf.d/miconblog.com.conf 파일
server {
	listen 80;
        server_name miconblog.com;

        location / {
                proxy_pass http://127.0.0.1:8888;
        	proxy_set_header X-Forwarded-For $remote_addr;
	        proxy_set_header Host $http_host;
        }

}

마찬가지로 운영중인 서비스도 같은 방식으로 맵핑한다.  

## /etc/nginx/conf.d/rlibro.com.conf 파일
server {
        server_name rlibro.com;

        location / {
                proxy_pass http://127.0.0.1:8080;
        	proxy_set_header X-Forwarded-For $remote_addr;
	        proxy_set_header Host $http_host;
        }
}

EC2 서버에 certbot 설치하기

이제 ELB를 선택한 또다른 이유중 하나인 SSL 인증서 문제를 해결해보자. SSL 인증서는 직접 구매해도 되지만 도메인을 가지고 있다면 Let’s Encrypt를 이용해 무료로 쓸수도 있다. 

Let’s Encrypt로 인증서를 발급받으려면 certbot 이라는 프로그램을 이용해야한다. 일단 certbot 패키지를 설치해야하는데, 내가 쓰고 있는 CentOS7 버전은 yum을 이용해 설치할수있다는데 몇몇 라이브러리의 파이썬 버전이 맞지 않아서 직접 다운로드 받아 설치했다.  설치는 아래 링크를 참고하자.

https://certbot.eff.org/lets-encrypt/centos6-nginx

Nginx 가 설치된 서버에서 certbot을 설치하고 아래 명령을 입력하면 certbot이 알아서 nginx 설정을 읽어와 원하는 도메인에 인증서를 설치해준다. 

$> ./certbot-auto --nginx

위 명령을 입력하면 앞에서 nginx에 2개의 멀티 호스트를 설정했기 때문에 certbot은 두 도메인 중 어떤 녀석을 HTTPS로 서비스하고 싶은지 물어봐준다. 당연히 나는 2번을 선택!

Requesting to rerun ./certbot-auto with root privileges...
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx

Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
1: miconblog.com
2: rlibro.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 2

... 중략 ... 

그럼 인증서를 /etc/letsencrpyt/live/도메인명/ 하위에 설치해준다. 그리고 이어서 http 요청이 들어오면 https로 강제 redirect 할지 말지를 묻는다. 나는 역시 강제 리다이랙션 옵션인 2번을 선택!

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2

.... 중략 ...

자 이제 인증서 설정이 끝났다. nginx를 재시작하면 miconblog.com 과 rlibro.com 두 서비스가 모두 정상 동작한다. 

그리고 SSL 인증서를 설치한 rlibro.com.conf 파일을 열어보면 certbot 직접 추가한 설정을 볼수있다. 

server {
    server_name rlibro.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
      	proxy_set_header X-Forwarded-For $remote_addr;
	proxy_set_header Host $http_host;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/rlibro.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/rlibro.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}
server {
    if ($host = rlibro.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80;
    server_name rlibro.com;
    return 404; # managed by Certbot
}

와~ 세상 정말 좋아졌다!

불꽃남자

UI 개발자

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.