美文网首页
containerpilot 的使用

containerpilot 的使用

作者: Robin92 | 来源:发表于2019-08-10 22:53 被阅读0次

    文章大多来自于阅读 https://yq.aliyun.com/articles/231714 后,自己的整理。

    (这里先解释自己读到的原理,纸上得来终觉浅,下次实践时再做补充。)

    现在流行微服务,注重 单一职责 的原则,那服务被打散了,如何知道所调用的服务是否存在、是否正常以及在哪里(IP:port)就成为了一种问题。

    (其实还不理解 consul 和 containpilot 的具体区别,下次了解了区别之后再在这里补充吧。)

    服务的发现与注册有两种模式:客户端模式服务端模式,两者的区别主要在于注册的位置(注册库)在客户端还是在服务端

    客户端模式.png 服务端模式.png

    它的工作原理是这样一个流程:

    • Register:当新加进来一个服务实例(同一个服务的不同实例)时,服务实例会注册到注册库(Service Registry)中
    • Query:当客户端发起一个 request 时,服务发现组件的客户端会去注册库中查询服务的信息
    • Request:发生在第二步找到可用的服务配置(可能有多个实例)之后,会进行真实的服务访问(多个实例时选择某一个就实现了负载均衡)

    服务注册中心(Service Registry)

    把服务集中在一个地方管理,目前有三种方式:

    • consul:提供了一站式的解决方案,存储服务信息,健康检查,DNS解析一应俱全,甚至提供了个简单的UI工具
    • etcd:是一个 KV 的分布式存储工具
    • zookeeper: 相对繁琐,不多介绍了

    所以,consul 的基本功能是存储服务信息,服务的配置信息还有应用的配置信息都可以放在这里,它也提供了 RESTful 的 api 实现查询,还自带了健康检查和 DNS 解析的功能。

    但即便这样,还免不了人工参与的方式,所以,这就引入了 containerpilot 来解决这一问题。(consul 的具体使用目前还不了解,后面了解了再补充)

    containerpilot

    containerpilot 做到了服务的发现与注册完全不用人工干预,只需要一些配置即可。

    具体是这样:

    • 所有 containerpilot 相关的配置放在一个固定的目录下面,例如 /etc/containerpilot
    • 在容器启动的时候执行脚本从依赖关系文件(例如 serviceDependencies.json)中读取出服务列表,并执行 containerpilot 的可执行文件(原作者说删除 socket 文件,这个我还不理解,后面补充)
    • containerpilot 读取配置文件 config.json5,通过模板语法,在不同的条件下根据 环境变量 激活不同的job

    重要的部分有这几步:

    • 连接到 consul,将当前服务注册进去,第一次生成依赖服务的地址 services.json
    • containerpilot 与 consul 建立通信后,获取依赖服务的列表,通过 consul-template 将服务的信息渲染到预定义好的模板文件中
    • watch在consul中依赖的服务,当检测到更新的时候给服务发送 SIGHUP 的信号提示服务重新读取依赖服务的最新地址 services.json
    • 通过调用 ping 命令对服务进行健康检查,在服务不健康甚至是容器异常退出的时候会将 consul 中服务的状态标记为不可用(不会解注册)

    环境变量

    containerpilot 是通过环境变量实现服务的注册与发现的

    配置依赖服务

    被托管服务如果依赖于其他服务,需在项目中添加 serviceDependencies.json 文件,构建 docker 镜像时把这个文件复制到 WORKDIR 下,示例如下:

    {
      "service1": ["service2", "service3"],  // “SERVICE_NAME”: ["other_service_name"]
      "service2": ["service4"]
    }
    

    上面例子表示服务1会调用(依赖于)服务2和服务3。
    对于不使用服务注册,只使用服务发现的服务,可以用 main 来作 SERVICE_NAME
    示例:

    {
      "main": ["service2", "service3"],
    }
    

    containerpilot 会根据 SERVICE_NAME 选取需要监控的依赖服务,比如设置 SERVICE_NAME 为 service1 ,则将监控 service2 和 service3,当依赖服务实例发生变化时,会更新 /etc/containerpilot/services.json ,生成的内容示例如下:

    {
      "service2": [
        "1.1.1.1:80",
        "2.2.2.2:80"
      ],
      "service3": [
        "3.3.3.3:80",
        "4.4.4.4:80"
      ]
    }
    

    key 为依赖的服务名,value 为该服务的实例地址数组。
    被托管服务要获取该文件的更新可通过如下方式:

    • 静态语言中,可以设置环境变量 SERVICES_SIGNAL_CHANGED ,然后代码中处理 SIGHUP 信号,收到信号时重新读取该文件。
    • 动态语言如 PHP 不好处理信号的,可以每次处理请求时都重新读取该文件。

    启动 containerpilot

    原文章中有如下示例脚本

    #!/bin/bash
    
    # 假设外部已传入 CONSUL_JOIN_ADDR 环境变量
    # 假设运行在 k8s 上,则 CONSUL_ADVERTISE 使用默认值即可
    export SERVICE_NAME="test"
    export SERVICE_PORT=80
    export SERVICE_COMMAND="myservice args"
    
    # containerpilot 默认使用健康检查命令 ./ping ,即需要把 ping 文件放在  WORKDIR 下,并在启动 containerpilot 前切换到 WORKDIR
    # WORKDIR 默认为 /
    cd /
    
    # 启动 containerpilot
    exec /etc/containerpilot/containerpilot.sh
    

    相关文章

      网友评论

          本文标题:containerpilot 的使用

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