kdumpを使えないEC2でnetconsoleを活用してkernel panic時のstack traceを取得する


##概要
EC2上のLinuxはkdumpが使えないため、crash dump解析ができない。
せめてkernel panic時のカーネルログぐらいは何とか取得できないものかと考えて試行錯誤したところ、netconsoleを使うことでstack traceが取得できることがわかった。


##動作検証
今回はEC2(最新のAmazonLinux)を用いて検証した(同一VPCで同一サブネット内の2つのインスタンス間で実施)。netconsoleが導入できば他のディストリビューションでも実行できるのではなかろうか。

###(受信側)kernel panic時のカーネルログが送られてくるか確認するために、listenモードでncコマンドを実行して待機する
```bash
$nc -u -l [destination port]
```

###(送信側)netconsoleを設定する
```bash
#modprobe netconsole netconsole=[source port]@[source ip]/eth0,[destination port]@[destination ip]/[MAC address]
#dmesg
```
```
(略)
[16170.226317] netpoll: netconsole: local port [source port]
[16170.229153] netpoll: netconsole: local IPv4 address [source ip]
[16170.232371] netpoll: netconsole: interface 'eth0'
[16170.234837] netpoll: netconsole: remote port [destination port]
[16170.237250] netpoll: netconsole: remote IPv4 address [destination ip]
[16170.240764] netpoll: netconsole: remote ethernet address [MAC address]
[16170.244360] console [netcon0] enabled
[16170.246398] netconsole: network logging started
```

###(送信側)sysrqを使ってcrashさせる
```bash
#echo 1 > /proc/sys/kernel/sysrq
#echo c > /proc/sysrq-trigger
```

###(受信側)受信側で送信側kernel panic発生時に出力されるメッセージが見れるか確認する
```bash
$nc -u -l [destination port]
```
```
[16248.310268] SysRq : Trigger a crash
[16248.312360] BUG: unable to handle kernel NULL pointer dereference at           (null)
[16248.314138] IP: [<ffffffff81328256>] sysrq_handle_crash+0x16/0x20
[16248.314138] PGD 3b7a1067 PUD 3b7a0067 PMD 0
[16248.314138] Oops: 0002 [#1] SMP
[16248.314138] Modules linked in: netconsole ipv6 binfmt_misc evbug evdev psmouse i2c_piix4 button i2c_core ext4 crc16 jbd2 mbcache dm_mirror dm_region_hash dm_log dm_mod
[16248.314138] CPU: 0 PID: 2633 Comm: bash Not tainted 3.14.27-25.47.amzn1.x86_64 #1
[16248.314138] Hardware name: Xen HVM domU, BIOS 4.2.amazon 12/03/2014
[16248.314138] task: ffff88003b3732a0 ti: ffff88003b22e000 task.ti: ffff88003b22e000
[16248.314138] RIP: 0010:[<ffffffff81328256>]  [<ffffffff81328256>] sysrq_handle_crash+0x16/0x20
[16248.314138] RSP: 0018:ffff88003b22fe88  EFLAGS: 00010082
[16248.314138] RAX: 000000000000000f RBX: ffffffff81a92380 RCX: 0000000000000000
[16248.314138] RDX: ffff88003fc0ea78 RSI: ffff88003fc0d148 RDI: 0000000000000063
[16248.314138] RBP: ffff88003b22fe88 R08: 0000000000000096 R09: 0000000000000186
[16248.314138] R10: 0000000000000185 R11: 0000000000000003 R12: 0000000000000002
[16248.314138] R13: 0000000000000063 R14: 0000000000000246 R15: 0000000000000008
[16248.314138] FS:  00007f5a9bbb0700(0000) GS:ffff88003fc00000(0000) knlGS:0000000000000000
[16248.314138] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[16248.314138] CR2: 0000000000000000 CR3: 000000003d63e000 CR4: 00000000001406f0
[16248.314138] Stack:
[16248.314138]  ffff88003b22fec0 ffffffff81328a08 0000000000000002 00007f5a9bbb7000
[16248.314138]  ffff88003b22ff50 0000000000000002 0000000001b9ed00 ffff88003b22fed8
[16248.314138]  ffffffff81328eb2 ffff88003b32eb40 ffff88003b22fef8 ffffffff8120abfd
[16248.314138] Call Trace:
[16248.314138]  [<ffffffff81328a08>] __handle_sysrq+0x138/0x1a0
[16248.314138]  [<ffffffff81328eb2>] write_sysrq_trigger+0x32/0x40
[16248.314138]  [<ffffffff8120abfd>] proc_reg_write+0x3d/0x80
[16248.314138]  [<ffffffff811a67fa>] vfs_write+0xba/0x1e0
[16248.314138]  [<ffffffff811a71e6>] SyS_write+0x46/0xb0
[16248.314138]  [<ffffffff810e9e86>] ? __audit_syscall_exit+0x236/0x2e0
[16248.314138]  [<ffffffff81495269>] system_call_fastpath+0x16/0x1b
[16248.314138] Code: 65 34 75 e5 4c 89 ef e8 f9 f7 ff ff eb db 0f 1f 80 00 00 00 00 0f 1f 44 00 00 55 c7 05 74 85 90 00 01 00 00 00 48 89 e5 0f ae f8 <c6> 04 25 00 00 00 00 01 5d c3 0f 1f 44 00 00 55 31 c0 c7 05 7e
[16248.314138] RIP  [<ffffffff81328256>] sysrq_handle_crash+0x16/0x20
[16248.314138]  RSP <ffff88003b22fe88>
[16248.314138] CR2: 0000000000000000
[16248.314138] ---[ end trace a7b90b5075702d43 ]---
[16248.314138] Kernel panic - not syncing: Fatal exception
```

おお！！見れましたね。これでとりあえずkernel panic発生時のstack traceぐらいは確認ができるようになりました。

##まとめ
今回の動作検証ではncを使ってカーネルログの転送が可能であるか確認したが、受信側でsyslogの設定をしておくことでcrashした際に送られてくる情報を管理できそう。またpanic_on_oops=1していればoopsからのkernel panic発生時でも取得できる。

EC2上のLinux環境では、kernel panic時のダンプとっての障害解析を諦めそうなところだったのでこれだけでも救われた気持ちになっている。