1. kdump는 무엇인가? (The kexec-based Crash Dumping Solution)

kdump는 kexec를 바탕으로 한 “커널 크래쉬 덤핑 메카니즘” 입니다. 이는 커널 패닉이 발생 하였을때, 시스템의 메모리 상태를 vmcore 라는 파일 형태로 생성하는 작업입니다.


2. kexec는 무엇인가?

kexec는 kdump의 핵심이라고 보시면 되겠습니다. kexec는 커널패닉이 발생하였을 때, BIOS를 거치지 않고 빠르게 새로운 커널로 부팅시키는 역할을 하는 녀석입니다. kdump가 작동하게 하는 녀석입니다. kexec로 새로운 캡쳐 커널을 사용하는 이유는 기존에 패닉이 발생한 상태에서의 커널이 아니라 새로운 커널이기 때문에 덤프를 하는 부분에서 좀더 완전하게 덤프를 생성할 수 있기 때문입니다.


3. kdump가 필요한 이유

윈도우에 블루스크린이 있는것처럼 리눅스에도 커널패닉이라는 것이 존재합니다. 데스크탑같은 경우는 그냥 재부팅 해버리거나 포맷해버리면 그만이지만, 서버와 같은 경우는 장애가 발생했을 때 재부팅을 하는것도 리스크가 있는 작업이고, 장애가 발생했을 때 그 원인을 찾아내서 같은 장애가 나타나지 않도록 하는 것이 중요합니다. 그 원인을 찾을 수 있는 실마리를 제공하는 것이 vmcore 라는 코어 파일이며, 코어파일을 생성하는 것이 kdump라고 생각하면 됩니다.


4. kdump와 kexec의 구동원리


< kexec와 kdump의 작동그림 >


4.1. kexec의 작동원리

kexec는 kdump의 핵심 기술입니다. kexec가 정확히 하는 역할은 시스템이 부팅시에 캡쳐 커널을 현재 커널에 정의 합니다. 메모리에 캡쳐 커널이 들어갈 곳을 예약한다고 보시면 됩니다. 이 과정이 그림에서 kexec -l 입니다.

그 다음 역할은 예약되어 있던 메모리에서 실제로 캡쳐커널을 부팅하는 역할입니다. 이 과정이 그림에서 kexec -e 입니다. kexec -l 로 덤프커널이 메모리에 로드되었다면, kexec -e 명령어로 언제든지 덤프커널로 부팅이 가능합니다.


4.2. kdump의 작동원리

kdump는 시스템이 처음 부팅할때 시스템이 예약된 곳에 캡쳐커널이 로드됩니다. 여기서는 kexec -p 라는 명령어로 로드가 되게 됩니다. 이 부분은 내부적으로 어떻게 작동되는지 정확히 확인한 부분은 아니지만 문서에 보면 kexec -p 는 커널 패닉을 위한 캡쳐 커널을 로드하는 옵션이라고 적혀있습니다.

아마도 kexec -l 이 그냥 캡쳐커널을 로드하는 작업이라면 kexec -p는 패닉이 발생시 자동으로 kexec -e 를 수행하여 바로 캡쳐 커널로 부팅이 되게 하는 명령어라고 생각하시면 될거 같습니다.

이렇게 kexec -e 로 캡쳐 커널이 부팅이 되면, kdump.conf에 설정되어 있는 값으로 kdump 프로세스가 진행이됩니다.


5. Kdump의 설치와 설정


5.1. 필요 패키지 설치


- kexec-tools-2.0.0-258.el6.x86_64.rpm

- 레드햇 리눅스 6.4 버전 기준 이며, kexec-tools 라는 패키지를 설치하시면 됩니다.

- yum install kexec-tools 나 rpm -ivh kexec-tools-2.0.0-258.el6.x86_64.rpm 로 설치하시면 됩니다


5.2. /boot/grub/grub.conf의 argument 변경

- /boot/grub/grub.conf 파일을 vi 편집기로 열어줍니다.

- kernel 라인에 crashkernel=auto 와 nmi_watchdog=1 를 추가 후 재부팅 합니다.

- grub.conf 의 argument를 지정한 후 반드시 재부팅을 해야합니다. 시스템은 재부팅 하면서 덤프커널이 로드될 메모리 영역을 할당 하기 때문입니다. 재부팅하지 않으면 kdump 서비스가 수행될 수 없습니다.



위의 그림을 보시면 kernel 이라고 시작한 라인 맨 마지막에 위의 두 옵션을 추가해주시면 됩니다.


- crashkernel=auto 는 캡쳐 커널을 로드하기위해 메모리에 예약하는 파라미터입니다.

- nmi_watchdog=1 은 nmi_watchdog 를 사용한다는 파라미터 입니다.


5.3. 커널 파라미터 변경

sysctl -a | grep nmi_watchdog 명령어를 입력하여, nmi_watchdog 파라미터를 확인합니다. 해당 값이 0이라면 정상적으로 nmi_watchdog가 작동하지 않기때문에 해당 값을 1로 변경해야 합니다.

설정방법은 vi /etc/sysctl.conf 하여 맨 마지막줄에 kernel.nmi_watchdog = 1 라고 입력한 후 sysctl -w 로 시스템에 적용합니다.

만약 sysctl -w 로 적용이 안될경우 /etc/sysctl.conf 내용은 그대로 두고 재부팅 하시면 됩니다.

참조. nmi_watchdog


- 리눅스 시스템을 운영하다 보면 데드락에 빠지는 경우가 있을 수 있습니다. 데드락에 빠지면 콘솔화면에 아무것도 출력되지 않고 키보드 입력도 되지 않을 수 있습니다. 이런 상황에서 덤프를 남기기 위한 방법중에 하나라고 생각하시면 되겠습니다. 그냥 꺼버리면 흔적이 남지 않기때문에 추후에 원인을 찾기도 어려운 상황이 될 수 있기때문입니다.


데드락 상황에서 SysRq나 nmi_watchdog을 이용할 수 있는데 SysRq는 인터럽트가 금지된 상황에서 커널이 프리즈되면 이용할 수 없습니다. nmi_watchdog 금지될 수 없는 인터럽트 이기때문에 인터럽트가 금지된 상황에서 사용하기 위한 옵션입니다.


- nmi_watchdog는 주기적으로 타이머 인터럽트를 발생 시킵니다. 인터럽트를 금지시키는 IRQ 핸들러가 데드락에 빠진다면 nmi_watchdog 에서 발생한 타이머 인터럽트 핸들러가 수행되지 않으면, 프리즈로 간주하여 크래시 덤프를 수행합니다.


참조. crashkernel=auto 의 메모리 할당


- 앞에 설명 드린부분 처럼 시스템이 패닉이 발생하게 되면 새로운 덤프 커널을 부팅한다고 하였습니다. crashkernel=auto 라는 파라미터는 이런 덤프 커널이 로드될 메모리 영역을 시스템이 부팅시에 미리 할당하는 역할을 수행합니다. 이 부분은 아키텍쳐마다 조금씩 다르게 설정 하게 됩니다. 여기서 저는 RHEL 6.2 버전 이상, x86 / x86_64 아키텍쳐 기준으로 설명 드리겠습니다.


- x86 시스템이 2G 이하의 메모리를 소유한 경우 crashkernel=128M     <– 라인을 추가합니다.

- x86 시스템이 2G 이상의 메모리를 소유한 경우 RHEL 6.2 버전 이후로는 crashkernel=auto 옵션을 사용합니다.

(*레드햇 홈페이지에서 확인해본 결과는 RHEL 6.0과 RHEL6.1 은 다른 값으로 설정하도록 가이드 되어있습니다.)


자 그럼 crashkernel=auto의 작동 원리를 살펴 보겠습니다.

auto 옵션은 기본적으로 128M 를 할당하는 것으로 시작되며, 여기서 물리메모리가 1테라바이트가 추가될때마다 64M 씩 추가가 되는 방식입니다.

예를 들어 현재 시스템이 1테라바이트의 메모리를 가지고 있다면, 총 192M가 예약이 되는 것입니다. (기본 128M + 64M) 하지만 이것은 기본 권고 값이며, 절대적으로 맞다고 볼 수 없습니다. 어차피 예약되는 이 메모리의 영역은 덤프 커널이 올라가는 영역이므로 시스템마다 다를 수 있습니다. 가장 안전한 방법은 권고사항대로 설정 후 직접 테스트는 해보는 방법을 추천합니다.

그럼 가이드에 따라서 예약할 메모리의 용량이 변할 수 있는 변수를 확인해 보겠습니다.


첫째. 스토리지의 갯수가 많을 경우.

둘째. 여러가지의 주변기기 드라이버 모듈을 가지고 있는 경우.

셋째. 덤프 필터링 유틸리티인 makedumpfile (물리메모리 4K의 페이지당 2bit를 사용)

첫째와 둘째는 커널안에 모듈이 계속 추가 되게되면 당연히 커널이 커지는 부분이기때문에 이해가 되실거라 생각됩니다.

셋째 요인 같은 경우는 makedumpfile입니다.

makedumpfile 유틸리티는 필터링 작업과 vmcore의 실질적인 복사 작업시에 메모리를 소모하게 됩니다.

  • 필터링 작업 메모리 소모량 = 물리페이지당 2bit를 소모 ( x86 에서 page는 4096byte단위)
  • 복사 작업 메모리 소모량 = 변동값이 아닌 대략 20MB 정도 소모


(1) 시스템이 44G 바이트의 메모리를 가지고 있을때에 makedumpfile 유틸리티가 사용하는 메모리 계산을 해보겠습니다.

a. 필터링 작업시 메모리 소모량 = 2.8 MB

44 GB = 45056 MB = 46137344 KB 입니다.

x86 아키텍쳐는 physical page가 4KB 입니다.

페이지의 최소단위인 4KB로 46137344KB (44GB) 를 나누면 페이지 수는 11534336 개 입니다.

makedumpfile 유틸리는 페이지당 2bit를 소모한다고 하였습니다.

11534336 X 2 = 23068672 bit 가 makedumpfile 이 필터링 하는데 소모하는 양입니다.

23068672 bit = 2883584 byte = 2816 Kbyte = 약 2.8 MB를 소모하게 됩니다.


b. 파일 복사 작업시 메모리 소모량 = 20 MB 고정

결과적으로 44GB 메모리 시스템에서 makedumpfile 유틸리티가 총 사용하는 양은 23MB 정도입니다.


(2) 시스템이 1테라 바이트의 메모리를 가지고 있을때에 makedumpfile 유틸리티가 사용하는 메모리 계산을 해보겠습니다.


a. 필터링 작업시 메모리 소모량 = 64 MB

1TB = 1024 GB = 1048576 MB = 1073741824 KB 입니다.

x86 아키텍쳐는 physical page가 4KB 입니다.

페이지의 최소단위인 4KB로 1073741824KB (1TB)를 나누면 페이지 수는 268435456개 입니다.


makedumpfile 유틸리는 페이지당 2bit를 소모한다고 하였습니다.

268435456 X 2 = 536870912 bit 가 makedumpfile 이 필터링 하는데 소모하는 양입니다.

536870912 bit = 67108864 byte = 65536 Kbyte = 64 MB가 소모하게 됩니다.


b. 파일 복사 작업시 메모리 소모량 = 20 MB 고정


결과적으로 1TB 메모리 시스템에서 makedumpfile 유틸리티가 총 사용하는 양은 84MB 정도입니다.


============================================================


이러한 이유로 makedumpfile 의 필터링 작업 변수로 인하여 1TB당 64MB가 추가적으로 할당되게 되는 것입니다. 결론적으로 crashkernel이 할당할 메모리 용량을 정하는 기준은


스토리지 갯수

각종 장치의 모듈 용량

makedumpfile의 필터링 작업시 필요한 메모리 용량 (기본 128M + 1TB당 64MB추가)

파일 복사 작업시 필요한 용량(고정)

RHEL 6.2 부터는 /boot/grub/grub.conf 의 커널 라인에 crashkernel=auto 로 사용하시면 됩니다.


5.4. /etc/kdump.conf 설정

a. vmcore 생성 경로 및 방법 설정

raw <partition>

raw <블럭 디바이스>

path <path>

nfs <nfs 마운트 경로>

net <nfs 마운트 경로>     #net은 nfs와 같습니다.

nfs4 <nfs 마운트 경로>     #nfs4를 이용합니다.

ssh <user@server>

net <user@server>     #net은 ssh와 같습니다.

파일시스템 타입 <LABEL>

파일시스템 타입 <UUID>

파일시스템 타입 <블럭 디바이스>


b. vmcore 생성시 filterling 설정

- core_collector -d 17 -c     # 덤프레벨 17로 하고 페이지별로 압축한다는 예이며, 아래는 덤프 레벨 상세 내용입니다.


<좌측 숫자가 레벨을 나타내며, x 표시된 부분은 dump하지 않습니다>

- 더 자세한 정보는 man makedumpfile 에서 확인 가능 합니다.


c. 덤프 실패시 취할 액션 설정

따로 설정하지 않으면 기본적으로 reboot 입니다.


default reboot     #재부팅.

default halt     #시스템이 halt 된 후 덤프 시도.

default poweroff     #시스템 종료.

default shell     #shell이 수행되며, 수동으로 덤프를 시도 가능.

default mount_root_run_init     #루트파일시스템을 마운트하고 init을 수행합니다. init스크립트는 덤프를 루트파일시스템의 /var/crash에 저장하려 합니다.

d. 기타 다른 옵션

link_delay <seconds>     #간혹 네트워크 초기화가 늦는 경우를 대비하여 덤프를 생성 후 전송하기 전에 일정시간을 기다립니다.

kump_post <binary 또는 script>     #덤프 생성 프로세스 완료 후 사용자가 지정한 실행파일이나 스크립트를 실행합니다.

kdump_pre <binary 또는 script>     #덤프 생성 프로세스 이전에 사용자가 지정한 실행 파일이나 스크립트 실행합니다.

extra_bins <binaries 또는 scripts>     #kdump initrd에 실행 파일들 이나 스크립트 들을 포함 시킵니다.

extra_modules <module(s)>     #kdump initrd에 로드하고자 하는 확장 커널 모듈에 대한 정의. 모듈들은 공백으로 구분 합니다.

debug_mem_level <0-3>     #kdump 스크립트 실행시 디버그 모드를 활성화 하는 것으로서 kdump 스크립트 수행할때에 메모리의 상태를 실시간으로 보여줍니다. 레드햇 권고값으로 시스템을 설정하고 테스트 할대에 디버그 모드를 사용하면 kdump의 메모리의 적정량을 확인할 수 있습니다.

e. 설정

여기서는 우선 기본값으로 설정되어 있는 path /var/crash 로 진행하겠습니다. /etc/kdump.conf 에서 vmcore 파일 생성과 방법에 대해서 정의한다고 말씀드렸습니다. vmcore파일은 시스템의 메모리를 덤프하는 것입니다. 이말은 곧 vmcore 가 생성될 영역은 최소한 시스템 메모리 이상은 되어야한다는 부분을 생각하셔야 되겠습니다.


5. Kdump Operation Flow



kdump순서도.png


  1. 시스템 패닉 발생
  2. kdump 커널로 부팅
  3. kdump initramfs 를 로드 하고 /init 을 실행합니다.
  4. /etc/kdump.conf 에 설정된 target에 덤프를 시작합니다. 설정이 되어있지 않다면, 기본적으로 설정된 곳에 덤프를 시작합니다.
  5. /etc/kdump.conf 에 설정한 core_collector 옵션에 맞게 vmcore를 생성합니다.
  6. 덤프가 성공했다면 14) 번으로 진행, 실패했다면 7) 번으로 진행됩니다.
  7. /etc/kdump.conf 에 default_action 이 Halt 라면 16) 번으로 진행, 아니라면 8) 번으로 진행됩니다.
  8. /etc/kdump.conf 에 default_action 이 reboot 이라면 14) 번으로 진행, 아니라면 9) 번으로 진행됩니다.
  9. /etc/kdump.conf 에 default_action 이 shell 이라면 15) 번으로 진행, 아니라면 10) 번으로 진행됩니다.
  10. /etc/kdump.conf 에 defalut_action 이 mount_root_run_init 이라면 11) 번으로 진행, 아니라면 14) 번으로 진행됩니다.
  11. 루트파일시스템을 마운트 하고 /sbin/init 을 실행합니다.
  12. kdump 서비스를 실행합니다.
  13. vmcore 파일을 생성합니다.
  14. 재부팅합니다.
  15. 쉘상태로 빠져나옵니다.
  16. 시스템을 종료합니다.

6. Kdump 서비스 실행

- service kdump start     #kdump 서비스를 수행합니다.

- chkconfig kdump on     #kdump 서비스는 런레벨 2,3,4,5 에서 항상 수행되도록 설정합니다.


7. Kdump 테스트

쉘에서 echo c > /proc/sysrq-trigger     #sysrq-trigger 호출하여 시스템 패닉을 발생시킵니다.

터미널에서 위의 명령어를 입력하게 되면 시스템이 멈춰있습니다. 그 사이 리눅스 내부에서는 Kdump가 진행되고 vmcore 생성이 완료되면 시스템이 재부팅 됩니다.


이상으로 RHEL 6.2 버전 이상에서 Kdump에 관하여 알아보았습니다.  잘못된 부분이 나 궁금하신 부분이 있으면 댓글 부탁드립니다.


감사합니다.

OpenSourceConsulting's profile image

OpenSourceConsulting

2014-11-13

Read more posts by this author