Ubuntu 16.04(Xenial)에 Python 3.9 설치하고 mod_wsgi 빌드하기

나는 몇년 전에 개발된 Django 기반의 웹 프로젝트를 인수받아 운영하고 있다. 

프로젝트의 규모가 꽤 크고 공공기관 고객도 꽤 있어서 여간 신경쓰이는 게 아니다. 그런데 어느날 다음과 같이 Python을 업그레이드하라는 경고 메시지가 나오기 시작했다. 

Cryptography 모듈이 다음 버전부터 Python 3.5를 지원하지 않는다는 통보이다. 공공기관들은 나름대로 보안 규칙이 있어서, 보안 결함이 발견된 모듈에 대해서 업그레이드를 해주어야 한다. 그래서 Python 버전을 올리고 Cryptography 모듈도 버전을 올리면 되는데, 그것이  그리 간단한 문제가 아니다. 

/venv/lib/python3.5/site-packages/OpenSSL/crypto.py:12: 
CryptographyDeprecationWarning: Python 3.5 support will be dropped in the next release of cryptography. 
Please upgrade your Python. from cryptography import x509


시스템은 대략 아래 그림과 같은 모양이다. Apache2 웹서버와 Django 2.2.13이 Python 3.5 위에서 동작하고 이 둘을 mod_wsgi 3.5가 연결해준다. 서버는 Ubuntu 16.04(Xenial) 버전인데, 이것이 지원하는 공식 패키지에는 Python 3.5가 최대이고, 따라서 mod_wsgi도 3.5버전이 최대이다. 


문제를 해결하려면 최신 버전인 Python 3.9와 mod_wsgi를 소스코드로 컴파일하는 수 밖에 없다. 이 글은 이 과정을 기록 유지 차원에서 담았다. 

1. Python3.9 소스코드를 가져와 빌드하고 설치한다. 

$ sudo apt install wget build-essential checkinstall
$ sudo apt install libreadline-gplv2-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev libffi-dev zlib1g-dev

$ cd /opt
$ sudo wget https://www.python.org/ftp/python/3.9.1/Python-3.9.1.tgz
$ sudo tar xzf Python-3.9.1.tgz
$ cd Python-3.9.1
$ sudo ./configure --enable-optimizations --enable-shared
$ sudo make altinstall

$ vi /etc/ld.so.conf
  (/usr/local/lib/python3.9 추가. 이렇게 해야 python3.9가 실행이 됨. shared로 빌드해서... ) 
$ sudo /sbin/ldconfig -v

Python은 enable-shared 옵션으로 컴파일하는데, mod_wsgi가 그걸 요구해서이다. make install이 아니라 make altinstall을 하는 이유는 시스템 기본 Python 버전(3.5)을 유지하기 위해서이다. Python은 시스템 전반적으로 많이 쓰이기 때문에, 부분적 필요에 의해서 Python 버전을 올릴 경우, 시스템의 다른 부분에서 문제가 생길 가능성이 있다. altinstall로 설치할 경우 python3.9 라고 치면 3.9 버전의 Python을 실행할 수 있다. 

마지막에 ld.so.conf를 수정하고, ldconfig를 실행하는 것은 shared 옵션으로 컴파일된 Python이 제대로 동작하기 위해 필요한 과정이다. Python이 필요로 하는 동적 라이브러리를 읽어들일 수 있도록 시스템 라이브러리로 등록하는 과정이다. 

이제 기존 웹 프로젝트의 venv를 3.9 버전용으로 만들어 주어야 한다. 대략 다음과 같은 순이다. 3.9 버전용 venv를 활성화하고 필요한 dependency들을 설치해주는 순서이다. 

$ python3.9 -m venv venv3.9
$ source venv3.9/bin/activate
  (커서 프롬프트가 venv3.9로 바뀜)
$ pip install -r requirements.txt

이제 mod_wsgi를 빌드하고 인스톨하면 된다. 

$ sudo apt install libffi-dev apache2-dev
$ cd /opt
$ sudo wget https://github.com/GrahamDumpleton/mod_wsgi/archive/4.7.1.tar.gz
$ sudo tar xvzf 4.7.1.tar.gz
$ cd mod_wsgi-4.7.1
$ sudo ./configure --with-python=/usr/local/bin/python3.9
$ sudo make
$ sudo make install

make install을 하면 새로 빌드된 mod_wsgi.so가 /usr/lib/apache2/modules 디렉토리로 복사된다. 만일 잘못될 것을 예방하고 싶다면, 미리 그 디렉토리에 있는 파일을 백업해둔다. 

$ root@webserver:/usr/lib/apache2/modules# ls -al *wsgi*
lrwxrwxrwx 1 root root 15 2월 11 00:38 mod_wsgi.so -> mod_wsgi.so-3.9
-rw-r--r-- 1 root root 207952 1월 25 2016 mod_wsgi.so-3.5
-rw-r--r-- 1 root root 989144 2월 11 00:37 mod_wsgi.so-3.9

나는 버전을 접미사로 붙이고 심볼릭 링크로 사용할 버전을 가리키는 식으로 했다. 

이제 다시 apache2를 재시작한다. /var/log/apache2/error.log를 보면 정상적으로 mod_wsgi가 도는지 확인할 수 있다. 버전이 맞는지 확인한다. 

AH00163: Apache/2.4.18 (Ubuntu) OpenSSL/1.0.2g 
mod_wsgi/4.7.1 Python/3.9 configured -- resuming normal operations



운영중이던 웹서비스도 정상적으로 도는 걸 확인했다. 

이왕 Python 3.9버전으로 올렸으니, 유지보수 편의성을 위해 Type Annotation을 적극적으로 활용해볼 생각이다. 


댓글 없음:

댓글 쓰기

인기글