故障

本文档解释了如何理解您的 API 请求发生了什么。

每个 HTTP 请求都有一个状态码。2xx 状态码表示 API 调用成功。然而,这通常不是故事的结尾。这通常仅意味着启动操作的请求已被接受。它并不意味着您请求的操作已成功完成。

通过请求 ID 跟踪错误

有两种类型的请求 ID。

类型

描述

本地请求 ID

由每个服务本地生成的唯一请求 ID,并且在参与该操作的所有服务(Nova、Cinder、Glance、Neutron 等)之间不同。格式为 req- + UUID (UUID4)。

全局请求 ID

用户指定的请求 ID,由参与该操作的所有服务(Nova、Cinder、Glance、Neutron 等)用作通用标识符。此请求 ID 在参与该操作的所有服务中是相同的。格式为 req- + UUID (UUID4)。

云环境通常拥有 ELK(Elastic Search、Logstash、Kibana)基础设施来收集其日志。查询这些流程的唯一方法是在所有相关消息中存在一个通用标识符。全局请求 ID 立即使现有的已部署工具更适合管理 OpenStack。

请求头

在每个 REST API 请求中,您可以从 microversion 2.46 开始在 X-Openstack-Request-Id 头中指定全局请求 ID。格式必须为 req- + UUID (UUID4)。如果格式不正确,Nova 将忽略全局请求 ID。

请求头示例

X-Openstack-Request-Id: req-3dccb8c4-08fe-4706-a91d-e843b8fe9ed2

响应头

在每个 REST API 请求中,X-Compute-Request-Id 会在响应头中返回。从 microversion 2.46 开始,X-Openstack-Request-Id 也会在响应头中返回。

X-Compute-Request-IdX-Openstack-Request-Id 是本地请求 ID。全局请求 ID 不会返回。

响应头示例

X-Compute-Request-Id: req-d7bc29d0-7b99-4aeb-a356-89975043ab5e
X-Openstack-Request-Id: req-d7bc29d0-7b99-4aeb-a356-89975043ab5e

服务器操作

大多数 服务器操作 API 都是异步的。通常,API 服务会执行一些最小的工作,然后将请求发送到 nova-compute 服务以完成操作,API 会向客户端返回 202 响应。客户端将轮询 API,直到操作完成,这可能是服务器状态的更改,但通常至少始终等待服务器 OS-EXT-STS:task_state 字段变为 null,表示操作已成功完成或出错。

如果服务器操作失败,并且服务器状态更改为 ERROR,则服务器详细信息中将显示 实例故障

os-instance-actions API 允许用户最终用户列出服务器操作的结果,通过请求 ID 引用请求的操作。当操作失败并且服务器状态未更改为 ERROR 时,这很有用。

为了说明,考虑使用 flavor m1.tiny 创建的服务器 (vm1)

$ openstack server create --flavor m1.tiny --image cirros-0.4.0-x86_64-disk --wait vm1
+-----------------------------+-----------------------------------------------------------------+
| Field                       | Value                                                           |
+-----------------------------+-----------------------------------------------------------------+
| OS-DCF:diskConfig           | MANUAL                                                          |
| OS-EXT-AZ:availability_zone | nova                                                            |
| OS-EXT-STS:power_state      | Running                                                         |
| OS-EXT-STS:task_state       | None                                                            |
| OS-EXT-STS:vm_state         | active                                                          |
| OS-SRV-USG:launched_at      | 2019-12-02T19:14:48.000000                                      |
| OS-SRV-USG:terminated_at    | None                                                            |
| accessIPv4                  |                                                                 |
| accessIPv6                  |                                                                 |
| addresses                   | private=10.0.0.60, fda0:e0c4:2764:0:f816:3eff:fe03:806          |
| adminPass                   | NgascCr3dYo4                                                    |
| config_drive                |                                                                 |
| created                     | 2019-12-02T19:14:42Z                                            |
| flavor                      | m1.tiny (1)                                                     |
| hostId                      | 22e88bec09a7e33606348fce0abac0ebbbe091a35e29db1498ec4e14        |
| id                          | 344174b8-34fd-4017-ae29-b9084dcf3861                            |
| image                       | cirros-0.4.0-x86_64-disk (cce5e6d6-d359-4152-b277-1b4f1871557f) |
| key_name                    | None                                                            |
| name                        | vm1                                                             |
| progress                    | 0                                                               |
| project_id                  | b22597ea961545f3bde1b2ede0bd5b91                                |
| properties                  |                                                                 |
| security_groups             | name='default'                                                  |
| status                      | ACTIVE                                                          |
| updated                     | 2019-12-02T19:14:49Z                                            |
| user_id                     | 046033fb3f824550999752b6525adbac                                |
| volumes_attached            |                                                                 |
+-----------------------------+-----------------------------------------------------------------+

服务器的所有者随后尝试将服务器调整为 flavor m1.small,由于没有可用于调整服务器的主机,因此失败

$ openstack server resize --flavor m1.small --wait vm1
Complete

尽管 openstack 命令显示操作已完成,但服务器显示原始 m1.tiny flavor,并且状态不是 VERIFY_RESIZE

$ openstack server show vm1 -f value -c status -c flavor
m1.tiny (1)
ACTIVE

由于状态不是 ERROR,因此服务器详细信息中没有 fault 字段,因此我们通过列出服务器的事件来查找详细信息

$ openstack server event list vm1
+------------------------------------------+--------------------------------------+--------+----------------------------+
| Request ID                               | Server ID                            | Action | Start Time                 |
+------------------------------------------+--------------------------------------+--------+----------------------------+
| req-ea1b0dfc-3186-42a9-84ff-c4f4fb130fae | 344174b8-34fd-4017-ae29-b9084dcf3861 | resize | 2019-12-02T19:15:35.000000 |
| req-4cdc4c93-0668-4ae6-98c8-a0a5fcc63d39 | 344174b8-34fd-4017-ae29-b9084dcf3861 | create | 2019-12-02T19:14:42.000000 |
+------------------------------------------+--------------------------------------+--------+----------------------------+

要查看 resize 操作的详细信息,我们使用该操作的请求 ID

$ openstack server event show vm1 req-ea1b0dfc-3186-42a9-84ff-c4f4fb130fae
+---------------+------------------------------------------+
| Field         | Value                                    |
+---------------+------------------------------------------+
| action        | resize                                   |
| instance_uuid | 344174b8-34fd-4017-ae29-b9084dcf3861     |
| message       | Error                                    |
| project_id    | b22597ea961545f3bde1b2ede0bd5b91         |
| request_id    | req-ea1b0dfc-3186-42a9-84ff-c4f4fb130fae |
| start_time    | 2019-12-02T19:15:35.000000               |
| user_id       | 046033fb3f824550999752b6525adbac         |
+---------------+------------------------------------------+

我们看到消息是“Error”,但不知道失败了什么。默认情况下,操作的事件详细信息不会显示给没有管理员角色的用户,因此使用 microversion 2.51 查看事件(此处 events 字段为 JSON 格式,以便于阅读)

$ openstack --os-compute-api-version 2.51 server event show vm1 req-ea1b0dfc-3186-42a9-84ff-c4f4fb130fae -f json -c events
{
  "events": [
    {
      "event": "cold_migrate",
      "start_time": "2019-12-02T19:15:35.000000",
      "finish_time": "2019-12-02T19:15:36.000000",
      "result": "Error"
    },
    {
      "event": "conductor_migrate_server",
      "start_time": "2019-12-02T19:15:35.000000",
      "finish_time": "2019-12-02T19:15:36.000000",
      "result": "Error"
    }
  ]
}

默认策略配置允许具有管理员角色的用户查看每个失败事件的 traceback,就像实例故障一样

$ source openrc admin admin
$ openstack --os-compute-api-version 2.51 server event show 344174b8-34fd-4017-ae29-b9084dcf3861 req-ea1b0dfc-3186-42a9-84ff-c4f4fb130fae -f json -c events
{
  "events": [
    {
      "event": "cold_migrate",
      "start_time": "2019-12-02T19:15:35.000000",
      "finish_time": "2019-12-02T19:15:36.000000",
      "result": "Error",
      "traceback": "  File \"/opt/stack/nova/nova/conductor/manager.py\",
      line 301, in migrate_server\n    host_list)\n
      File \"/opt/stack/nova/nova/conductor/manager.py\", line 367, in
      _cold_migrate\n    raise exception.NoValidHost(reason=msg)\n"
    },
    {
      "event": "conductor_migrate_server",
      "start_time": "2019-12-02T19:15:35.000000",
      "finish_time": "2019-12-02T19:15:36.000000",
      "result": "Error",
      "traceback": "  File \"/opt/stack/nova/nova/compute/utils.py\",
      line 1410, in decorated_function\n    return function(self, context,
      *args, **kwargs)\n  File \"/opt/stack/nova/nova/conductor/manager.py\",
      line 301, in migrate_server\n    host_list)\n
      File \"/opt/stack/nova/nova/conductor/manager.py\", line 367, in
      _cold_migrate\n    raise exception.NoValidHost(reason=msg)\n"
    }
  ]
}

日志

默认情况下,系统上的所有日志都包含全局请求 ID 和本地请求 ID(如果可用)。这允许管理员跟踪 API 请求处理,因为它在所有不同的 nova 服务或 nova 调用期间的其他组件服务之间过渡。

当 nova 服务在 X-Openstack-Request-Id 头中接收到其他组件的本地请求 ID 时,本地请求 ID 会输出到日志以及 nova 服务的本地请求 ID。

提示

如果在客户端库中使用会话客户端,请将 DEBUG 级别设置为 keystoneauth 日志级别。如果不是,请将 DEBUG 级别设置为客户端库包。例如,glanceclientcinderclient

下面提供了示例日志输出。在此示例中,nova 正在使用本地请求 ID req-034279a7-f2dd-40ff-9c93-75768fda494d,而 neutron 正在使用本地请求 ID req-39b315da-e1eb-4ab5-a45b-3f2dbdaba787

Jun 19 09:16:34 devstack-master nova-compute[27857]: DEBUG keystoneauth.session [None req-034279a7-f2dd-40ff-9c93-75768fda494d admin admin] POST call to network for http://10.0.2.15:9696/v2.0/ports used request id req-39b315da-e1eb-4ab5-a45b-3f2dbdaba787 {{(pid=27857) request /usr/local/lib/python2.7/dist-packages/keystoneauth1/session.py:640}}

注意

本地请求 ID 对于创建“调用图”很有用。

实例故障

Nova 经常为处理 API 请求时发生的异常添加实例故障数据库条目。这通常包括更多面向管理员的信息,例如堆栈跟踪。对于状态为 ERRORDELETED 的服务器,GET /servers/{server_id} 请求将在 server 资源响应体中包含一个 fault 对象。例如

GET https://10.211.2.122/compute/v2.1/servers/c76a7603-95be-4368-87e9-7b9b89fb1d7e
{
   "server": {
      "id": "c76a7603-95be-4368-87e9-7b9b89fb1d7e",
      "fault": {
         "created": "2018-04-10T13:49:40Z",
         "message": "No valid host was found.",
         "code": 500
      },
      "status": "ERROR",
      ...
   }
}

通知

在许多情况下,还会发出描述错误的通知。这是一个面向管理员的 API,在将其视为结构化日志时效果最佳。

同步故障

如果处理我们的 API 请求时发生错误,您将收到非 2xx API 状态码。系统还在响应体中返回有关故障的其他信息。

示例:故障:JSON 响应

{
   "itemNotFound":{
      "code": 404,
      "message":"Aggregate agg_h1 could not be found."
   }
}

为了方便起见,错误 code 返回在响应体中。 message 部分返回适合向最终用户显示的易于理解的消息。 details 部分是可选的,可能包含信息——例如,堆栈跟踪——以帮助跟踪错误。 details 部分可能不适合向最终用户显示。

故障的根元素(例如,computeFault)可能会根据错误的类型而变化。以下链接包含一个可能的元素列表及其关联的错误代码。

有关可能的错误代码的更多信息,请参见:https://specs.openstack.org/openstack/api-wg/guidelines/http/response-codes.html

异步故障

错误可能发生在服务器构建期间或服务器执行操作时。

在这些情况下,服务器通常被置于 ERROR 状态。对于某些操作,例如调整大小,操作可能会失败,但实例会在尝试操作之前优雅地返回到其原始状态。在这两种情况下,您应该能够从上面描述的 服务器操作 API 中找到更多信息。

当服务器被置于 ERROR 状态时,故障会嵌入到有问题的服务器中。请注意,这些异步故障遵循与同步故障相同的格式。故障包含错误代码、人类可读的消息以及有关错误的可选详细信息。此外,异步故障可能还包含一个 created 时间戳,该时间戳指定了故障发生的时间。

示例:处于错误状态的服务器:JSON 响应

{
    "server": {
        "id": "52415800-8b69-11e0-9b19-734f0000ffff",
        "tenant_id": "1234",
        "user_id": "5678",
        "name": "sample-server",
        "created": "2010-08-10T12:00:00Z",
        "hostId": "e4d909c290d0fb1ca068ffafff22cbd0",
        "status": "ERROR",
        "progress": 66,
        "image" : {
            "id": "52415800-8b69-11e0-9b19-734f6f007777"
        },
        "flavor" : {
            "id": "52415800-8b69-11e0-9b19-734f216543fd"
        },
        "fault" : {
            "code" : 500,
            "created": "2010-08-10T11:59:59Z",
            "message": "No valid host was found. There are not enough hosts available.",
            "details": [snip]
        },
        "links": [
            {
                "rel": "self",
                "href": "http://servers.api.openstack.org/v2/1234/servers/52415800-8b69-11e0-9b19-734f000004d2"
            },
            {
                "rel": "bookmark",
                "href": "http://servers.api.openstack.org/1234/servers/52415800-8b69-11e0-9b19-734f000004d2"
            }
        ]
    }
}