分类 技术志 下的文章

Kubernetes网络插件(CNI)基准测试的最新结果

本文翻译自Alexis Ducastel的文章《Benchmark results of Kubernetes network plugins (CNI) over 10Gbit/s network (Updated: April 2019)》

本文是我之前的基准测试的最新更新,这次测试在最新版Kubernetes 1.14上运行,其中CNI版本在2019年4月更新。

首先,非常感谢Cilium团队对我的帮助,包括协助审查测试结果以及更正我的指标监控脚本。

自2018年11月以来都有哪些新变化

如果你只是想知道自上次以来发生的变化,这里有一个简短的总结:

Flannel仍然是CNI竞赛中最快和最精简的那个选手,但它仍然不支持NetworkPolicies(网络策略),也不支持加密。

Romana不再维护,因此我们决定将其从基准测试中剔除。

WeaveNet现在同时支持Ingress和Egress的NetworkPolicies!但性能要略低于之前的版本。

如果您想获得最佳性能,Calico仍需要手动定制MTU。Calico为安装CNI提供了两个新选项,无需专用ETCD存储

  • 将状态存储在Kubernetes API中作为数据存储区(集群<50个节点)
  • 使用Typha代理将状态存储在Kubernetes API中,以减轻K8S API(集群> 50个节点)的压力

Calico宣布在Istio之上支持应用层策略(Application Layer Policy),为应用层带来安全性。

Cilium现在支持加密!Cilium使用IPSec隧道提供加密,并为WeaveNet提供了加密网络的替代方案。但是,在启用加密的情况下,WeaveNet比Cilium更快。这是由于Cilium 1.4.2仅支持CBC加密,若使用GCM将会更好,但它将是1.5版本的Cilium的一部分。

由于嵌入了ETCD operator,因此Cilium现在更容易部署。

Cilium团队还通过降低内存消耗和CPU成本,努力减少CNI占用空间。但他们仍然比其他选手更重。

基准测试的上下文

基准测试是在通过Supermicro 10Gbit交换机连接的三台Supermicro裸机服务器上进行的。服务器通过DAC SFP +无源电缆直接连接到交换机,并在激活巨型帧(MTU 9000)的同一VLAN中设置。

Kubernetes 1.14.0​在Ubuntu 18.04 LTS上运行,运行Docker 18.09.2(此linux版本中的默认docker版本)。

为了提高可重复性,我们选择始终在第一个节点上设置master,在第二个服务器上设置基准测试的服务器部分,在第三个服务器上设置客户端部分。这是通过Kubernetes deployments中的NodeSelector实现的。

以下是我们将用于描述基准测试结果和解释的表情图:

img{512x368}

为基准测试选择CNI

这个基准测试仅仅关注那些入选kubernetes正式文档:“create a single master cluster with kubeadm”中的CNI列表。在提到的9个CNI中,我们只测试其中的6个,不包括那些我们无法轻松安装和/或不通过以下文档开箱即用的工具(Romana,Contiv-VPP和JuniperContrail / TungstenFabric)

以下是我们将要比较的CNI列表:

  • Calico v3.6
  • Canal v3.6(事实上,Flannel用于网络+ Calico用于防火墙)
  • Cilium 1.4.2
  • Flannel 0.11.0
  • Kube-router 0.2.5
  • WeaveNet 2.5.1

安装

CNI越容易设置,我们对其第一印象就越好。所有参与基准测试的CNI都很容易设置(一个或两个命令行)。

如前所述,服务器和交换机都配置了Jumbo帧激活(通过将MTU设置为9000)。我们非常感谢CNI可以自动发现要使用的MTU,具体取决于适配器。事实上,Cilium和Flannel是唯一能够正确自动检测MTU的选手。大多数其他CNI在GitHub中引发了启用MTU自动检测的问题,但是现在,我们需要通过修改Calico,Canal和Kube-router的ConfigMap或WeaveNet的ENV var来手动修复它。

也许您想知道错误的MTU会产生什么影响?这里有一个图表,显示WeaveNet与默认MTU和WeaveNet与Jumbo帧之间的区别:

img{512x368}

那么,既然我们知道MTU对性能非常重要,那么这些CNI如何自动检测MTU:

img{512x368}

正如我们在上图中看到的,我们必须对Calico,Canal,Kube-router和WeaveNet应用一些MTU调整以获得最佳性能。Cilium和Flannel能够自行正确地自动检测MTU,确保开箱即用的最佳性能。

安全

在比较这些CNI的安全性时,我们谈论两件事:它们加密通信的能力,以及它们对Kubernetes网络策略的实现(根据实际测试,而不是来自他们的文档)。

只有两个CNI可以实现加密通信:Cilium和WeaveNet。通过将加密密码设置为CNI的ENV变量可以来启用WeaveNet加密。WeaveNet文档有点令人困惑,但这很容易做到。Cilium加密是通过创建Kubernetes Secrets和daemonSet修改的命令设置的(比WeaveNet复杂一点,但是Cilium有很棒的文档记录了它)。

在网络策略实现方面,通过实施Ingress和Egress规则,Calico,Canal,Cilium和WeaveNet是最好的控制面板。Kube-router实际上只实现了Ingress规则。

Flannel没有实现网络策略。

以下是结果摘要:

img{512x368}

性能

该基准测试显示每次测试的三次运行(至少)的平均带宽。我们正在测试TCP和UDP性能(使用iperf3),真实应用程序,如HTTP(使用Nginx和curl),或FTP(使用vsftpd和curl),最后是使用SCP协议进行应用程序加密的行为(使用OpenSSH服务器和客户端)。

对于所有测试,我们还在裸机节点(绿色条)上运行基准测试,以比较CNI与本机网络性能的有效性。为了与我们的基准比例保持一致,我们在图表上使用以下颜色:

  • 黄色=非常好
  • 橙色=好
  • 蓝色=一般
  • 红色=差

因为我们不关注错误配置的CNI的性能,所以我们只会显示MTU调整的CNI基准测试结果。(NOTA BENE:如果激活加密,Cilium无法正确计算MTU,因此您必须在v1.4中手动将MTU降低到8900.下一版1.5将自动适应。)

结果如下:

img{512x368}

每个CNI都在TCP基准测试中表现良好。由于加密成本,启用加密的CNI远远落后于其他CNI。

img{512x368}

同样,在UDP基准测试中,所有CNI都表现良好。加密的CNI现在彼此非常接近。Cilium落后于其竞争对手,但事实上,它仅略高于裸机结果的2,3%,这是公平的。我们应该记住的是,Cilium和Flannel都是唯一能够正确自动检测MTU的CNI,从而提供了开箱即用的结果。

img{512x368}

真实世界的应用程序怎么样?使用HTTP基准测试,我们可以看到全局性能略低于TCP测试。即使HTTP支持TCP,在TCP基准测试中,iperf3配置为避免任何“TCP慢启动”副作用,这可以有效地影响HTTP基准测试。这里的每个选手的表现都相当不错,Kube-router有明显的优势,WeaveNet在这项测试中表现非常糟糕,比裸机少了约20%。Cilium加密和WeaveNet加密现在都远远落后于裸机性能。

img{512x368}

使用FTP,另一个TCP支持的协议,结果更加复杂。虽然Flannel和Kube-router的表现非常好,但是Calico,Canal和Cilium稍稍落后,在裸机速度下约为10%。WeaveNet与裸机性能相差甚远,差距为17>%。无论如何,WeaveNet的加密版本比Cilium加密的性能高出约40%。

img{512x368}

通过SCP,我们可以清楚地看到SSH协议的加密成本。大多数CNI表现良好,但WeaveNet再次落后于其他人。当然,由于双重加密成本(SSH加密+ CNI加密)。

以下是性能摘要总结:

img{512x368}

资源消耗

现在让我们比较这些CNI在负载很重的情况下处理所带来的资源消耗如何(在TCP 10Gbit传输期间)。在性能测试中,我们将CNI与裸金属(绿色条)进行比较。对于资源消耗测试,我们还显示了没有任何CNI设置的新闲置Kubernetes(紫色条)的消耗。然后我们可以计算出CNI真正消耗的开销。

让我们从内存方面开始吧。以下是传输期间以MB为单位的平均节点RAM使用率(无缓冲区/缓存)。

img{512x368}

Flannel和Kube-router表现非常好,只有大约50MB的内存占用,其次是Calico和Canal,70MB。WeaveNet的消费量明显高于其竞争对手,资源占用约为130MB。凭借400MB的内存占用,Cilium具有最高的基准内存消耗。

现在,让我们检查CPU消耗。警告:图形单位不是百分比,而是permil。因此裸金属的38 permil实际上是3.8%。结果如下:

img{512x368}

Calico,Canal,Flannel和Kube-router都非常高效的CPU使用,与没有CNI的kubernetes相比,开销仅多出2%。远远落后于WeaveNet,开销约为5%,然后是Cilium,CPU开销超过7%。

以下是资源消耗的摘要:

img{512x368}

摘要

以下是所有结果的汇总概述:

img{512x368}

结论

最后一部分是主观的,并传达了我自己对结果的解释。请记住,此基准测试仅在一个非常小的集群(3个节点)上测试单个连接中的吞吐速度。它不反映大型集群(> 50个节点)的网络行为,也没有多少连接并发。

如果你在相应的场景中,我建议使用以下CNI:

  • 您的群集中有低资源节点(只有几GB的RAM,几个核心)并且您不需要安全功能,请使用Flannel。它是我们测试过的最精简的CNI之一。此外,它与大量架构兼容(amd64,arm,arm64等)。它是唯一一个能够正确自动检测MTU的CNI,和Cilium一起,因此您无需配置任何内容即可使其正常工作。Kube-router也很好,但标准较低,需要您手动设置MTU。
  • 出于安全原因,您需要加密网络,请使用WeaveNet。如果您使用巨型帧并通过在环境变量中提供密码来激活加密,请不要忘记设置MTU大小。但话说回过来,忘掉性能,这就是加密的代价。
  • 对于其他常见用法,我会推荐Calico。这种CNI广泛用于许多kubernetes部署工具(Kops,Kubespray,Rancher等)。就像WeaveNet一样,如果您使用的是巨型帧,请不要忘记在ConfigMap中设置MTU。事实证明,它在资源消耗,性能和安全性方面具有多用途和高效性。

最后但并非最不重要的,我建议你关注Cilium的工作。他们的团队非常活跃,他们正在努力提高他们的CNI(功能,资源节约,性能,安全性,多集群跨越……),他们的路线图听起来非常有趣。

img{512x368}


我的网课“Kubernetes实战:高可用集群搭建、配置、运维与应用”在慕课网上线了,感谢小伙伴们学习支持!

我爱发短信:企业级短信平台定制开发专家 https://tonybai.com/
smspush : 可部署在企业内部的定制化短信平台,三网覆盖,不惧大并发接入,可定制扩展; 短信内容你来定,不再受约束, 接口丰富,支持长短信,签名可选。

著名云主机服务厂商DigitalOcean发布最新的主机计划,入门级Droplet配置升级为:1 core CPU、1G内存、25G高速SSD,价格5$/月。有使用DigitalOcean需求的朋友,可以打开这个链接地址:https://m.do.co/c/bff6eed92687 开启你的DO主机之路。

我的联系方式:

微博:https://weibo.com/bigwhite20xx
微信公众号:iamtonybai
博客:tonybai.com
github: https://github.com/bigwhite

微信赞赏:
img{512x368}

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。

使用nomad实现工作负载版本升级

书接上文

《使用nomad实现集群管理和微服务部署调度》一文中,我们介绍了使用nomad进行集群管理和工作负载调度的轻量级方案(相较于Kubernetes方案)。在本文中,我们继续对方案进行延展,介绍一下在nomad集群中工作负载版本升级的一些常用模式和实现方法,包括滚动升级蓝绿部署金丝雀部署

一. 初始状态

这里我们利用基于tcp+sni路由(listener端口为9996)的httpsbackend-sni-1的job作为演示job,该job的初始部署nomad job文件为:httpsbackend-tcp-sni-1.nomad (注:不同的是,这里将count初始值改为了3)。

当前httpsbackend-sni-1这个job的状态如下:

# nomad job status httpsbackend-sni-1
ID            = httpsbackend-sni-1
Name          = httpsbackend-sni-1
Submit Date   = 2019-04-08T10:57:29+08:00
Type          = service
Priority      = 50
Datacenters   = dc1
Status        = running
Periodic      = false
Parameterized = false

Summary
Task Group          Queued  Starting  Running  Failed  Complete  Lost
httpsbackend-sni-1  0       0         3        0       3         0

Allocations
ID        Node ID   Task Group          Version  Desired  Status    Created    Modified
7ac186b8  7acdd7bc  httpsbackend-sni-1  22       run      running   1m18s ago  1m1s ago
8a79085f  c281658a  httpsbackend-sni-1  22       run      running   1m18s ago  46s ago
f9ffef32  9e3ef19f  httpsbackend-sni-1  22       run      running   1m18s ago  59s ago
0ed95591  9e3ef19f  httpsbackend-sni-1  20       stop     complete  5d19h ago  7m16s ago
604d2151  9e3ef19f  httpsbackend-sni-1  20       stop     complete  5d19h ago  7m16s ago
06404fff  7acdd7bc  httpsbackend-sni-1  20       stop     complete  5d20h ago  7m14s ago

fabio路由表如下:

img{512x368}

# curl -k https://mysite-sni-1.com:9996/
this is httpsbackendservice, version: v1.0.0

接下来,我们就以这个job为基础,使用各种版本升级模式对其进行更新。

二. 滚动更新(rolling update)

下面是blog.itaysk.com上一篇文章中的有关滚动更新的示意图:

img{512x368}
可以大致看出所谓滚动更新就是对目标环境下老版本的程序进行逐批的替换,每批的数量可以是1,也可以大于1,根据目标实例的个数自定义。替换过程中,新老版本是并存的,直到所有目标实例都被替换为新版本。

nomad支持通过在job描述文件中增加update配置来支持滚动更新。我们创建httpsbackend-tcp-sni-1-rolling-update.nomad,考虑篇幅,这里仅列出与httpsbackend-tcp-sni-1.nomad的差异:

# diff httpsbackend-tcp-sni-1-rolling-update.nomad ./httpsbackend-tcp-sni-1.nomad
14,19d13
<     update {
<       max_parallel = 1
<       min_healthy_time = "30s"
<       healthy_deadline = "5m"
<     }
<
23c17
<         image = "bigwhite/httpsbackendservice:v1.0.1"
---
>         image = "bigwhite/httpsbackendservice:v1.0.0"

新job nomad文件使用了v1.0.1版本的httpsbackendservice image,增加了update {…}配置环节,其中的max_parallel指示的是滚动更新每批更新的数量,这里是1,也就是说一批仅用新版本替换一个老版本实例。

执行滚动更新:

# nomad job run httpsbackend-tcp-sni-1-rolling-update.nomad
==> Monitoring evaluation "8d39ab53"
    Evaluation triggered by job "httpsbackend-sni-1"
    Evaluation within deployment: "348ef16b"
    Allocation "88c1a29e" created: node "7acdd7bc", group "httpsbackend-sni-1"
    Evaluation status changed: "pending" -> "complete"
==> Evaluation "8d39ab53" finished with status "complete"

httpsbackendservice job的task group有三个task实例,因此更新需要一些时间,我们在更新过程中查看job status:

# nomad job status httpsbackend-sni-1
ID            = httpsbackend-sni-1
Name          = httpsbackend-sni-1
Submit Date   = 2019-04-08T13:06:35+08:00
Type          = service
Priority      = 50
Datacenters   = dc1
Status        = running
Periodic      = false
Parameterized = false

Summary
Task Group          Queued  Starting  Running  Failed  Complete  Lost
httpsbackend-sni-1  0       0         3        0       4         0

Latest Deployment
ID          = 348ef16b
Status      = running
Description = Deployment is running

Deployed
Task Group          Desired  Placed  Healthy  Unhealthy  Progress Deadline
httpsbackend-sni-1  3        1       0        0          2019-04-08T13:16:35+08:00

Allocations
ID        Node ID   Task Group          Version  Desired  Status    Created   Modified
88c1a29e  7acdd7bc  httpsbackend-sni-1  23       run      running   44s ago   41s ago
7ac186b8  7acdd7bc  httpsbackend-sni-1  22       run      running   2h9m ago  2h9m ago
8a79085f  c281658a  httpsbackend-sni-1  22       run      running   2h9m ago  2h9m ago
f9ffef32  9e3ef19f  httpsbackend-sni-1  22       stop     complete  2h9m ago  44s ago

我们看到nomad job status命令输出的信息中多出了“Latest Deployment”一个小节,在该小节中,我们看到了一个ID为348ef16b的deployment正在run。这个deployment对应的就是这次的滚动更新,我们看到下面的allocations列表中,一个version为22的allocation已经stop,一个version为23的allocation已经run,这说明nomad已经完成了一个task实例的版本升级。

我们再来查看一下job执行的最终状态:

# nomad job status httpsbackend-sni-1
ID            = httpsbackend-sni-1
Name          = httpsbackend-sni-1
Submit Date   = 2019-04-08T13:06:35+08:00
Type          = service
Priority      = 50
Datacenters   = dc1
Status        = running
Periodic      = false
Parameterized = false

Summary
Task Group          Queued  Starting  Running  Failed  Complete  Lost
httpsbackend-sni-1  0       0         3        0       6         0

Latest Deployment
ID          = 348ef16b
Status      = successful
Description = Deployment completed successfully

Deployed
Task Group          Desired  Placed  Healthy  Unhealthy  Progress Deadline
httpsbackend-sni-1  3        3       3        0          2019-04-08T13:18:43+08:00

Allocations
ID        Node ID   Task Group          Version  Desired  Status    Created    Modified
da1b545b  7acdd7bc  httpsbackend-sni-1  23       run      running   34s ago    2s ago
44da5693  9e3ef19f  httpsbackend-sni-1  23       run      running   1m25s ago  36s ago
88c1a29e  7acdd7bc  httpsbackend-sni-1  23       run      running   2m10s ago  1m26s ago
7ac186b8  7acdd7bc  httpsbackend-sni-1  22       stop     complete  2h11m ago  1m24s ago
8a79085f  c281658a  httpsbackend-sni-1  22       stop     complete  2h11m ago  34s ago
f9ffef32  9e3ef19f  httpsbackend-sni-1  22       stop     complete  2h11m ago  2m10s ago

我们看到job执行的最终结果:ID为348ef16b的deployment执行成功;所有version 为23的allocations都处于running状态。task group的三个task实例都处于healthy状态。这说明滚动更新成功了!

我们也可以通过nomad提供的deployment子命令查看deployment的状态,deployment id作为命令参数:

# nomad deployment list
ID        Job ID              Job Version  Status      Description
348ef16b  httpsbackend-sni-1  23           successful  Deployment completed successfully

# nomad deployment status 348ef16b
ID          = 348ef16b
Job ID      = httpsbackend-sni-1
Job Version = 23
Status      = successful
Description = Deployment completed successfully

Deployed
Task Group          Desired  Placed  Healthy  Unhealthy  Progress Deadline
httpsbackend-sni-1  3        3       3        0          2019-04-08T13:18:43+08:00

滚动更新后的路由:

img{512x368}

测试一下部署成功的新版本服务:

# curl -k https://mysite-sni-1.com:9996/
this is httpsbackendservice, version: v1.0.1

三. 金丝雀部署(canary deployment)

金丝雀部署是另外一种十分有用的部署模式,下面示意图来自blog.itaysk.com:

img{512x368}

金丝雀 (Canary)得名于矿工的一个工作习惯:下矿洞前,先会放一只金丝雀进去探测是否有有毒气体,看金丝雀能否活下来。如果金丝雀活下来,则继续下矿操作;否则停止下矿。金丝雀部署亦是先部署少量新版本的服务实例,发布后,开发者可简单地通过手工测试验证新版本实例,又或通过完善的自动化测试基础设施对新版本实例进行详尽验证;甚至是直接接收部分生产流量以充分验证新版本功能、稳定性、性能等,以给予开发者更多信心。如果金丝雀实例通过全部测试验证,则把所有老版本全部升级为新版本。如果金丝雀测试失败,则直接回退金丝雀实例,发布失败。

nomad支持两种模式的canary部署:既支持部署canary实例去直接接收生产流量(按比例权重),也可以将其与生产实例隔离开来(利用路由)单独测试验证,下面分别说说这两种模式。

1. 部署canary实例去直接接收生产流量(按比例权重)

我们创建一个新的nomad job文件:httpsbackend-tcp-sni-1-canary-1.nomad

# diff  httpsbackend-tcp-sni-1-canary-1.nomad  httpsbackend-tcp-sni-1-rolling-update.nomad
18d17
<       canary = 1
24c23
<         image = "bigwhite/httpsbackendservice:v1.0.2"
---
>         image = "bigwhite/httpsbackendservice:v1.0.1"

我们看到除了新版本task使用v1.0.2版image之外,最大的不同就是在update {…}配置区域增加了一行:

canary = 1

我们来plan一下该nomad文件:

# nomad job plan httpsbackend-tcp-sni-1-canary-1.nomad
+/- Job: "httpsbackend-sni-1"
+/- Task Group: "httpsbackend-sni-1" (1 canary, 3 ignore)
  +/- Update {
        AutoRevert:       "false"
    +/- Canary:           "0" => "1"
        HealthCheck:      "checks"
        HealthyDeadline:  "300000000000"
        MaxParallel:      "1"
        MinHealthyTime:   "30000000000"
        ProgressDeadline: "600000000000"
      }
  +/- Task: "httpsbackend-sni-1" (forces create/destroy update)
    +/- Config {
      +/- image:              "bigwhite/httpsbackendservice:v1.0.1" => "bigwhite/httpsbackendservice:v1.0.2"
          logging[0][type]:   "json-file"
          port_map[0][https]: "7777"
        }

Scheduler dry-run:
- All tasks successfully allocated.

... ...

我们看到nomad分析的结果是:需要创建一个canary实例,忽略三个已经存在的旧版本task实例。同时task group的canary属性从“0”变为了“1”。

我们来run该job:

# nomad job run httpsbackend-tcp-sni-1-canary-1.nomad
==> Monitoring evaluation "0494a8a9"
    Evaluation triggered by job "httpsbackend-sni-1"
    Evaluation within deployment: "3e541fb3"
    Allocation "4d678e67" created: node "c281658a", group "httpsbackend-sni-1"
    Evaluation status changed: "pending" -> "complete"
==> Evaluation "0494a8a9" finished with status "complete"

查看job的run状态:

# nomad job status httpsbackend-sni-1
ID            = httpsbackend-sni-1
Name          = httpsbackend-sni-1
Submit Date   = 2019-04-08T21:04:49+08:00
Type          = service
Priority      = 50
Datacenters   = dc1
Status        = running
Periodic      = false
Parameterized = false

Summary
Task Group          Queued  Starting  Running  Failed  Complete  Lost
httpsbackend-sni-1  0       0         4        0       6         0

Latest Deployment
ID          = 3e541fb3
Status      = running
Description = Deployment is running but requires promotion

Deployed
Task Group          Promoted  Desired  Canaries  Placed  Healthy  Unhealthy  Progress Deadline
httpsbackend-sni-1  false     3        1         1       0        0          2019-04-08T21:14:49+08:00

Allocations
ID        Node ID   Task Group          Version  Desired  Status    Created    Modified
4d678e67  c281658a  httpsbackend-sni-1  24       run      running   31s ago    15s ago
da1b545b  7acdd7bc  httpsbackend-sni-1  23       run      running   7h57m ago  7h56m ago
44da5693  9e3ef19f  httpsbackend-sni-1  23       run      running   7h57m ago  7h57m ago
88c1a29e  7acdd7bc  httpsbackend-sni-1  23       run      running   7h58m ago  7h58m ago

# nomad deployment status 3e541fb3
ID          = 3e541fb3
Job ID      = httpsbackend-sni-1
Job Version = 24
Status      = running
Description = Deployment is running but requires promotion

Deployed
Task Group          Promoted  Desired  Canaries  Placed  Healthy  Unhealthy  Progress Deadline
httpsbackend-sni-1  false     3        1         1       1        0          2019-04-08T21:15:35+08:00

我们看到:

  • 处于running状态的allocations变成了4个,但是只有一个是version = 24的,其余都为version = 23。version = 24这个显然是我们新部署的canary实例,而另外三个则为原有的老版本实例。

  • 在Deployment输出信息中,我们看到了一个描述信息:“Deployment is running but requires promotion”,意思是此次用于部署canary实例的Deployment已经running了,但是还未到最终状态,还需要promote命令。只有promote后,整个的更新工作才算是ok。

下面是canary部署后的fabio的路由:

img{512x368}

我们看到canary实例与其余老版本的路由规则是一致的,并平分的负载权重。也就是说新部署的canary实例与老版本实例一起承载生产流量(canary实例占25%的权重),我们来验证一下:

# curl -k  https://mysite-sni-1.com:9996/
this is httpsbackendservice, version: v1.0.2
# curl -k  https://mysite-sni-1.com:9996/
this is httpsbackendservice, version: v1.0.1
# curl -k  https://mysite-sni-1.com:9996/
this is httpsbackendservice, version: v1.0.1
# curl -k  https://mysite-sni-1.com:9996/
this is httpsbackendservice, version: v1.0.1

我们看到第一个请求的流量就打到了我们部署的Canary实例身上了。

如果经过一段时间的验证后,证明canary实例满足要求,我们就要继续推动部署的进程使得该nomad deployment走向最终状态:即将老版本的实例都升级为新版本。

# nomad deployment promote 3e541fb3
==> Monitoring evaluation "b5e29b1a"
    Evaluation triggered by job "httpsbackend-sni-1"
    Evaluation within deployment: "3e541fb3"
    Allocation "085a518e" created: node "7acdd7bc", group "httpsbackend-sni-1"
    Evaluation status changed: "pending" -> "complete"
==> Evaluation "b5e29b1a" finished with status "complete"

# nomad job status httpsbackend-sni-1
ID            = httpsbackend-sni-1
Name          = httpsbackend-sni-1
Submit Date   = 2019-04-08T21:04:49+08:00
Type          = service
Priority      = 50
Datacenters   = dc1
Status        = running
Periodic      = false
Parameterized = false

Summary
Task Group          Queued  Starting  Running  Failed  Complete  Lost
httpsbackend-sni-1  0       0         3        0       9         0

Latest Deployment
ID          = 3e541fb3
Status      = successful
Description = Deployment completed successfully

Deployed
Task Group          Promoted  Desired  Canaries  Placed  Healthy  Unhealthy  Progress Deadline
httpsbackend-sni-1  true      3        1         3       3        0          2019-04-08T21:30:54+08:00

Allocations
ID        Node ID   Task Group          Version  Desired  Status    Created     Modified
40276d89  9e3ef19f  httpsbackend-sni-1  24       run      running   56s ago     11s ago
085a518e  7acdd7bc  httpsbackend-sni-1  24       run      running   1m49s ago   58s ago
4d678e67  c281658a  httpsbackend-sni-1  24       run      running   16m17s ago  1m49s ago
da1b545b  7acdd7bc  httpsbackend-sni-1  23       stop     complete  8h12m ago   56s ago
44da5693  9e3ef19f  httpsbackend-sni-1  23       stop     complete  8h13m ago   1m48s ago
88c1a29e  7acdd7bc  httpsbackend-sni-1  23       stop     complete  8h14m ago   1m47s ago

通过deployment promote命令使得canary deployment进程继续推进,直到将所有老版本的实例都用canary实例替换掉。也就是我们最终看到的上面的version = 24的allocations都处于running状态,并且一共是三个实例。

我们再来测试一下升级后的服务:

# curl -k  https://mysite-sni-1.com:9996/
this is httpsbackendservice, version: v1.0.2
# curl -k  https://mysite-sni-1.com:9996/
this is httpsbackendservice, version: v1.0.2
# curl -k  https://mysite-sni-1.com:9996/
this is httpsbackendservice, version: v1.0.2

我们看到:所有实例都升级到了v1.0.2版本。

2.将canary实例与生产实例隔离开来(利用路由)单独测试验证

如果开发者对自己的代码很有信心,不需要将canary实例暴露在生产流量中去验证,nomad也支持将canary实例与生产实例隔离开来(利用路由)单独测试验证。

我们基于httpsbackend-tcp-sni-1-canary-1.nomad改写出一个httpsbackend-tcp-sni-1-canary-2.nomad:

# diff httpsbackend-tcp-sni-1-canary-2.nomad httpsbackend-tcp-sni-1-canary-1.nomad
24c24
<         image = "bigwhite/httpsbackendservice:v1.0.3"
---
>         image = "bigwhite/httpsbackendservice:v1.0.2"
43d42
<     canary_tags = ["urlprefix-canary.mysite-sni-1.com/ proto=tcp+sni"]

我们看到,在新的job文件中,我们除了将image版本升级为v1.0.3,我们还在service{…}配置区域增加了下面这行:

canary_tags = ["urlprefix-canary.mysite-sni-1.com/ proto=tcp+sni"]

该配置是canary实例专有的,这里我们通过在canary_tags为canary实例单独定义了路由,以免和老版本实例共享路由分担生产流量。

我们照例运行该job并查看job执行后的status:

# nomad job run httpsbackend-tcp-sni-1-canary-2.nomad
==> Monitoring evaluation "44e36161"
    Evaluation triggered by job "httpsbackend-sni-1"
    Evaluation within deployment: "e43d2551"
    Allocation "73319890" created: node "7acdd7bc", group "httpsbackend-sni-1"
    Evaluation status changed: "pending" -> "complete"
==> Evaluation "44e36161" finished with status "complete"

# nomad job status httpsbackend-sni-1
ID            = httpsbackend-sni-1
Name          = httpsbackend-sni-1
Submit Date   = 2019-04-08T21:35:03+08:00
Type          = service
Priority      = 50
Datacenters   = dc1
Status        = running
Periodic      = false
Parameterized = false

Summary
Task Group          Queued  Starting  Running  Failed  Complete  Lost
httpsbackend-sni-1  0       0         4        0       9         0

Latest Deployment
ID          = e43d2551
Status      = running
Description = Deployment is running but requires promotion

Deployed
Task Group          Promoted  Desired  Canaries  Placed  Healthy  Unhealthy  Progress Deadline
httpsbackend-sni-1  false     3        1         1       1        0          2019-04-08T21:45:51+08:00

Allocations
ID        Node ID   Task Group          Version  Desired  Status    Created     Modified
73319890  7acdd7bc  httpsbackend-sni-1  25       run      running   2m24s ago   1m36s ago
40276d89  9e3ef19f  httpsbackend-sni-1  24       run      running   17m18s ago  16m33s ago
085a518e  7acdd7bc  httpsbackend-sni-1  24       run      running   18m11s ago  17m20s ago
4d678e67  c281658a  httpsbackend-sni-1  24       run      running   32m39s ago  18m11s ago

这个输出信息和之前的canary模式差别不大。但是从fabio路由表上我们看到如下信息:

img{512x368}

fabio单独为canary实例生成了一个新路由,以区别于老版本的三个实例的路由。

开发人员单独测试canary实例时,可以通过下面方式注入流量:

# curl -k  https://canary.mysite-sni-1.com:9996/
this is httpsbackendservice, version: v1.0.3

而生产流量依旧流入老版本的实例中:

# curl -k  https://mysite-sni-1.com:9996/
this is httpsbackendservice, version: v1.0.2
# curl -k  https://mysite-sni-1.com:9996/
this is httpsbackendservice, version: v1.0.2
# curl -k  https://mysite-sni-1.com:9996/
this is httpsbackendservice, version: v1.0.2

canary实例经过测试验证后,同样可以通过promote完成对老版本的升级部署:

# nomad deployment promote e43d2551
==> Monitoring evaluation "34a67391"
    Evaluation triggered by job "httpsbackend-sni-1"
    Evaluation within deployment: "e43d2551"
    Allocation "193cbc2f" created: node "c281658a", group "httpsbackend-sni-1"
    Evaluation status changed: "pending" -> "complete"
==> Evaluation "34a67391" finished with status "complete"

# nomad job status httpsbackend-sni-1
ID            = httpsbackend-sni-1
Name          = httpsbackend-sni-1
Submit Date   = 2019-04-08T21:35:03+08:00
Type          = service
Priority      = 50
Datacenters   = dc1
Status        = running
Periodic      = false
Parameterized = false

Summary
Task Group          Queued  Starting  Running  Failed  Complete  Lost
httpsbackend-sni-1  0       0         3        0       12        0

Latest Deployment
ID          = e43d2551
Status      = successful
Description = Deployment completed successfully

Deployed
Task Group          Promoted  Desired  Canaries  Placed  Healthy  Unhealthy  Progress Deadline
httpsbackend-sni-1  true      3        1         3       3        0          2019-04-08T21:58:24+08:00

Allocations
ID        Node ID   Task Group          Version  Desired  Status    Created     Modified
528a75bd  7acdd7bc  httpsbackend-sni-1  25       run      running   51s ago     10s ago
193cbc2f  c281658a  httpsbackend-sni-1  25       run      running   1m39s ago   52s ago
73319890  7acdd7bc  httpsbackend-sni-1  25       run      running   13m31s ago  1m39s ago
40276d89  9e3ef19f  httpsbackend-sni-1  24       stop     complete  28m25s ago  50s ago
085a518e  7acdd7bc  httpsbackend-sni-1  24       stop     complete  29m18s ago  1m38s ago
4d678e67  c281658a  httpsbackend-sni-1  24       stop     complete  43m46s ago  1m39s ago

同时,canary实例在fabiolb上的路由也会自动删除掉。canary_tags在promote后将不再起作用,fabio使用的是tags。

# curl -k  https://canary.mysite-sni-1.com:9996/
curl: (35) gnutls_handshake() failed: The TLS connection was non-properly terminated.
# curl -k  https://mysite-sni-1.com:9996/
this is httpsbackendservice, version: v1.0.3
# curl -k  https://mysite-sni-1.com:9996/
this is httpsbackendservice, version: v1.0.3
# curl -k  https://mysite-sni-1.com:9996/
this is httpsbackendservice, version: v1.0.3

四. 蓝绿部署(blue-green deployment)

下面的蓝绿部署模式的示意图同样来自blog.itaysk.com:

img{512x368}

与之前的滚动更新、金丝雀部署不同的是,蓝绿部署需要“两套”环境,通过路由指向来切换流量究竟经过哪套环境。

但是在nomad官方关于blue-green部署的例子中,nomad实际只维护了一套环境,并且例子中是利用nomad的canary机制来实现的蓝绿部署。这种实现方式并非严格遵循“蓝绿部署”的公认的定义。

但nomad官方对于blue-green部署的理解似乎仅限如此。我们也来看一下nomad的这种“全量金丝雀”的蓝绿方案:

我们创建httpsbackend-tcp-sni-1-blue-green.nomad文件,重点内容差异如下:

# diff httpsbackend-tcp-sni-1-blue-green.nomad httpsbackend-tcp-sni-1-canary-1.nomad
18c18
<       canary = 3
---
>       canary = 1
24c24
<         image = "bigwhite/httpsbackendservice:v1.0.4"
---
>         image = "bigwhite/httpsbackendservice:v1.0.2"

我们看到这里canary = 3,与count值相同,这也是将其称为“全量金丝雀”的原因。

使用该文件部署新版本实例:

# nomad job run httpsbackend-tcp-sni-1-blue-green.nomad
==> Monitoring evaluation "7a5074f3"
    Evaluation triggered by job "httpsbackend-sni-1"
    Evaluation within deployment: "3c8740f2"
    Allocation "338ee344" created: node "c281658a", group "httpsbackend-sni-1"
    Allocation "3dec73d2" created: node "9e3ef19f", group "httpsbackend-sni-1"
    Allocation "e6975673" created: node "9e3ef19f", group "httpsbackend-sni-1"
    Evaluation status changed: "pending" -> "complete"
==> Evaluation "7a5074f3" finished with status "complete"

# nomad job status httpsbackend-sni-1
ID            = httpsbackend-sni-1
Name          = httpsbackend-sni-1
Submit Date   = 2019-04-09T13:38:49+08:00
Type          = service
Priority      = 50
Datacenters   = dc1
Status        = running
Periodic      = false
Parameterized = false

Summary
Task Group          Queued  Starting  Running  Failed  Complete  Lost
httpsbackend-sni-1  0       0         6        0       12        0

Latest Deployment
ID          = 3c8740f2
Status      = running
Description = Deployment is running but requires promotion

Deployed
Task Group          Promoted  Desired  Canaries  Placed  Healthy  Unhealthy  Progress Deadline
httpsbackend-sni-1  false     3        3         3       3        0          2019-04-09T13:49:41+08:00

Allocations
ID        Node ID   Task Group          Version  Desired  Status   Created     Modified
338ee344  c281658a  httpsbackend-sni-1  26       run      running  57s ago     5s ago
3dec73d2  9e3ef19f  httpsbackend-sni-1  26       run      running  57s ago     11s ago
e6975673  9e3ef19f  httpsbackend-sni-1  26       run      running  57s ago     10s ago
528a75bd  7acdd7bc  httpsbackend-sni-1  25       run      running  15h52m ago  15h51m ago
193cbc2f  c281658a  httpsbackend-sni-1  25       run      running  15h52m ago  15h52m ago
73319890  7acdd7bc  httpsbackend-sni-1  25       run      running  16h4m ago   15h52m ago

部署ok后,6个实例共同接收生产流量。当然我们也可以通过canary_tags为新的部署设定不同路由,选择哪一种要看部署新实例后打算对新实例如何进行测试。

测试验证ok后,像canary deployment一样,通过promote命令用新版本替换老版本。

# nomad deployment promote 3c8740f2
==> Monitoring evaluation "fad3a69b"
    Evaluation triggered by job "httpsbackend-sni-1"
    Evaluation within deployment: "3c8740f2"
    Evaluation status changed: "pending" -> "complete"
==> Evaluation "fad3a69b" finished with status "complete"

# nomad job status httpsbackend-sni-1
ID            = httpsbackend-sni-1
Name          = httpsbackend-sni-1
Submit Date   = 2019-04-09T13:38:49+08:00
Type          = service
Priority      = 50
Datacenters   = dc1
Status        = running
Periodic      = false
Parameterized = false

Summary
Task Group          Queued  Starting  Running  Failed  Complete  Lost
httpsbackend-sni-1  0       0         3        0       15        0

Latest Deployment
ID          = 3c8740f2
Status      = successful
Description = Deployment completed successfully

Deployed
Task Group          Promoted  Desired  Canaries  Placed  Healthy  Unhealthy  Progress Deadline
httpsbackend-sni-1  true      3        3         3       3        0          2019-04-09T13:49:41+08:00

Allocations
ID        Node ID   Task Group          Version  Desired  Status    Created     Modified
338ee344  c281658a  httpsbackend-sni-1  26       run      running   4m43s ago   15s ago
3dec73d2  9e3ef19f  httpsbackend-sni-1  26       run      running   4m43s ago   15s ago
e6975673  9e3ef19f  httpsbackend-sni-1  26       run      running   4m43s ago   15s ago
528a75bd  7acdd7bc  httpsbackend-sni-1  25       stop     complete  15h55m ago  14s ago
193cbc2f  c281658a  httpsbackend-sni-1  25       stop     complete  15h56m ago  15s ago
73319890  7acdd7bc  httpsbackend-sni-1  25       stop     complete  16h8m ago   14s ago

测试结果:

# curl -k https://mysite-sni-1.com:9996/
this is httpsbackendservice, version: v1.0.4

如果要快速切换回原来的版本,可以使用:

nomad job revert httpsbackend-sni-1 {old_allocation_version}

五. 其他

本文涉及到的nomad job文件源码可在这里下载。


我的网课“Kubernetes实战:高可用集群搭建、配置、运维与应用”在慕课网上线了,感谢小伙伴们学习支持!

我爱发短信:企业级短信平台定制开发专家 https://tonybai.com/
smspush : 可部署在企业内部的定制化短信平台,三网覆盖,不惧大并发接入,可定制扩展; 短信内容你来定,不再受约束, 接口丰富,支持长短信,签名可选。

著名云主机服务厂商DigitalOcean发布最新的主机计划,入门级Droplet配置升级为:1 core CPU、1G内存、25G高速SSD,价格5$/月。有使用DigitalOcean需求的朋友,可以打开这个链接地址:https://m.do.co/c/bff6eed92687 开启你的DO主机之路。

我的联系方式:

微博:https://weibo.com/bigwhite20xx
微信公众号:iamtonybai
博客:tonybai.com
github: https://github.com/bigwhite

微信赞赏:
img{512x368}

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats