Last Updated on 7월 30, 2022 by Jade(정현호)
안녕하세요
이번 포스팅에서는 PHP-FPM 설치 및 구성 그리고 기존에 설치된 Apache 와의 연동에 대해서 다루도록 하겠습니다.
먼저 Source Compile 로 APM 스택 구성 - 3번째 PHP 설치 글로 연관된 이전글 아래와 같습니다
1. Apache 2.4 + OpenSSL 1.1.1 Source Compile 설치
2. MySQL 5.7 설치 - Source Compile / Binary 설치
APM 연동은 Apache -> MySQL -> PHP 순으로 진행 됩니다.
[참고1] CentOS 7.8/7.9 버전에 YUM(RPM) 으로 APM 설치는 아래 포스팅을 참조하시면 됩니다.
[참고2] CentOS 8.3 버전에 DNF(RPM) 으로 APM 설치는 아래 포스팅을 참조하시면 됩니다.
Contents
PHP-FPM 으로 전환
포스팅에서 사용하는 서버의 환경이 Oracle Cloud 프리티어로 이전하면서 초기의 구성은 Apache + mod_php + Tomcat 으로 사용하였습니다.
이런 구성에서 블로그와 페도라 한국 사용자 모임의 사이트 변경을 위해 신규 개발 소스를 배포 하다보니 Apache의 부하나 메모리 사용량이 증가 하였고 서버의 메모리도 부족해 지는 상황이 되었습니다.
그래서 구조를 변경 하기로 결정하였으며 1개의 서버에서 Apache + Mod_PHP 로 운영하는 구조에서 2개의 서버로 분리하여 Apache + PHP-FPM 로 구성하는 것으로 변경 하게 되었습니다.
Free Tier 계정을 추가로 발급 받아 Instance를 2대를 더 확보 하여 서버를 분리 하였고
Cloud Tenancy 간의 Local-Peer 연결은 오라클 김범준 엔지니어의 도움을 받았습니다.
Cloud Engineer / Advanced Support Engineer
KR ACS Cloud Lead Engineer
Oracle Cloud Infrastructure
Oracle Database
Oracle Cloud Tenancy 간의 Local-Peer 연결에 대한 내용은 아래 포스팅을 참조하시면 됩니다.
CGI 와 Fast CGI
CGI는 요청(Request)가 들어올때 때마다 신규 프로세스를 생성/구동하여 이 과정에서 부하 증가 등의 이슈가 있으며 FastCGI의 경우 FastCGI 어플리케이션 구동 시 미리 프로세스를 생성한 뒤 해당 프로세스를 활용함으로써 일반 속도가 빠르고 부하가 적습니다
또한 apache 에 모듈이 Add-on 되어 함께 수행되는 mod_php 방식에 비해 프로세스와 데몬이 별도로 분리 되어 있는 방식의 php-fpm 이 Apache의 부하나 사용량을 줄일수 있습니다.
성능에 대한 비교는 아래 내용을 참고해보시면 됩니다.
Apache 구성 정보
포스팅에서는 Apache 는 2.4.46 버전 과 OpenSSL 1.1.1 버전을 Compile 하여 설치 하였으며 MPM은 event 방식으로 설치 하였습니다.
자세한 설치내역은 아래 이전글을 참조하시면 됩니다.
Apache 설치시 사용한 configure 내역
[root]# export CPPFLAGS="-I/usr/local/openssl-1.1.1h"
[root]# ./configure --prefix=/usr/local/apache2.4.46 \
--enable-mods-shared=all --enable-http2 \
--enable-ext-filter --enable-ssl \
--with-ssl=/usr/local/openssl-1.1.1h \
--enable-so --enable-cache --enable-proxy \
--enable-deflate --enable-suexec --enable-file-cache \
--with-mpm=event --with-apr=/usr/local/apr-1.7.0 \
--with-apr-util=/usr/local/apr-util-1.6.1 \
--with-pcre=/usr/local/pcre-8.44/bin/pcre-config \
--enable-modules=all --enable-module=shared
PHP 설치 및 구성
PHP 및 PHP-FPM 설치 및 구성에 대해서 확인 해 보도록 하겠습니다.
Apache -> MySQL -> PHP 순으로 설치를 진행하였으며 그에 따라 Apache , MySQL 은 구성이 완료 된 상태 입니다.
MySQL Library 심볼릭 링크 생성
먼저 Apache 의 mpm 방식을 thread 방식인 worker나 event 방식으로 컴파일로 설치를 하였고 그 다음 MySQL 설치시에도 관련 된 옵션(--enable-thread-safe-client)으로 설치가 되어야 합니다. MySQL 을 그렇게 설치 하지 못했을 경우 PHP 설치 시 libmysqlclient_r 라이브러리를 참조 할수 없어서 에러가 발생 합니다
하지만 MySQL 을 소스컴파일로 설치시 cmake 로 설치 되는 버전부터는 --enable-thread-safe-client 옵션을 줄수가 없어서 MySQL 설치 시 심볼릭 링크로 대체 해야 합니다.
MySQL Library 심볼릭 링크 생성
[root]# cd /usr/local/mysql/lib
--> 설치된 MySQL 디렉토리에서 lib 디렉토리로 이동합니다.
아래 구문을 그대로 실행하여 심볼릭 링크를 생성 하면 됩니다
[root]# for f in libmysqlclient.so*; do ln -s $f $(echo $f | sed s/libmysqlclient/libmysqlclient_r/); done [root]# ln -s libmysqlclient.a libmysqlclient_r.a
[참고] 현재 글은 PHP 7.2 설치의 내용 입니다.
PHP 7.4 설치에 관한 내용이 필요하시면 아래 링크를 참조하시면 됩니다
포스팅 하는 기준으로 PHP 7.4를 설치 하는 과정에서 몇가지 에러와 필요한 패키지를 소스 컴파일해서 설치를 해야 하기 때문에 설치 하실 버전은 설치 과정 등을 고려 해서 선택 하시면 될것 같습니다.
PHP 다운로드 및 설치
파일 다운로드
[root]# wget https://www.php.net/distributions/php-7.2.33.tar.gz [root]# tar zxvf php-7.2.33.tar.gz [root]# cd php-7.2.33
Configure 설정
[root]# ./configure --prefix=/usr/local/php-7.2.33 \ --with-apxs2=/usr/local/apache2.4.43/bin/apxs \ --with-config-file-path=/etc \ --with-pdo-mysql=/usr/local/mysql --enable-soap \ --enable-mbstring --with-gd=shared --with-gd \ --with-jpeg-dir --enable-sockets --with-openssl \ --with-zlib --with-gettext --enable-sigchild \ --with-iconv --with-libxml-dir --with-png-dir \ --enable-opcache --enable-fpm \ --with-fpm-user=apache --with-fpm-group=apache \ --with-freetype-dir --with-curl --enable-exif \ --enable-zip --enable-bcmath --enable-mbstring=all \ --with-mysqli=/usr/local/mysql/bin/mysql_config
빌드 수행
[root]# make; make install
설치 후 심볼릭 링크 생성
심볼릭 링크 생성은 필수는 아닙니다
경로의 단일화 및 사용 편의성을 위해 하는 것이며 이 작업은 필수는 아닙니다.
[root]# cd /usr/local [root]# ln -s php-7.2.33 php
.bash_profile 에 path 추가
[root]# vi .bash_profile export PATH=$PAHT:/usr/local/php/bin:/usr/local/php/sbin
PHP 추가 모듈 설치
mcrypt 와 imagick 추가 모듈 2개를 더 설치 하도록 하겠습니다.
mcrypt 모듈 설치
wget https://pecl.php.net/get/mcrypt-1.0.3.tgz
tar xvzf mcrypt-1.0.3.tgz
cd mcrypt-1.0.3
phpize
./configure --with-php-config=/usr/local/php-7.2.33/bin/php-config
make -j 3 && make install
imagick 모듈 설치
yum -y install ImageMagick-devel
wget http://pecl.php.net/get/imagick-3.4.4.tgz
tar zxvf imagick-3.4.4.tgz
cd imagick-3.4.4
/usr/local/php-7.2.33/bin/phpize
./configure --with-php-config=/usr/local/php-7.2.33/bin/php-config
make && make install
php.ini 파일 수정
먼저 php.ini 파일이 /etc 위치에 없을 경우 설치 source 파일 디렉토리에서 복사를 합니다.
[root]# cd /설치소스경로
[root]# cp php.ini-production /etc/php.ini
php.ini 파일 수정
[root]# vi /etc/php.ini
1) 아래 6개는 주석 제거 및 내용 수정
extension_dir = "/usr/local/php-7.2.33/lib/php/extensions/no-debug-zts-20170718/"
(경로는 다 다릅니다.)
date.timezone = Asia/Seoul
expose_php = Off
post_max_size = 500M
upload_max_filesize = 200M
memory_limit = 512M
2) 3개 모듈의 추가 내용을 입력 합니다.
[mcrypt]
extension=mcrypt.so
[opcache]
zend_extension=opcache.so
opcache.enable=1
opcache.memory_consumption=192
; 단위는 MB 이며 default는 7.0 부터 128MB 입니다(이전은 64MB)
; 192 는 예시임으로 꼭 같게 하지 않아도 됩니다
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
opcache.revalidate_path=1
opcache.dups_fix=1
opcache.fast_shutdown=1
opcache.enable_file_override=1
opcache.enable_cli=0
[imagick]
extension=imagick.so
[참고] OpCache는 PHP 5.5 버전 부터 기본에 포함 되었으며 이전에는 zend optimizer
를 별도로 설치 및 plugin 하여 사용 하였습니다.
사용 용도는 컴파일 / 실행 / 결과 의 순으로 처리되는 PHP에 대해서 Opcache(예전의 Zend Optimizer)를 이용하여 컴파일된 PHP 코드를 메모리에 Cache 해서 접속요청에 더 빠르게 응답을 줄수 있는 기능 입니다
php-fpm 설정
PHP 설치 시 PHP-FPM 도 같이 설치 하였기 때문에 PHP-FPM 에 관련된 내역은 설치가 완료된 상태 입니다.
설치가 되어있는 PHP-FPM 에 대한 설정을 확인해 보도록 하겠습니다.
필요 디렉토리 생성 및 설정
# 로그 디렉토리 생성
[root]# mkdir -p /var/log/php-fpm/
-> 로그가 생성될 디렉토리를 생성 합니다.
# Socket Directory 생성 및 tmpdir 관련 설정
[root]# mkdir -p /run/php/
-> socket 이 생성될 디렉토리를 생성 해줍니다.
재부팅 후에 디렉토리가 생성될 수 있도록 tmpfiles 에 설정 합니다.
[root]# cd /usr/lib/tmpfiles.d
[root]# vi php.conf
d /run/php 0755 root root -
--> php.conf 파일에 내용 입력
php-fpm.conf 설정
PHP-FPM 의 공통 설정 파일인 php-fpm.conf 을 설정 하겠습니다.
php-fpm.conf 파일 생성
defualt 로 존재하는 파일을 사용하여 conf 파일 생성 및 설정을 하면 됩니다.
[root]# cd /usr/local/php-7.2.33/etc
[root]# cp php-fpm.conf.default php-fpm.conf
php-fpm.conf 파일 수정
위에서 복사하여 생성한 php-fpm.conf 파일을 수정 하도록 하겠습니다.
[root]# vi php-fpm.conf ### 아래 내용 입력 ### pid = run/php-fpm.pid -> 주석제거 error_log = /var/log/php-fpm/error.log -> 주석제거, 수정 ; Log level ; Possible Values: alert, error, warning, notice, debug ; Default Value: notice log_level = debug -> 설정시 접속 관련 debug 을 위해 설정한 것으로 default로 하여도 됩니다. daemonize = yes -> 주석 해제 include=/usr/local/php-7.2.33/etc/php-fpm.d/*.conf -> 주석제거, 수정
PHP-FPM Pool 설정
이번에는 접속에 대한 부분(접속 포트,바인딩 방법, 접속자 수 등)을 설정하는 Pool 설정을 하도록 하겠습니다.
포스팅의 설치 환경 기준으로 php-fpm.d 디렉토리 아래 입니다.
[root]# cd /usr/local/php-7.2.33/etc/php-fpm.d [root]# cp www.conf.default sitename.conf [root]# vi sitename.conf
위에서 언급된 sitename.conf 파일명은 포스팅의 예시 입니다.
기본 파일명인 www.conf 를 사용해도 되며 파일명은 자유롭게 사용하시면 됩니다.
파일 내용은 아래와 같이 내용을 변경 하도록 하겠습니다.
(설정은 계속 이어 집니다)
[www] --> 주석제거, 내용변경 --> pool 이름은 지정하면 됩니다. user = apache group = apache --> 주석제거, php-fpm 을 기동할 유저 및 그룹 지정 listen.owner = apache listen.group = apache listen.mode = 0660 --> 주석제거, php-fpm.sock 파일에 대한 ownership 및 permission 설정
• IP 접속 방식과 UDS
php-fpm 을 사용시 접속 방법은 크게 2가지 방법으로 사용 할 수 있습니다.
IP 방식 과 UDS 라는 Unix Domain Socket 으로 .sock 파일을 이용 하는 것입니다.
1) Apache 또는 Nginx 와 같은 웹 서버 와 PHP-FPM 을 같은 서버 사용하는 환경이라면 UDS 로 사용하는 부분이 조금 더 편하게 프로세스 간의 통신으로 사용 할 수 있습니다
물론 같은 서버내에서 사용하는 환경이라도 IP 방식으로 사용 할 수 있습니다.
UDS 혹은 IP 방식으로 사용 할지를 선택하여 사용 하시면 됩니다.
2) Apache 또는 Nginx 와 같은 웹서버 와 PHP-FPM 이 서버가 분리 되어 사용하는 환경이라면 IP접속 방식을 사용 해야 합니다.
• listen 설정
1) UDS를 사용 할 경우
listen = /var/run/php-fpm/php-fpm.sock
--> 같은 서버내에서 사용하는 보통의 환경에서는 UDS 로 사용하시면 됩니다.
2) IP 를 사용 할 경우
listen = 9000
--> 같은 서버내에서 사용하는 보통의 환경에서는 127.0.0.1:9000 으로 사용하여 됩니다
--> 저는 다른 서버에서 접속하는 환경으로 사용할 예정으로 포트만 기재하여 모든곳에서 다 접속이 가능하도록 설정 하도록 하겠습니다.
위의 설명을 참조하여 각 환경에 맞게 listen 에 대해서 설정을 하면 됩니다
• php-fpm 프로세스 조정
pm 으로 시작하는 파라미터5개와 연관되어 있으며 아래의 설명을 읽어보시고 적절한 수치로 설정하시면 됩니다.
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 40
pm.max_requests = 500
위의 수치는 포스팅에서의 예시 수치 입니다.
pm.max_children 는 설정된 PHP Pool(여기서는 www) 내에서 가동할 수 있는 최대 자식 프로세스 수를 의미 합니다
pm.start_servers 는 php-fpm 을 실행할 때 초기에 생성하는 자식 프로세스의 개수입니다
pm.min_spare_servers 는 idle 상태의 자식 프로세스 개수가 이 개수보다 작으면 자식 프로세스를 생성합니다
pm.max_spare_servers 는 idle 상태의 자식 프로세스의 최대 개수를 의미 합니다.
pm.max_requests 는 각 프로세스가 최대 request를 처리하면 수 입니다.
500 으로 설정되어 있다면 500번 request 후 프로세스를 다시 생성 합니다
프로세스가 점진적인 메모리 증가에 대한부분을 방지 할 수 있습니다.
apache 에서 유사한 설정으로는 MaxRequestsPerChild 있습니다.
• 로그 관련 설정
로그 관련 설정으로 아래와 같이 진행하도록 하겠습니다.
access.log = /var/log/php-fpm/$pool.access.log --> 주석제거, 경로 변경 access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%" --> 주석제거 slowlog = /var/log/php-fpm/$pool.log.slow --> 주석제거, 경로 변경 request_slowlog_timeout = 1 --> 주석제거, 내용변경 --> 값은 변경 하여 사용해도 됩니다. catch_workers_output = yes -> 주석 해제 php_admin_value[error_log] = /var/log/fpm-php/$pool.error.log --> 주석제거, 경로 변경 php_admin_flag[log_errors] = on --> 주석제거
OS 추가 설정 변경
포스팅에서 사용하는 서버의 구성은 서버를 3개 이상 버를 이용하여 3-Tier 환경으로 구성 하였으며,1번 노드는 apache httpd , 2번은 mysql , 3번 노드는 php-fpm 으로 구성하였습니다.
서버가 여러개로 나워져있으므로 firewall , /etc/hosts 등의 추가적인 설정을 진행하도록 하겠습니다.
먼저 각 서버간의 설정 및 접속을 편하게 하기 위해 저는 /etc/hosts 에 등록하여 사용하였습니다.
[참고] 같은 서버내에서 구성할 경우 이 단계는 생략 하고 다음(아래) 단계로 이동하시면 됩니다.
/hosts 정보 입력
# vi /etc/hosts
123.123.123.101 node1
123.123.123.102 node2
123.123.123.103 node3
* node , ip 등은 모두 예시 입니다.
* 이 작업은 필수는 아닙니다.
MySQL DB 포트 오픈
-- 특정 IP(123.123.123.123) 에 대해서 3306 포트 오픈 할 경우 firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address=123.123.123.123 port port="3306" protocol="tcp" accept' 또는 -- 모든 IP 에 대해서 3306 포트 오픈 할 경우 firewall-cmd --permanent --add-port=3306/tcp
php-fpm 포트 오픈
-- 특정 IP(123.123.123.123) 에 대해서 9000번 포트를 오픈할 경우 firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address=123.123.123.123 port port="9000" protocol="tcp" accept' 또는 -- 모든 IP 에 대해서 9000번 포트 오픈 firewall-cmd --permanent --add-port=9000/tcp
Firewall적용 및 확인
방화벽 설정이 완료 되었다면 룰 적용 및 적용된 룰을 확인 해봅니다.
[root]# firewall-cmd --reload [root]# firewall-cmd --list-all
필요에 따라 db user의 host의 변경
필요에 따라, 구성에 따라 다릅니다.
mysql> update mysql.user set host='123.123.123.123' where user='dbuser' and host='123.123.123.100'; myslq > flush privileges;
대부분 설정 블로그나 웹 문서가 같은 서버내에서 구성으로 되어 있으며 별도의 서버로 분리하여 설정한 내용을 찾기가 어려워서 php 웹 소스를 어느서버에 있어야 하는지에 대한 부분은 테스트를 통해 Apache가 있어야 하는 web서버 와 php-fpm 이 구동되어 있는 서버에도 같이 있어야 하는 결론을 내렸습니다
소스를 각각 관리 하는 어려움이 있어서 nfs나 rsync 등을 고려 하였으나 보안상 그리고 파일이 첨부되거나 변경되는 사항에 대해서 바로 적용 되어 사용할수 있도록 내부 간 통신임으로 sshfs를 통해 파일시스템을 마운트 해서 사용 했습니다.
php-fpm 서비스 등록 및 시작
PHP-FPM 에 대해서 시작과 종료를 위한 서비스를 등록 하도록 하겠습니다.
Source 컴파일로 설치 하였기 때문에 서비스 등록을 위해서 서비스 파일이 필요 하며 컴파일이 완료 되면 서비스 파일도 작성이 되어 있으므로 해당 파일을 사용하여 서비스를 등록 하면 됩니다.
[root]# cd /root/source/php-7.2.33/sapi/fpm [root]# cp php-fpm.service /etc/systemd/system/php-fpm.service [root]# systemctl daemon-reload [root]# systemctl enable php-fpm [root]# systemctl start php-fpm
Apache 설정 및 재시작
PHP-FPM 에 대해서 Apache 의 설정을 진행 하도록 하겠습니다.
httpd.conf 파일 수정
[root]# vi /usr/local/apache2.4/conf/httpd.conf
1) php5_module 비활성화
먼저 기존에 php module이 로드 된 내용이 있다면 주석 이나 삭제 처리 합니다
#LoadModule php5_module modules/libphp5.so
2) Proxy 내용 추가
virtualhost 를 사용한다면 <virtualhost> </virtualhost> 사이에 Proxy 내용을 추가 합니다
virtualhost 를 사용하지 않으면 편하신 곳에 아래의 proxy 설정 내용을 입력 합니다.
php-fpm-pool 의 listen 설정에 따라서 이부분도 설정이 달라 지게 됩니다.
2-1) listen 을 UDS 방식으로 설정하여 사용시
PHP-FPM 에서 아래와 같이 UDS 가 설정되어 있는 경우
listen = /var/run/php-fpm/php-fpm.sock
ProxtPassMatch 구문을 아래와 같이 사용 하면 됩니다.
socket 파일이 각 시스템의 설정과 맞는지 확인 합니다.
ProxyRequests Off ProxyPreserveHost On ProxyErrorOverride on ProxyTimeout 600 <FilesMatch \.(php|phar)$> SetHandler "proxy:unix:/run/php/php-fpm.sock|fcgi://localhost" </FilesMatch>
SetHandler 절에 파일명은 위에서 설정한 PHP-FPM의 Socket의 경로와 파일명이 같아야 합니다
PHP-FPM : listen=/run/php/php-fpm.sock 사용시
2-2) listen 을 IP 방식으로 설정시
PHP-FPM 에서 아래와 같이 IP 나 포트로 로 설정되어 있는 경우
listen = 9000
아래와 같이 사용 하시면 됩니다.
ProxyRequests Off ProxyPreserveHost On ProxyErrorOverride on ProxyTimeout 600 <FilesMatch \.(php|phar)$> SetHandler "proxy:fcgi://node3:9000" </FilesMatch>
node3:9000
이부분은 php-fpm 이 실행되고 있는 서버의 IP 또는 /etc/hosts 에 지정한 호스트명을 사용하면 됩니다.
Apache 재시작
설정이 완료 되었다면 설정 내역을 저장 후 apache를 재시작 하거나 reload(graceful) 을 합니다
[root]# systemctl restart httpd
or
[root]# systemctl reload httpd
php 로 구성된 사이트가 정상적으로 접속 되는지, 로그에 특이사항이 있는지를 마지막으로 체크 합니다.
이어지는 글
웹 기반 MySQL 관리툴 - PHPMyAdmin 설치 및 설정
Apache 2.4 에 웹 방화벽인 ModSecurity 구성
연관된 다른 글
proxy_balancer 를 이용한 PHP-FPM 다중화 - 로드 발란스 구성
PHP 7.4 소스컴파일(Source Compile) 설치
PHP 8.0 출시 소식 과 8.0 설치 진행 내역
Principal DBA(MySQL, AWS Aurora, Oracle)
핀테크 서비스인 핀다에서 데이터베이스를 운영하고 있어요(at finda.co.kr)
Previous - 당근마켓, 위메프, Oracle Korea ACS / Fedora Kor UserGroup 운영중
Database 외에도 NoSQL , Linux , Python, Cloud, Http/PHP CGI 등에도 관심이 있습니다
purityboy83@gmail.com / admin@hoing.io
안녕하세요
저는 httpd와 php-fpm을 분리하는 테스트를 하고 있습니다.
각각 컨테이너로 구성이 되어있고
작성해주신 글을 보면서 listen 설정으로 연동(?)은 된 것 같습니다
httpd쪽에서 php파일을 열게 될 경우 php-fpm쪽 root directory에도 php파일이 존재해야하는데
php-fpm의 root directory가 어디인지 도무지 알 수 가 없네요 ㅠㅠ
tomcat은 root directory가 있어서 설정이 가능한데 php-fpm은 제가 잘 모르는건지 싶네요..
안녕하세요
httpd 와 php-fpm 이 물리적 서버로 분리되어있거나 또는 컨테이너로 분리 되어있을 경우
경로를 동일 하게 맞춰주시고 파일을 위치시켜주시면 됩니다.
감사합니다.
감사합니다
시도해보겠습니다!
즐거운 주말 보내세요