容器编排服务变更策略调研

本文调研目前流行的三款容器编排平台的服务变更策略,包括kubernetes、swarm、nomad。 其中它们的版本信息如下:

平台 版本
kubernetes v1.8
swarm v1.2.8
nomad v0.6.3

下面分别介绍一下这些平台的服务变更策略。

kubernetes

在Kubernetes中,是由deployment控制器来控制服务变更的过程,它目前提供了两种服务变更策略,分别是:

下面分别介绍一下这两种服务变更策略。

Recreate

Recreate这种服务变更策略非常简单粗暴,要把deployment关联的现存Pod全部杀掉之后,才能进行升级。

RollingUpdate

RollingUpdate是滚动更新的意思,可以通过这种策略来精确的控制服务变更的过程。在deployment中有两个字段是与服务变更的过程有关,分别是Max UnavailableMax Surge,下面分别介绍一下这两个字段的含义。

Max Unavailable

.spec.strategy.rollingUpdate.maxUnavailable是一个可选的字段,用来表明在升级过程中Pod的最大不可用数目,如果超过这个数目的话,deployment便不会销毁旧的实例,停止更新的过程。

这个值可以是一个绝对数值,也可以是一个百分比,默认值是25%。有一点需要注意的是,当.spec.strategy.rollingUpdate.maxSurge为0时,.spec.strategy.rollingUpdate.maxUnavailable不能为0。

举个例子当该值设置成30%时,deployment会立马将旧的ReplicaSet缩减为原来的70%,然后新建新的ReplicaSet,当新的ReplicaSet已经ready之后才能继续完成升级操作。

Max Surge

.spec.strategy.rollingUpdate.maxSurge是一个可选字段,它表明了可以创建超过期望Pod个数的最大数目,它可以是一个绝对值,也可以是一个百分比形式。它的值和.spec.strategy.rollingUpdate.maxUnavailable不能同时为0。

举个例子,当这个值设置成30%时,当滚动更新开始时,新的ReplicaSet可以立马开始扩容,但是要保证新的ReplicaSet和旧的ReplicaSet的Pod数目不能超过Pod期望数目的130%

小结

比如deployment的定义如下:

那么在更新过程中,旧的ReplicaSet会缩容到70%,也就是7个Pod,新的ReplicaSet会扩容到6个Pod,要同时保证不可用的数目在30%以下,总的Pod数目在130%以下,当新的ReplicaSet有Pod启动好了,那么会继续缩容旧的ReplicaSet。 kubernetes Deployment

swarm

swarm是docker官方推出的一款容器编排管理工具,它通过docker service的形式来管理容器实例的变更过程。在创建docker service前,必须先初始化swarm集群,比如创建一个http服务:

# docker swarm init && docker service create --name http --replicas 2 -p 80:80 katacoda/docker-http-server:v1

可以通过docker service的方式来滚动更新和弹性扩展服务。涉及到服务的更新过程是通过docker service update来实现的,它有以下字段控制着实例的变更过程。

Docker Service

Nomad

Nomad是Hashicorp设计的一款容器编排系统,它拥有服务变更策略多种多样,包括了:

下面分别简单的介绍一下这几种服务变更策略。

RollingUpdate

RollingUpdate是滚动变更的意思,它是nomad第一个支持的服务变更策略,为了在jobtask中使用这种服务变更策略,需要在更新策略中使用update这个配置,也叫update stanza类似如下:

job "geo-api-server" {
  ...
  group "api-server" {
    ...
    # Add an update stanza to enable rolling updates of the service
    update {
      max_parallel = 2
      min_healthy_time = "30s"
      healthy_deadline = "10m"
    }
    ...
  }
}

在这个例子中通过增加update stanzaapi-server这个任务组增加了服务变更策略,当api-server这个任务组需要更新时,会首先创建2个新版本的实例,并且要求新版本的实例要保持Health状态30秒,才可以继续进行服务变更。

也就是说nomadRollingUpdate的服务更新策略与update stanza息息相关,下面简单的介绍一下update stanza

update Stanza

update Stanza指明了任务组的更新策略,如果不指定的话那么服务变更时将不会出发滚动升级和Cannary,主要一下更新参数:

Blue/Green & Canary Deployments

有时候rolling upgrades在生产环境中没有提供足够的灵活性,很多企业在生产环境更新时,会通过部署一个canary,技术上叫做蓝绿部署,这种方式来确保服务能够稳定的变更,以减少不可用的时间。

这个是通过update stanza中的canary配置来实现的,假如配置如下:

job "docs" {
  ...
  group "api" {
    count = 5

    update {
      max_parallel     = 1
      canary           = 5
      min_healthy_time = "30s"
      healthy_deadline = "10m"
      auto_revert      = true
    }
    ...
  }
}

在升级时,会创建5个新版本的实例(canary部分),通过查看部署信息:

Latest Deployment
ID          = 32a080c1
Status      = running
Description = Deployment is running but requires promotion

如果本次的升级没有异常时,可以进行主体服务的升级,将旧版本的服务下掉

# 将旧版本的5个实例下掉
nomad deployment promote 32a080c1

如果升级出现异常,可以回滚上个版本

nomad deployment fail 32a080c1

这样新版本的5个实例会被下掉,本次上线服务主体不受影响。

Handling Signals

现代操作系统支持信号机制,nomad在杀掉一个应用之前,会给这个应用发送一个信号,这个信号是可以配置的,这种方式允许一些应用当被nomad杀掉的时候,有机会进行优雅的退出、销毁资源操作等等。同时nomad允许指定一个时间,在杀死该应用时,等待用户程序的退出。

nomad终结一个进程时,会给该进程发送SIGINT信号,在nomad下的进程应该响应这个信号,以优雅的退出,如果超过配置的时间内还没有处理该信号,那么这个进程会被强制杀掉。


纸上得来终觉浅,绝知此事要躬行~