实施 Sahara 集群验证检查

https://blueprints.launchpad.net/sahara/+spec/cluster-verification

目前我们没有通过 Sahara 界面检查集群进程状态的功能。我们的计划是实施集群验证,并能够为特定集群重新触发这些验证。

问题描述

Sahara 没有集群进程健康状况的检查。集群可能已损坏或不可用,但 Sahara 仍然认为其状态为 ACTIVE。这可能会导致最终用户损失等等。

提议的变更

首先,让我们在此进行一些重要的定义。集群健康检查是对集群进行有限功能检查。例如,实例的可访问性、将一些数据写入 HDFS 等。每个健康检查都将实现为类对象,实现来自抽象基类 (abc) 的几个重要方法

class ExampleHealthCheck(object):
    def __init__(self, cluster, *args, **kwargs):
        self.cluster = cluster
        # other stuff

    @abc.abstractmethod
    def available(self):
        # method will verify

    @abc.abstractmethod
    def check(self):
        # actual health will in here

    def execute(self):
        # based in availability of the check and results
        # of check will write correct data into database

健康检查的 check 方法的预期行为是在一切正常时返回一些重要数据,并在出现错误时引发带有详细失败原因信息的异常。让我们描述健康检查的重要状态。

  • GREEN 状态:集群健康,健康检查通过。在这种情况下,描述中可以包含以下信息:HDFS 可用于 写入数据所有 datanode 都处于活动状态且可用

  • YELLOW 状态:YellowHealthError 将作为操作结果引发,这意味着集群可能存在问题。但是,集群仍然可以运行作业。例如,在异常消息中,我们将看到以下信息:10 datanode 中有 2 个无法工作

  • RED 状态:在这种情况下,将引发 RedHealthError,这意味着集群存在严重问题,我们无法保证集群仍然能够执行操作。例如,活动 datanode 的数量少于复制因子 可能是这种情况下的消息。

  • CHECKING 状态,健康检查仍在运行或刚刚创建。

集群验证是多个集群健康检查的组合。集群验证将指示集群的当前状态:GREENYELLOWRED。我们将集群的最新验证存储在数据库中。我们还将验证结果发送到 Ceilometer,以查看集群健康的进度。

还有一种想法是在多个健康检查中运行几个作业,但这可能会对集群健康造成太大损害,可能以后再做。

我们还可以引入一个定期任务来刷新集群的健康状态。

因此,应该在新的 sahara.conf 部分 cluster_health_verification 中添加几个额外的选项

  • enable_health_verification 默认情况下将为 True,允许禁用定期集群验证

  • verification_period 变量用于定义定期任务中两次健康验证之间的周期。默认情况下,我建议每 10 分钟运行一次验证。

建议的检查

本节将描述集群功能的的基本检查。一些检查会影响几乎所有插件,而另一些检查仅特定于某个插件。

基本检查:

这里有几个适用于所有可能集群的基本检查。

  • 检查以验证所有实例的可访问性。如果某些实例不可访问,我们将处于 RED 状态。

  • 检查是否挂载了所有卷。如果某个卷未挂载,我们将处于 YELLOW 状态。

HDFS 检查:

  • 将验证 namenode 是否正在运行的检查。当然,在 CDH 和 Ambari 插件的 HA 模式下,只有 vanilla 插件集群和未部署 HA 模式的集群才会出现 RED 状态。

  • 将验证活动 datanode 数量的检查。只有当所有 datanode 都处于活动状态时,我们才会处于 GREEN 状态,当活动 datanode 的数量少于 dfs.replicaton 时,我们将处于 RED 状态,在所有其他情况下,我们将处于 YELLOW 状态。

  • 检查以验证集群是否能够将一些数据写入 HDFS。如果出现问题,我们将处于 RED 状态。

  • HDFS 中的可用空间量。我们将此值与 HDFS 中保留的内存进行比较,如果可用空间量小于提供的量,则检查将被认为失败。如果检查未通过,我们将处于 YELLOW 状态,并建议使用额外的 datanode 扩展集群(或清理一些数据)。我认为,我们不应该在此处添加任何额外的配置选项,只是因为此检查永远不会报告 RED 状态。

HA 检查:

  • 如果至少一个备用服务正在运行,则处于 YELLOW 状态;否则,处于 RED 状态。同时影响 YARN 和 HDFS。

YARN 检查:

  • Resourcemanger 处于活动状态。显然,如果出现问题,则处于 RED 状态。

  • 活动 nodemanager 的数量。YELLOW 状态,如果某些内容不可用,RED 状态,如果活动 nodemanager 的数量少于 50%

Kafka 检查:

  • 检查 Kafka 是否可运行:创建示例主题,将一些消息放入主题,消费消息。RED 状态,如果出现问题。

CDH 插件检查:

本节将描述 CDH 插件的特定检查。对于这些检查,我们需要扩展 Sahara 当前的 cm_api 工具实现。API 方法可以获取集群的当前健康状况。以下是 yarn 服务的响应示例。

这是一个糟糕的案例示例

"yarn01": {
  "checks": [
    {
      "name": "YARN_JOBHISTORY_HEALTH",
      "summary": "GOOD"
    },
    {
      "name": "YARN_NODE_MANAGERS_HEALTHY",
      "summary": "CONCERNING"
    },
    {
      "name": "YARN_RESOURCEMANAGERS_HEALTH",
      "summary": "BAD"
    }
  ],
  "summary": "BAD"
}

以及好的案例示例

"yarn01": {
  "checks": [
    {
      "name": "YARN_JOBHISTORY_HEALTH",
      "summary": "GOOD"
    },
    {
      "name": "YARN_NODE_MANAGERS_HEALTHY",
      "summary": "GOOD"
    },
    {
      "name": "YARN_RESOURCEMANAGERS_HEALTH",
      "summary": "GOOD"
    }
  ],
  "summary": "GOOD"
}

基于上述响应,我们将计算集群的健康状况。Cloudera 可以通过 API 返回的可能状态是 DISABLED,当服务停止时,以及 CONCERNING,如果即将出现问题。在此健康检查中,Sahara 的状态将根据以下表计算

+--------------+--------------------------------+
| Sahara state |   Cloudera state               |
+--------------+--------------------------------+
| GREEN        | All services GOOD              |
+--------------+--------------------------------+
| YELLOW       | At least 1 service CONCERNING  |
+--------------+--------------------------------+
| RED          | At least 1 service BAD/DISABLED|
+--------------+--------------------------------+

有关 Cloudera 健康检查的更多信息,请参见此处:[0]

Ambari 插件:

当前的 HDP 2.0.6 将仅支持基本的验证。这里的重点是为 Ambari 插件实施额外的检查。Ambari 插件中存在一些检查的想法

  • Ambari 警报验证。Ambari 插件在集群的当前状态出现问题时会发出一些警报。我们可以通过 Ambari API 获取警报。如果这里至少有一个警报,建议使用 YELLOW 状态进行验证,否则我们将使用 GREEN 状态。

  • Ambari 服务检查验证。Ambari 插件在这里有很多服务检查,可以通过 Ambari API 重新触发。这些检查在 [1] 中有很好的描述。如果至少一个检查失败,我们将使用 RED 状态,否则使用 GREEN 状态。

替代方案

所有健康检查都可以通过该选项禁用。

数据模型影响

数据模型影响的图形描述

+----------------------------+    +-------------------------------+
|       verifications        |    |           health_checks       |
+----------------------------+    +-----------------+-------------+
|    id      | Primary Key   |    | id              | Primary Key |
+------------+---------------+    +-----------------+-------------+
| cluster_id | Foreign Key   |  +-| verification_id | Foreign Key |
+----------------------------+  | +-----------------+-------------+
| created_at |               |  | | created_at      |             |
+------------+---------------+  | +-----------------+-------------+
| updated_at |               |  | | updated_at      |             |
+------------+---------------+  | +-----------------+-------------+
| checks     |               | <+ | status          |             |
+------------+---------------+    +-----------------+-------------+
| status     |               |    | description     |             |
+------------+---------------+    +-----------------+-------------+
                                  | name            |             |
                                  +-----------------+-------------+

我们将有两个额外的表来存储验证和健康检查。

第一个验证表将包含以下列:id、cluster_id(外键)、created_at、updated_at。

还将添加一个新表来存储健康检查结果。此表将包含以下列:id、verification_id、description、status、created_at 和 updated_at。

我们将获得集群验证和集群健康检查之间的级联关系,以便从健康检查正确访问集群验证,反之亦然。同样的关系将存在于集群和验证之间,以达到相同的目的。

此外,为了聚合最新验证的结果以及禁用/启用特定集群的验证,将向集群模型添加一列:verifications_status。我们不会为此目的使用 status,只是为了将这两个变量分开(我们已经在 Sahara 的许多地方使用 status)。

验证示例

  1. 一个健康检查仍在运行

"cluster_verification": {
  "id": "1",
  "cluster_id": "1111",
  "created_at": "2013-10-09 12:37:19.295701",
  "updated_at": "2013-10-09 12:37:19.295701",
  "status": "CHECKING",
  "checks": [
    {
      "id": "123",
      "created_at": "2013-10-09 12:37:19.295701",
      "updated_at": "2013-10-09 12:37:19.295701",
      "status": "GREEN",
      "description": "some description",
      "name": "same_name"
    },
    {
      "id": "221",
      "created_at": "2013-10-09 12:37:19.295701",
      "updated_at": "2013-10-09 12:37:19.295701",
      "status": "CHECKING",
      "description": "some description",
      "name": "same_name"
    },
  ]
}
  1. 所有健康检查都已完成,但有一个失败

"cluster_verification": {
  "id": "2",
  "cluster_id": "1112",
  "created_at": "2013-10-09 12:37:19.295701",
  "updated_at": "2013-10-09 12:37:30.295701",
  "STATUS": "RED",
  "checks": [
    {
      ..
      "status": "RED",
      "description": "Resourcemanager is down",
      ..
    },
    {
      ..
      "status": "GREEN",
      "description": "HDFS is healthy",
    }
  ]
}

REST API 影响

接收集群验证结果的机制非常简单。我们将只使用常规 GET 方法来获取集群。

因此,主要的 API 方法将如下所示:GET <tenant_id>/clusters/<cluster_id>。在这种情况下,我们将返回包含验证的集群的详细信息。

响应示例

{
  "status": "Active",
  "id": "1111",
  "cluster_template_id": "5a9a09a3-9349-43bd-9058-16c401fad2d5",
  "name": "sample",
  "verifications_status": "RUNNING",
  ..
  "verification": {
    "id": "1",
    "cluster_id": "1111",
    "created_at": "2013-10-09 12:37:19.295701",
    "updated_at": "2013-10-09 12:37:19.295701",
    "checks": [
      {
        "id": "123",
        "created_at": "2013-10-09 12:37:19.295701",
        "updated_at": "2013-10-09 12:37:19.295701",
        "status": "GREEN",
        "description": "some description",
        "name": "same_name"
      },
      {
        "id": "221",
        "created_at": "2013-10-09 12:37:19.295701",
        "updated_at": "2013-10-09 12:37:19.295701",
        "status": "CHECKING",
        "description": "some description",
        "name": "same_name"
      },
    ]
  }
}

要重新触发集群验证,需要向以下 API 方法添加一些额外的行为

PATCH <tenant_id>/clusters/<cluster_id>

如果将以下数据提供给此 API 方法,我们将重新触发验证

{
  'verification': {
    'status': 'START'
  }
}

如果集群的验证被禁用或验证正在集群上运行时,将拒绝启动。

我们还可以禁用特定集群的验证,以避免不必要的噪声验证,直到通过以下请求数据修复健康问题

{
  'verification': {
    'status': 'DISABLE'
  }
}

并且在我们需要重新启用健康检查时启用它。如果用户尝试禁用验证,则只会禁用未来的验证,因此健康检查仍然会运行。

如果向此数据添加任何其他内容,我们将把请求标记为无效。我们还将实施新的验证方法,以拒绝已经在运行一个验证的集群上的验证。

其他最终用户影响

需要通过 python-saharaclient 实施请求来运行检查并获取其结果。

部署者影响

无。

开发者影响

无。

Sahara-image-elements impact

无。

Sahara-dashboard / Horizon 影响

Dashboard 影响需要在集群详细信息中添加一个新选项卡,其中包含验证结果。

实现

负责人

主要负责人

vgridnev

其他贡献者

apavlov-n, esikachev

工作项

  1. 实施基本的验证框架(带有基本检查)

  2. Python-saharaclient 支持添加

  3. 应实施 CLI 支持

  4. 在 Horizon 中实施带有验证结果的选项卡

  5. 需要添加带有新 api 方法的 WADL 文档

  6. 应实施所有其他检查

  7. 应添加对场景框架的支持,以允许重新触发。

  8. 实施将历史记录发送到 Ceilometer。

依赖项

测试

该功能将通过单元测试和手动测试覆盖。将添加一个新的测试提交(不用于合并),以显示所有验证都已通过(由于我们正处于场景框架的移动过程中)。

文档影响

文档应使用其他信息进行更新,说明 如何 修复 健康检查结果中描述的问题。

参考资料

[0] http://www.cloudera.com/content/www/en-us/documentation/enterprise/latest/topics/cm_ht.html [1] https://cwiki.apache.org/confluence/display/AMBARI/Running+Service+Checks