우분투(Ubuntu) APM - Apache PHP Mysql 구성 및 설정

Last Updated on 1월 10, 2021 by 태랑(정현호)



APM은 Apache + PHP + Mysql 의 약자



APM 은 웹 서버를 구축하고 PHP 로 작성된 웹 어플리케이션을 구동하기 위해 이전부터 많이 사용해온 스택 입니다.


PHP 를 구동 하기 위한 서버 스택의 구성은 여러가지 방식으로 할 수 있습니다.
Apache + PHP(mod_php) + Mysql 나 MariaDB
Apache + PHP-FPM + Mysql 나 MariaDB
Nginx + PHP-FPM + Mysql 나 MariaDB


이번 글에서는 apt(deb) 방식으로 Apache + PHP-FPM + Mysql 설치 연동을 기술 하도록 하겠습니다

*  APM/LEMP ,도메인 설정 등을 완료 후 워드프레스 이외 제로보드XE 나 라이믹스(Rhymix),그누보드 등 사용하여도 됩니다





설치 환경

OS: Ubuntu 18.04

APACHE 2.4.46 + PHP 7.4 + Mysql 5.7

설치순서는 apache mysql php 순으로 설치 하겠습니다


- 프롬프트는  ubuntu$  입니다.
- 향후 HTTP/2 적용 과 HTTPS TLS v1.3을 적용하기 위해서 최신 버전을 사용하였습니다
- TLS 1.3 을 사용하기 위해서는 openssl 와 웹 서버의 특정 버전 이상이 필요 합니다.
OpenSSL 1.1.1 이상이 필요하고 apache 2.4.37 이상 이 필요 합니다.
참고로 nginx 는 1.13.0 이상이 필요 합니다

- HTTP/2 를 사용하기 위해서는 libnghttp2 libnghttp2-devel 라이브러리와 openssl 1.0.2 이상 버전이 필요 합니다
또한 Apache는 2.4.17 이상이어야 합니다.


- 먼저 우분투 기초 설정을 보시지 않으신분은 기초 설정을 참조하여 먼저 설정 하시면 더 좋습니다.







Apache 설치



기본 Repository 로 설치를 하게 되면 Apache 버전이 2.4.29 버전으로 설치 되기 때문에 별도 Repository를 추가하여 설치하도록 하겠습니다.

ubuntu$ sudo add-apt-repository ppa:ondrej/apache2
ubuntu$ sudo apt update
ubuntu$ sudo apt upgrade

ubuntu$ sudo apt install apache2 \
libapache2-mod-fcgid libapache2-mod-proxy-uwsgi \
libapache2-mod-xforward openssl


Old
ubuntu$ /usr/sbin/apache2 -v
Server version: Apache/2.4.29 (Ubuntu)
Server built: 2020-08-12T21:33:25

New
ubuntu$ /usr/sbin/apache2 -V
Server version: Apache/2.4.46 (Ubuntu)
Server built: 2020-08-10T12:32:00


ubuntu$ /usr/bin/openssl version
OpenSSL 1.1.1g 21 Apr 2020



Apache 가 설치되면 바로 구동된 상태 입니다.
브라우저로 IP 주소로 접속해서 기본 페이지가 로딩 되는지 확인합니다.







MySQL 설치



먼저 mysql 설치 가능 버전 확인 합니다.


ubuntu$ sudo apt-cache search mysql-server


mysql-server - MySQL database server (metapackage depending on the latest version)
mysql-server-5.7 - MySQL database server binaries and system database setup
mysql-server-core-5.7 - MySQL database server binaries
default-mysql-server - MySQL database server binaries and system database setup (metapackage)
default-mysql-server-core - MySQL database server binaries (metapackage)
mariadb-server-10.1 - MariaDB database server binaries
mariadb-server-core-10.1 - MariaDB database core server files
percona-xtradb-cluster-server-5.7 - Percona XtraDB Cluster database server binaries
mariadb-server-10.5 - MariaDB database server binaries
mariadb-server-core-10.5 - MariaDB database core server files

* 여기서는 5.7을 설치합니다.
* 버전을 다르게 latest version 를 설치하셔도 됩니다.







아래 명령어를 입력하여 mysql 을 설치 합니다.


ubuntu$ sudo apt install mysql-server-5.7 \

mysql-server-core-5.7 mysql-client-5.7 \
mysql-client-core-5.7






설치 직후 Mysql 은 가동된 상태 입니다.

ubuntu$ ps -ef |grep mysql

mysql 11401 1 1 15:41 ? 00:00:00 /usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pid






MySQL 설치가 완료가 되었습니다

root 유저에서는  ubuntu$ mysql
일반 유저에서  ubuntu$ sudo mysql

를 사용하면 패스워드 없이 접속이 가능 합니다.




이는 우분투 에서 mysql 접속 방법을 기존의 패스워드 방식이 아니라 auth_socket 플러그인을 이용하여 인증 로그인을 하기 때문입니다

apt 로 설치하게 되면 접속 인증 방식에 대해서 OS 인증방식으로 설정되어 db가 생성됩니다.


mysql> select user,host,plugin from mysql.user where User='root';
+------+-----------+-------------+
| user | host | plugin |
+------+-----------+-------------+
| root | localhost | auth_socket |
+------+-----------+-------------+
1 row in set (0.00 sec)


# mysql 비밀번호 로그인 방식으로 변경

기본적으로는 OS 인증으로 패스워드 없이 로그인 할 수 있습니다.
ubuntu$ sudo mysql

root 유저에서는
root# mysql



* 기존과 같이 패스워드 입력 방식으로 사용하길 원할 경우 아래 절차대로 진행 하시면 됩니다.
OS 인증을 통하여 사용 하실려는 경우 패스워드 변경 절차는 생략하여도 됩니다.





# 기존 패스워드 방식으로 변경, 한줄로 입력 합니다.

mysql> UPDATE mysql.user SET plugin = 'mysql_native_password', authentication_string = PASSWORD('패스워드입력') WHERE User = 'root';

mysql> commit;
mysql> FLUSH PRIVILEGES;
mysql> quit







# MySQL 설정 변경 

설정 파일의 위치는 2곳에 있습니다.
/etc/mysql/mysql.conf.d/
/etc/mysql/conf.d/


그 중에 [mysqld] 항목은 /etc/mysql/mysql.conf.d/mysqld.cnf 에 내용이 있습니다.





먼저 mysqld.cnf 에서 몇가지 수정 하겠습니다.

ubuntu$ sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf



[mysqld] <-- 절에 아래 내용을 추가로 입력해 줍니다.

user=mysql
server-id=1
log_bin = binlog
expire_logs_days=10
innodb_buffer_pool_size = 384M
   # -> 값은 더 크게 해도 되고 128MB 단위로 변경하면 됩니다.
innodb_file_per_table=TRUE
log_timestamps=SYSTEM
character-set-client-handshake=OFF
skip-character-set-client-handshake
max_allowed_packet=500M
init_connect=SET collation_connection = utf8mb4_general_ci
init_connect=SET NAMES utf8mb4
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci


bind-address = 127.0.0.1

to

bind-address = 0.0.0.0
-> 외부에서 직접 접속 하려는 환경이라면 위의 값을 public-ip 나 0.0.0.0 으로 설정 합니다.






설정파일을 수정하였다면 mysql을 재시작합니다.

ubuntu$ sudo systemctl restart mysql





재시작이 완료되었다면 몇가지를 확인 해봅니다.

ubuntu$ mysql -u root -p
Enter password: [패스워드 입력]
Welcome to the MySQL monitor. Commands end with ; or \g.
< 중략 >





# status 로 조회

mysql> status;
--------------
mysql Ver 14.14 Distrib 5.7.32, for Linux (x86_64) using EditLine wrapper

<중략>
Server version: 5.7.32-0ubuntu0.18.04.1 (Ubuntu)
<중략>
Server characterset: utf8mb4
Db characterset: utf8mb4
Client characterset: utf8mb4
Conn. characterset: utf8mb4







innodb_buffer_pool_size 조회 

mysql> show global variables like '%innodb_buffer_pool_size%';
+-------------------------+-----------+
| Variable_name | Value |
+-------------------------+-----------+
| innodb_buffer_pool_size | 402653184 |
+-------------------------+-----------+




여기까지 설정하면 apt 로 mysql 설치가 완료 된 것 입니다








PHP 7.4 설치



= 최신 버전 설치를 위한 저장소 등록 및 PHP 설치

ubuntu$ sudo apt -y install software-properties-common
ubuntu$ sudo add-apt-repository ppa:ondrej/php
ubuntu$ sudo apt update


ubuntu$ sudo apt install php7.4 php7.4-cli php7.4-fpm \
php7.4-bcmath php7.4-bz2 php7.4-common php7.4-curl \
php7.4-dba php7.4-gd php7.4-json php7.4-mbstring php7.4-opcache \
php7.4-readline php7.4-soap php7.4-xml php7.4-xmlrpc php7.4-zip \
php7.4-ctype php7.4-pdo php7.4-redis php7.4-mysql php7.4-imagick \
php7.4-intl php7.4-mysqlnd php7.4-gmp php7.4-geoip php7.4-dev -y







# 설치 후 php.ini 기본 수정

/etc/php/7.4/fpm/php.ini 파일을 수정하여 5개 항목에 대해서 수정 및 추가 합니다.

ubuntu$ sudo vi /etc/php/7.4/fpm/php.ini

date.timezone = Asia/Seoul
expose_php = Off
post_max_size = 500M
upload_max_filesize = 200M
memory_limit = 512M
-> memory_limit 의 default 값은 128M 입니다
-> 위의 용량 사이즈는 절대적인 수치가 아닙니다. 필요에 따라서 줄이거나 늘려도 됩니다.






# php-fpm Opcache Config

참고) PHP 5.5 버전 부터 기본에 포함 되었으며 이전에는 zend optimizer 를 별도로 설치 및 plugin 하여 사용 하였습니다.

사용 용도는 컴파일 / 실행 / 결과 의 순으로 처리되는 PHP에 대해서 Opcache(예전의 Zend Optimizer)를
이용하여 컴파일된 PHP 코드를 메모리에 Cache 해서 접속요청에 더 빠르게 응답을 줄수 있는 기능 입니다

hp7.x 버전부터 Opcache 의 기본 메모리가 128M 입니다.
메모리를 변경하거나 다른 파라미터를 조정 하고자 한다면 opcache.ini 에서 설정할 수 있습니다.


ubuntu$ cd /etc/php/7.4/mods-available
ubuntu$ sudo vi opcache.ini


opcache.ini 파일에는 opcache.so 모듈이 plugin 되어 활성화는 되어 있는 상태 입니다
그외 별도의 내용은 없어서 활성화 상태에서 기본값으로 동작 중 입니다


추가적으로 opcache의 파라미터의 변경하시려면 아래의 내용을 참조하여 수치를 변경 하시면 됩니다.  추가적인 opcache configuration 은 아래 링크를 참조하시면 됩니다.
https://www.php.net/manual/en/opcache.configuration.php



opcache.enable=1 - Zend Opacache 활성화 여부 결정 , 1일때 활성화 됨
opcache.enable_cli=1 - PHP CLI 버전에서(명령행 버전에서도) Zend Opcache 활성화 여부 결정
opcache.memory_consumption - 캐쉬에 사용할 메모리 크기. 7.0부터 기본 크기는 128M
opcache.interned_strings_buffer=8 - 메모리에서 interned 문자열을 위해 사용할 메모리량
opcache.fast_shutdown=1 - 활성화 시 accelerated code 에 대해서 사용되어짐
opcache.interned_strings_buffer - Opcache 가 사용하는 내부 스트링( class name 이나 file등)을 저장하기 위한 메모리의 크기.
opcache.max_accelerated_files - Opcache 가 캐쉬할 최대 파일 갯수.

opcache.validate_timestamps - Default 1 / 0(off)이 아닐 경우 opcache.revalidate_freq 에 설정된
시간마다 코드와 캐쉬의 변경 여부를 체크

validate_timestamps 가 꺼져 있을 경우 코드의 변경 여부를 체크하지 않으므로 PHP 소스가 수정되어도 반영되지 않음
그러므로 변경 사항을 반영하려면 httpd 를 재기동하거나 httpd 에 SIGUSR2 시그널을 전송해야함

opcache.file_cache_only=1 - makes sure that the in-memory opcache is disabled and only files are used, which is what you want for CLI.
1 로 설정할 경우 in-memory opcache 사용이 안됨 = php-fpm 에서 사용할수 없음


기본적으로 활성화 및 Default value 설정되어 있기 때문에 PHP-FPM 사용 가능 합니다.



먼저 추가 해볼 수 있는 파라미터 2개만 추가 하겠습니다
그외 파라미터는 Default 값에 따라 활성화 및 Default value 로 동작 중입니다.


opcache.enable=1
;-> 활성화가 되어있지만 명시적으로 한번더 기재를 해주겠습니다.


opcache.memory_consumption=256
;-> 입력의 예시 이며 단위는 MB 입니다
;-> 이부분(메모리 변경) 은 필수는 아닙니다.




[참고] 설정 파일 및 경로

파일 경로 
/etc/php/7.4/fpm/
/etc/php/7.4/fpm/conf.d
/etc/php/7.4/fpm/pool.d


주요 설정 파일

/etc/php/7.4/fpm/php.ini
/etc/php/7.4/fpm/php-fpm.conf
/etc/php/7.4/fpm/pool.d/www.conf






PHP-FPM 설정



PHP 와 Apache 와의 연동은 PHP-FPM사용 하도록 하겠습니다


Apache 의 가장 큰 장점은 수많은 플러그인 모듈을 사용한 아주 다양한 기능을 사용 할 수 있다는 점 입니다


다만 많이 추가된 모듈 과 사용 환경에 따라 process 기반의 prefork 방식에 의해서 동접자에 따라서 메모리 사용률이 높아지거나 성능에 대한 degrade 가 발생하기도 합니다


이런 부분에서 PHP를 Apache 와 별도로 분리하면서 Apache의 메모리 사용량이나 CPU 사용량 등의 부하를 분산 할 수도 있습니다.



또한 NTS(Non Thread Safe) 으로 PHP를 컴파일 한것이 아닌 경우에는 Apache + Mod_PHP는 prefork 방식을 사용 했어야 했습니다


하지만 PHP-FPM을 사용하게 됨에 따라 Apache 도 Event MPM 을 사용 할 수 있어서 더욱 성능을 개선을 할수 있기 때문에 PHP-FPM 을 보통 사용하는 편 입니다.


향후 Nginx 로의 변경시 변경이 자유롭고 Apache MPM방식을 event(thread) 방식을 사용할 수 있는 장점이 있습니다.





# php-fpm.conf  파일 수정

ubuntu$ cd /etc/php/7.4/fpm
ubuntu$ sudo vi php-fpm.conf


error_log = /var/log/php7.4-fpm.log
-> 주석 해제 혹은 위치 경로 수정, 위와 동일 할 수 도 있습니다.

;log_level = notice
-> Log Level은 alert, error, warning, notice, debug 이 있습니다.
-> Config설정 및 nginx 정상 연동에 대해서 더 자세한 정보가 필요 하다면 잠시 debug 로 사용 해도 됩니다
-> 기본은 notice 레벨 입니다.


include=/etc/php/7.4/fpm/pool.d/*.conf
=> 주석이 해제 되어있는지 확인 및 경로를 확인 합니다.



그 다음으로
php-fpm.conf 파일 보다는 실제로 접속을 받고 처리하는 FPM Pool 설정파일에 대해서 수정 및 설정할 내역이 존재 합니다.

FPM Pool은 별도의 Container 적인 의미를 갖고 있습니다  
Pool 별로 max process 수 와 포트를 지정 할 수 있고 PHP로 사용중인 여러 웹페이지(사이트가 있다면) Pool을 분리하여(포트를 분리 하여) 웹 서비스 별 - PHP Pool 을 지정하여 사용할 수 있습니다.

꼭 1개를 써야 하는 것도 꼭 다수를 써야하는 것도 아닙니다.






# Pool 설정 - 기본 파일 www.conf 

ubuntu$ cd /etc/php/7.4/fpm/pool.d/
ubuntu$ sudo vi www.conf


user = www-data
group = www-data
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
=> 유저 및 그룹이 www-data 로 되어 있는지 확인 합니다.
=> mode 는 0660 으로 설정 합니다.


listen = /run/php/php7.4-fpm.sock
=> 이부분은 접속을 받는 방식을 설정하는 부분으로 Socket(UDS) 방식으로 사용 하거나 IP 방식으로 사용하거나 둘중 하나를 선택하여 설정해야 합니다.
=> IP 방식으로는 아래와 같이 지정 할 수 있습니다.
listen = 123.123.123.123.123:9000
listen = 127.0.0.1:9000
listen = 9000   <== 이와 같이 IP 없이 포트만 기재하면 모든 주소에서 접속이 가능한 상태 입니다
                    (listen on a TCP socket to all addresses)

소켓 방식은 위와 같이 파일명을 지정해주면 됩니다.
listen = /run/php/php7.4-fpm.sock

같은 서버에서 Apache 와 php-fpm 사용 하는 설정으로 할 것임으로 socket 을 지정하여 설정하도록 하겠습니다. 



# 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 있습니다.





[참고]
PHP-FPM 메모리 사용현황 및 세션 계산

아래 명령어를 이용하면 현재 fork된 php-fpm 프로세스 당 메모리 사용량을 확인 할 수 있습니다.
[root]# ps --no-headers -o "rss,cmd" -C php-fpm | awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"M") }'


시스템에 가용한 메모리나 사용 할 정도에서 프로세스당 사용메모리를 나누어서 최대 자식프로세스 개수를 산정 해도 되겠습니다

ex) PHP에 6GB 를 사용 하려고 함 , PHP-FPM이 현재 사용중인 메모리량이 대략 60MB 임
6000MB / 60MB = 자식 프로세스 개수 100개 로 설정

이와 같이 각 시스템 마다 메모리 상황을 고려하여 적절한 pm.max_children 값을 선정하여 설정하면 되겠습니다.






= 그외 로그 관련 설정 변경

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 = 5
--> 주석제거, 내용변경
--> 단위는 초로 5는 예시 입니다. 해당 시간은 선택해서 변경 하시면 됩니다.

php_admin_value[error_log] = /var/log/fpm-php.$pool.error.log
--> 주석제거 및 경로 및 파일명 변경

php_admin_flag[log_errors] = on

--> 주석제거


* 위에서는 최대한 로그 파일을 유사하게 맞추려고 경로 나 파일명을 조정 한 것 입니다.



php-fpm 을 재시작 합니다.
ubuntu$ sudo systemctl restart php7.4-fpm







Apache 설정 및 기동



[참고] 설정 파일 및 경로

파일 경로 
/etc/apache2/
/etc/apache2/conf-available
/etc/apache2/mods-available
/etc/apache2/sites-available

주요 설정 파일
/etc/apache2/apache2.conf






apache2.conf 파일 수정

ubuntu$ cd /etc/apache2
ubuntu$ sudo vi apache2.conf


<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>

에서 Options 를 수정 합니다.

#Options Indexes FollowSymLinks
-> 주석 처리 후 아래 내용으로 입력

Options MultiViews FollowSymLinks
-> 내용 변경






내용을 저장 후 종료 합니다.

:wq





000-default.conf 파일을 수정 합니다

ubuntu$ cd /etc/apache2/sites-enabled
ubuntu$ sudo vi 000-default.conf

ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
=> CustomLog 밑에 아래의 Directory 절을 추가 합니다.


<Directory /var/www/html>
Options MultiViews FollowSymLinks
AllowOverride ALL
DirectoryIndex index.php index.html index.htm
<RequireAll>
Require all granted
</RequireAll>
</Directory>









php7.4-fpm.conf 파일을 심볼릭을 생성 합니다.

sudo ln -s /etc/apache2/conf-available/php7.4-fpm.conf \
/etc/apache2/conf-enabled/php7.4-fpm.conf


[참고] /etc/apache2/conf-available/php7.4-fpm.conf
OS의 종류 및 설치되는 패키지에 따라서 conf  파일내 내용이 조금씩은 틀립니다.


현재 우분투 환경에서 설치된 패키지에서는 php7.4-fpm.conf 파일에 바로 사용할 수 있게 FileMatch가 설정된 상태입니다.

그래서 FileMatch 나 ProxyMatch 등을 설명 내용이 없는 것입니다.

cat /etc/apache2/conf-enabled/php7.4-fpm.conf
으로 파일 내용을 살펴보면 따로 설정할 내용이 없이 사용 할 수 있는걸 확인 할 수 있습니다.

Apache 와 PHP-FPM 서버를 분리한다면 SetHandler 에서 socket방식에서 IP방식으로 변경은 필요 합니다.







이제 FastCGI 구성에 필요한 Apache 모듈을 활성화해야합니다


다음 명령을 실행하여 필수 모듈을 활성화 할 수 있습니다.


ubuntu$ sudo a2enmod actions fcgid alias proxy_fcgi





php 정상 연동 확인 위하여 phpinfo 파일을 생성 합니다.
ubuntu$ cd /var/www/html
ubuntu$ sudo vi phpinfo.php

아래 내용 입력

<?php
phpinfo();
?>



# 이제 Apache 를 재시작 후 PHP 연동을 확인 합니다.
ubuntu$ sudo systemctl restart apache2






이어지는 다음글  :  웹 기반 mysql 관리툴 - phpmyadmin


연관된 글:

Apache 웹 방화벽 - Mod_Security

무료 도메인 발급 받기 - freenom.com

무료 SSL 인증서 발급 및 HTTP/2 적용

Bind를 이용하여 DNS 서버 구축

답글 남기기