使用Nomad构建弹性基础架构:重新启动任务

Nomad是一个功能强大、灵活的调度器,适用于长期运行的服务和批处理任务。通过广泛的驱动程序,Nomad可以调度基于容器的工作负载、原始二进制文件、java应用程序等等。Nomad操作简单,易伸缩,与HashiCorp Consul(服务注册),Vault(证书管理)产品无缝集成。

Nomad为开发人员提供了自助服务基础设施。Nomad任务使用高级声明格式语法进行描述,该语法是版本控制的,并将基础结构作为代码进行推广。一旦任务提交给Nomad,它就负责部署和确保服务的可用性。运行Nomad的好处之一是提高了计算基础设施的可靠性和弹性。

欢迎来到我们关于用Nomad构建弹性基础设施的系列文章,在这里我们将探讨Nomad如何处理意外故障、停机和集群基础设施的日常维护,通常不需要操作员干预。

在第一篇文章中,我们将了解Nomad如何自动重启失败和无响应的任务,以及如何将反复失败的任务重新调度到其他节点。

Tasks and job 声明

Diagram showing simplified Nomad job workflow.

一个Nomad task是由其驱动程序在Nomad客户端节点上执行的命令、服务、应用程序或其他工作负载。task可以是短时间的批处理作业(batch)或长时间运行的服务(service),例如web应用程序、数据库服务器或API。

Tasks是在用HCL语法的声明性job规范中定义的。Job文件提交给Nomad服务端,服务端决定在何处以及如何将job文件中定义的task分配给客户端节点。另一种概念化的理解是:job规范表示工作负载的期望状态,Nomad服务端创建并维护其实际状态。

job定义的层次是:job→group→task。每个job文件只有一个job,但是一个job可能有多个group,每个group可能有多个task。group包含一组要放在同一个节点上的task。

下面是一个定义Redis工作负载的简单job文件:

job "example" {
  datacenters = ["dc1"]
  type = "service"

  constraint {
    attribute = "${attr.kernel.name}"
    value     = "linux"
  }
  group "cache" {
    count = 1

    task "redis" {
      driver = "docker"

      config {
        image = "redis:3.2"
      }
      resources {
        cpu    = 500 # 500 MHz
        memory = 256 # 256MB
      }
    }
  }
}

job作者可以为他们的工作负载定义约束和资源。约束(constraint)通过内核类型和版本等属性限制了工作负载在节点上的位置。资源(resources)需求包括运行task所需的内存、网络、CPU等。

有三种类型的job:systemservicebatch,它们决定Nomad将用于此job中task的调度器service 调度器被设计用来调度永远不会宕机的长寿命服务。batch作业对短期性能波动的敏感性要小得多,寿命也很短,几分钟到几天就可以完成。system调度器用于注册应该在满足作业约束的所有客户端上运行的作业。当某个客户端加入到集群或转换到就绪状态时也会调用它。

Nomad允许job作者为自动重新启动失败和无响应的任务指定策略,并自动将失败的任务重新调度到其他节点,从而使任务工作负载具有弹性。

Diagram showing Nomad job workflow, local restarts, and rescheduling.

重启失败的任务

任务失败可能发生在任务未能成功完成时,例如批处理(batch)类型作业或服务(service)由于致命错误或内存耗尽而失败。

Nomad将根据job文件的restart节中的指令在同一个节点上重启失败的任务。attempts指定允许重启的次数,delay指定Nomad在重启任务之前应该等待多长时间,interval限制尝试重新启动到间隔时间的时间量。使用(fail)模式指定在给定间隔内的所有重启尝试都已耗尽之后,如果job没有运行,Nomad应该做什么。

默认的失败模式是fail,它告诉Nomad不要尝试重启job。这是对非幂等job的推荐值,这些job在几次失败后不太可能成功。另一个选项是delay,告诉Nomad在重启作业之前等待interval指定的时间。

下面的restart节告诉Nomad在30分钟内最多重启2次,每次重启之间延迟15秒,在2次重启之后不要再尝试重启。这也是非批处理类型job的默认重启策略。


group "cache" {
  ...
  restart {
    attempts = 2
    interval = "30m"
    delay = "15s"
    mode = "fail"
  }
  task "redis" {
    ...
  }
}

这种本地重启行为旨在使任务对bug、内存泄漏和其他临时问题具有弹性。这类似于使用过程管理器,例如systemd、upstart或Nomad外部的runit。

重启没有响应的任务

另一个常见的场景是需要重启一个任务,该任务还没有失败,但已经变得没有响应或不健康。

Nomad将根据check_restart节中的指令重启没有响应的任务。这将与Consul健康检查功能结合。当健康检查失败limit次时,Nomad将重启任务。limit值为1表示在第一次失败时重启。默认值0则表示禁止基于健康检查的重启。

失败必须是连续的。一次健康检查将重置计数,因此在passing状态和失败状态之间交替进行的服务可能不会重启。使用grace指定重启后恢复健康检查的等待时间。设置 ignore_warnings = true 让Nomad将警告状态当作一个passing状态,而不触发重启。

下面的check_restart策略告诉Nomad在其健康检查连续失败3次后重启Redis任务,在重启任务后等待90秒以恢复健康检查,并在警告状态下重启(除了失败之外)。

task "redis" {
  ...
  service {
    check_restart {
      limit = 3
      grace = "90s"
      ignore_warnings = false
    }
  }
}

在传统的数据中心环境中,重启失败的任务通常由流程管理器(process supervisor)处理,该管理器需要由操作员配置。自动检测和重新启动不健康的任务更加复杂,需要定制脚本集成监控系统或操作员干预。而对于Nomad,它们会自动发生,不需要操作员干预。

重新调度失败任务

在指定的重启次数之后没有成功运行的任务可能会失败,原因是它们运行的节点出现了问题,例如硬件故障、内核死锁或其他不可恢复的错误。

使用reschedule节,操作员告诉Nomad在什么情况下要将失败的作业重新调度(reschedule)到另一个节点。

Nomad更喜欢重新调度到以前没有用于此任务的节点。与restart节一样,您可以使用attempts指定Nomad应该尝试的重新调度的次数,delay指定Nomad应该在重新调度尝试之间等待多长时间,interval指定重新调度尝试限制的间隔时间。

另外,使用delay_function指定用于计算初始延迟后的后续重新调度尝试的函数。选项有常数(constant)、指数(exponential)和斐波那契数(fibonacci)。对于service任务,斐波那契调度具有快速重新调度的特性,它可以在短时间内从中断中恢复,同时减慢速度以避免在较长时间内中断时出现中断。当使用指数或斐波那契delay_function时,使用max_delay设置延迟时间的上限,在此之后延迟时间不会增加。将unlimited设置为true或false以允许无限制的重新调度尝试。

要完全禁用重新调度,设置 attempts = 0 unlimited = false

下面的reschedule 节告诉Nomad尝试重新调度任务组无限次,并在随后的尝试之间以指数级增加延迟,开始延迟30秒,最多1小时。

group "cache" {  
...  reschedule {    
    delay          = "30s"    
    delay_function = "exponential"    
    max_delay      = "1hr"    
    unlimited      = true  
    }
}

reschedule 节不适用于system作业,因为它们在每个节点上都运行。

从Nomad 0.8.4版本开始,reschedule 节在部署期间应用。

在传统的数据中心中,节点故障将由监控系统检测到,并触发报警给操作员。然后操作人员需要手动进行干预,要么恢复失败的节点,要么将工作负载迁移到另一个节点。有了重新调度功能,操作员可以为最常见的故障场景进行规划,Nomad将自动响应,无需人工干预。Nomad应用了合理的默认值,这样大多数用户都可以在本地重新启动和重新调度,而不必考虑各种重启参数。

总结

在我们用Nomad构建弹性基础架构系列的第一篇文章中,我们介绍了Nomad如何通过自动重新启动和重新调度失败和无响应的任务,为计算基础架构提供弹性。

对于失败的任务,操作员使用restart节指定Nomad的本地重启策略。当与Consul和check_restart节一起使用时,Nomad将根据重启参数在本地重启无响应的任务。操作员通过reschedule 节指定Nomad重新调度失败任务的策略。

在下一篇文章中,我们将讨论Nomad客户端如何通过驱动健康检查和活跃的心跳来实现快速、准确的调度以及自我修复。

猜你喜欢

转载自blog.csdn.net/zl1zl2zl3/article/details/82932103
今日推荐