Amazon Web Services ブログ

新着 – カーネルパニックをトリガーし、応答しない EC2 インスタンスを診断

オンプレミスのデータセンターにデプロイされたシステムで作業を行っていたころ、ときどき、応答しないサーバーのデバッグをしなければならないことがありました。その場合、通常は誰かに頼んで、フリーズしたサーバーでマスク不可能割り込み (NMI、non-maskable interrupt) ボタンを物理的に押してもらうか、あるいはシリアルインターフェイス (はい、シリアルです。RS-232 など) を介してコマンドコントローラーに信号を送信してもらう必要がありました。このコマンドによってシステムがトリガーされ、フリーズしたカーネルの状態がファイルにダンプされて、さらなる分析が行われます。このようなファイルは通常、コアダンプあるいはクラッシュダンプと呼ばれます。クラッシュダンプには、クラッシュしたプロセスのメモリのイメージ、システムレジスター、プログラムカウンター、その他フリーズの主要因を特定するのに役立つ情報が含まれています。

本日発表された新しい Amazon Elastic Compute Cloud (EC2) API を使うと、EC2 インスタンスでのカーネルパニックの生成を、リモートでトリガーすることができます。EC2:SendDiagnosticInterrupt API は、物理マシンで NMI ボタンを押す場合と同様に、診断割り込みを、実行中の EC2 インスタンスに送信します。それにより、インスタンスのハイパーバイザーがマスク不可能割り込み (NMI、non-maskable interrupt) をオペレーティングシステムに送信します。NMI 割り込みを受信したときのオペレーティングシステムの挙動は、システムの設定に依存します。通常はカーネルパニックの状態に入ります。カーネルパニックの挙動もオペレーティングシステムの設定に依存し、クラッシュダンプデータファイルの生成がトリガーされたり、バックトレースが取得されたり、差し替えのカーネルがロードされたり、システムが再起動されたりします。

組織内でこの API を使用できる人を管理するには IAM ポリシーを使用します。以下に例を示します。

クラウドエンジニアやシステムエンジニア、あるいはカーネル診断やデバッグ作業のスペシャリストが、クラッシュダンプの中からカーネルがフリーズした原因を分析するための非常に重要な情報を見つけ出します。ダンプを調べるときは、WinDbg (Windows) や crash (Linux) といったツールを使用します。

診断割り込みの使用
この API の使用プロセスは、3 つのステップからなります。まず、割り込みを受信したときの OS の挙動を設定しておく必要があります。

Windows Server AMI のメモリダンプは、デフォルトですでにオンの状態になっています。メモリダンプが保存された後の自動再起動も選択されています。メモリダンプファイルのデフォルトの場所は %SystemRoot% です。これは C:\Windows に相当します。

これらのオプションには、次の場所に進むとアクセスできます。
スタート > コントロール パネル > システム > システムの詳細設定 > 起動と回復

Amazon Linux 2 の場合kdump と kexec をインストールおよび設定する必要があります。 これはワンタイムのセットアップです。

$ sudo yum install kexec-tools

次に、ファイル /etc/default/grub を編集して、クラッシュカーネル用に予約するメモリの量を割り当てます。この例では、crashkernel=160M を追加して 160M を予約しています。割り当てるメモリの量は、お使いのインスタンスのメモリ容量に依存します。一般に、kdump をテストして、割り当てられたメモリで十分かどうかを確認することが推奨されています。crashkernel カーネルパラメータの完全な構文は、kernel doc に記載されています。

GRUB_CMDLINE_LINUX_DEFAULT="crashkernel=160M console=tty0 console=ttyS0,115200n8 net.ifnames=0 biosdevname=0 nvme_core.io_timeout=4294967295 rd.emergency=poweroff rd.shell=0"

次に、grub の設定を再構築します。

$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg

最後に、/etc/sysctl.conf を編集して、次の行を追加します。kernel.unknown_nmi_panic=1。これで、割り込みを受信したときにカーネルパニックをトリガーするよう、カーネルに命令できます。

以上でインスタンスを再起動する準備が整いました。 すべてのインスタンスでこれらを自動設定するために、ユーザーデータのスクリプトまたは AMI に、必ずこれらのコマンドを含めます。 インスタンスが再起動したら、kdump が正常に開始されていることを確認します。

$ systemctl status kdump.service
● kdump.service - Crash recovery kernel arming
   Loaded: loaded (/usr/lib/systemd/system/kdump.service; enabled; vendor preset: enabled)
   Active: active (exited) since Fri 2019-07-05 15:09:04 UTC; 3h 13min ago
  Process: 2494 ExecStart=/usr/bin/kdumpctl start (code=exited, status=0/SUCCESS)
 Main PID: 2494 (code=exited, status=0/SUCCESS)
   CGroup: /system.slice/kdump.service

Jul 05 15:09:02 ip-172-31-15-244.ec2.internal systemd[1]: Starting Crash recovery kernel arming...
Jul 05 15:09:04 ip-172-31-15-244.ec2.internal kdumpctl[2494]: kexec: loaded kdump kernel
Jul 05 15:09:04 ip-172-31-15-244.ec2.internal kdumpctl[2494]: Starting kdump: [OK]
Jul 05 15:09:04 ip-172-31-15-244.ec2.internal systemd[1]: Started Crash recovery kernel arming.

他のオペレーティングシステムを使った場合の手順は、当社のドキュメントに記載されています。

ここまでのワンタイム設定が完了したら、2 番目のステップに進んでこの API をトリガーできます。このステップは、AWS CLI または SDK が設定されているマシンであれば、どのマシンからでも行えます。以下に例を示します。

$ aws ec2 send-diagnostic-interrupt --region us-east-1 --instance-id <value>

CLI の戻り値がありませんが、これは手順通りです。インスタンスでターミナルセッションを開いている場合は、切断されます。インスタンスが再起動します。インスタンスに再接続すると、/var/crash にクラッシュダンプがあることを確認できます。

最後の 3 番目のステップでは、クラッシュダンプの内容を分析します。Linux システムの場合、お使いのカーネルのバージョンに合った crash ユーティリティとデバッグシンボルをインストールしておく必要があります。カーネルのバージョンは、kdump が取り込んだものと同じでなければならないことに注意してください。実行中のカーネルがどのカーネルであるのかを確認するには、uname -r コマンドを使用します。

$ sudo yum install crash
$ sudo debuginfo-install kernel
$ sudo crash /usr/lib/debug/lib/modules/4.14.128-112.105.amzn2.x86_64/vmlinux /var/crash/127.0.0.1-2019-07-05-15\:08\:43/vmcore

crash 7.2.6-1.amzn2.0.1
... output suppressed for brevity ...

      KERNEL: /usr/lib/debug/lib/modules/4.14.128-112.105.amzn2.x86_64/vmlinux
    DUMPFILE: /var/crash/127.0.0.1-2019-07-05-15:08:43/vmcore  [PARTIAL DUMP]
        CPUS: 2
        DATE: Fri Jul  5 15:08:38 2019
      UPTIME: 00:07:23
LOAD AVERAGE: 0.00, 0.00, 0.00
       TASKS: 104
    NODENAME: ip-172-31-15-244.ec2.internal
     RELEASE: 4.14.128-112.105.amzn2.x86_64
     VERSION: #1 SMP Wed Jun 19 16:53:40 UTC 2019
     MACHINE: x86_64  (2500 Mhz)
      MEMORY: 7.9 GB
       PANIC: "Kernel panic - not syncing: NMI: Not continuing"
         PID: 0
     COMMAND: "swapper/0"
        TASK: ffffffff82013480  (1 of 2)  [THREAD_INFO: ffffffff82013480]
         CPU: 0
       STATE: TASK_RUNNING (PANIC)

多くの場合、カーネルクラッシュダンプの収集は、カーネルのデバッグ情報を収集するための唯一の方法となります。したがって、この手順を頻繁にテストするようにしてください。特に、オペレーティングシステムのアップデート後や新規 AMI を作成するときは必ずテストします。

診断割り込みを送信する権限の管理
組織内の誰が診断割り込みを送信できるか、および、どのインスタンスに送信できるかについては、リソースレベルのアクセス許可を持つ IAM ポリシーを使って管理できます。以下に例を示します。

{
   "Version": "2012-10-17",
   "Statement": [
      {
      "Effect": "Allow",
      "Action": "ec2:SendDiagnosticInterrupt",
      "Resource": "arn:aws:ec2:region:account-id:instance/instance-id"
      }
   ]
}

料金
この機能の使用には、追加料金は発生しません。ただし、診断割り込みの受信後もお使いのインスタンスが ‘running’ 状態のままだと、インスタンスの請求は通常どおりに継続します。

可用性
診断割り込みは、AWS Nitro システムで稼働している、A1 (ARM ベース) を除くすべての EC2 インスタンスに送信できます。本記事の執筆時点では、C5、C5d、C5n、i3.metal、I3en、M5、M5a、M5ad、M5d、p3dn.24xlarge、R5、R5a、R5ad、R5d、T3、T3a、Z1d が該当します。

Diagnostic Interrupt API は、すべてのパブリック AWS リージョン、および GovCloud (米国) で提供が開始されました。本日からさっそく使用できます。

— seb