作者:刘安
爱可生测试团队成员,主要负责 DTLE 开源项目相关测试任务,擅长 Python 自动化测试开发。
本文来源:原创投稿
*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
背景:
最近接到一个工单:DTLE client 被部署在两个机房,其中只有 DTLE clinst 可以相互访问,所以希望故障转移时能在对应机房内切换。
网络结构如下图:

通过分析网络结构可知:
- 
DTLE client 只能访问本地机房的 MySQL  - 
如果发生故障转移,只能调度到本地机房的 DTLE client 上执行才能保证新的 task 能访问到对应的 MySQL 实例  
因为 DTLE 只是作为 Nomad 的插件运行,其只负责数据传输任务,任务调度工作则是由 Nomad 来完成的,所以还是要到 Nomad 的文档里去寻找答案。
查看 Nomad 的文档发现可以通过在 job 中配置constraint属性来指定故障转移的范围,接下来我们就展示一下constraint属性怎么使用。
一、DTLE job 的结构
一个 DTLE job 里包含两个 group ,每个 gourp 里包含一个 task ,task 里包含了 DTLE 任务的配置信息,task 最终被部署到 DTLE client 上执行。如下图:

二、constraint 简介
- 
constraint可以严格限制符合条件的 client 集,该属性可以定义在 job、group 或者 task 层上。 
由于 DTLE job 的每个 group 下只有一个 task ,我们的目的是约束 task 的故障转移域,而源端 task 和目标端 task 又有不同的故障转移域,所以对于工单中遇到的问题,我们可以把constraint定义在 group 层或者 task 层。
- 
constraint的参数包括attribute、operator和valuea.
attribute指定要过滤的属性,可以是任何Nomad的节点属性。以下是节点属性的完整列表:Variable Description Example Value ${node.unique.id}36 character unique client identifier 9afa5da1-8f39-25a2-48dc-ba31fd7c0023${node.region}Client’s region global${node.datacenter}Client’s datacenter dc1${node.unique.name}Client’s name nomad-client-10-1-2-4${node.class}Client’s class linux-64bit${attr.} Property given by propertyon the client${attr.cpu.arch} => amd64${meta.} Metadata value given by keyon the client${meta.foo} => bar 
| Property | Description | 
|---|---|
${attr.cpu.arch} | 
CPU architecture of the client (e.g. amd64, 386) | 
${attr.cpu.numcores} | 
Number of CPU cores on the client | 
${attr.cpu.totalcompute} | 
cpu.frequency × cpu.numcores but may be overridden by client.cpu_total_compute | 
${attr.consul.datacenter} | 
The Consul datacenter of the client (if Consul is found) | 
${attr.driver. | 
See the task drivers for property documentation | 
${attr.unique.hostname} | 
Hostname of the client | 
${attr.unique.network.ip-address} | 
The IP address fingerprinted by the client and from which task ports are allocated | 
${attr.kernel.name} | 
Kernel of the client (e.g. linux, darwin) | 
${attr.kernel.version} | 
Version of the client kernel (e.g. 3.19.0-25-generic, 15.0.0) | 
${attr.platform.aws.ami-id} | 
AMI ID of the client (if on AWS EC2) | 
${attr.platform.aws.instance-type} | 
Instance type of the client (if on AWS EC2) | 
${attr.platform.aws.placement.availability-zone} | 
Availability Zone of the client (if on AWS EC2) | 
${attr.os.name} | 
Operating system of the client (e.g. ubuntu, windows, darwin) | 
${attr.os.version} | 
Version of the client OS | 
以上属性中${node.datacenter}、${node.unique.name}等都是可以在DTLE节点启动时在配置文件中指定的
b. operator指定比较运算符,默认值为=。更多的运算符可以在 https://www.nomadproject.io/docs/job-specification/constraint#operator 查看。
c. value指定要与使用指定操作的属性进行比较的值, 默认值为空字符串。
三、具体操作
- 
挑选合适的节点属性
a.
${node.unique.id}、${node.unique.name}只能过滤指定的一个节点,所以不能做故障转移的筛选条件b. 根据Nomad的文档介绍,一个job下的task是不能部署在两个不同的region上的,所以
${node.region}不能做故障转移的筛选条件c.
${attr.<property>}是 DTLE 节点添加到集群时自动收集的节点服务器信息,所以不适合做故障转移的筛选条件d. 最后只剩下
${node.datacenter}、${node.class}、${meta.<key>}三个可配置的属性作为故障转移的筛选条件。其中${node.datacenter}、${node.class}可以看做在节点上配置一个可供筛选的标签,而${meta.<key>}则可以看做是在节点上同时配置多个可供筛选的标签 - 
部署DTLE 集群
a. 部署一个有三个 DTLE client 节点的集群,一个节点的
datacenter设为shanghai,两个节点的datacenter设为beijing 
   # dtle配置文件
   name = "dtle-1" # rename for each node
   datacenter = "shanghai" 
   ...

b. 提交一个 DTLE job ,分别配置源端 task 和目标端 task 的constraint属性为shanghai和beijing
   job "test_constraint" {
     # 此处表示该job可以运行在datacenter为"shanghai"和"beijing"的节点上。${node.class}、${meta.<key>}不需关注此项配置
     datacenters = ["shanghai", "beijing"]
   
     group "Src" {
       constraint {
         attribute  = "${node.datacenter}"
         operator   = "="
         value      = "shanghai"
       }
       task "src" {
         driver = "dtle"
         config {
           ReplicateDoDb = [{
             TableSchema = "test"
           }]
           ConnectionConfig = {
             Host = "172.100.9.1"
             Port = 3306
             User = "test_src"
             Password = "test_src"
           }
         }
       }
     }
     group "Dest" {
       constraint {
         attribute  = "${node.datacenter}"
         operator   = "="
         value      = "beijing"
       }
       task "dest" {
         driver = "dtle"
         config {
           ConnectionConfig = {
             Host = "172.100.9.2"
             Port = 3306
             User = "test_dest"
             Password = "test_dest"
           }
         }
       }
     }
   }
c. 查看 task 分配状态,task 被正确的分配在不同的datacenter节点上
查看 job overview 页面:

查看 clients 页面:

d. 停止dtle-2节点,按预期目标端 task 转移到datacenter同为beijing的dtle-3节点上运行
查看 job overview 页面,故障转移完成:

clients 页面:

e. 停止dtle-3节点。因为没有datacenter为beijing的 DTLE 节点,即使还有dtle-1在正常运行,但是无法完成故障转移,任务失败
查看 job overview 页面,显示无法找到datacenter为beijing的 DTLE 节点:

查看 clients 页面:

四、结语
本文展示了如何利用datacenter属性来实现故障转移域的限制。如何利用 Nomad 的其他属性、其他的比较运算符来配置约束条件,大家可以在 DTLE 开源群中一起讨论。
参考文档:
https://www.nomadproject.io/docs/job-specification/constraint
https://www.nomadproject.io/docs/runtime/interpolation#interpreted_node_vars
DTLE repo:
https://github.com/actiontech/dtle
QQ讨论群:852990221