글 • 문태준 taejun@tunelinux.pe.kr

tunelinux.pe.kr/database.sarang.net 운영자



연재 순서

1. 시스템 모니터링 I

2. 시스템 모니터링 II

3. 운영체제와 커널 차원에서의 튜닝과 보안

4. 응용프로그램에서의 최적화

5. 시스템 모니터링 자동화




시스템의 성능은 여러 가지 프로그램의 요청에 대해 현재의 시스템 자원을 얼마나 효율적으로 조정하여 사용하는가에 달려있다. 일반적으로 가장 중요한 시스템 자원은 CPU, 메모리, 디스크 입출력이며 인터넷 서비스가 일반화된 상황에서 네트워크에 대한 부분도 중요하게 다뤄져야 한다. 시스템을 안정적으로 관리하기 위해서는 지속적인 시스템 관리를 통해 문제 발생시 적절히 대처할 수 있는 기술이 필요하다. 이와 관련된 내용은 일반적인 시스템 관리 서적 및 여러 가지 자료를 통해 많이 언급되었기 때문에 여기서는 시스템 모니터링 결과를 정확히 판단하는 방법과 시스템의 문제에 대한 효과적인 대처 방법을 중심으로 알아보겠다.



1. 시스템 모니터링 분야와 관련 프로그램

문제를 점검할 모니터링 분야에 대한 시스템 모니터링 프로그램을 먼저 알아보자. 여기 있는 프로그램들은 대부분 운영체제를 설치하면서 자동으로 설치가 되는 프로그램들이다. (sar, iostat, nmap, netcat, ntop 등은 별도로 설치를 해야 하는 모니터링 프로그램이다)



분야
모니터링 프로그램

CPU
top, ps, uptime, vmstat, pstree, iostat, sar

메모리
free, vmstat, sar

디스크 I/O
df, du, quota, iostat, sar

네트워크
ping, netstat, traceroute, tcpdump, nmap, netcat, ntop

파일(소켓포함)
Lsof


표 1 . 시스템 분야별 모니터링 프로그램

시스템이 정상적으로 작동하고 있을 때 정기적으로 모니터링을 해 두어야 시스템에 문제가 생겼을 경우 신속하게 분석하여 문제를 해결할 수 있다. 즉, 주기적인 점검이 계속되어야 한다는 것이다. 보통 이런 작업등은 반복적이고 지루한 과정이므로 자동화하기 위한 노력이 필요하며 관리자가 직접 스크립트를 작성할 수도 있고 SNMP(Simple Network Management Protocol, 간이 망 관리 프로토콜) 등의 프로그램을 응용하여 자동화할 수도 있다. 모니터링 자동화에 대해서는 이후 강의에서 다룰 예정이다.



2. 시스템 모니터링과 문제 찾기

2.1 시스템의 부하 확인

시스템에 문제가 생겼을 경우 가장 먼저 어떤 프로그램을 실행하고 어떻게 사용하고 있었는지 점검해야 한다. 그리고 uptime을 이용하여 시스템의 부하를 확인한다. 일반적으로 웹서비스의 경우에는 낮 시간대에 접속이 폭주하므로 점심시간 무렵에 시스템의 부하가 올라갈 것이다. 그런데 접속이 폭주할 시간이 아닌대도 시스템의 부하가 높아지고 있다면 특정한 프로그램에서 문제가 발생하여 시스템의 자원을 소비하고 있을 가능성이 크고 서비스 거부 공격을 받고 있을 수도 있다. 시스템 부하가 어떻게 변동하고 있는지 확인을 했다면 ps와 top을 이용하여 구체적으로 프로세스의 상태를 점검한다.



2.2 ps와 top를 이용한 프로세스 모니터링

ps와 top을 살펴보면서 주의할 점과 중요하게 살펴볼 내용에 대해서 설명하겠다. top에서 CPU 상태는 사용자 모드, 시스템 모드, 우선 순위가 조정된 작업(niced task) 과 cpu 휴지시간(idle) 을 모두 포함한다. 그런데 여기서 우선 순위가 조정된 작업은 시스템과 사용자 시간에서 이미 계산이 되어 있으므로 100퍼센트가 넘을 수 있다.

ps와 top을 이용하여 모니터링을 할 경우 먼저 살펴보아야 하는 것이 디스크 액세스나 페이징을 기다리고 있는 프로세스가 있는가이다. 이런 경우에는 I/O와 메모리를 같이 점검해야 한다. 리눅스에서 프로세스 대기 상태는 인터럽트 허용과 인터럽트 금지의 두 가지 형태가 있다. 세마포어를 기다리거나 파일을 읽을 수 있게 되길 기다리는 것처럼 자원을 기다리는 일반적인 대기상태는 대개 인터럽트로 처리가 가능하다(인터럽트가 허용되는 sleep 상태는 ps, top 등에서 S로 나타난다). 그렇지만 인터럽트가 금지되는 대기 상태는 스왑 파일에서 메모리로 페이지를 읽어들이는 것과 같이 일이 끝마치기를 기다리고 있는 상태이다.

프로세스 상태에서 D는 인터럽트가 불가능한 sleep 상태로 page fault 등을 의미하며 page fault 등을 통해 I/O중인 상태를 나타낸다. W는 상주하는 페이지가 없다는 것을 의미하며 프로세스가 스왑아웃된 상태를 나타낸다. 여기서 W는 커널 프로세스에 대해서는 정확히 동작을 하지 않는다는 의미이다. 일반적인 응용프로그램을 실행하면 주기억장치에 상주한 후 프로세스가 처리되고 상대적인 주소를 가지게 된다. 그런데 커널은 다른 응용프로그램처럼 상대적 어드레스를 가지는 것이 아니라 시스템이 부팅된 후 가장 먼저 주기억 상치에 상주하기 때문에 언제나 같은 주기억 장치의 번지에 상주하게 된다. 그러므로 커널 프로세스에서 스왑을 하는 일도 없고 당연히 해서도 안되는 것이다.

ps와 top에서 메모리와 관련된 부분중 차이가 나는 것이 있다. 프로세스의 메모리 구조는 텍스트, 데이터, 스택 등으로 이루어져 있다. 텍스트에는 프로그램 코드와 상수가 정의되어 있으며 읽기만 가능한 메모리 영역이다. 데이터는 정적 변수가 저장되어 있는 영역이고 스택은 동적으로 할당되는 데이터, 함수 내의 변수, 함수의 리턴 어드레스 등이 저장되는 영역이다.

ps에서 보는 프로세스 정보는 ‘/proc/PID/’의 정보를 보여주는 것이다. ‘/proc/PID/status’의 내용을 확인해 보자. ps의 VSZ는 가상 메모리에서 사용중인 모든 메모리를 합친 VmSize를 보여준다. 그러나 top에서 SIZE는 코드, 데이터, 스택을 합친 크기를 보여준다. 가상 메모리는 커널에서 자동으로 조절하기 때문에 문제가 생길 일은 없으며 RSS를 통해서 실제 물리적 메모리에서 사용하는 메모리 양을 알 수 있다. 그리고 SIZE와 RSS 필드에는 페이지 테이블과 프로세스의 task_struct는 포함되어 있지 않은데 최소 12KB의 메모리를 항상 사용한다.



# cat /proc/413/status

Name: named

State: S (sleeping)

Pid: 413

PPid: 1

TracerPid: 0

Uid: 25 25 25 25

Gid: 25 25 25 25

FDSize: 32

Groups: 25

VmSize: 2596 kB

VmLck: 0 kB

VmRSS: 852 kB

VmData: 756 kB

VmStk: 28 kB

VmExe: 560 kB

VmLib: 1196 kB

SigPnd: 0000000000000000

SigBlk: 0000000000000000

SigIgn: 8000000000000000

SigCgt: 0000000009015a0b

CapInh: 0000000000000000

CapPrm: 0000000000000000

CapEff: 0000000000000000


리스트 1 . /proc 에서 프로세스 정보 확인하기

2.3 vmstat를 이용한 메모리와 디스크 I/O 확인



# vmstat 5 5

procs memory swap io system cpu

r b w swpd free buff cache si so bi bo in cs us sy id

7 0 0 96940 1588 14712 337044 0 9 18 27 116 40 3 0 96

4 0 0 96940 1648 14700 336172 0 0 805 118 197 260 91 9 0

1 1 0 96940 1588 14700 335680 0 0 1000 106 203 268 93 7 0

3 1 0 96940 1708 14496 334652 0 0 1273 604 220 272 94 6 0


리스트 2. vmstat 이용한 cpu, i/o 모니터링



vmstat를 이용하여 CPU와 I/O 활동을 모니터링할 수 있는데 vmstat에서 나오는 첫 줄은 부팅 이후의 각 통계치에 대한 평균값을 보여주므로 무시하고 두 번째 줄부터 통계를 보면 된다. vmstat에서 중요한 것은 procs 영역의 b 필드이다. r은 현재 실행중인 프로세스 수이고 b는 인터럽트가 불가능한 sleep 상태에 있는 프로세스로 I/O 처리를 하는 동안 블럭 처리된 프로세스이며 w는 강제로 스왑아웃된 프로세스 수이다. si와 so는 스왑인, 스왑아웃을 말한다.

스왑아웃이 지속적으로 발생한다면 메모리가 부족한 것이다. 그러나 일정 간격을 두고 주기적으로 스왑아웃이 발생하는 것은 정상적인 일이다. BSD 시스템에서는 비상호 대화적인 작업을 스왑아웃 한다. 현재 실행하고 있는 프로그램에서 스왑아웃이 계속 발생한다면 프로그램이 멈출 수도 있으며 심각하게 메모리가 부족하다는 것을 의미한다. 스왑아웃필드(so)는 항상 0에 가까워야 한다. 그렇지 않다면 프로세스들은 가상 메모리를 놓고 경쟁하게 되며 시스템은 페이징 상태가 된다. 페이징 활동은 심각한 가용 메모리(free)의 부족과 직접적인 관련을 가지며 간접적으로는 시스템의 높은 CPU 사용 시간 비율(sy)과 관련이 있다. 프로세스가 시작할 때 항상 이미지와 데이터를 page-in 해야 하므로 page-in 열에서 높은 숫자가 항상 심각한 것은 아니라는 사실은 기억하고 있어야 한다.

시스템에서 사용하는 시간이 지나치고 높으면(50퍼센트 이상) 디스크 I/O에서 문제가 있을 가능성이 크다. 시스템 전체의 부하가 높은데 CPU에서 휴지시간(idle time, id 항목)이 일반적으로 10퍼센트를 넘는다면 I/O나 메모리에 문제가 있을 가능성이 크다. 휴지시간(id)이 항상 0이라면 CPU를 100퍼센트 사용하고 있는 상태이다. CPU의 기능을 최대한 활용하는 것은 좋은 현상이다. 그런데 항상 100퍼센트로 활용중인 상태라면 어떤 작업이 계속 축적되고 있다는 것이며 CPU가 과부하를 가진다는 의미한다. 이 때는 CPU를 계속 사용하고 있는 프로세스를 찾아야 하며 디스크의 활동이 분산되지 않았다면 I/O 작업을 효율적으로 분산시켜야 한다.

대부분의 사용자가 vmstat에서 si, so(스왑인, 스왑 아웃)를 주로 보고 id가 넉넉하면 시스템에 무리가 없는 것으로 생각한다. 이는 시스템의 상황에 대해서 잘못 파악할 가능성이 많은 것으로 b의 수치가 높은 경우 I/O작업을 위해 CPU가 계속 대기 상태로 있는 경우이다. 이런 경우에는 디스크 I/O 문제를 확인해야 한다.



2.4 nice를 이용한 우선 순위 조정

nice는 프로세스의 우선 순위를 조정하는 것이다. 그런데 시스템에 문제가 있는 경우 nice를 이용하는 것은 임시방편일 뿐이다. 부하가 계속 증가한다면 nice를 이용하는 것에도 한계가 있다. 시스템을 업그레이드하거나 부하를 분산할 시스템을 구입해야 한다.

커널이나 프로그램의 컴파일을 하는 경우에도 nice를 이용하면 조금이나마 속도의 향상이 있다. 그렇지만 때로는 nice를 잘못 사용하여 문제가 생길 수 있으니 조심해야 한다. 예를 들어 오라클에서는 오라클 사용자 프로세스와 백그라운드 프로세스들을 같은 우선 순위에 유지해야 한다. 오라클 DB의 설계가 그러한 우선 순위로 되어 있기 때문이다. 우선 순위를 변경할 경우 내용과 반응 시간에 원하지 않는 효과를 초래할 수도 있다. 예를 들어 로그 작성 프로세스(LGWR, log write process)에 낮은 우선 순위를 부여할 경우, 이 프로세스는 충분한 횟수만큼 작동하지 못하고 LGWR은 병목현상을 일으키게 된다. 반대로 LGWR이 높은 우선 순위를 부여받게 되면, 사용자 프로세스는 느린 반응시간에 시달리게 될 것이다. 세부적인 원리를 이해하지 못한채 이런 기능을 사용하면 시스템에 커다른 문제가 생길 수 있다는 것을 꼭 기억하기 바란다.



2.5 free를 이용한 자유 메모리 확인과 버퍼 캐쉬

메모리를 점검하기 위해 흔히 free를 사용한다. 그런데 free의 결과를 잘못 이해하면 전혀 이상한 결과를 초래할 수 있다.



$ free

total used free shared buffers cached

Mem: 513368 508316 5052 0 12688 339436

-/+ buffers/cache: 156192 357176

Swap: 1028152 96940 931212


리스트 3. free 이용하여 메모리 확인하기



먼저 버퍼 캐쉬에 대하여 알아보자(kldp.org/Translations/html/SysAdminGuide-KLDP/buffer-cache.html 참조) 디스크를 읽는 일은 메모리를 읽는 것보다 아주 느리다. 더구나 디스크의 동일한 영역을 짧은 시간 동안 반복해서 계속 읽는 일은 아주 빈번하다. 예를 들어, 누군가 e메일 메시지를 읽고, 답장을 하기 위해 편집기로 불러들이고, 그걸 보내기 위해 메일 프로그램에게 다시 읽게 하는 과정을 생각해 보자. 또한 ‘ls’와 같은 명령어를 시스템의 모든 사용자들이 얼마나 자주 사용할지 생각해 보자. 따라서 디스크로부터 한번 읽어들인 정보를 메모리에 상당시간 보관한다면 읽을 때만 시간이 소요될 뿐 속도가 전반적으로 빨라질 것이다. 바로 이런 것을 가리켜 디스크 버퍼링(disk buffering)이라고 하며, 이런 목적으로 쓰이는 메모리를 버퍼 캐쉬(buffer cache)라고 부른다.

그러나 메모리는 아쉽게도 한정되어 있는 중요한 자원이기 때문에 버퍼 캐쉬는 일반적으로 큰 크기를 가질 수 없다. 즉, 우리에게 필요한 모든 데이터를 담아둘 수 있을 정도로 크지는 않다. 따라서 캐쉬가 가득 채워지면 오랫동안 쓰이지 않은 데이터는 버려지며 그 빈 공간을 새로운 데이터가 채우게 된다.

이런 디스크 버퍼링은 쓰기에도 똑같이 적용된다. 데이터들은 쓰여지자 마자 곧바로 다시 읽혀지므로(예를 들어, 소스 코드 파일은 일단 파일로 저장된 후, 컴파일러에 의해 다시 읽혀진다), 이런 데이터들을 캐쉬에 넣어두는 것이 효율적이다. 또한 쓰기 작업을 디스크에 직접 하지 않고 캐쉬에 넣어두면, 프로그램들이 그만큼 출력을 빨리 끝낼 수 있기 때문에 전반적인 시스템 성능 향상에도 도움이 된다.

대부분의 운영체제들이 버퍼 캐쉬를 갖고 있기는 하지만 모두 위와 같은 원리로 동작하는 것은 아니다. 한가지 방법은 ‘write-through’라는 것인데, 이 방법은 쓰기를 할 때면 언제나 디스크에도 즉시 기록하는 것이다(물론 캐쉬에도 남겨둔다). 또 다른 방법은 write-back이라 불리는 것으로 일단 캐쉬에 기록해 두었다가 나중에 한꺼번에 디스크에 기록하는 방식이다. 효율적이기는 write-back 방식이 뛰어나지만, 대신 약간의 에러가 발생할 소지가 있다. 즉, 시스템이 갑자기 멈춰버린다거나, 갑자기 전원이 꺼진다거나 캐쉬 내용을 미처 기록해 두기 전에 플로피 디스크를 빼 버린다면, 캐쉬에 담겨 있던 내용들은 고스란히 없어져 버리고 만다. 특히 손실된 정보가 파일 시스템 유지에 필요한 데이터였다면, 자칫 전체 파일 시스템을 망가뜨리고 마는 결과를 초래할 수도 있다.

그런데 사실상 캐쉬는 파일을 버퍼링하는 것은 아니고, 실제로는 디스크 입출력의 가장 작은 단위인 블럭을 버퍼링한다(리눅스에서는 보통 1KB 크기이다). 그러므로 디렉토리라든가, 수퍼 블럭들, 다른 파일 시스템의 유지 데이터, 심지어 파일 시스템이 없는 디스크까지도 캐쉬될 수 있는 것이다.

캐쉬의 효율성은 기본적으로 그 크기에 좌우된다. 캐쉬의 크기가 너무 작으면 다른 데이터를 캐쉬하기 위해서 캐쉬된 데이터를 계속 내보내야 하므로, 사실상 작은 캐쉬는 별 쓸모가 없는 셈이다. 캐쉬의 최소 크기는 얼마나 많은 데이터가 읽고 씌여지는 지와, 같은 데이터가 얼마나 자주 액세스 되는지에 달려있는데 이것을 알아보기 위한 유일한 방법은 실험해 보는 것 뿐이다.

만일 캐쉬의 크기가 고정되어 있다면, 그 크기가 너무 큰 것도 곤란한 일이다. 캐쉬가 너무 크면 여유 메모리는 그만큼 줄어들 것이고, 많은 스와핑을 일으켜서 시스템은 느려지게 된다. 리눅스는 자동적으로 모든 램의 빈공간을 버퍼 캐쉬로 사용하여 메모리의 효율성을 높이려 하는데, 프로그램들이 많은 메모리를 필요로 할 때는 자동적으로 캐쉬를 크기를 줄여 준다. 그래서 완전 자동화된 리눅스는 캐쉬를 사용하는 데 있어서 전혀 신경쓸 필요가 없는 OS인 것이다. 다만 셧다운 할 때와 플로피를 빼낼 때의 절차는 꼭 지켜야 한다.

위와 같이 디스크 접근을 줄여 시스템의 성능을 향상시킬 목적으로 있는 것이 버퍼 캐쉬이다. 만일 캐쉬의 크기가 고정되어 있다면 그 크기가 너무 커도 메모리 부족 현상이 생길 수 있고 지나친 스와핑을 발생하게 해서 시스템이 느려질 가능성이 크다. 리눅스에서는 자동적으로 모든 램의 빈 공간을 버퍼 캐쉬로 사용하여 메모리를 효율성을 높이고 있으며 프로그램에서 많은 메모리를 필요로 하는 경우에는 자동으로 캐쉬의 크기를 줄인다. 위에서 실제로 사용 가능한 메모리는 ‘free+buffers+cached’이다. 다음 내용을 보면 현재 메모리를 알아볼 수 있는 원리를 잘 반영하고 있다.



-/+ buffers/cache: 156192 357176



자 그러면 이제 올바른 답을 내릴 수 있을 것이다. 현재 여유가 있는 메모리는 ‘free+buffers+cached’를 합친 양으로 위의 소스에서는 357M이다. 그리고 전체 열에 나오는 수치도 실제 물리적인 램 양보다는 약간 적은 양이 표시된다. 왜냐하면 커널이 자체적으로 사용하고 있는 메모리를 뺀 양이기 때문이다.



2.6 iostat와 sar 활용한 디스크 I/O 및 시스템 모니터링

vmstat 명령을 통해 I/O부하를 확인할 수 있다는 것을 알았다. 그런데 여러 개의 하드 디스크를 사용하는 경우 vmstat를 이용해서는 어느 디스크에서 속도가 느리거나 병목 현상이 생기는지 확인을 할 수 없다. 다만 디스크 전체의 평균값만 나타내기 때문이다. 이런 경우에 사용할 수 있는 프로그램이 iostat이다. iostat 프로그램은 레드햇 6.2에는 기본으로 들어있지 않지만 레드햇 7.0 이후 버전에는 기본으로 들어있다(배포본은 6.2이지만 커널은 2.4대에 보안 및 reiserfs, lvm패치 등을 사용하고 있다). iostat는 sysstat라는 패키지에 들어있으며 현재 설치되지 않은 경우에는 다음 사이트에서 다운로드 받을 수 있다.

http://perso.wanadoo.fr/sebastien.godard/

http://freshmeat.net/에서 검색을 해도 된다.



# lynx ftp://metalab.unc.edu/pub/Linux/system/status/sysstat-4.0.1-1.i386.rpm

# rpm -Uvh sysstat-4.0.1-1.i386.rpm

sysstat ##################################################



# rpm -ql sysstat

/usr/bin/iostat

/usr/bin/isag

/usr/bin/mpstat

/usr/bin/sar

/usr/lib/sa/sa1

/usr/lib/sa/sa2

/usr/lib/sa/sadc

/usr/man/man1/iostat.1

/usr/man/man1/isag.1

/usr/man/man1/mpstat.1

/usr/man/man1/sar.1

/usr/man/man8/sa1.8

/usr/man/man8/sa2.8

/usr/man/man8/sadc.8

/usr/share/locale/de/LC_MESSAGES/sysstat.mo

/usr/share/locale/es/LC_MESSAGES/sysstat.mo

/usr/share/locale/fr/LC_MESSAGES/sysstat.mo

/usr/share/locale/pt/LC_MESSAGES/sysstat.mo

/var/log/sa


리스트 4. sysstat 프로그램 설치



iostat만이 아니라 isag, mpstat, sar, sa1, sa2, sadc 등의 프로그램이 같이 들어있다. 여기서 iostat와 sar는 다른 유닉스에서도 시스템 모니터링을 위해서 자주 사용하고 있는 프로그램이다. 여기서도 iostat와 sar을 같이 살펴보겠다.



# iostat

Linux 2.4.4 (tunelinux.pe.kr) 07/17/01



avg-cpu: %user %nice %sys %idle

0.30 0.00 27.30 72.40



Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn

dev8-0 252.20 4.80 60099.20 24 300496

dev8-1 0.00 0.00 0.00 0 0

dev8-2 379.80 48880.00 9.60 244400 48

dev8-3 0.00 0.00 0.00 0 0


리스트 5. iostat 이용하여 디스크 I/O 모니터링하기



위에서 보듯이 iostat는 CPU와 디스크 I/O에 대한 통계를 보여준다. CPU가 여러 개 있는 SMP 시스템에서 CPU 통계는 모든 프로세스를 합한 평균값을 나타낸다. 사용자 모드(응용 프로그램), nice 우선권을 가진 사용자 모드, 시스템 모드(커널), CPU idle 시간으로 통계를 보여준다. CPU 관련 통계는 다른 프로그램을 이용해도 확인을 할 수 있으므로 여기에서 관심이 가는 것은 디스크 드라이브에 대한 통계이다. 여기에서는 현재 네 개의 디바이스가 있다. 출력한 결과가 나타내는 의미는 다음가 같다.



Tps
해당 디바이스에 대한 초당 전송 숫자인데, 여기서는 디바이스에 대한 I/O 요청을 말한다

Blk_read/s
해당 디바이스에서 초당 읽은 블럭 수

Blk_wrtn/s
해당 디바이스에서 초당 기록한 블럭 수

Blk_read
전체 읽은 총 블럭 수

Blk_wrtn
전체 기록한 총 블럭 수


표 2. iostat 의 모니터링 대상



이외에도 초당 읽은 섹터 수, 디바이스에 요청한 평균 크기(섹터 단위) 디바이스에 요청한 평균 큐의 크기, 해당 디바이스 I/O요청을 했을 때의 CPU 시간 등도 모니터링이 가능하다. 그런데 이 기능을 위해서는 커널 패치가 필요한데 아직까지 2.4 버전은 보이지 않는 것 같다. 리눅스에서는 아직까지 디스크 어카운팅 기능이 부족해서 각 블럭 디바이스에 대한 KB/s는 기본적으로 사용하지 못하고 있다고 프로그램 제작자는 지적하고 있다. 그래서 위에서 확장된 다른 기능을 보기 위해서는 커널 패치를 해야 한다는 것이다. ‘/proc/stat’와 ‘/proc/partitions’가 iostat 패키지와 연관된 파일이다. 솔라리스에도 iostat 프로그램이 있는데 여기에서는 ‘-xn’이라는 옵션을 이용하여 큐에서 기다린 시간, 디스크의 바쁜 정도, 평균 서비스 시간 등을 확인할 수 있다. 큐에서 서비스를 받기 위해 기다린 시간을 통해 디스크 병목 여부를 판단하고 디스크의 바쁜 정도의 변화에 따른 응답 시간 변화를 살펴 볼 수 있다.

Sysstat 패키지에 같이 들어있는 모니터링 프로그램 중 하나인 sar 프로그램은 시스템의 다양한 활동에 대하여 모니터링을 할 수 있는데 모니터링 대상이 상당히 넓은 편이다. 기본값은 CPU 활동에 대한 통계를 출력한다. sar는 각종 활동에 대한 통계를 다른 프로그램을 이용하여 파일로 저장하고 통계치를 출력할 수 있는 기능을 제공한다.



# sar –A 5

Linux 2.4.4 (tunelinux.pe.kr) 07/17/01



02:31:58 AM proc/s

02:32:03 AM 0.00



02:31:58 AM cswch/s

02:32:03 AM 8.80



02:31:58 AM CPU %user %nice %system %idle

02:32:03 AM all 0.00 0.00 0.20 99.80

02:32:03 AM 0 0.00 0.00 0.40 99.60

02:32:03 AM 1 0.00 0.00 0.00 100.00


리스트 5. sar 이용한 시스템 모니터링



sar에서 모니터링 가능한 항목은 다음과 같다.



- I/O 전송량

- 페이징

- 프로세스 생성 숫자

- 블락 디바이스 활동

- 인터럽트

- 네트워크 통계

- run 큐 및 시스템 부하 평균

- 메모리와 스왑 공간 활용 통계

- 메모리 통계

- CPU 이용도

- 특정 프로세스에 대한 CPU 이용도

- inode, 파일, 기타 커널 테이블에 대한 상태

- 시스템 스위칭 활동(context switch)

- 스와핑 통계

- 특정 프로세스 통계

- 특정 프로세스의 자식 프로세스 통계

- TTY 디바이스 활동



sar을 이용해 iostat와 비슷하게 I/O통계를 낼 수 있음은 물론 위의 내용과 같이 다양한 시스템 상태를 모니터링할 수 있다. 일반적인 리눅스 서적이나 자료에는 iostat나 sar에 대한 소개가 거의 없는 편이어서 아직까지는 사용하는 사람이 적은 듯 하다. 예를 들어 메모리 규모에 맞게 최대 열 수 있는 파일 갯수 (file-max)와 아이노드 개수를 조정하는데 sar를 이용하여 실제 얼마나 파일 핸들을 사용했는지 최대 file-max와 실제 사용한 파일 핸들의 비율 등도 통계를 낼 수가 있다. 이러한 통계를 주기적으로 내어 적절하게 활용하기 바란다. 참고로 최대 파일 핸들의 경우 4M당 256개로 잡아주고 아이노드 개수는 이의 3-4배 정도로 설정을 한다. file-max 는 /proc/sys/fs/file-max 를 이용하여 설정하며 /proc/sys/fs/file-nr 파일을 이용 현재 할당된 파일수를 확인할 수 있다.



# sar -v 5 5

Linux 2.4.4 (tunelinux.pe.kr) 07/17/01



03:30:21 dentunusd file-sz %file-sz inode-sz super-sz %super-sz dquot-sz %dquot-sz rtsig-sz %rtsig-sz

03:30:26 97582 92 0.28 92582 8 3.12 0 0.00 0 0.00

03:30:31 97582 93 0.28 92600 8 3.12 0 0.00 0 0.00

03:30:36 97582 93 0.28 92610 8 3.12 0 0.00 0 0.00

03:30:41 97582 93 0.28 92622 8 3.12 0 0.00 0 0.00

03:30:46 97582 93 0.28 92636 8 3.12 0 0.00 0 0.00

Average: 97582 93 0.28 92610 8 3.12 0 0.00 0 0.00


리스트 6. sar 이용하여 파일 및 아이노드 상황 모니터링



2.7 df 이용하여 하드 디스크 공간 확인하기

df는 현재 시스템에 마운트된 드라이브의 빈 디스크 공간을 보여준다. 간단한 프로그램이므로 길게 설명할 필요는 없지만 한가지 알아두어야 할 것이 블락 크기이다. 리눅스에서 기본 블락 크기는 1,024byte이다. df, du 등을 사용할 때 블락 크기를 잘못 지정하면 나오는 결과에 대하여 잘못 파악할 수 있는 가능성이 있다. (물론 아래처럼 블락 크기를 바꾸어서 내용을 보는 경우는 거의 없을 것이라 생각이 된다) 지나친 노파심일수 있겠지만 컴퓨터에서는 기본 단위에 대해 잘못 파악을 하는 경우 전혀 엉뚱한 일이 생길 수 있는 것은 한두가지가 아닐 것이다.



리스트 7. df 이용하여 하드 디스크 공간 확인하기

# df --block-size=512

Filesystem 512-blocks Used Available Use% Mounted on

/dev/sda2 4032088 1607824 2219440 42% /

/dev/sda1 124386 21972 95992 19% /boot

/dev/sda4 12444672 5684496 6128024 48% /home

/dev/sdc2 34265688 2748664 29776384 8% /var

tmpfs 4185192 0 4185192 0% /dev/shm



# df

Filesystem 1k-blocks Used Available Use% Mounted on

/dev/sda2 2016044 803912 1109720 42% /

/dev/sda1 62193 10986 47996 19% /boot

/dev/sda4 6222336 2842248 3064012 48% /home

/dev/sdc2 17132844 1374332 14888192 8% /var

tmpfs 2092596 0 2092596 0% /dev/shm
2005/07/04 12:38 2005/07/04 12:38
MRTG 이용한 네트워크 모니터링

http://tunelinux.pe.kr/tune/tunning-pse/pse-05.html
2005/07/04 12:36 2005/07/04 12:36

iptables 기초 사용법

FAQ 2005/07/04 12:35
iptables 기초 설정법에 관한 글입니다.

iptables 설정하기

iptables는 커널 2.4로 올라가면서 새롭게 나타난 것이다. 이 것은 기존의 ipchains를
교체 한 것이다. 여기에서는 간단히 외부에서 들어오는 것을 필터링 하는 것으로 설정하는
방법을 모색한다.
iptables는 테이블 형식으로 관리를 한다. 그리고 먼저 등록 된것이 효력을 발생하기때문
에 등록을 하는 순서가 중요하다. 모든 것을 거부하는 설정이 먼저오게 되면 드 이후에 포
트를 열어주는 설정이 와도 효과가 없다. 그러므로 허용하는 정책이 먼저오고 나서 거부하
는 정책이 와야한다.

예) iptables -A INPUT -p tcp --dport 22:30 -j DROP
iptables -A INPUT -p tcp --dport 25 -j ACCEPT

이 경우에는 먼저 22번부터 30번까지의 포트를 목적지로 하는 패킷이 들어오면 무시하라는
줄이 먼저 들어 있다. 그리고 다음에 25번 포트를 열라는 명령이 있다. 그러나 이 명령은
먼저온 거부 메시지때문에 패킷이 이미 거부된 상태이어서 효력이 없다. 따라서 이 경우는
잘못 설정한 것으로 볼 수가 있다. 그러므로 제대로 설정을 하려면 이렇게 바꾸어야한다.

예) iptables -A INPUT -p tcp --dport 25 -j ACCEPT
iptables -A INPUT -p tcp --dport 22:30 -j DROP

이렇게 하면 먼저 25번 포트로 들어오는 것을 허용하고 난후에 다른 것을 막아내기 때문에
제대로 된 설정이 된다.

Usage: iptables -[ADC] chain rule-specification [options]
iptables -[RI] chain rulenum rule-specification [options]
iptables -D chain rulenum [options]
iptables -[LFZ] [chain] [options]
iptables -[NX] chain
iptables -E old-chain-name new-chain-name
iptables -P chain target [options]
iptables -h (print this help information)

이 부분은 전체적인 옵션을 적는 것을 간략히 보여주는 것이다.
아직 커널 2.4대를 써보는 것이 얼마되지 않아서 정확한 개념과 고급적인 설정은 파악이 되
지 않은 상태이다. 다만 iptable을 추가하고 삭제하고 필수적인 부분을 이해해보자.
iptables을 이용해서 추가하는 것은

iptables -A 체인이름 옵션

의 형식을 사용한다. 이 때에 iptables에 등록이 되는데 이것을 확인하는 것은
iptables -L로 확인이 가능하다.

예) iptables -L

나타나는 목록은 다음과 같다.

Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain FORWARD (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

아직은 아무것도 등록이 되지않은 상태이다. 여기에 등록을 하는 것이다.

iptables -A INPUT -p tcp --dport 22 -j ACCEPT

이 명령을 사용하면 한줄이 등록이 된다. 결과는 다음과 같다.

Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh

Chain FORWARD (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

처음에 한줄이 등록이 된다. 여기에 등록된 라인은 ssh를 사용하는 것을 허용하는 것이
다.
이 한줄을 설명하면
먼저 -A 옵션은 추가하도록하는 것이다. 그리고 따라오는 INPUT은 chain명이다. 그리고
다음에 따라오는 -p는 protocol에 관한 옵션이다. 여기에서는 tcp에 관한 설정임을 명시
하였다. 그리고 source와 destination은 명시하지 않았기 때문에 전체포트와 아이피가
대상이 된다. -dport는 패킷이 대상으로 삼는 포트를 명시한 것이다 여기에서 22라고 표기
한 것은 ssh서비스 포트이다. 그리고 마지막에 -j ACCEPT는 허용하도록 정책을 정하는 것
이다. 따라서 여기로의 ssh서비스를 요청하는 패킷은 허용되도록 설정을 한 것이다.
다음은 전체적인 설정을 한 것이다.

#!/bin/sh
# iptables 모듈 등록하기
modprobe iptable_filter
# ssh 열기
/usr/local/bin/iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# httpd 열기
/usr/local/bin/iptables -A INPUT -p tcp --dport 80 -j ACCEPT
# pop3 열기
/usr/local/bin/iptables -A INPUT -p tcp --dport 109 -j ACCEPT
# pop2 열기
/usr/local/bin/iptables -A INPUT -p tcp --dport 110 -j ACCEPT
# imap 열기
/usr/local/bin/iptables -A INPUT -p tcp --dport 143 -j ACCEPT
# mysqld 열기
/usr/local/bin/iptables -A INPUT -p tcp --dport 3306 -j ACCEPT
# ftpd 열기
/usr/local/bin/iptables -A INPUT -p tcp --dport 21 -j ACCEPT
# ftp-data 열기
/usr/local/bin/iptables -A INPUT -p tcp --dport 20 -j ACCEPT
# ircd 열어주기
/usr/local/bin/iptables -A INPUT -p tcp --dport 6667 -j ACCEPT
/usr/local/bin/iptables -A INPUT -p udp --dport 6667 -j ACCEPT
# 전부 거절하기
/usr/local/bin/iptables -A INPUT -p tcp --dport 1:30000 -j DROP
/usr/local/bin/iptables -A INPUT -p icmp --icmp-type echo-request -j DROP

이 것은 허용하는 서비스가 한정적이다. 우선 ssh, http, pop3, pop2, imap, mysql,
ftp, ircd를 위해서 서비스를 요청하는 패킷은 허용하고 나머지는 전부 거부하는 설정이
다. 이 설정을 자세히 보면 tcp와 icmp를 대상으로 하였다. icmp는 그 중에서 ping을 막
은 것이다. 특히 echo-request만을 막아서 핑 요청은 거부하지만 서버에서의 핑테스트는
가능하다. 또한 거절하는 줄인
/usr/local/bin/iptables -A INPUT -p tcp --dport 1:30000 -j DROP
이 라인에서 --dport 다음에 1:30000으로 지정되어 있다. 이 부분은 서버를 경유하여서
다른 곳으로 가고자하는 경우에 클라이언트 프로그램이 사용할 포트를 남겨주기 위함이다.
1번포트에서 30000번 포트까지는 완전히 tcp에 대헤서 막는 것이다. 알려진 포트는 1024
이나 해킹 프로그램붕에서 그이후를 사용하여서 소켓을 여는 경우를 방지하기 위함이다. 만
약에 서버에서 나갈 이유가 없으면 전부 막으면 된다. 1:65535로 설정하면 전체 포트가 막
힌다.

다음의 출력은 결과이다.

Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
ACCEPT tcp -- anywhere anywhere tcp dpt:www
ACCEPT tcp -- anywhere anywhere tcp dpt:www
ACCEPT tcp -- anywhere anywhere tcp dpt:pop2
ACCEPT tcp -- anywhere anywhere tcp dpt:pop3
ACCEPT tcp -- anywhere anywhere tcp dpt:imap2
ACCEPT tcp -- anywhere anywhere tcp dpt:mysql
ACCEPT tcp -- anywhere anywhere tcp dpt:ftp
ACCEPT tcp -- anywhere anywhere tcp dpt:ftp-data
ACCEPT tcp -- anywhere anywhere tcp dpt:ircd
ACCEPT udp -- anywhere anywhere udp dpt:ircd
DROP tcp -- anywhere anywhere tcp dpts:tcpmux:30000
DROP icmp -- anywhere anywhere icmp echo-request

Chain FORWARD (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

이와 같이 설정을 한다면 대부분의 것에 대해서 설정 할수가 있다. NAT와 MASQUERADE는
좀더 다양한 설정을 이용하여서 적용할 수가 있다. 이러한 iptables는 원하지 않은 서비스
에 의해서 서버가 위험에 노출되지 않도록 하는 것이 목적이다. 좀더 나은 설정을 하게 되
면 서버의 보안은 굳건히 하는 것에 도움이 된다.
이 iptables 설정은 조금만 공부를 하면 쉽게 습득이 가능하다. 그러므로 문서를 보는 것
이 중요하다. 이 설정은 기본이므로 좀더 많은 것은 관련 문서를 이용하기를 바란다.
2005/07/04 12:35 2005/07/04 12:35