亚马逊AWS官方博客

新增功能 — 触发内核错误以诊断 EC2 实例无响应的问题

当年我处理在本地数据中心部署的系统中时,有时我不得不对无响应的服务器进行调试。这通常会需要让一个人在被冻结的服务器上亲手按下一个不可屏蔽中断 (NMI) 按钮,或者通过一个串行接口(是的,串口,例如 RS-232)向某个命令控制器发送一个信号。此命令会触发系统将被冻结内核的状态转储到一个文件中以供进一步的分析。该文件通常被叫做内核转储或崩溃转储。崩溃转储包含崩溃进程的内存、系统寄存器、程序计数器以及用于确定冻结根本原因有帮助的其他信息的镜像。

今天,我们宣布推出一个新的 Amazon Elastic Compute Cloud (EC2) API,借助此 API 可以在 EC2 实例上远程触发生成内核错误。EC2:SendDiagnosticInterrupt API 将会向正在运行的 EC2 实例发送一个诊断中断,类似于在物理服务器上按下 NMI 按钮。这将导致该实例的虚拟机监视器向操作系统发送一条不可屏蔽中断 (NMI) 按钮命令。收到 NMI 中断时操作系统的行为取决于它的配置。一般而言,这会涉及进入内核错误状态。内核错误行为也取决于操作系统的配置,它可能会触发生成崩溃转储数据文件,获取回溯跟踪,加载替代内核或重启系统。

您可以通过 IAM 策略来控制组织中谁有权使用该 API,我将在下例中解释这一点。

云和系统工程师或者内核诊断调试专业人员可在崩溃转储中找到针对的信息,从而分析内核冻结的原因。WinDbg(Windows 平台)和 crash(Linux 平台)等工具都可用于检查转储文件。

诊断中断的使用
此 API 的使用共有三步。首先,您需要配置收到中断时的操作系统行为。

默认情况下,我们的 Windows Server AMI 已经打开了内存转储功能。此外还选择了内存转储保存后自动重启选项。内存转储文件的默认位置是 %SystemRoot%,这相当于 C:\Windows

您可以通过以下路径来访问这些选项:
启动 > 控制面板 > 系统 > 高级系统设置 > 启动和故障恢复

在 Amazon Linux 2 上,您需要安装并配置 kdumpkexec。 这是一个一次性的设置。

$ sudo yum install kexec-tools

然后编辑文件 /etc/default/grub 以分配要为崩溃内核预留的内存量。在此例中,我们通过添加 crashkernel=160M 预留了 160M。要分配的内存量取决于实例的内存大小。一般建议是通过测试 kdump 来检查分配的内存是否足够。kernel 文档提供了 crashkernel 内核参数的完整语法。

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.

我们的文档包含了有关其他操作系统的说明。

完成此一次性的配置后,您就可以开始第二步,也就是触发该 API。您可以从配置了 AWS CLI软件开发工具包的任何计算机执行此操作。例如:

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

CLI 没有返回值,这与预期一致。如果您在该实例上打开了一个终端会话,则该会话会断开。您的实例会重启。您重新连接到实例,并在 /var/crash 中找到崩溃转储。

第三步也是最后一步,就是分析崩溃转储的内容。在 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"
      }
   ]
}

定价
使用此功能不会产生额外的费用。但由于您的实例在收到诊断中断后,会继续处于“正在运行”状态,实例费用将会继续正常收取。

可用性
除基于 ARM 的 A1 实例外,您可以向所有 AWS Nitro 系统支持的 EC2 实例发送诊断中断。在本文撰写之时,这包括 C5、C5d、C5n、i3.metal、I3en、M5、M5a、M5ad、M5d、p3dn.24xlarge、R5、R5a、R5ad、R5d、T3、T3a 和 Z1d 等。

诊断中断 API 现已在所有公有 AWS 区域和 GovCloud (US) 区域与开放,您可以立即开始使用。

— seb