[Nginx, uWSGI, Flask] 설치 on AWS EC2

2DH·2023년 7월 27일
0

Nginx,uWSGI,Flask

목록 보기
1/2

해당 게시물은 Quicksight Embedding 을 위해 WebApplication 개발 전 DNS와 SSL이 적용된 웹사이트가 필요하여 사전 PoC차원에서 작성하는 게시물입니다.

Webserver : Nginx
Middle Ware : uWSGI(Flast ↔ Nginx)
Python Framework : Flask

들어가기 앞서

사용자는 브라우저를 또는 각종 Application을 통해 HTTP 요청을 해당 웹 서버에 요청합니다.

해당 요청을 처음 받는 것이 웹서버(Nginx) 이고 해당 웹서버는 동적처리를 위한 WAS(Web Application Server)에 동적 요청을 해야하는데 Nginx는 Python 또는 동적으로 수행하는 프로그래밍 언어를 실행 할 수가 없습니다. 그래서 해당 요청을 프로그래밍 언어로 변환해주는 중계자 역할을 찾아야 하는데 uWSGI 가 해당 역할을 수행합니다.

WSGI(Web Server Gateway Interface) 는 웹서버와 웹어플리케이션의 중계자 역할로 웹서버와 같은 서버에 있으므로 네트워크 통신이 아니라 유닉스 소켓(Unix Socket) 통신을 하는 것이 속도면에서 효율이 좋습니다.

1. AWS VPC & EC2

1.1 VPC

  • 3개 가용영역을 사용하는 VPC

1.2 EC2

  • AZ : AZ-b
  • Subnet : Public Subnet
  • EC2 Type : t3-medium
  • Public IP Allow(외부 접근 가능하게)
    • 설치 테스트 용도로만 이렇게 사용하고 실제 Product는 Private Subnet에 위치해야함.

1.3 보안그룹

  • 22 (SSH), 80(HTTP) => 회사 IP Open

2. Python 가상환경 설치

2.1 라이브러리 업데이트 및 설치

sudo apt update && \
sudo apt install build-essential -y

sudo apt-get install python3-pip
sudo apt install python3.10-venv # 이거 설치 하지 않으면 가상환경을 만들 수 없다.

ubuntu@ip-10-0-27-179:~$ python3 -V
Python 3.10.6
ubuntu@ip-10-0-27-179:~$ pip3 -V
pip 22.0.2 from /usr/lib/python3/dist-packages/pip (python 3.10)

2.2 가상 환경 생성 및 활성화

python3 -m venv geek-venv
cd geek-venv

source bin/activate

2.3 Update pip Version

pip install --upgrade pip

2.4 Deactivate

cd bin

deactivate 

3. uWSGI 설치

uWSGI와 uWSGI Emperor를 설치

uWSGI Emperor

uWSGI Emperor는 uWSGI 애플리케이션 서버의 기능으로, Python 웹 애플리케이션을 배포하고 관리하는 데 널리 사용됩니다. uWSGI Emperor 모드는 여러 uWSGI 애플리케이션 인스턴스를 관리할 수 있는 마스터 프로세스 역할을 합니다. 이를 통해 여러 프로세스 또는 서버에서 웹 응용 프로그램을 확장하여 더 나은 성능과 고가용성을 제공할 수 있습니다.

  1. 단순화된 관리: 개별 uWSGI 프로세스를 수동으로 시작하고 중지하는 대신 Emperor 프로세스를 사용하여 여러 애플리케이션의 관리를 자동으로 처리할 수 있습니다.
  2. 리소스 공유: uWSGI 핵심 프로세스 및 구성과 같은 공통 리소스를 공유함으로써 독립 실행형 모드에서 각 애플리케이션을 실행하는 것과 비교하여 오버헤드가 줄어듭니다.
  3. 간편한 확장: 모니터링되는 디렉터리에 더 많은 uWSGI 애플리케이션 인스턴스(구성 파일)를 추가하여 애플리케이션을 쉽게 확장할 수 있으므로 증가된 트래픽과 사용자 요구를 처리할 수 있습니다.
  4. 격리 및 안정성: 각 애플리케이션이 별도의 uWSGI 프로세스로 실행되기 때문에 한 애플리케이션의 문제가 다른 애플리케이션에 영향을 미칠 가능성이 적어 보다 안정적인 환경을 제공합니다.

3.1 uwsgi 설치

sudo apt-get update
sudo apt-get install build-essential -y
 
# Minimal Install (Recommended for Production Environment)
 
sudo apt-get install uwsgi uwsgi-plugin-python3 -y
 
# Complete Install (Generally used for Development Environment)
 
sudo apt-get install uwsgi uwsgi-extra uwsgi-plugins-all uwsgi-plugin-python3 -y

3.2 Version 확인

uwsgi --version

ubuntu@ip-10-0-27-179:~/geek-venv/bin$ uwsgi --version
2.0.20-debian

3.3 uwsgi emperor 설치

sudo apt-get install uwsgi-emperor -y

3.4 INFO: uWSGI Directories

# uWSGI file system
## Default root configuration
/usr/share/uwsgi/conf/default.ini

## Configuration location for applications
/etc/uwsgi/apps-available
/etc/uwsgi/apps-enabled

# uWSGI (Emperor) file system
## Default root configuration
/etc/uwsgi-emperor/emperor.ini

## Configuration location for applications
/etc/uwsgi-emperor/vassals

## Logs
/var/log/uwsgi/emperor.log

## Socket
/var/run/

3.5 Appendix(참조)

3.5.1 Start uwsgi-emperor

sudo service uwsgi-emperor start

3.5.2 Restart

sudo service uwsgi-emperor restart

3.5.3 Stop

sudo service uwsgi-emperor stop

4. Nginx 설치

4.1 Nginx 설치

# Minimal Install (Recommended for Production Environment)
sudo apt-get install nginx nginx-extras
 
# Complete Install (Generally used For Development Environment)
sudo apt-get install nginx-full

4.2 Verison 확인

nginx -V

4.3 테스트

curl http://localhost

sudo systemctl status nginx

4.4 기본 Nginx configuration(설정) 삭제

  • curl http://localhost command will return a connection refused
  • We will fix this in the next guide.
sudo rm /etc/nginx/sites-enabled/default
 
sudo service nginx restart

5. uWSGI Configuration


5.1 Configuration File 생성

sudo vi /etc/uwsgi/apps-available/geek_flask_app.ini
[uwsgi]
 
project         = geek_flask_app
chdir           = /var/www/geek_flask_app
module          = app_wsgi
virtualenv      = /home/ubuntu/geek-venv
plugins         = http,python3
socket          = /var/run/%n.sock
chmod-socket    = 666
http-socket     = 127.0.0.1:8081
enable-threads  = true
vacuum          = true
die-on-term     = true
sudo ln -s /etc/uwsgi/apps-available/geek_flask_app.ini /etc/uwsgi-emperor/vassals/geek_flask_app.ini

5.3 Reload uwsgi-emperor service

sudo service uwsgi-emperor reload

5.4 emperor.log 확인

아직 Application이 배포 되지 않아 파일이 없다.

sudo tail -f /var/log/uwsgi/emperor.log

# nothing, cuz not deployed

5.5 emperor configuration 수정

  • Run uWSGI Emperor service as root user
  • 특정 사용자가 (Ubuntu User) 프로세스를 소유한다면 해당 특정 사용자를 UID, GID에 입력하고 Root 사용자가 이용한다면 주석처리가 필요.
sudo vi /etc/uwsgi-emperor/emperor.ini

5.6 uwsgi emperor process 재시작

sudo service uwsgi-emperor restart

6. NGINX Configuration

6.1 conf file 생성

sudo vi /etc/nginx/sites-available/geek_flask_app.conf
  • 들어온 요청을 Nginx로 uwsgi_pass 설정
  • 브라우저(80) → Nginx → /run/geek_flask_app.sock 으로 보내고(uwsgi) uwsgi가 Flask(127.0.0.1:8081)로 전달
  • AWS ACM으로 SSL 인증서를 받기 전 내용이다. 해당 내용은 SSL 인증을 하기 위해서는 변경이 필요하다.
server
{
  listen        80;
  server_name   _;
 
  location /
  {
    include     uwsgi_params;
    uwsgi_pass  unix:/run/geek_flask_app.sock;
  }
}
sudo ln -s /etc/nginx/sites-available/geek_flask_app.conf /etc/nginx/sites-enabled/geek_flask_app.conf

6.3 nginx configuration 테스트

sudo nginx -t

7. Flask App/API, uWSGI and NGINX를 이용하여 배포.

7.1 디렉토리와 파일 생성

7.1.1 디렉토리 구조

|__ /var/www
  |__ geek_flask_app
    |__ api
      |__ __init__.py
      |__ res
        |__ __init__.py
        |__ endpoints.py
    |__ app_wsgi.py
    |__ requirements.txt
cd /var/www
sudo mkdir -p geek_flask_app/api/res

7.1.2 /var/www/geek_flask_app/api/init.py

sudo vi /var/www/geek_flask_app/api/__init__.py
from flask import Flask
 
application = Flask(__name__)
 
import api.res.endpoints

7.1.3 /var/www/geek_flask_app/app_wsgi.py

  • Flask 앱과 wsgi를 연결하는 부분
sudo vi /var/www/geek_flask_app/app_wsgi.py
from api import application

7.1.4 /var/www/geek_flask_app/api/res/endpoints.py

sudo vi /var/www/geek_flask_app/api/res/endpoints.py
# -*- coding: utf-8 -*-
 
from flask import jsonify
from api import application
 
@application.route('/', methods=['GET'])
def get_app_properties():
  name = 'geek-flask-api'
  version = '0.0.1'
 
  app_properties = \
  {
    'name': name
    , 'version' : version
  }
 
  return jsonify(app_properties)

7.1.5 /var/www/geek_flask_app/requirements.txt

sudo vi /var/www/geek_flask_app/requirements.txt

flask

7.2 Python 라이브러리 설치

source ~/geek-venv/bin/activate

cd /var/www/flask_app
pip install -r requirements.txt

deactivate

7.3 Reload uwsgi-emperor service

sudo service uwsgi-emperor reload

7.4 flask app is deployed 검증

  • using http-socket defined in uwsgi configuration
  • 처음에는 안나왔는데 다시 uwsgi-emperor reload and restart하니깐 됐음.
curl http://127.0.0.1:8081

7.5 NGINX와 python flask가 uWSGI를 통해 통신하는지 검증

sudo service nginx restart
curl http://localhost

7.6 Flask API 추가

  • uwsgi-emperor 를 재시작해야 Application에 적용할 수 있다.
sudo vi endpoints.py
@application.route('/user', methods=['GET'])
def get_user_information():
    user_info = {
        'name':'lee',
        'age' : 34
    }
    return jsonify(user_info)
sudo service uwsgi-emperor restart

7.7 외부 접근 테스트 (EC2 Public IP)


다음은 해당 웹 서비스를 AWS DNS인 Route53을 이용하여 IP가 아닌 DNS로 접근하는 방법을 게시할 예정입니다.

참조

[Infra] flask, nginx, uwsgi(1) 개념
uWSGI Archives - aster.cloud
[Python] Flask, Gunicorn, Nginx로 EC2배포하기[2]

profile
Becoming the Data Engineer

0개의 댓글