容器监控方案 cAdvisor + Elasticsearch

qvac1318 7年前
   <h2>当前环境</h2>    <ol>     <li>docker 1.12.1</li>     <li>centos 7</li>    </ol>    <h2>前言</h2>    <p>什么是微服务?微服务带来的好处?想必大家都了解了很多。但在真正实践中,还是有各种各样的挑战。今天就想和大家分享一下,在服务容器化场景中的服务监控问题。</p>    <p>传统的服务监控,一般都是针对宿主机的,有对 CPU、内存、进程数、IO 等监控。这些指标做得非常全面,也能很好的反应宿主机的健康状况。可到了服务容器化的场景中,似乎变得有些力不从心。一台宿主机上会起 n 个容器,每个容器都会独立分配资源,如 CPU、内存等。如果还是仅仅针对宿主机做监控,效果可能不太理想。</p>    <p>我们的容器化部署采用的是 docker 技术,所以下面会针对 docker 来进行一系列的服务监控,以及将监控的数据集成进我们已有的日志中心(ELK)。</p>    <p>关于日志中心的搭建,有兴趣的可看我之前写过的一篇 <a href="/misc/goto?guid=4959749330457409505" rel="nofollow,noindex">“基于ELK+Filebeat搭建日志中心”</a> 。</p>    <h2>docker 容器监控</h2>    <h3>cAdvisor 介绍</h3>    <p>关于 docker 的监控,我们这里采用的是由 Google 开源的的监控工具 <a href="/misc/goto?guid=4958863528768582628" rel="nofollow,noindex">cAdvisor</a> 。采用它的主要原因有:</p>    <ul>     <li>对 docker 容器提供了原生的支持;</li>     <li>开箱即用的特性,降低了部署的成本;</li>     <li>除了自身提供简单的可视化界面外,还提供了外部存储的扩展,如 ES(Elasticsearch)、kafka、InfluxDB等。</li>    </ul>    <p>Google的cAdvisor(Container Advisor)“为容器用户提供了了解运行时容器资源使用和性能特征的方法”。cAdvisor的容器抽象基于Google的lmctfy容器栈,因此原生支持Docker容器并能够“开箱即用”地支持其他的容器类型。cAdvisor部署为一个运行中的daemon,它会收集、聚集、处理并导出运行中容器的信息。这些信息能够包含容器级别的资源隔离参数、资源的历史使用状况、反映资源使用和网络统计数据完整历史状况的柱状图。</p>    <h3>cAdvisor 部署</h3>    <p>由于 cAdvisor 本身也进行了容器化,所以部署极其简单。只需在运行有 docker-daemon 的宿主机上,运行如下命令:</p>    <pre>  docker run \  --volume=/:/rootfs:ro \  --volume=/var/run:/var/run:rw \  --volume=/sys:/sys:ro \  --volume=/var/lib/docker/:/var/lib/docker:ro \  --publish=8080:8080 \  --detach=true \  --name=cadvisor \  google/cadvisor:latest</pre>    <h3>cAdvisor 演示</h3>    <p><img src="https://simg.open-open.com/show/9710efd8738dc709072d414eaf9bc503.png"> <img src="https://simg.open-open.com/show/ba782f271a57d4e6b58b872af317585a.png"> <img src="https://simg.open-open.com/show/ac8a725a2aee940bf76db5220a3f2244.png"></p>    <p>它提供了简单的可视化界面,为我们提供了容器的整体情况,以及每个容器的独立数据,数据包括有 CPU、内存、网络IO、磁盘IO等使用情况。</p>    <h3>cAdvisor 参数说明</h3>    <p>上面的部署只是为了演示使用的,所以参数都使用的是缺省值。为了更好的运用 cAdvisor,有些参数我们还是需要了解的( <em> <a href="/misc/goto?guid=4959749330573706173" rel="nofollow,noindex">详细信息参考官方文档</a> </em> ):</p>    <table>     <thead>      <tr>       <th>参数</th>       <th>默认值</th>       <th>说明</th>      </tr>     </thead>     <tbody>      <tr>       <td>-allow_dynamic_housekeeping</td>       <td>true</td>       <td>设置数据采集的频率间隔是动态的,这取决于容器的活跃程度。若设为false,采集的时间间隔将和预期的保持一致,但这会增加资源的使用率。</td>      </tr>      <tr>       <td>-global_housekeeping_interval</td>       <td>1m0s</td>       <td>设置cAdvisor全局的采集行为的时间间隔,主要通过内核事件来发现新容器的产生。</td>      </tr>      <tr>       <td>-housekeeping_interval</td>       <td>1s</td>       <td>每个已发现的容器的数据采集频率。</td>      </tr>      <tr>       <td>-machine_id_file</td>       <td>/etc/machine-id,/var/lib/dbus/machine-id</td>       <td>标识宿主机ID的文件地址,可以设置多个文件,当第一个不存在时,会依次向后查找,文件地址用逗号分隔</td>      </tr>      <tr>       <td>-storage_duration</td>       <td>2m0s</td>       <td>在内存中保存最近多久的历史数据</td>      </tr>      <tr>       <td>-storage_driver</td>       <td>Empty(none)</td>       <td>设置采集的缓存数据将推送至的存储驱动,可选项有: , bigquery, ES, influxdb, kafka, redis, statsd, stdout。</td>      </tr>     </tbody>    </table>    <h3>cAdvisor 不足</h3>    <p>从上述的参数列表中可以看出,cAdvisor 做到的是实时监控,数据存储在内存中,并且只会保存很短的一段时间。所以它是做不到监控数据的存储,换句话说,它是记录下近几天的监控数据。为此它提供了有关的存储驱动,帮助我们将实时数据传输到我们指定的数据存储器中。</p>    <p>其次,cAdvisor监听的是宿主机 docker 主进程的变化,这就意味着单单依靠它是做不到分布式的监控。所以,这更添加了我们将它与 ELK 做集成的理由。</p>    <h2>与日志中心(ELK)集成</h2>    <h3>背景</h3>    <p>为了降低维护成本,我们这里选择 ES 作为存储驱动,将 cAdvisor 与我们已有的 ELK 日志中心进行集成。这也降低了使用者的复杂度,通过同一个平台,解决了日志收集与服务监控的问题。</p>    <h3>架构</h3>    <p><img src="https://simg.open-open.com/show/887152cb154b52f2fd0ec89f145a21d8.png"></p>    <p>从上图不难看出,cAdvisor 也是采用了协同进程的概念,通过监听 docker 主进程的事件,将采集到的数据远程传输的方式,push 到 ES 中。并且通过 Machine ID 来区分不同宿主机的容器信息,实现了数据的分布式监控。</p>    <h3>cAdvisor 支持 ES 5</h3>    <p>其实我们用它与 ES 集成的时候,还是略坑的。如果你用的 ES 是 5.0+,那就杯具了。因为 cAdvisor 官方目前仅对 ES 2 进行了支持。具体的情况可以查看官方 Github 下的讨论: <a href="/misc/goto?guid=4959749330660340282" rel="nofollow,noindex">https://github.com/google/cadvisor/pull/1597</a> 。</p>    <p>这当然也体现了开源的力量。从上述的讨论中可以看出,对 ES 5 的支持已经有人提供了,也经过了测试验证,只是因为官方为了考虑兼容 ES 2,所以暂时没有采纳合并请求。但这给了我们解决方案,虽然官方不提供,我们可以根据社区提供的 ES 5 的代码,进行手动的 build 生成 cadvisor 执行文件。在以官方镜像启动容器时,将我们生成的 cadvisor 执行文件以文件挂载方式替换原有的执行文件,这就做到了对 ES 5的支持( <em>相信官方会很快对 ES 5 进行支持,我们也不用采用这种迂回的方式了</em> )。</p>    <p>为了避免自己在手动编译过程会出现一些问题,我这里也提供了 build 好的 cadvisor 执行文件,下载地址: <a href="/misc/goto?guid=4959749330742771312" rel="nofollow,noindex">https://github.com/jasonGeng88/cadvisor/releases/download/es5/cadvisor</a></p>    <h3>部署</h3>    <pre>  docker run \  --volume=/:/rootfs:ro \  --volume=/var/run:/var/run:rw \  --volume=/sys:/sys:ro \  --volume=/var/lib/docker/:/var/lib/docker:ro \  --volume=$YOUR_PATH/cadvisor:/usr/bin/cadvisor \  --publish=8080:8080 \  --detach=true \  --name=cadvisor \  google/cadvisor:latest \  -storage_driver=elasticsearch.v5 \  -storage_driver_es_index="cadvisor" \  -storage_driver_es_host="http://$ELASTICSEARCH_IP:9200"</pre>    <h3>展示( <em>Demo数据</em> )</h3>    <p><img src="https://simg.open-open.com/show/5505a88dd3de8d8f368efbb1b65cc326.png"> <img src="https://simg.open-open.com/show/c72defbd2904e554cddeca8b846fcee5.png"></p>    <h2>总结</h2>    <p>本文介绍了微服务下的容器监控方案,从“开箱即用”的 cAdvisor 讲起,虽然它也能输出我们想要的监控数据。但是作为一个完整的应用,我们还要考虑它的可行性、易用性和可扩展性。同时要从实际出发,结合现有的框架体系,将 cAdvisor 融入进已有的 ELK 日志中心,并且对数据可以进行自定义的图表展示,使用上更灵活。</p>    <p> </p>    <p> </p>