리눅스 서버 메모리 증설 포인트 확인 방법
# swap 영역 확인
total used free shared buff/cache available
Mem: 16122556 14116980 218736 360 1786840 1735812
Swap: 20971516 768256 20203260
# swap영역은 물리 메모리 사용영역이 부족할 경우를 대비해 만들어 놓은 영역, 메모리 부족할 경우
# disk I/O 작업을 진행하기 때문에 메모리 작업과 비교했을 때 처리속도가 느려진다. swap영역을 사용 할
# 경우 시스템 성능 저하가 일어난다.
# 만일 해당 시스템이 swap 영역을 사용한다는 것 자체가 시스템 메모리 부족한 이유로 사용한다는 의미이기
# 때문에 어떤 프로세스가 메모리를 사용하는지 확인해 볼 필요가 있다.
# 해결책 : 서비스 용도가 아닌 관리 용도의 프로세스에 메모리 누수가 있어 메모리를 점유하려 하고, 그 과정
# 에서 swap 영역을 사용하고 있을 수도 있기 때문에 구별해서 해당 프로세스를 죽여 메모리 부족현상
# 으로 인한 성능저하를 해결할 수 있다.
1. proc 파일 시스템 smaps 파일확인
# 예제) mongodb-server
$ ps -ef | grep mongod
root 2070 2038 36 3월09 ? 2-20:44:38 mongod -f /etc/mongod.conf
$ sudo su cd /proc/2070/ && cat smaps | more
3a8206932000-3a8246932000 ---p 00000000 00:00 0
Size: 1048576 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Rss: 0 kB
Pss: 0 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 0 kB
Anonymous: 0 kB
LazyFree: 0 kB
AnonHugePages: 0 kB
ShmemPmdMapped: 0 kB
Shared_Hugetlb: 0 kB
Private_Hugetlb: 0 kB
Swap: 0 kB
SwapPss: 0 kB
Locked: 0 kB
ProtectionKey: 0
VmFlags: mr mw me sd
55921703e000-55921a801000 r-xp 00000000 103:04 620757098 /usr/bin/mongod
Size: 57100 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Rss: 10992 kB
# 위 mongodb 프로세스는 Swap 영역을 사용하고 있는 것이 없다.
# 해당 프로세스의 논리적 메모리 "3a8206932000-3a8246932000" 사이에 있는 메모리 크기는 "1048576 kB" 이며,
# swap 영역에는 없다.
# 예제) mongodb-server docker 프로세스 확인
$ ps -ef | grep docker
root 2038 22020 0 3월09 ? 00:00:17 containerd-shim -namespace ...
$ cd /proc/22020/ && cat smaps | more
c000000000-c000200000 rw-p 00000000 00:00 0
Size: 2048 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Rss: 1168 kB
Pss: 1168 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 1168 kB
Referenced: 1160 kB
Anonymous: 1168 kB
LazyFree: 0 kB
AnonHugePages: 0 kB
ShmemPmdMapped: 0 kB
Shared_Hugetlb: 0 kB
Private_Hugetlb: 0 kB
Swap: 592 kB
SwapPss: 592 kB
Locked: 0 kB
ProtectionKey: 0
VmFlags: rd wr mr mw me ac sd
c000200000-c000a00000 rw-p 00000000 00:00 0
Size: 8192 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Rss: 3052 kB
Pss: 3052 kB
# 하지만 mongodb를 운영중인 docker 데몬을 보면 "592kB"가 swap 영역에 있다.
2. 전체 프로세스 swap 메모리 확인방법
# smem 유틸리티 설치
$ sudo amazon-linux-extras install epel
$ sudo yum -y install smem
# smem 조회
$ sudo smem -t
PID User Command Swap USS PSS RSS
7955 root tail -f mongod.log.1 -n 200 92 4 17 196
7954 root sudo tail -f mongod.log.1 - 1140 4 21 252
4262 root /usr/sbin/acpid 44 96 100 192
1833 root /usr/sbin/lvmetad -f 208 104 110 236
3945 root /sbin/agetty --keep-baud 11 36 108 119 232
3944 root /sbin/agetty --noclear tty1 36 112 123 236
2955 libstoragemgmt /usr/bin/lsmd -d 64 116 124 252
22338 rngd /sbin/rngd -f --fill-waterm 848 120 130 284
3045 root /usr/sbin/gssproxy -D 400 128 135 264
3833 root /usr/sbin/atd -f 112 128 137 288
2855 rpc /sbin/rpcbind -w 404 160 172 344
3641 root /usr/libexec/postfix/master 960 180 195 396
3644 postfix qmgr -l -t unix -u 968 156 203 580
2860 root /usr/sbin/irqbalance --fore 172 208 234 532
2713 root /sbin/auditd 288 264 288 524
32321 root /usr/sbin/crond -n 508 196 300 1076
3425 root /sbin/dhclient -6 -nw -lf / 1852 184 331 752
2939 chrony /usr/sbin/chronyd 404 328 365 684
12978 root /usr/sbin/sshd -D 932 112 411 1376
3297 root /sbin/dhclient -q -lf /var/ 1816 356 521 1008
2248 root /usr/lib/systemd/systemd-ud 476 744 794 1152
2867 dbus /usr/bin/dbus-daemon --syst 408 760 840 1272
2786 root /usr/lib/systemd/systemd-lo 180 836 910 1324
9885 ec2-user sshd: ec2-user@pts/0 68 232 1636 4436
21882 root /usr/sbin/rsyslogd -n 74764 936 2382 4632
2038 root containerd-shim -namespace 568 2416 2416 2420
1 root /usr/lib/systemd/systemd -- 352 2460 2568 3068
9886 ec2-user -bash 0 2272 2670 4276
4587 postfix pickup -l -t unix -u 0 2296 3311 6436
15765 root sudo smem -t 0 1808 3443 7456
9868 root sshd: ec2-user [priv 4 944 3532 8600
15664 root /usr/bin/amazon-ssm-agent 5940 4564 4568 4636
22020 root /usr/bin/containerd 14176 9664 9669 9776
15766 root python /bin/smem -t 0 9668 10175 12008
14351 root /usr/lib/systemd/systemd-jo 120 6752 10256 14972
15733 root /usr/bin/ssm-agent-worker 9736 13768 13772 13852
17226 root /usr/bin/dockerd -H fd:// - 28068 14132 14143 14296
23936 root /usr/local/bin/mongodb_expo 1108 15692 15692 15696
29352 root /opt/aws/amazon-cloudwatch- 3552 32376 32376 32380
2070 root mongod -f /etc/mongod.conf 588308 13799384 13799384 13799388
-------------------------------------------------------------------------------
40 8 739112 13924768 13938573 13971780
# 마지막 줄이 전체 합계이며, "739112kB"가 swap에 사용된 것을 확인할 수가 있다.
# 제일 많이 사용중인 프로세스는 mongodb 메모리 사용량이 많을 것을 확인할 수 있다.
3. 버디시스템
# 커널은 버디 시스템을 통해서 메모리를 할당, 버디 시스템은 물리 메모리를 연속된 메모리 영역으로 관리한다.
# 버디시스템 구조
1개 4KB -> 4KB -> 4KB -> ...
2개 4KB+4KB -> 4KB+4KB -> 4KB+4KB -> ...
4개 4KB+4KB+4KB+4KB -> 4KB+4KB+4KB+4KB -> 4KB+4KB+4KB+4KB -> ...
# 버디시스템 현재상황 확인하기
$ sudo cat /proc/buddyinfo
Node 0, zone DMA 1 0 0 1 2 1 1 0 1 1 3
Node 0, zone DMA32 14777 3878 1162 164 138 112 43 8 2 0 0
Node 0, zone Normal 76 8213 721 575 244 37 4 1 0 0 0
# 각각의 행은 2의 배수로 1, 2, 4개의 영역을 의미한다.
# 커널은 프로세스가 사용하는 메모리 중 Inactive 리스트에 있는 메모리를 골라서 swap영역으로 이동시킨다.
# 그 다음 해당 메모리 영역을 해제하고 다른 프로세스에 할당한다.
# 커널은 기본적으로 유휴 메모리가 있을 경우 캐시로 활용하려 하고, 메모리 사용 요청이 증가하면 캐시로
# 활용하고 있는 메모리를 재할당해서 프로세스에 할당하는 기본적인 동작 원리임.
4. vm.swappiness, vm.vfs_cache_pressure
# vm.swappiness : 커널이 얼마나 공격적으로 메모리 영역을 swap 영역으로 옮기는 것을 결정하는 파라미터
# 기본값 : 60
# vm.vfs_cache_pressure : 캐시를 재할당 한다고 했을 때 페이지캐시를 더많이 재할당할지, inode 캐시를 재할당할지 결정한다.
# 기본값 : 100
# 참고) dentry : 디렉터리 캐시 / inode : inode 캐시
4.1 vm.swappiness 설정값 확인
$ sudo sysctl -a | grep -i vm.swappiness
vm.swappiness = 60
# vm.swappiness 값이 작으면 : 캐시 메모리를 재할당
# vm.swappiness 값이 높으면 : 메모리 swap영역 사용
4.2 vm.vfs_cache_pressure 설정값 확인
$ sudo sysctl -a | grep -i vm.vfs_cache_pressure
vm.vfs_cache_pressure = 100
# vm.vfs_cache_pressure 값이 0이면 dentry와 inode 캐시를 반환하지 않아 시스템의 메모리 부족
# 현상을 일으킬 수 있기 때문에 0으로 설정하면 안된다.
# vm.vfs_cache_pressure 값의 변화에 따라 dentry, inode 캐시의 양이 변동되기 때문이므로 해당 값이
# 100 이상이 되면 미사용 중이 아닌 캐시들도 반환하기 때문에 성능저하가 발생할 수 있으므로, 해당 워크로드에
# 맞게 테스트 후 설정을 적용해야 한다.
5. 메모리 증설 포인트
# swap 영역의 사용은 현재 워크로드에 메모리가 부족하다는 것으로 알 수 있음.
5.1 운영 시스템이 swap을 사용한다면 대처방법
# 1. 메모리의 사용량이 선형적으로 증가하는 경우
# 이런 case는 보통 메모리 누수를 의심, 애플리케이션이 요청을 처리하고 요청처리가 끝나면 메모리를 해제
# 해야하는데, 제대로 해제되지 않으면 사용하는 메모리가 계속 늘어난다.
# 2. 순간적으로 메모리 사용량이 폭증하는 경우
# 평상시 메모리 사용은 일정하지만 순간적으로 요청이 증가하면 메모리 사용량이 폭증해서 swap을 사용하게 된다.
# 안정적인 서비스를 위해 사용한 메모리의 최대치를 계산해서 메모리를 증설
# 만약 서비스에 크게 영향을 끼치는 정도가 아니라면 swap을 사용
5.1.1 pmap 프로세스 메모리 영역별 크기 확인방법
# 예제) mongodb 서버 예제
# mongodb proc 확인 및 영역 확인
$ sudo pmap 2070
2070: mongod -f /etc/mongod.conf
00003a8206932000 1048576K ----- [ anon ]
000055921703e000 57100K r-x-- mongod
000055921a802000 924K r---- mongod
000055921a8e9000 944K rw--- mongod
000055921a9d5000 3060K rw--- [ anon ]
000055921aeae000 14974352K rw--- [ anon ]
...
5.1.2 gdb 메모리 덤프 생성방법
# gdb 설치
$ sudo yum -y install gdb
# 메모리 덤프 할 논리주소 확인
$ sudo cat /proc/2070/smaps
7ffb558c9000-7ffb55b64000 r-xp 00000000 103:04 2067792041 /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1
Size: 2668 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Rss: 100 kB
Pss: 100 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 100 kB
Private_Dirty: 0 kB
Referenced: 80 kB
Anonymous: 0 kB
LazyFree: 0 kB
AnonHugePages: 0 kB
ShmemPmdMapped: 0 kB
Shared_Hugetlb: 0 kB
Private_Hugetlb: 0 kB
Swap: 0 kB
SwapPss: 0 kB
Locked: 0 kB
ProtectionKey: 0
VmFlags: rd ex mr mw me sd
# 메모리 덤프 생성
$ sudo gdb -p 2070
...
(gdb) dump memory /home/ec2-user/memory_dump 0x7ffb558c9000 0x7ffb55b64000
# smaps로 확인한 주소 앞에 "0x"를 붙혀 메모리 논리주소를 작성해서 생성한다.
# 메모리 덤프 읽기
$ sudo strings /home/ec2-user/memory_dump
ETLL
%%Hm
CJAAQ
eeX=
==Ns
3--Jg
6yy_&
aaY8GG
G^]]V
11M|
uu\)
rUUT
9MMR
99Ov
...
...