Browsing Tag

manvscloud blog

NCP

[NCP] AWS to NCloud Server Migration – #2편

안녕하세요. ManVSCloud 김수현입니다.

오늘 “AWS TO NCLOUD SERVER MIGRATION – #2편”에서는 간단한 Install과 제가 기본적으로 설정하는 설정값들을 보여드리며 정보를 공유하고자 합니다.


Base Install

[root@manvscloud-web-pub-kr1 ~]# cat /etc/redhat-release
CentOS Linux release 7.8.2003 (Core)

“[NCP] AWS TO NCLOUD SERVER MIGRATION – #1편”에서 생성한 서버에 기본 설치와 설정 작업을 진행하기로 했습니다.

🧩 Nginx 설치
vi /etc/yum.repos.d/Nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1
[root@manvscloud-web-pub-kr1 ~]# yum install nginx -y

CentOS 7에서는 위와 같이 repo를 추가 후 설치를 진행하면 설치간에 큰 어려움은 없을 것입니다.

이후 LB를 붙이면 Nginx Access Log에서 LB의 로그로 나오기때문에 Client IP를 보기 위해서는 nginx -V 2>&1 | grep ‘http_realip_module’ 로 확인하여 http_realip_module이 있는지 확인이 되어야합니다.

RPM 설치 시 이 모듈이 들어가있는데 컴파일로 설치를 진행할 경우 이 부분을 잘 체크해주셔야합니다.

[root@manvscloud-web-pub-kr1 ~]# nginx -V 2>&1 | grep 'http_realip_module'
configure arguments: --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-compat --with-debug --with-file-aio --with-google_perftools_module --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_degradation_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_mp4_module --with-http_perl_module=dynamic --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_xslt_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-stream_ssl_preread_module --with-threads --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic' --with-ld-opt='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E'
🔮 PHP 설치
[root@manvscloud-web-pub-kr1 src]# yum -y install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
[root@manvscloud-web-pub-kr1 src]# yum -y install epel-release yum-utils
[root@manvscloud-web-pub-kr1 src]# yum-config-manager --disable remi-php54
[root@manvscloud-web-pub-kr1 src]# yum-config-manager --enable remi-php74
[root@manvscloud-web-pub-kr1 src]# yum install -y php php-json php-cli php-gd php-pear php-common php-mysqlnd php-fpm php-mbstring php-opcache php-process php-xmlrpc php-pdo php-xml php-bcmath php-devel php-zip php-mcrypt
[root@manvscloud-web-pub-kr1 src]# yum groupinstall " Development Tools" -y
[root@manvscloud-web-pub-kr1 src]# yum install ImageMagick ImageMagick-devel -y
[root@manvscloud-web-pub-kr1 src]# pecl install imagick
[root@manvscloud-web-pub-kr1 src]# echo "extension=imagick.so" >> /etc/php.ini
[root@manvscloud-web-pub-kr1 src]# systemctl enable php-fpm
[root@manvscloud-web-pub-kr1 src]# systemctl start php-fpm

PHP는 remi를 이용하여 설치를 진행했습니다.
Migration할 때 주의할 점 중 하나는 PHP의 모듈을 맞춰주는 것입니다.
기존 서버와 이전하는 서버에서 php -m 로 확인해줍시다.

🧿 MariaDB 설치
vi /etc/yum.repos.d/MariaDB.repo
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.5/centos7-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
yum install MariaDB-server MariaDB-client -y

MariaDB도 repo만 추가해주면 쉽게 설치할 수 있습니다.
MariaDB의 버전은 baseurl 부분에서 10.5 부분을 원하시는 버전으로 변경하면 원하시는 버전으로 설치가 가능합니다.

🎫 Memcached

Memcached의 경우 개인 사이트 운영에 큰 효과를 가져다주지 못한다는 평이 있었으나 개인 블로그 용도뿐만 아니라 다양한 테스트를 해볼 예정이기에 memcached를 도입하기로 했습니다.

[root@manvscloud-web-pub-kr1 ~]# yum clean all
[root@manvscloud-web-pub-kr1 ~]# yum update -y
[root@manvscloud-web-pub-kr1 ~]# yum install memcached -y
[root@manvscloud-web-pub-kr1 ~]# cat /etc/sysconfig/memcached 
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS=""

/etc/sysconfig/memcached 값을 아래와 같이 변경해주었습니다.

[root@manvscloud-web-pub-kr1 ~]# cp -avp /etc/sysconfig/memcached /etc/sysconfig/memcached_org
[root@manvscloud-web-pub-kr1 ~]# vi /etc/sysconfig/memcached
PORT="11111"
USER="memcached"
MAXCONN="2048"
CACHESIZE="4096"
OPTIONS=""

[root@manvscloud-web-pub-kr1 ~]# systemctl enable memcached
[root@manvscloud-web-pub-kr1 ~]# systemctl start memcached

php-memcached도 설치해줍시다!

[root@manvscloud-web-pub-kr1 ~]# yum install php-memcached -y

php.ini를 보면 session.save_handler가 files로 되어있습니다.

이를 memcached로 변경해줄 것입니다.
아래처럼 작업을 진행할 수 있습니다.

[root@manvscloud-web-pub-kr1 ~]# cp -avp /etc/php.ini /etc/php.ini_org
[root@manvscloud-web-pub-kr1 ~]# cat -n /etc/php.ini | grep -E "session.save_handler|session.save_path"
  1214	session.save_handler = files
  1222	;     session.save_path = "N;/path"
  1238	;     session.save_path = "N;MODE;/path"
  1247	;session.save_path = "/tmp"
  1332	;       (see session.save_path above), then garbage collection does *not*
[root@manvscloud-web-pub-kr1 ~]# sed -i '1214s/files/memcached/g' /etc/php.ini
[root@manvscloud-web-pub-kr1 ~]# perl -p -i -e '$.==1222 and print "session.save_path = \"127.0.0.1:11111\"\n"' /etc/php.ini
[root@manvscloud-web-pub-kr1 ~]# cat -n /etc/php.ini | grep -E "session.save_handler|session.save_path "
  1214	session.save_handler = memcached
  1222	session.save_path = "127.0.0.1:11111"
  1223	;     session.save_path = "N;/path"
  1239	;     session.save_path = "N;MODE;/path"
  1248	;session.save_path = "/tmp"
  1333	;       (see session.save_path above), then garbage collection does *not*
[root@manvscloud-web-pub-kr1 ~]# systemctl restart memcached
[root@manvscloud-web-pub-kr1 ~]# systemctl restart php-fpm

그냥 블로그만 운영하던 서버다보니 크게 설치할 것들이 별로 없습니다.
이제 기본 세팅만 진행해보도록 합시다.


Default Settings

우선 sshd 설정을 먼저 진행하기로 했습니다.
설정 조건은 아래와 같습니다.

  • SSH 포트를 22에서 15222로 변경할 것
  • manvscloud 사용자 생성 및 sudo로 root권한 사용
  • root로 바로 접속할 수 없도록 설정
  • 접속 시 Password가 아닌 Public Key 파일을 이용하여 로그인
[root@manvscloud-web-pub-kr1 ~]# useradd manvscloud
// 먼저 서버에 key 파일을 업로드 한 뒤 작업을 진행하였습니다.

[root@manvscloud-web-pub-kr1 ~]# chmod 400 manvscloud.pem
[root@manvscloud-web-pub-kr1 ~]# mkdir /home/manvscloud/.ssh
[root@manvscloud-web-pub-kr1 ~]# ssh-keygen -y -f manvscloud.pem > /home/manvscloud/.ssh/authorized_keys
[root@manvscloud-web-pub-kr1 ~]# chown -R manvscloud:manvscloud /home/manvscloud/.ssh
[root@manvscloud-web-pub-kr1 ~]# chmod 700 /home/manvscloud/.ssh
[root@manvscloud-web-pub-kr1 ~]# chmod 600 /home/manvscloud/.ssh/authorized_keys

[root@manvscloud-web-pub-kr1 ~]# id manvscloud
uid=1001(manvscloud) gid=1001(manvscloud) groups=1001(manvscloud)
[root@manvscloud-web-pub-kr1 ~]# gpasswd -a manvscloud wheel
Adding user manvscloud to group wheel
[root@manvscloud-web-pub-kr1 ~]# gpasswd -a manvscloud systemd-journal
Adding user manvscloud to group systemd-journal

[root@manvscloud-web-pub-kr1 ~]# grep -E "wheel|systemd-journal" /etc/group
wheel:x:10:manvscloud
systemd-journal:x:190:manvscloud

[root@manvscloud-web-pub-kr1 ~]# cat << EOF > /etc/sudoers.d/10-manvscloud-users
> # User rules for manvscloud
> manvscloud ALL=(ALL) NOPASSWD:ALL
> EOF
[root@manvscloud-web-pub-kr1 ~]# chmod 440 /etc/sudoers.d/10-manvscloud-users
[root@manvscloud-web-pub-kr1 ~]# passwd -l root
Locking password for user root.
passwd: Success

///etc/ssh/sshd_config 파일 수정

[root@manvscloud-web-pub-kr1 ~]# cat -n /etc/ssh/sshd_config  | grep -E "Port|PermitRootLogin|PasswordAuthentication"
    17	#Port 22
    38	PermitRootLogin yes
    63	#PasswordAuthentication yes
    65	PasswordAuthentication yes
    88	# PasswordAuthentication.  Depending on your PAM configuration,
    90	# the setting of "PermitRootLogin without-password".
    92	# PAM authentication, then enable this but set PasswordAuthentication
   100	#GatewayPorts no


[root@manvscloud-web-pub-kr1 ~]# cp -avp /etc/ssh/sshd_config /etc/ssh/sshd_config_org
[root@manvscloud-web-pub-kr1 ~]# sed -i '38s/yes/no/g' /etc/ssh/sshd_config
[root@manvscloud-web-pub-kr1 ~]# sed -i '65s/yes/no/g' /etc/ssh/sshd_config
[root@manvscloud-web-pub-kr1 ~]# perl -p -i -e '$.==17 and print " Port 15222\n"' /etc/ssh/sshd_config

[root@manvscloud-web-pub-kr1 ~]# systemctl restart sshd

다음은 php설정을 해줄 것입니다.

우선 php.ini 파일과 www.conf 파일을 수정할건데 pm 값을 조정하는 최적화 작업은 기본 설정에서 제외하였습니다.

php.ini파일에서는 아래와 같이 값을 변경해주었습니다.

   date.timezone = "Asia/Seoul"
   expose_php = Off
   short_open_tag = On
   allow_url_fopen = Off
   max_execution_time = 60
   memory_limit = 128M

이번 이전에서 포인트로 정한 php-fpm의 파일 소켓 통신을 설정하는 부분입니다.
www.conf에서 기존 listen이 127.0.0.1:9000로 TCP/IP 소켓 통신이 기본값인데 이를 /run/php-fpm/www.sock 으로 변경하여 Unix Socket 통신이 되도록 하였습니다.

[root@manvscloud-web-pub-kr1 ~]# cat -n /etc/php-fpm.d/www.conf | grep listen | grep -v ";"
    38	listen = 127.0.0.1:9000
    64	listen.allowed_clients = 127.0.0.1
[root@manvscloud-web-pub-kr1 ~]# sed -i '38s$127.0.0.1:9000$/run/php-fpm/www.sock$g' /etc/php-fpm.d/www.conf
[root@manvscloud-web-pub-kr1 ~]# cat -n /etc/php-fpm.d/www.conf | grep listen | grep -v ";"
    38	listen = /run/php-fpm/www.sock
    64	listen.allowed_clients = 127.0.0.1

이 Unix Socket 방식은 TCP의 소켓과 동일하게 API로 데이터를 주고받을 수 있는데 이는 로컬 파일 기반 소켓이라서 Nginx와 함께 쓰기 위해 php-fpm를 같은 로컬내에 존재하도록 하였습니다. 이 방식은 localhost 내에 프로세스 간 통신이라 속도도 우월하고 메모리 소모를 줄일 수 있습니다.

📄 nofile 설정
vi /etc/security/limits.conf
*               soft    nofile          65535
*               hard    nofile          65535

위 설정을 해주지 않으면 파일 열기 최대 개수가 soft/1024, hard/4096이 default인 것으로 기억합니다.

💿 History
[root@manvscloud-web-pub-kr1 ~]# cat -n /etc/profile | grep HISTFILESIZE
    78	HISTFILESIZE=0
[root@manvscloud-web-pub-kr1 ~]# sed -i '78s/0/5000/g' /etc/profile
[root@manvscloud-web-pub-kr1 ~]# cat -n /etc/profile | grep HISTFILESIZE
    78	HISTFILESIZE=5000
[root@manvscloud-web-pub-kr1 ~]# echo export HISTTIMEFORMAT=\"[%F %T] \" > /etc/profile.d/bash_history.sh
[root@manvscloud-web-pub-kr1 ~]# chmod 755 /etc/profile.d/bash_history.sh
[root@manvscloud-web-pub-kr1 ~]# init 6

저는 history를 자주 이용하는 편입니다.
그런데 기본 설정을 하고 다음 날 서버에 접속했는데 history가 하나도 남아있지 않아 확인해보니 HISTFILESIZE가 0으로 되어있어 이를 변경해주기로 하였습니다.

값을 5000으로 변경해주고 HISTTIMEFORMAT을 주어 history에 시간대도 확인할 수 있도록 설정해두었습니다.

Nginx와 MariaDB 설정은 다음 #3편에서 스토리지 추가 및 NAS 연결과 함께 설정을 진행할 것입니다.


Personal Comments

#3편에서는 “ManVSCloud 신규 Architecture” 공개와 함께 스토리지 추가 및 NAS 연결에 대한 포스팅을 진행할 것입니다.

제가 이번에 진행하는 AWS to NCloud 이전 작업에서 설정되는 부분이나 이렇게 이전이 될 수도 있구나하는 걸 재밌게 봐주셨으면 합니다.

긴 글 읽어주셔서 감사합니다.


NCP

[NCP] AWS to NCloud Server Migration – #1편

안녕하세요. ManVSCloud 김수현입니다.

이미지 출처 : https://www.mk.co.kr/news/it/view/2021/08/819941/

네이버 클라우드의 빠른 성장이 지속되고 있습니다.
현재 국내 클라우드 기업중 네이버 클라우드가 독보적으로No.1이라 봅니다.

올해 7월 네이버 클라우드는 공공기관 시장에서 97.64%의 점유율의 성적을 보이며
왜 네이버 클라우드인지 증명해냈습니다.

제 manvscloud.com 블로그도 이제 AWS를 떠나 네이버 클라우드 플랫폼으로 이전하게 되었습니다.

현재 전체적인 환경을 파악하고 있으며 네이버 클라우드 플랫폼에서는 기존 AWS에서 사용하던 아키텍처와 다르게 사용하고 싶어 새로운 아키텍처를 구상하고 있습니다.

네이버 클라우드 플랫폼의 기술력과 발전 가능성을 고려해본다면 먼저 네이버 클라우드를 시작하고 싶다라는 생각이 듭니다.


AWS Env

우선 네이버 클라우드 플랫폼으로 이전하기 전에 기존 AWS 환경에서 구성되어있던 아키텍처와 인스턴스 내 각 서비스들의 버전들을 파악하기로 했습니다.

먼저 기존 아키텍처는 예전에 만들어둔 것으로 가져왔습니다.
조금 추가된 부분이 있다면 AWS 한국 리전에서는 SNS에서 SMS 기능을 선택할 수 없습니다. 그렇기 때문에 추가적인 Lambda 작업이 있었습니다…

(네이버 클라우드는 따로 추가적인 작업없이 간단하게 모니터링 설정에서 SMS 문자 알림을 받을 수 있도록 설정할 수 있기에 이런 고통에서 벗어날 수 있게 되었습니다…😂)

[root@ip-10-0-1-68 ~]# cat /etc/*-release
NAME="Amazon Linux"
VERSION="2"
ID="amzn"
ID_LIKE="centos rhel fedora"
VERSION_ID="2"
PRETTY_NAME="Amazon Linux 2"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
HOME_URL="https://amazonlinux.com/"
Amazon Linux release 2 (Karoo)

Linux 버전은 Amazon Linux AMI 2 를 사용하고 있었습니다.
네이버 클라우드로 이전하게 되면 CentOS 7을 사용할 것입니다.
원래 Rocky Linux 8을 써보고 싶었지만 아직 Rocky Linux 소식이 없어 CentOS 7로 결정하게 되었습니다.

[root@ip-10-0-1-68 home]# apachectl -v
Server version: Apache/2.4.46 ()
Server built:   Aug 24 2020 18:54:20

[root@ip-10-0-1-68 home]# php -v
PHP 7.4.15 (cli) (built: Feb 11 2021 17:53:39) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.15, Copyright (c), by Zend Technologies

두번째로 제 블로그는 APM으로 구성되어 있는데 이번 기회에 Apache에서 Nginx로 변경을 결정했습니다. 또한 Nginx 와 php 간에 TCP Socket을 사용하지 않고 Unix Socket을 사용해볼 것입니다. 이는 제가 늘 보고 배우는 Linuxer 님의 Blog를 보고 저도 이를 적용해보기로 마음먹게 되었습니다.

마지막으로 DB입니다. 원래 아키텍처는 WEB과 DB가 나뉘어져 있었습니다.
단, 인스턴스 하나가 죽으면 서비스가 마비가 되어 이번에 네이버 클라우드로 이전하면 WEB과 DB를 하나의 서버로 쓰되 이중화를 구성하기로 했습니다.

최종적으로 아키텍처가 완성되면 추가 블로깅 및 설명해볼 것입니다.


Naver Cloud Platform, Resource Creation

🌏 VPC
manvscloud-vpc
subnet

VPC를 구성하는 부분은 이제 너무 쉬우니 이렇게 구성했습니다!만 보여주고 넘어가도록 하겠습니다.

💻Server
server creation

서버는 하나만 생성해두었습니다.

서버 하나에 기본적인 설치 및 구성을 끝내두고 이미지를 생성하여 생성한 이미지를 이용하여 이중화를 구성할 것입니다.

참고로 오늘은 “AWS TO NCLOUD SERVER MIGRATION”에 대한 전반적인 느낌만 잡아가는 포스팅이며 추가 포스팅에서 완성된 아키텍처와 함께 어떻게 설치가되고 이전을 어떤 방식으로 진행했는지도 함께 적어볼 것입니다.

💾 Object Storage + Global CDN

현재 고민 중인 부분은 cdn을 어떻게 해결할까에 대한 부분입니다.
기존 AWS S3에 생각보다 많은 데이터가 쌓이게 되었고 이를 Object Storage에 넘겨준 뒤 나중에 DB에서도 수정해줘야하는 부분이 있기도 하고 기존에 CDN을 사용하고 있는 방식이 WordPress의 AWS 플러그인이라 이 부분이 잘 될지 확신이 되지 않기에 CDN은 조금 테스트를 진행해본 뒤 결정하게 될 것같습니다.


Personal Comments

이전을 진행하며 조금이나마 이런 기능을 만들어주었으면 좋겠다고 생각되는 부분이 있어
오늘은 네이버 클라우드에 바라는 점이 있다면 몇가지를 써보도록 하겠습니다.

  • SSL 인증서
    : Certificate Manager라는 서비스가 있는데 이는 외부에서 구매한 인증서를 입력하고 추가하는 것이라 추가적인 절차가 필요합니다.
    AWS의 ACM과 같은 서비스가 어서 생겼으면 좋겠습니다.
    (이 기능이 AWS를 사용하는동안 생각보다 매우 편리했기에 네이버 클라우드에도 도입되길 바랍니다.)
  • WAF
    : 네이버 클라우드에서 WAF를 사용하려면 Security Monitoring 라는 서비스에서 [이용 문의]를 통해서 사용이 가능합니다. 아직 AWS WAF처럼 사용자 선택하고 Count/Block 하는 방식이 아닌 신청해서 사용하는 방식으로 보입니다. 물론 네이버 클라우드 플랫폼의 WAF는 주간/월간 보고서 등의 장점도 있지만 사용자 지정 방식의 WAF도 생기다면 부담스럽지 않게 사용해볼 수 있을 것같습니다.
  • 주기적인 이미지/스냅샷 관리
    : 이미지/스냅샷을 사용자가 직접 백업 일정을 지정하고 진행하는 기능이 아직 없습니다.
    물론 Cloud Functions을 이용하면 해서 이런 기능을 만들 수는 있겠지만 개발자가 아닐 경우 난감할 수 있겠다 생각됩니다.
    그렇기 때문에 네이버 클라우드에서는 Backup이라는 서비스를 제공합니다.
    네이버 클라우드에서 직접 고객의 데이터를 백업해주고 보관해주는 서비스인데 상당히 괜찮습니다. 이 서비스만 신청해두면 사실 고객 입장에서는 직접적인 백업 관리를 하지 않아도 되니 용량별 비용만 고려하면 되어 오히려 편할 수 있습니다.

네이버 클라우드 플랫폼은 늘 빠른 업데이트와 기능 추가를 하고 있어 이러한 사용자들의 의견만 있다면 위 기능들 역시 금방 생길 거라 봅니다.

긴 글 읽어주셔서 감사합니다.


NCP

[NCP] 안녕하세요. 네이버 클라우드 Support Master 입니다.

안녕하세요. ManVSCloud 김수현입니다.

오늘 네이버 클라우드 플랫폼(Naver Cloud Platform) 공식 블로그에서 9인의 Master 멤버가 공개되었습니다.

다소 부족한 점이 많으나 공식 테크 앰버서더, 즉 Master 멤버의 기회가 주어져 Support Master로서 여러분들에게 큰 도움을 드릴 수 있게되었습니다.


Support Master

Support Master로서 저는 많은 네이버 클라우드 사용자 또는 사용하시고자 하는 분들을 Supporting을 하고자 Support Master가 되었습니다.

클라우드를 배워보고자하는 학생분들이나 온프레미스 환경에서 서비스를 운영하시다가 클라우드 환경으로 서비스를 이전하고자 하는 분 등 다양한 유저들에게 제가 알고 있는 지식을 공유하여 조금 더 네이버 클라우드를 쉽게 접하고 원활한 서비스를 운영하실 수 있도록 하는 것이 저의 목적입니다.

우선 네이버 클라우드에 대한 주제로 정기적인 블로그 포스팅이 있을 것이며 추가적인 도움을 드릴 수 있을 만한 자료를 준비하고 있습니다.

이 부분은 제 블로그를 통해 추가 공지될 예정입니다.


Naver Cloud Platform

네이버 클라우드에 대해 궁금하신 부분이 있으실 경우 댓글 남겨주시면 답변 도와드리도록 하겠습니다.

또한 이런 기회를 얻을 수 있도록 클라우드에 처음 흥미를 주신 서태호(Network Master)님과 기술 성장에 늘 도움주신 Linuxer님에게 늘 감사드리며 Master 활동 준비 및 지원해주시는 네이버 클라우드 플랫폼(Naver Cloud Platform)에 감사의 인사 올립니다.


Notice/News

[Notice] 포스팅 일정 공지

안녕하세요. ManVSCloud 김수현입니다.

2021-08-01까지 CKA(Certified Kubernetes Administrator) 시험에 집중하기 위해 블로그 추가 포스팅은 시험 이후 업로드될 예정입니다.

기간 : ~ 2021-08-01

매번 포스팅을 읽어주셔서 다시 한 번 감사의 인사드리며 시험 이후 후기 포스팅으로 찾아뵙겠습니다.

요즘 날씨가 많이 더워졌습니다.
무더위에 건강 잘 챙기시기 바랍니다.

Notice/News

[NOTICE] 포스팅 일정 공지 (2021-07-02)

안녕하세요. ManVSCloud 김수현입니다.

매번 포스팅을 읽어주셔서 매번 감사합니다.
다름이 아니라 이번 주 포스팅 일정에 대한 내용으로 공지 안내드립니다.

1주일에 2개의 포스팅을 목표로 하고있으나
이번 주는 회사 업무 및 추가적인 스케줄로 인해 이번 주 일요일에 업로드 될 예정입니다.

다시 한 번 감사의 인사 올립니다.

IT/Linux/Kubernetes

[Linux] Cannot allocate memory, 캐시 메모리 제거 및 swap 생성

안녕하세요. ManVSCloud 김수현입니다.

오늘은 최근 제 블로그가 간헐적 끊김이 있어 확인 후
Memory 부족 원인을 파악하고 해결까지에 대한 내용을 작성해보았습니다.


Symptom & Identify the cause

어제 블로그에 포스팅 후 블로그 페이지가 정상적으로 출력되지 않는 현상이 발생했습니다.
서버 접속 시 Cannot allocate memory 에러가 발생하는 중이었으며 명령어 입출력이 정상적이지않은 상태라 우선 인스턴스 재부팅을 진행하게 되었습니다.

-bash: fork: Cannot allocate memory

대시보드에서 자원 사용률을 살펴보았는데 다른 자원 사용률은 정상인데 유독 Memory만 90% 이상 사용 중!! Memory 문제가 있는 것을 알게되었습니다.

VSZ, RSS 확인 시 Apache, PHP에서만 대량 사용 중이라 웹 로그를 먼저 확인해보았습니다.
1주일 단위로 logrotate가 걸려있어 최근 로그만 파악할 수 있는 상태였는데 우선 공격성으로 대량 접근하는 IP가 존재하는지 확인하였고 의심되는 IP는 WAF에서 추가 검토하였는데 따로 공격성 접근은 아닌 것으로 파악되었습니다.

[root@ip-10-0-1-68 httpd]# cat /var/log/httpd/access_log | awk '{print $1}' | sort -n | uniq -c | grep -Ev "10.0|172.16|192.168|-" | sort -rn | head -n 10
    399 88.150.-.-
    319 121.125.-.-
    200 125.141.-.-
    186 63.141.-.-
     83 66.249.-.-
     75 66.249.-.-
     49 117.111.-.-
     46 52.79.-.-
     37 66.249.-.-
     36 45.146.-.-

sar를 이용하여 추가 검토를 진행하였습니다.
인스턴스 재시작 후에도 메모리 사용량이 80% 이상 계속 유지 중이었습니다.

[root@ip-10-0-1-68 ~]# sar -r
Linux 4.14.193-149.317.amzn2.x86_64 (ip-10-0-1-68.ap-northeast-2.compute.internal) 	05/22/2021 	_x86_64_	(1 CPU)

12:00:02 AM kbmemfree kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
12:10:01 AM     65860    941080     93.46         0    103936   4407680    437.73    785580     28120       120
12:20:01 AM     58924    948016     94.15         0    106820   4414144    438.37    789028     31556       176
12:30:01 AM     66768    940172     93.37         0    103328   4410048    437.97    784968     28244       208
12:40:01 AM     64996    941944     93.55         0    102724   4410256    437.99    787600     26904       232
12:50:01 AM     61056    945884     93.94         0    103356   4414996    438.46    792132     26448        40
01:00:01 AM     68052    938888     93.24         0     96388   4412948    438.25    787572     24756       112
01:10:01 AM     63336    943604     93.71         0    100240   4414108    438.37    789356     27116       112
01:20:02 AM     65780    941160     93.47         0    102172   4408852    437.85    785084     29272       112
01:30:01 AM     61096    945844     93.93         0    108252   4408644    437.83    
.
. [생략]
.
08:26:04 AM       LINUX RESTART
08:36:33 AM       LINUX RESTART
08:40:02 AM kbmemfree kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
08:50:01 AM    192852    814088     80.85      2088    365732   3775100    374.91    401104    280868       296
09:00:01 AM    203284    803656     79.81      2088    378252   3162244    314.04    376764    289192       328
09:10:01 AM    195364    811576     80.60      2088    378620   3171048    314.92    384684    289380       332
09:20:01 AM    194748    812192     80.66      2088    379568   3173428    315.16    383840    290344       328
09:30:01 AM    181256    825684     82.00      2088    379744   3187564    316.56    407336    280344       328
Average:       193501    813439     80.78      2088    376383   3293877    327.12    390746    286026       322

마지막으로 free 명령어로 확인해보니 buff/cache가 비워지지 않고 그대로 남아있는 상태였습니다.

[root@ip-10-0-1-68 ~]# free -m
              total        used        free      shared  buff/cache   available
Mem:            983         448         125          60         408         338
Swap:             0           0           0

우선 아래 명령어를 이용하여 캐시 메모리를 지우고 메모리 확보를 진행 하였습니다.

[root@ip-10-0-1-68 ~]# sync && echo 3 > /proc/sys/vm/drop_caches
[root@ip-10-0-1-68 ~]# free -m
              total        used        free      shared  buff/cache   available
Mem:            983         435         365          60         182         358
Swap:             0           0           0

(sync && echo 3 > /proc/sys/vm/drop_caches 명령어에 대해서는 아래에서 추가적인 설명을 하도록하겠습니다.)

이후 메모리는 정상화 되었으나 추가적인 조치를 하지 않으면 동일한 장애가 다시 발생할 수 있어 우선 swap을 생성하기로 했습니다.


Create Swap

약 2~3G 정도 크기의 볼륨을 생성해줍니다.
swap 볼륨을 추가할 인스턴스와 연결을 시켜줍니다.
[root@ip-10-0-1-68 ~]# fdisk -l
Disk /dev/xvda: 15 GiB, 16106127360 bytes, 31457280 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 66F46060-ED00-4D14-9841-F5CB6310A14A

Device       Start      End  Sectors Size Type
/dev/xvda1    4096 31457246 31453151  15G Linux filesystem
/dev/xvda128  2048     4095     2048   1M BIOS boot

Partition table entries are not in disk order.


Disk /dev/xvdb: 3 GiB, 3221225472 bytes, 6291456 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

연결이 잘됐는지 확인 후 이제 파티션을 아래와 같이 생성해주었습니다.

[root@ip-10-0-1-68 ~]# fdisk /dev/xvdb
Welcome to fdisk (util-linux 2.30.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0xb9e2e385.

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-6291455, default 2048): 
Last sector, +sectors or +size{K,M,G,T,P} (2048-6291455, default 6291455): 

Created a new partition 1 of type 'Linux' and of size 3 GiB.

Command (m for help): t
Selected partition 1
Hex code (type L to list all codes): 82
Changed type of partition 'Linux' to 'Linux swap / Solaris'.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

[root@ip-10-0-1-68 ~]# fdisk -l | tail -n 9
Disk /dev/xvdb: 3 GiB, 3221225472 bytes, 6291456 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xb9e2e385

Device     Boot Start     End Sectors Size Id Type
/dev/xvdb1       2048 6291455 6289408   3G 82 Linux swap / Solaris

swap 파티션이 잘 생성되었다면 mkswap으로 swap을 만들어주고 blkid에 나온 UUID를 참고하여 /etc/fstab에 추가해줍니다.
이 부분을 잘못 추가하게될 경우 정상 부팅이 되지않아 번거로운 추가 작업이 생길 수 있으니 잘 추가해줍시다.

[root@ip-10-0-1-68 ~]# mkswap /dev/xvdb1
[root@ip-10-0-1-68 ~]# blkid /dev/xvdb1
/dev/xvdb1: UUID="dc082f63-27d8-41b1-ad74-8b019162f766" TYPE="swap" PARTUUID="b9e2e385-01"
[root@ip-10-0-1-68 ~]# vi /etc/fstab

UUID=dc082f63-27d8-41b1-ad74-8b019162f766       swap    swap    defaults        0 0

[root@ip-10-0-1-68 ~]# swapon -a
[root@ip-10-0-1-68 ~]# swapon -s
Filename				Type		Size	Used	Priority
/dev/xvdb1                             	partition	3144700	0	-2

swapon 명령어에 -a 옵션을 주면 /etc/fstab에 있는 swap 파티션을 모두 enable 합니다.
-s 옵션은 사용중인 스왑 장치를 요약하여 볼 수 있습니다.

저는 볼륨을 2개 추가하여 하여 swap 볼륨 하나가 장애가 발생하더라도 나머지 하나로 작동할 수 있도록 해두었습니다.

[root@ip-10-0-1-68 ~]# swapon -s
Filename				Type		Size	Used	Priority
/dev/xvdb1                             	partition	3144700	0	-2
/dev/xvdc1                             	partition	3144700	0	-3

[root@ip-10-0-1-68 ~]# free -m
              total        used        free      shared  buff/cache   available
Mem:            983         461         332          60         188         328
Swap:          6141           0        6141

Swapfile

swap 볼륨을 따로 추가할 수 없을 수도 있습니다.
그때는 swapfile을 만들어서 사용할 수 있는데 간단하게 swapfile을 만드는 방법만 설명하겠습니다.

// dd 명령어를 이용해서 용량 지정 및 swap파일을 만들어줍니다. 
(mkdir로 디렉토리 만들어두는 것 아닙니다.)
[root@manvscloud-test-pub-kr2 ~]# dd if=/dev/zero of=/swapfile bs=1MiB count=4096
4096+0 records in
4096+0 records out
4294967296 bytes (4.3 GB) copied, 12.3267 s, 348 MB/s
//권한 변경
[root@manvscloud-test-pub-kr2 ~]# chmod 600 /swapfile
//스왑 생성
[root@manvscloud-test-pub-kr2 ~]# mkswap /swapfile
Setting up swapspace version 1, size = 4194300 KiB
no label, UUID=4e0d57c0-dd8f-4527-af2d-659ce04921b7

이후 /etc/fstab에 등록해주고 swapon -a 해주는 것은 동일합니다.

/swap01                          swap                swap    defaults        0 0

sync && echo 3 > /proc/sys/vm/drop_caches

Linux에서 아래 명령어를 이용하여 캐시를 비울 수 있습니다.

  • PageCache만 비우기
    sync && echo 1 > /proc/sys/vm/drop_caches
    (= sync; echo 1 > /proc/sys/vm/drop_caches)
  • dentries와 inodes 비우기
    sync && echo 2 > /proc/sys/vm/drop_caches
    (= sync; echo 2 > /proc/sys/vm/drop_caches)
  • PageCache, dentries, inodes 모두 비우기
    sync && echo 3 > /proc/sys/vm/drop_caches
    (= sync; echo 3 > /proc/sys/vm/drop_caches)

sync를 통해 파일 시스템 버퍼를 플러시합니다.
(개발쪽은 잘 모르지만 JAVA나 Python에서 flush() 함수가 버퍼 비우는 용도로 사용되는걸 본 적이 있습니다)

단 echo 3을 사용한다면 모두 비우기가 가능하지만 디스크 I/O가 활발한 시스템에서 사용하게 된다면 CPU 자원 사용량이 일시적으로 상승합니다.

  • pagecache : 리눅스 커널에 의해 사용되는 기본 디스크 캐시.
    대부분의 경우 커널은 디스크에서 읽거나 디스크에 쓸 때 페이지 캐시를 참조합니다.
    I/O 속도와 퍼포먼스를 높이기 위해 시스템이 할당한 임시 메모리 저장소로 임시 메모리에 저장된 파일을 다시 읽을 때 해당 메모리에서 바로 불러오기에 디스크의 읽기,쓰기 속도가 빨라집니다. (Windows에서는 동일한 역할로 페이지 파일이 있습니다.)
  • dentries : dcache, 즉 디렉토리 항목 캐시입니다. 경로/파일명을 특정 dentry로 변환하여 빠른 조회를 제공하며 디스크가 아닌 RAM에 저장됩니다. (inode를 검색하여 수행됩니다.)
  • inodes : 파일과 디렉토리에 관한 정보를 담고 있는 자료 구조
    (물리적 위치, 크기, 생성 일시, 권한)
[root@ip-10-0-1-68 ~]# vmstat -m | head -n 1; vmstat -m | grep proc_inode_cache
Cache                       Num  Total   Size  Pages
proc_inode_cache          13570  13570    688     23

⬆ (위 명령어로 inode 캐시값 확인이 가능합니다.)

※ TIP-1 (Slab) 😎

서비스 프로세스 할당량을 계산해보아도 전체 메모리에 비해 유휴 메모리가 없을 때가 있을 것입니다. 이는 커널에서 메모리를 사용하고 있기때문인데 커널에서 사용하고 있는 메모리는 slab 메모리 영역을 확인하면 얼마나 사용하고 있는지 알 수 있습니다.

[root@ip-10-0-1-68 ~]# cat /proc/meminfo | grep Slab
Slab:              48832 kB

Slab에 대한 내용이 깊이있게 설명되어 있는 곳은 링크로 남겨두었으니 참고바랍니다.

  • Slab : 메모리 영역 중 커널이 직접 사용하는 영역을 Slab영역이며 dentries와 inodes 캐시가 이 영역에 해당됩니다.
    (slabtop 명령어를 이용하여 현재 시스템의 slab 자료 구조 상태를 확인할 수 있습니다.)
[root@ip-10-0-1-68 ~]# slabtop
 Active / Total Objects (% used)    : 232162 / 241799 (96.0%)
 Active / Total Slabs (% used)      : 7662 / 7662 (100.0%)
 Active / Total Caches (% used)     : 74 / 101 (73.3%)
 Active / Total Size (% used)       : 55501.21K / 58750.71K (94.5%)
 Minimum / Average / Maximum Object : 0.01K / 0.24K / 9.50K

  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME                   
 39580  39403  99%    0.20K   1979	 20	 7916K vm_area_struct
 38080  38080 100%    0.06K    595	 64	 2380K anon_vma_chain
 30072  30072 100%    0.19K   1432	 21	 5728K dentry
 19136  19089  99%    0.09K    416	 46	 1664K anon_vma
 15504  14550  93%    0.04K    152	102	  608K Acpi-Namespace
 15210  15210 100%    0.13K    507	 30	 2028K kernfs_node_cache
 13570  13570 100%    0.67K    590	 23	 9440K proc_inode_cache
 10868  10476  96%    0.60K    418	 26	 6688K inode_cache
  7808   6525  83%    0.03K     61	128	  244K kmalloc-32
  5746   4799  83%    0.94K    169	 34	 5408K xfs_inode
  5248   3838  73%    0.06K     82	 64	  328K kmalloc-64
  5180   3660  70%    0.57K    185	 28	 2960K radix_tree_node
  3822   2783  72%    0.09K     91	 42	  364K kmalloc-96
  3264   2517  77%    0.25K    102	 32	  816K kmalloc-256
  3248   3248 100%    0.07K     58	 56	  232K Acpi-Operand
  3072   3072 100%    0.02K     12	256        48K kmalloc-16
  3060   3060 100%    0.05K     36	 85	  144K ftrace_event_field
  2560   2560 100%    0.01K	 5	512        20K kmalloc-8
  2037   1762  86%    0.19K     97	 21	  388K kmalloc-192
  1610   1610 100%    0.09K     35	 46	  140K trace_event_file
  1536   1258  81%    0.50K     48	 32	  768K kmalloc-512
  1344   1046  77%    0.12K     42	 32	  168K kmalloc-128

※ TIP-2 (vfs_cache_pressure) 😎

vfs_cache_pressure는 리눅스 커널의 vm구조와 관련된 파라미터입니다.
vfs_cache_pressure를 이용해서 커널에게 디렉토리와 inode Object에 대한 캐시로 사용된 메모리를 반환하도록하는데 이 값이 0일 경우 커널이 오브젝트에 대한 캐시를 반환하지 않아 Out Of Memory가 발생합니다.
보통 이 값이 100으로 설정되어 있으나 자주 캐시를 반환하기 위해서는 이 값을 변경해주어야하며 값이 높아질수록 메모리에서 캐시를 보관하지 않게되어 dentries와 inodes 캐시를 줄일 수 있습니다.

[root@ip-10-0-1-68 ~]# cat /proc/sys/vm/vfs_cache_pressure
100

기본값은 100으로 되어있습니다.
/proc/sys/vm/vfs_cache_pressure 에 값을 지정해주는 것은 일회성이니 sysctl.conf에 설정해줍니다.

[root@ip-10-0-1-68 ~]# vi /etc/sysctl.conf 이후 아래값을 추가 및 저장, load 해줍니다
vm.vfs_cache_pressure = 10000
[root@ip-10-0-1-68 ~]# sysctl -p

Personal Comments and Wrap-up

아직 캐시 메모리를 비우고 swap 생성만 해두었습니다.
이걸로 완벽하게 해결됐다고 보기는 어렵습니다. 이후 메모리 사용량 경보를 추가하여 알림 설정을 하고 현재 오토스케일링 추가를 생각하고 있습니다.
(우선 오토스케일링 추가 전 서버 내 자원 최적화 작업을 먼저 진행해야겠습니다.)

그리고 이번 메모리 최적화에 도움주신 리눅서님에게 감사의 인사올립니다.
(아… 난 왜 swap을 잊고있었지? 매번 감사합니다…🙇🏻‍♂️ 덕분에 이번 기회로 메모리에 대해 많이 공부한 것같습니다.)

Notice/News

[NOTICE] 블로그 성능 개선 작업 완료 (2021-05-17)

안녕하세요. ManVSCloud 김수현입니다.

2021년 5월 17일 예정되어 있던 블로그 성능 개선 작업이 정상적으로 완료되었습니다.

※ 작업 내용
→ DNS 작업 (작업 시간동안 임시 Parking 페이지로 출력될 예정입니다.)
→ 데이터 백업(Snapshot)
→ 소프트웨어 버전 업그레이드
→ EC2, RDS 인스턴스 재시작
→ DNS 원복

※ 작업 시간
→ 예정 시간 : 2021-05-17 월요일, 00:00 ~ 06:00(KST)
→ 소요 시간 : 2021-05-17 월요일, 00:00 ~ 02:40(KST)


세부 작업 내용

http://parking.manvscloud.com

http://manvscloud.com 또는 https://manvscloud.com 접속 시 http://parking.manvscloud.com 사이트로 리다이렉트 되도록 설정한 뒤 작업하였습니다.

parking 페이지의 경우 cdn을 이용하려고 했는데 이번 작업 준비 기간이 다소 부족하여
제 테스트 서버를 사용하게 되었습니다.

  • 작업 전 스냅샷 (naming-20210517)
  • PHP 버전 업그레이드 (PHP 7.3.23 → 7.4.15)
<작업 전>
[root@ip-10-0-1-68 ~]# php -v
PHP 7.3.23 (cli) (built: Oct 21 2020 18:39:40) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.23, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.3.23, Copyright (c) 1999-2018, by Zend Technologies

<작업 후>
[root@ip-10-0-1-68 mcrypt-1.0.2]# php -v
PHP 7.4.15 (cli) (built: Feb 11 2021 17:53:39) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.15, Copyright (c), by Zend Technologies
  • PHP 모듈 추가 설치

PHP 7.4 버전으로 설치 후 mcrypt 모듈이 정상적으로 설치되지 않았습니다.
(가끔 버전업 시 해당 버전에서 특정 모듈 지원 중단으로 설치가 안될 때가 있습니다.)
mcrypt 모듈이 설치가 되지않아 수동으로 설치 해주었습니다.

[root@ip-10-0-1-68 ~]# yum install libmcrypt-devel
[root@ip-10-0-1-68 ~]# cd /usr/local/src
[root@ip-10-0-1-68 ~]# wget https://pecl.php.net/get/mcrypt-1.0.2.tgz
[root@ip-10-0-1-68 ~]# tar xvfz mcrypt-1.0.2.tgz
[root@ip-10-0-1-68 ~]# cd mcrypt-1.0.2
[root@ip-10-0-1-68 ~]# phpize
[root@ip-10-0-1-68 ~]# ./configure
[root@ip-10-0-1-68 ~]# make
[root@ip-10-0-1-68 ~]# make install
[root@ip-10-0-1-68 ~]# echo extension=mcrypt >> /etc/php.ini
  • RDS 버전 업그레이드 및 파라미터 그룹 설정

저는 주로 파라미터 그룹 설정을 아래와 같이 사용합니다.
상황에따라 max_allowed_packet, max_heap_table_size, tmp_table_size 등의 값을 조정해주어야겠습니다.

character_set_client utf8mb4
character_set_connection utf8mb4
character_set_database utf8mb4
character_set_filesystem utf8mb4
character_set_results utf8mb4
character_set_server utf8mb4
collation_connection utf8mb4_general_ci
(collation_server은 utf8mb4_general_ci 를 선택할 수 없어서 그냥 빼버렸습니다.)
time_zone asia/seoul
connect_timeout 3600
skip_name_resolve 1

  • WordPress 최신 버전 업데이트 (5.5.2 → 5.7.2)
  • EC2, RDS 인스턴스 재부팅
  • DNS 원복

마무리

오래 미루어왔던 블로그 품질 향상 및 안정화를 위한 작업이 완료되었습니다.
늘 워드프레스 관리자 사이트에서 Site Health에 노란불이 들어왔었는데 작업 후 확실히 깔끔해진 기분입니다.

개인적으로 작업 시간은 (작업에 필요한 시간 + 장애 시 복구 시간)을 다 합쳐서 정하는 편입니다. 이번 작업은 야간 당직 중 남는 시간 틈틈이 작업을 진행하려 했기에 6시간을 예상했었는데 다행히 당직 간에 큰 일이 없어서 빠르게 작업을 끝낼 수 있었던 것같습니다.
아마 중간중간에 일이 없었다면 1시간 내로 작업이 끝났을 것같군요.
작업이 잘 마무리되어 다행입니다.

다음 포스팅은 [NCP] 네이버 클라우드에서의 보안 – Account 으로 찾아뵙겠습니다.

긴 글 읽어주셔서 감사합니다.

Notice/News

[Notice] 블로그 성능 개선 작업 안내 (2021-05-17)

안녕하세요. ManVSCloud 김수현입니다.

최근 블로그 방문자 수가 늘어 사이트 작업 시 공지 후 작업을 진행하기로 하였습니다.

2021년 5월 17일 새벽 간에 안정적인 서비스를 위한 소프트웨어 버전 업그레이드 작업이 예정되어 있습니다.
작업 내용과 일정은 아래에 추가해두었으며 해당 시간동안 블로그 페이지가 정상적으로 출력되지 않을 수 있으니 참고하시기 바랍니다.

※ 작업 내용
→ DNS 작업 (작업 시간동안 임시 Parking 페이지로 출력될 예정입니다.)
→ 데이터 백업(Snapshot)
→ 소프트웨어 버전 업그레이드
→ EC2, RDS 인스턴스 재시작
→ DNS 원복

※ 작업 시간
→ 2021-05-17 월요일, 00:00 ~ 06:00(KST)

블로그의 품질 향상과 안정화를 위한 작업으로 작업 이후 Site Health 개선과 재부팅 작업으로 인한 캐시 메모리 확보로 사이트가 조금이나마 쾌적한 환경으로 운영될 것으로 보입니다.

감사합니다.

AWS

[AWS] Configuration of ManVSCloud Blog (with AWS WAF)

안녕하세요. ManVSCloud 김수현입니다.

최근 AWS Network Online Study 2기에서 AWS의 WAF에 대한 스터디가 진행되었습니다.
스터디 후 제 블로그에도 AWS WAF 기능을 도입하기로 결정하였습니다.

그리하여 오늘은 WAF 설정을 어떻게 했는지와 WAF 기능이 도입된 현재의 제 블로그가 어떻게 구성되어 있는지에 대해 포스팅 해보려합니다.


AWS WAF

사진 출처 : Anlab

우선 WAF란 Web Application Firewall, 웹 어플리케이션에 특화된 방화벽이라 볼 수 있습니다.
2019년 Anlab 자료에 따르면 웹/어플리케이션의 취약점을 이용한 공격이 상당히 많은 비중을 차지하고 있으며 다양한 방법의 공격이 존재합니다.

제 블로그도 AWS의 Security Group에서 80,443 포트는 0.0.0.0/0으로 OPEN 되어 있었기에
어떻게 웹 공격을 최소화 할 수 있을지 많은 고민을 하였습니다.

특히 해외 지역에서 공격성 접근이 많이 존재한다는 것을 알고 있어 해외쪽을 우선 차단하려 했습니다.
EC2 내에서 Apache의 Geoip를 이용하거나 iptables Geoip 등 다른 방법도 존재했지만
해당 인스턴스까지 접근하는 것자체가 조금 찝찝한 부분이 있어 WAF를 도입하기 전까지
제 블로그는 Route53의 지역 기반 라우팅을 이용하여 국내에서만 접근이 가능하도록 설정해둔 상태였었습니다.

현재는 WAF를 설정하였고 Route53의 지역 기반 라우팅을 이용하여 중국만 차단해두고 나머지 나라에서도 접근이 가능하도록 설정해둔 상태입니다.

제 블로그에서는 AWS WAF를 아래와 같이 설정하였습니다.

Associated AWS resouces : Application Load Balancer
Associated AWS resouces : ManVSCloud-Web-ALB-01 (Application Load Balancer)

Rule은 최대 100개까지 생성이 가능하고 Managed Rule Groups과 Own Rule and Rule Groups을 이용하여 추가가 가능합니다.
managed rule groups에는 다양한 보안 업체의 rule groups이 존재했는데 제 WAF에는 “AWS managed rule groups”을 적용했습니다.

AWS managed rule groups

AWS managed rule groups을 펼쳐보니… 아주 많이 있네요…
저는 Anonymous IP list, Core rule set, WordPress application 3개를 추가해둔 상태입니다.
(참고로 선택하실 때에 Capacity가 1500이 넘지 않도록 선택해주세요.)
(WCUs가 1500이 넘어야할 경우 Amazon에 문의하셔야합니다.)

  • Admin protection
    노출된 관리 페이지에 대한 외부 액세스를 차단할 수있는 규칙이 포함되어 있습니다.
    이는 타사 소프트웨어를 실행 중이거나 악의적인 행위자가 애플리케이션에 대한 관리 액세스 권한을 얻을 위험을 줄이려는 경우 유용 할 수 있습니다.
  • Amazon IP reputation list
    이 그룹에는 Amazon 위협 인텔리전스를 기반으로하는 규칙이 포함됩니다. 이는 봇 또는 기타 위협과 관련된 소스를 차단하려는 경우 유용합니다.
  • Anonymous IP list
    이 그룹에는 뷰어 ID의 난독화를 허용하는 서비스의 요청을 차단할 수있는 규칙이 포함되어 있습니다. 여기에는 VPN, 프록시, Tor 노드 및 호스팅 공급자에서 시작된 요청이 포함될 수 있습니다. 이는 애플리케이션에서 신원을 숨기려고 할 수있는 뷰어를 필터링하려는 경우에 유용합니다.
  • Core rule set
    일반적으로 웹 응용 프로그램에 적용되는 규칙을 포함합니다. 이를 통해 OWASP 출판물에 설명된 것과 같은 광범위한 취약성에 대한 공격으로부터 보호할 수 있습니다.
  • Known bad inputs
    잘못된 것으로 알려져 있고 취약성의 악용 또는 발견과 관련된 요청 패턴을 차단할 수있는 규칙을 포함합니다. 이를 통해 악의적 인 공격자가 취약한 애플리케이션을 발견할 위험을 줄일 수 있습니다.
  • Linux operating system
    LFI 공격을 포함하여 Linux에 특정한 취약성 악용과 관련된 요청 패턴을 차단하는 규칙을 포함합니다. 이렇게하면 파일 콘텐츠를 노출하거나 공격자가 액세스 할 수없는 코드를 실행하는 공격을 방지 할 수 있습니다.
  • PHP application
    안전하지 않은 PHP 함수 삽입을 포함하여 PHP 사용과 관련된 취약점 악용과 관련된 요청 패턴을 차단하는 규칙을 포함합니다. 이를 사용하면 공격자가 코드나 명령을 원격으로 실행할 수있는 악용을 방지 할 수 있습니다.
  • POSIX operating system
    LFI 공격을 포함하여 POSIX / POSIX-like OS에 특정한 취약성을 악용하는 것과 관련된 요청 패턴을 차단하는 규칙을 포함합니다. 이렇게하면 파일 콘텐츠를 노출하거나 액세스가 허용되지 않아야하는 코드를 실행하는 공격을 방지 할 수 있습니다.
  • SQL database
    SQL injection 공격과 같은 SQL 데이터베이스 악용과 관련된 요청 패턴을 차단할 수있는 규칙을 포함합니다. 이를 사용하면 권한 없는 쿼리의 원격 주입을 방지 할 수 있습니다.
  • Windows operating system
    Windows와 관련된 취약점 (예 : PowerShell 명령) 악용과 관련된 요청 패턴을 차단하는 규칙을 포함합니다. 이를 통해 공격자가 무단 명령을 실행하거나 악성 코드를 실행할 수있는 익스플로잇을 방지 할 수 있습니다.
  • WordPress application
    WordPress 애플리케이션 그룹에는 WordPress 사이트와 관련된 취약성 악용과 관련된 요청 패턴을 차단하는 규칙이 포함되어 있습니다.

우선 WAF를 적용하고 Anonymous IP list를 제외한 나머지 Action을 Count로 적용해두었습니다. Count 모드로 탐지하여 운영상 문제가 있을 부분이 잡히는지 확인 후에 Block되도록 변경 예정입니다.

그러고보니 Anonymous IP list에 BLOCK된 로그가 있었는데 사진이 어디론가 사라지고 말았습니다. 따로 추가적인 모니터링 구성을 해주지 않으면 샘플 로그가 3시간까지밖에 남지않아 아쉽네요… 그래도 AWS WAF는 참 마음에 드는 기능인 듯합니다. (비용이 괜찮거든요…)


ManVSCloud

자, 그럼 이제 ManVSCloud 블로그가 어떻게 만들어져있고 어떻게 구성되어 있는지 알아보겠습니다.

아시다시피 제 블로그는 Amazon Web Services (AWS)를 이용하여 만들어졌습니다.
Apache + PHP + MariaDB와 WordPress로 웹 서비스를 운영 중입니다.

OS : Amazon Linux 2 x86_64
Apache : 2.4.46
PHP : 7.3.23
MariaDB : 10.4.13
(DB는 RDS 이용중입니다.)

아래 그림을 참고하여 조금 더 자세히 알아보도록 하겠습니다.

ManVSCloud Blog Architecture
(우클릭 후 ‘새 탭에서 이미지 열기’를 이용하면 이미지를 크게 볼 수 있습니다.)

아키텍처를 직접 그려보는 일이 없어 잘 그린 게 맞나싶네요…
일단 WAF를 제외하고 프리 티어를 최대한 활용하려 노력했습니다.
(물론 가용성은 조금 떨어집니다… )

Route53에 manvscloud.com 도메인을 등록하여 GEO Restriction을 이용해 중국에서는 제 블로그로 접속을 할 수 없지만 중국을 제외한 나머지 지역에서는 A레코드 별칭으로 저의 Application Load Balancer로 향하게 됩니다.

ALB 상단에서 WAF가 등록된 Rule에 따라 ALLOW/BLOCK 합니다.
허용된 접속자만 저의 블로그로 접속할 수 있게됩니다.
(참고로 ALB 쪽에서 ACM을 추가하여 SSL 인증서가 적용되도록 해두었습니다.)

ALB-보안그룹

무조건 ALB를 통해서만 접속이 가능하며 EC2 인스턴스로 80/443 접속이 불가능합니다.
현재 제 EC2 인스턴스에는 IAM 역할 하나와 2개의 보안그룹이 연결되어 있습니다.

보안그룹은 접속용 Admin 보안그룹(ssh, ftp 등)과 web 서버용 보안그룹(http,https)으로
나누어두었습니다.

인스턴스의 80,443는 Application Load Balancer만 연결되어있어 ALB를 제외한 다른 곳에서는 직접적인 접근이 접근이 불가능합니다.

그리고 연결되어 있는 IAM은 아래와 같이 되어있습니다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "cloudwatch:PutMetricData",
                "ec2:DescribeTags",
                "cloudwatch:GetMetricStatistics",
                "cloudwatch:ListMetrics",
                "s3:*"
            ],
            "Resource": "*"
        }
    ]
}

CloudWatch가 EC2로 부터 Metric을 수집하여 대시보드로 추가적인 Report를 확인하였으며
경보를 추가하여 SNS에 등록된 구독자에게 E-mail로 알림을 보낼 수 있도록 설정 해둔 상태입니다.
제가 E-mail이 아닌 텔레그램을 이용하여 모바일로 알림을 받도록 설정하려 했는데 일정이 너무 빠듯하여 계속 미뤄지고 있네요…

S3도 추가해두었는데 이는 현재 진행중인 작업으로 mysqldump 와 특정 log 파일들을 S3로 백업하여 아카이브로 저장할 예정입니다.

마지막으로 블로그에 업로드되는 이미지들은 S3에 저장되고 해당 정적 이미지들은 Cloudfront를 이용하여 배포됩니다.

개발자 모드에서 확인해보시면 cdn.manvscloud.com 도메인으로 따로 이미지를 불러오고 있는 것을 알 수 있습니다.
ex) https://cdn.manvscloud.com/wp-content/uploads/2021/03/06075013/ncp-manvscloud-1024×562.png

최근 cloudfront에 Origin Shield를 적용하고 Hit가 상당히 많아졌습니다.
캐시를 이용하여 웹이 조금 더 빨라져 상당히 기분이 좋습니다.

현재 캐시 적중률 늘리기에 대해서도 포스팅 중인데 먼저 해결하려 했던
“Cloudfront + Lambda@Edge를 활용한 Image Resizing” 포스팅이 아직 잘 해결되지 않고 있어 늦춰지고 있습니다.

빠른 시일내에 포스팅 할 수 있도록 해보겠습니다.


Thanks to everyone

이번에 제 블로그 아키텍처를 그리며 참 많은 생각이 들었습니다.
AWS를 시작한지 1년이라는 시간이 지났습니다.

클라우드에 대해 궁금했고 AWS를 배워보고자 한 카카오톡 오픈채팅방에 들리게 되었습니다. 클라우드를 시작하기에 조금의 기반도 갖춰지지 않은 상태에서
“아마존 웹 서비스 AWS Discovery Book” 책을 하나 구매한 채 하나씩 따라해보았고
어느 날 “AWSKRUG – AWS 한국사용자모임 – 강남 비기너”에서 AWS 네트워크에 관련된 내용으로 스터디가 있어 참가하게 되었습니다.

당시 Master Seo님께서 많은 것을 알려주셨습니다.
많은 사람들 앞에서 그렇게 알려주시는 모습이 진짜 너무 멋있었습니다.
아마 그때부터 정말 열심히 해보자는 마음이 들게 되었던 것같습니다.

물론 당시 제 노트북의 OS가 한창 리눅스를 연습하고 싶어 리눅스를 설치해둔 상태라
ssh 접속하는 방법도 모르던 때다보니 제대로 따라가지 못한 것이 생각나네요.

이후 Master Seo님이 운영하시는 Brunch 블로그 URL을 외워가서 몇 번이고 다시 해보았었습니다. 정말 제가 클라우드를 시작할 때 많은 영향을 주신 분입니다.

그리고 또 한 번의 기회가 생깁니다.

제 스승님… 리눅서님이 우리 사당스터디를 모집하셨습니다.
이 스터디에서 참 많은 걸 배우게 됐습니다. 정말 많이요.
스터디원 모두에게 늘 감사하는 마음을 갖고있습니다.

여기서 첫 클라우드 자격증 SAA를 얻게되었으며 이후 참 많은 자격증을 따며 공부하였습니다. NCA, AZ-300, AZ-301, CLF, DBS…

블로그 아키텍처를 그려나가는데 문득 내가 언제 이런걸 할 수 있게 된거지?…라고 생각이 들며 조금 가슴이 뭉클해졌습니다.
1년이라는 시간동안 저를 어디까지 성장을 시켜주신 건지… 😦

그리고 제가 요즘 많이 배우고 있는 AWS Network Online Study!!
제 매주 일요일의 행복입니다.

특히 가시다님의 8주차 WAF 강의는 정말 재밌으면서도 많은 도움되었던 강의 중에 하나입니다! 덕분에 블로그에 WAF를 추가할 수 있게 되었습니다.
벌써 8주차가 끝나버렸습니다.
11주차가 끝나버리면 이젠 매주 일요일 뭐할지 걱정되네요.

이상으로 제가 성장할 수 있도록 가르침을 주신 모든 분들께 감사의 인사올립니다.

긴 글 읽어주셔서 감사합니다.