프록시 개념과 EC2 내 nginx 를 이용한 로드밸런싱 실습

Ywoosang·2021년 11월 16일
2
post-thumbnail

들어가며

IE나 크롬, 엣지, 파어어폭스 등 웹 클라이언트는 HTTP 프로토콜에 의해 해당 주소의 컴퓨터 IP를 찾은 후에 기본적으로 80 포트를 통해 서비스를 요청하면서 웹 서버와 통신한다. 이처럼 직접적으로 네트워크 요청을 보낼 수도 있지만 중간에서 대리해주는 프록시 서버를 이용해 요청과 응답을 처리하는 방법이 있다. 이번 포스팅에서 프록시에 대한 개념과 Nginx 를 이용해 리버스 프록시를 설정하는 방법에 대해 정리해본다.

Proxy

  • 프록시는 서버와 클라이언트 사이 중계 기능을 해 대리로 통신을 수행하는 기능을 의미한다.
  • 프록시 서버는 서버와 클라이언트 사이 중계 기능을 하는 서버를 의미한다.

프록시는 크게 Forward Proxy 와 Reverse Proxy 로 나뉘며 프록시를 이용할 경우 다음과 같은 순서로 서버와 클라이언트 사이 요청과 응답이 처리된다.

  1. 클라이언트에서 프록시 서버로 데이터 요청
  2. 프록시 서버에서 다시 웹 서버로 실제 데이터 요청
  3. 웹 서버에서 프록시 서버로 데이터 반환
  4. 프록시 서버에서 클라이언트로 데이터 응답

Forward Proxy

포워드 프록시는 클라이언트(사용자)가 인터넷에 직접 접근하는게 아니라 프록시 서버가 요청을 받고 인터넷에 연결하여 결과를 클라이언트에 전달 (forward) 해주는 것이다. 포워드 프록시 서버는 대부분 캐싱 기능이 있으므로 캐시에 데이터가 남아 있다면 다음 요청시 캐시된 데이터로부터 컨텐츠를 제공해 성능 향상을 가져올 수 있다. 사용자 PC 가 직접 사이트에 요청을 전송해 연결하는 것이 아니라 포워드 프록시 서버가 사용자 pc의 요청을 받아 사이트에 연결하는 것이므로 인트라넷에서 정해진 사이트만 연결할 수 있도록 설정하는 등 웹 사용환경을 제한할 수 있다. 따라서 보안이 중요한 기업 환경 등에서 많이 사용된다.

클라이언트의 요청을 포워드 프록시 서버에서 받고 인터넷 상에 클라이언트의 요청을 받을 서버에서 응답 결과를 받아와 클라이언트에게 전달하는 그림이다.

Reverse Proxy

다른 서버의 정보를 프록시를 통해 받아오는 부류의 프록시를 뜻한다. 단, 포워드 프록시와는 다르게 사용자가 요청하는 Endpoint는 접근하고자 하는 최종 목적지 서버가 아닌, 리버스 프록시가 된다.

리버스 프록시를 사용했던 몇 가지 경우를 정리해보자면 다음과 같다.

HA(High Availability) 를 위한 Load Balancing

리버스프록시를 이용해 사용자들의 요청을 필요한 애플리케이션 서버에 분산시킬 수 있다. 만약 WAS 가 1개라면 서버 한대 분량의 부하만 받을 수 있을 것이다. 사용자가 늘어 서버를 여러개 사용해야 할 때 nginx를 리버스 프록시 역할로 앞단에 두고 서버를 nginx 를 통해 통신하도록 할 수 있다. nginx 가 요청을 받아 WAS 에 전달해주는 역할을 해 부하(Load) 가 고르게 (Balance) 들어가게 될 텐데 이때 nginx 는 리버스 프록시를 이용해 로드밸런서 역할을 한 것이다.

API Gateway 역할

라우팅에 따라 각 엔드 포인트로 클라이언트의 요청을 대리 전송한다. 보통 MSA 를 사용할때 nginx 를 API Gateway 로 앞단에 두고 클라이언트가 마이크로서비스를 직접 호출하지 않도록 한다. 시스템의 내부 구조는 숨기고 외부의 요청에 대한 응답을 프록시가 클라이언트에게 전달하는 것이다. 이렇게 되면 클라이언트와 마이크로 서비스 사이에 리버스 프록시 서버가 위치해 각각의 마이크로서비스로 요청되는 모든 정보를 리버스프록시 서버를 거쳐 처리하도록 한다. 이렇게 클라이언트는 각각의 마이크로서비스들과 통신하는 것이 아닌 api gateway와 통신하게 된다.

Web Acceleration 역할

인바운드와 아웃바운드 데이터를 압축할 수 있으며 요청되는 컨텐츠를 캐시해 클라이언트와 서버 간 불필요한 트래픽을 줄일 수 있다. SSL 암호화 등을 수행해 웹서버의 부하를 감소시킬 수 있어 성능이 개선된다.

보안상 이용

리버스 프록시 서버가 앞에서 대리로 요청을 받기 때문에 인트라넷으로 향하는 요청을 차단하는 역할을 할 수 있다. 따라서 인트라넷의 보안공격에 대해 추가적인 방어 역할을 수행할 수 있다.

Nginx 를 이용한 로드 밸런싱

리버스프록시 역할을 하는 nginx 로 로드밸런서를 만들어 보자.

nginx 설정

AWS 인스턴스를 생성해 SSH 로 접속한다.

인스턴스내에서 nginx 를 설치한다.

sudo amazon-linux-extras install nginx1

nginx 설정을 확인한다. nginx 설정파일들을 불러오는 include /etc/nginx/conf.d/*.conf; 부분이 확인된다. 따라서 /etc/nginx/conf.d 경로에 들어가 원하는 이름으로 .conf 확장자 파일을 만들면 해당 내용이 적용된다.

로드밸런싱을 설정해보자. 여기서는 default.conf 로 설정 파일을 만들었다.

cd /etc/nginx/conf.d
vim default.conf

upstream 방식으로 두개에 서버를 설정하여 80포트(nginx)로 요청이 들어오면 분산하도록 설정된다. 분산 알고리즘은 별도 설정을 하지 않는다면 라운드로빈 방식이 기본이다. 인스턴스의 내부 아이피를 통해 실행중인 포트번호(프로그램)에 로드밸런싱을 수행하도록 한다.이렇게 되면 두 서버에 라운드로빈 방식으로 요청이 고르게 분산된다.

// default.conf
upstream myserver {
    server 172.31.45.173:8000;
    server 172.31.45.173:8001;
}

server {
    listen 80;

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

nginx 서비스를 시작한다.

sudo service nginx start

nginx 로그를 확인하려면 다음 명령어를 이용한다.

sudo tail -f /var/log/nginx/access.log

웹서버 설정

다음으로 FastAPI 로 간단한 웹 애플리케이션 서버를 만든다. CORS 설정은 프록시 설명 목적이므로 모두 허용했다.

# app.py
import uvicorn
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware 

app = FastAPI()
app.add_middleware(
    CORSMiddleware,
    allow_origins="*",
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"]
)

@app.get("/")
async def index():
    return {
        "server": "sample"
    }

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

python 과 pip 를 설치해준다. amazon linux2 는 yum 을 이용한다.

sudo yum update -y
sudo yum install -y python3 pip3

FastAPI 와 uvicorn 을 설치한다.

pip install fastapi
pip install uvicorn

파이썬을 사용할 때는 가상환경을 생성하고 패키지를 설치한 뒤 requirements.txt 를 기반으로 설치하는 것이 일반적이다. 여기서는 프록시 설명 목적이므로 인스턴스 내에서 수동으로 설치했다.

app 디렉토리를 파이썬 실행 파일을 EC2 기본 경로인 /home/ec2-user에 만든다. vim 에디터로 app1.py,app2.py 를 각각 생성한다. 코드는 위에 있는 FastAPI 코드를 붙여넣고 포트번호만 각각 8000번, 8001번으로 바꿔준다.

mkdir app
cd app
vim app1.py
vim app2.py

두 서버를 시작한다.

python3 app1.py
python3 app2.py

인스턴스의 public ip 로 들어가 nginx 의 로드밸런싱을 확인해보자.

새로고침을 할 때마다 요청이 고르게 들어오는 것을 확인할 수 있다면 성공이다.

참고자료
https://www.lesstif.com/system-admin/forward-proxy-reverse-proxy-21430345.html
https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9D%EC%8B%9C_%EC%84%9C%EB%B2%84
https://bcp0109.tistory.com/194
https://johyungen.tistory.com/397
https://firework-ham.tistory.com/23
https://ckddn9496.tistory.com/36
https://kobumddaring.tistory.com/45
https://kamang-it.tistory.com/entry/WebServernginxnginx%EB%A1%9C-%EB%A1%9C%EB%93%9C%EB%B0%B8%EB%9F%B0%EC%8B%B1-%ED%95%98%EA%B8%B0

profile
백엔드와 인프라에 관심이 많은 개발자 입니다

0개의 댓글