美文网首页
服务配置和Consul KV数据集

服务配置和Consul KV数据集

作者: fossilman | 来源:发表于2020-05-21 09:44 被阅读0次

    Consul模板

    Consul模板工具可以使用编程的方式从包括Consul KV数据集在内的各种位置渲染配置文件,模板工具基于Go模板,并有许多相同的属性。
    Consul模板具有多种用途,我们将重点介绍其中的两个:

    1. 更新配置文件: Consul模板工具可用于更新服务配置文件,一种常见的用法是管理负载均衡配置文件,这些文件需要在许多无法直接连接到Consul群集的计算机上定期动态更新;
    2. 发现有关Consul群集和服务的数据:可以收集有关Consul群集中服务的信息。例如,用户可以收集群集上运行的所有服务的列表,或者可以发现Redis所有服务的地址。注意,这个操作在生产环境有所限制。
      在本章节中,我们将简要讨论Consul模板的工作原理,安装方法以及两个用例,在阅读本章节前,我们假设您对Consul KV和Go模板有所了解。

    Consul模板简介

    Consul模板是一个简单但功能强大的工具。启动后,它将读取一个到多个模板文件,并向Consul发出查询,加载它们所需的所有数据。通常,consul-template作为守护程序运行,一开始获取初始值,之后持续监控更新,在集群中发生任何相关更改时都会重新加载模板。用户也可以使用-once标志仅加载一次模板,这在测试或者由其他脚本触发时比较有用。最后,更新过程完成后,模板还可以运行后置命令。例如,它可以在进行配置更改后将HUP信号发送到负载均衡器服务。
    Consul模板工具非常灵活,可以适应许多不同的环境和工作流程。根据使用情况,用户可能在少数几个主机上只有一个consul-template实例,或者也可能需要在每个主机上运行多个实例。每个Consul模板过程都可以管理多个不相关的文件,如果这些文件共享数据依赖项,则将根据需要对提取的内容进行重复数据删除,这样可以减少Consul服务器上可能共享的负载。

    安装Consul模板

    在本章节中,我们在开发者模式下使用本地Consul代理,先执行consul agent -dev,Consul代理正常运行后才能进行以下其他步骤。
    Consul模板工具本身不包含在Consul二进制文件中,需要单独安装。用户可以直接安装预编译的二进制文件,也可以下载源代码自行编译,我们将安装预编译的二进制文件,首先,先下载consul-template二进制文件:

    $ curl -O https://releases.hashicorp.com/consul-template/0.19.5/consul-template<_version_OS>.tgz
    

    接下来,将二进制文件加入$PATH路径中:

    $ tar -zxf consul-template<_version_OS>.tgz
    

    用例:Consul KV数据集

    在第一个用例中,我们将渲染一个模板,该模板会从Consul KV数据集中提取HashiCorp地址。我们需要创建一个包含HashiCorp地址的简单模板,运行consul-template,为Consul KV数据集添加一个HashiCorp地址的值,最后查看渲染的文件。
    首先,我们需要创建一个模板文件find_address.tpl来查询Consul KV数据集:

    {{ key "/hashicorp/street_address" }}
    

    运行consul-template命令,同时指定要使用的模板和需要更新的文件:

    $ consul-template -template "find_address.tpl:hashicorp_address.txt"
    

    consul-template命令会持续运行,用户使用CTRL+c可以停止其运行,然后我们打开一个新终端,使用命令行指令将数据写入Consul:

    $ consul kv put hashicorp/street_address "101 2nd St" 
    Success! Data written to: hashicorp/street_address
    

    我们可以通过查看hashicorp_address.txt文件来确保有数据写入文件:

    $ cat hashicorp_address.txt 
    101 2nd St
    

    如果用户执行命令consul kv put hashicorp/street_address "22b Baker ST"更新hashicorp/street_address值,可以看到该文件立即更新。这个过程虽然很简单,但是意义很强大,比如用户可以用相同的过程来更新HAProxy负载均衡器配置。

    用例:发现所有服务

    在此示例中,我们将发现Consul群集中运行的所有服务,我们使用上一个示例中的开发环境接着开发。
    首先,我们将需要创建一个新模板all-services.tpl来查询所有服务。

    {{range services}}# {{.Name}}{{range service .Name}}
    {{.Address}}{{end}}
    
    {{end}}
    

    接下来,运行consul-template命令指定我们刚刚创建的模板,并使用-once标志,表示仅运行一次:

    $ consul-template -template="all-services.tpl:all-services.txt" -once
    

    如果您在本地代理上完成此操作,则可以通过all-services.txt文件查看consul服务:

    # consul
    127.0.0.7
    

    在开发或生产集群上,用户会看到所有服务的列表:

    # consul
    104.131.121.232
    
    # redis
    104.131.86.92
    104.131.109.224
    104.131.59.59
    
    # web
    104.131.86.92
    104.131.109.224
    104.131.59.59
    

    使用会话实现应用程序领导者选举

    对于某些应用程序,例如HDFS,有必要将一个实例设置为领导者,这样可以确保应用程序数据是最新且稳定的,本章节介绍了如何使用Consul为服务实例构建面向客户端(client-side)的领导者选举,Consul对会话的支持可帮助用户构建一个能够正常处理故障的系统。
    这篇章节的内容与Consul本身的领导者选举无关,如果对该部分内容感兴趣,可以参考consensus协议。

    竞争服务实例

    想象一下,用户有一组服务实例正在争夺给定服务的领导地位,所有参与的服务实例都应商定一个给定的密钥进行协调,一个好的模式就是:

    service/<service name>/leader
    

    在本章节中,我们的完整密钥可能是service/dbservice/leader,为了简化行文,我们将密钥定义为lead

    创建会话

    首先使用HTTP API创建一个会话:

    $ curl  -X PUT -d '{"Name": "dbservice"}' http://localhost:8500/v1/session/create
    

    这将返回一个包含会话ID的JSON对象:

    {
      "ID": "4ca8e74b-6350-7587-addf-a18084928f3c"
    }
    
    获取会话

    下一步是某个服务实例使用PUT方法获取给定密钥的会话,请求需要拼接?acquire=<session>查询参数。
    PUT方法中的<body>应该是代表本地实例的JSON对象。该值对Consul不透明,但应包含客户端与用户应用程序进行通信所需的必要信息(例如,它可以是包含节点名称和应用程序端口的JSON对象)。

    $ curl -X PUT -d <body> http://localhost:8500/v1/kv/lead?acquire=4ca8e74b-6350-7587-addf-a18084928f3c
    

    响应结果为truefalse,如果为true,则表示已经获取到,本地服务实例现在为领导者,如果返回值为false,则说明其他某个节点获得了

    监听会话

    现在,所有其他实例都处于空闲等待状态。在这种状态下,它们会监听密钥lead的变化,锁可能随时会被释放,实例也可能失效。领导者也必须注意变化,因为运维人员可能手动释放锁,或者系统故障检查误报自动释放锁。
    默认情况下,会话仅使用Gossip故障检测器,也就是说,只要默认的Serf健康检查未声明该节点不健康,就认为该节点保留着会话。如果需要,也可以指定其他检查。
    通过对<key>使用阻塞查询(blocking query)来监听变化。如果它们察觉到<key>的会话为空,则说明此时没有领导者,然后会重试获取锁。每次尝试获取密钥都需要有一段时间间隔,Consul强制使用了lock-delay

    释放会话

    领导者可以解除锁来释放资源:

    $ curl -X PUT http://localhost:8500/v1/kv/lead?release=4ca8e74b-6350-7587-addf-a18084928f3c
    

    发现领导者

    关于领导者选举,另一种常见的场景是,非领导者实例希望在实例集群中辨认出哪个实例是领导者,与选举领导者一样,所有参与的实例都应就用于协调的密钥达成一致,该密钥将被称为公正密钥(just key)

    获取密钥

    服务实例需要做的非常简单,它们仅需读取密钥就能找到当前的领导者,如果密钥有关联的会话,则说明已经有领导者了。

    $ curl -X GET http://localhost:8500/v1/kv/lead
    [
      {
        "Session": "4ca8e74b-6350-7587-addf-a18084928f3c",
        "Value": "Ym9keQ==",
        "Flags": 0,
        "Key": "dbservice",
        "LockIndex": 1,
        "ModifyIndex": 29,
        "CreateIndex": 29
      }
    ]
    

    如果有领导者,则value字段会显示与应用程序相关的信息,信息使用Base64编码。

    获取会话信息

    用户可以查询/v1/session/info端点获取会话的详细信息:

    $ curl -X GET http://localhost:8500/v1/session/info/4ca8e74b-6350-7587-addf-a18084928f3c
    [
      {
        "LockDelay": 1.5e+10,
        "Checks": [
          "serfHealth"
        ],
        "Node": "consul-primary-bjsiobmvdij6-node-lhe5ihreel7y",
        "Name": "dbservice",
        "ID": "4ca8e74b-6350-7587-addf-a18084928f3c",
        "CreateIndex": 28
      }
    ]
    

    使用会话实现分布式信号量

    当用户想要调度许多服务,同时某些资源有访问限制时,分布式信号量(distributed semaphore)可能会很有用。在本章节中,我们将重点介绍如何使用Consul对会话的支持以及利用Consul KV数据集来构建分布式信号量。有多种方式可以构建信号量,本章节不会全部覆盖。
    在阅读本章节前,用户应该熟悉Consul KV数据集Consul会话

    信号量中的竞争节点

    想象一下,我们有一组试图获取信号量中插槽(slot)的节点,所有参与竞争的节点都应达成以下三个共识:

    • KV数据集中用于调度的前缀;
    • 单独的键值(Key)作为锁;
    • 持有插槽数量的限制。
    会话

    第一步是为每个竞争节点创建一个会话,会话使我们能够构建可以正常处理故障的系统。

    $ curl -X PUT -d '{"Name": "db-semaphore"}' \ 
        http://localhost:8500/v1/session/create
    

    响应值是包含会话ID的JSON对象。

    {
      "ID": "4ca8e74b-6350-7587-addf-a18084928f3c"
    }
    
    创建竞争锁

    接下来,我们创建一个竞争锁(lock contender)。每个竞争者都会创建一个与会话相关联的KV条目(KV entry)。这样做的目的是,如果竞争者持有某个插槽并发生故障,则其会话会与键值分离 ,然后其他竞争者可以检测到该会话,用户可以发送PUT请求创建竞争锁:

    curl -X PUT -d <body> http://localhost:8500/v1/kv/<prefix>/<session>?acquire=<session>
    

    body的值一般为与该竞争锁相关的有意义的内容 ,比如节点的名称,Consul本身不关注body的内容,这个值对运维人员有用,<session>的值是/v1/session/create请求的返回值。
    该调用结果返回true或者false。如果为true,则说明创建竞争锁创建成功。如果为false,则表明创建失败,这通常意味着会话失效。

    创建键值(Key)

    下一步是创建一个键值(Key),用来协调插槽的持有者。 <prefix>/.lock是该键值的一个不错选择,我们称这个特殊的键值为<lock>

    $ curl -X PUT -d <body> http://localhost:8500/v1/kv/<lock>?cas=0
    

    由于正在创建锁,此处cas索引值为0,仅当该值不存在时才放入,body的内容为信号量的插槽限制和当前所有者的会话ID,内容如下所示:

    {
      "Limit": 2,
      "Holders": ["<session>"]
    }
    

    信号量管理

    <prefix>发送GET请求可以读取信号量当前状态:

    $ curl http://localhost:8500/v1/kv/<prefix>?recurse
    

    在返回值中,我们应该重点关注两个值:<lock><session>

    [
      {
        "LockIndex": 0,
        "Key": "<lock>",
        "Flags": 0,
        "Value": "eyJMaW1pdCI6IDIsIkhvbGRlcnMiOlsiPHNlc3Npb24+Il19",
        "Session": "",
        "CreateIndex": 898,
        "ModifyIndex": 901
      },
      {
        "LockIndex": 1,
        "Key": "<prefix>/<session>",
        "Flags": 0,
        "Value": null,
        "Session": "<session>",
        "CreateIndex": 897,
        "ModifyIndex": 897
      }
    ]
    

    返回的响应中,<lock>字段使用的是Base64编码。
    读取<lock>数据并将其解码后,我们可以验证LimitHolders计数是否一致,这用于检测潜在冲突。下一步是确定当前哪些插槽(slot)仍在运行。查询响应结果返回了所有竞争者条目,通过扫描这些条目,我们可以创建了一组会话值,不在该组中的所有Holders都会被修剪。实际上,我们将根据列表结果创建一组实时竞争者,并与Holder进行一定的区别以检测和修剪任何可能失败的Holder。在此示例中,<session>存在于Holders中,并附加在键<prefix>/<session>上,因此不需要修剪。
    如果修剪后的持有者数量少于限制数量,则竞争者会尝试通过将其自己的会话添加到持有者(Holders)列表中,并对<lock>进行Check-And-Set操作,这会执行乐观更新。
    我们可以通过以下方式获取:

    $ curl -X PUT -d <Updated Lock Body> http://localhost:8500/v1/kv/<lock>?cas=<lock-modify-index>
    

    lock-modify-index<lock>已知的最新ModifyIndex值,在此示例中为901
    如果该请求返回true,竞争者将在信号量中保留一个插槽,如果返回false,则可能是与另一个竞争者发生了争夺。
    当重新尝试进行数据采集时,我们会注意到<prefix>的更新。这是因为可能会释放插槽,或者节点发生故障等等。通过对/kv/<prefix>recurse接口进行阻塞查询可以监控更新。
    插槽持有者必须不断关注<prefix>的更新,因为运维人员可以释放插槽,或者由于故障检测器误报而自动释放插槽。在更改<prefix>时,必须重新检查锁的持有人(Holders)列表,以确保仍保留该插槽。另外,如果监听器无法连接插槽,则应视为丢失。
    此信号量系统纯粹是建议性的。因此,还是应该由客户端来确定在执行某些关键操作之前(和期间)是否已保留插槽。
    最后,如果插槽持有者希望自愿释放插槽,则应通过对<lock>进行检查并设置(Check-And-Set)操作以从Holders对象中删除其会话。完成后,竞争者密钥<prefix>/<session>和会话都会被删除。

    相关文章

      网友评论

          本文标题:服务配置和Consul KV数据集

          本文链接:https://www.haomeiwen.com/subject/nurgohtx.html