借助 IBM® Bluemix™,比以往更容易将开发工作迁移到云环境中,在云中您可充分利用该平台和它的服务。在 Bluemix 部署的应用程序内,往往需要通过集中化的日志来监视应用程序组件的行为。在本文中,我介绍的为分布式架构提供集中化日志的方法只是实现此目标的一种方式。建议您读完本文,以确定此解决方案是否适合您。(备注:本文将重点介绍单个微型服务,但是,同样的原理在拥有多个需要集中化日志的微型服务时也适用。)
本文中描述的架构很简单,但在彼此独立地部署容器和应用程序时,部署就会变得非常复杂。理解架构的不同部分很重要。这些要点对应用程序开发很有帮助,尤其是 Bluemix 服务所提供的微型服务的开发,而容器让您拥有一个集中的日志存放位置。
回页首
我的解决方案中使用的技术包括:
Docker-compose
(请注意,IBM Container 目前不支持此命令) “ 本文将介绍一种为组成基于 Bluemix 的应用程序的微型服务提供集中化日志功能的方式,同时还会分析所涉及的各种技术。 ”
为您的微型服务构建集中化的日志系统可能是一个重要任务,但 Bluemix 使得完成此任务变得更容易。Bluemix 是您的所有微型服务要部署到的平台。它也是托管集中化日志系统的实际容器。使用 Docker 构建您将运行和部署的容器。
微型服务使用 Node.js 构建,并借助 Bluemix 中支持的 Cloud Foundry 技术来部署。Docker 容器内的集中化日志是使用 Elasticsearch、Logstash 和 Kibana (ELK) 堆栈来构建的。
ELK 是一个构建于 Apache Lucene 之上的开源引擎,它充当着您的日志消息的一个无模式的 JSON 数据库。Logstash 是一个数据处理管道,它转换日志消息并将其发送到 Elasticsearch 来存储。Logstash 可从各种来源接收不同格式的日志。Kibana 用于根据您在特定时刻的需求来可视化数据。
Docker 是一个开放平台,开发人员可在它之上构建、发布和运行分布式应用程序或服务。它旨在自动化应用程序在沙箱化的软件容器中的部署,并提供另一个抽象层。在您希望发布一个沙箱化的容器来存放日志时,Docker 非常适合您的需求。
观看: 探索 IBM Bluemix
回页首
我们使用的技术的一个好处是,它们是开源的,能花费最少的工作l量轻松部署到 Bluemix 中。借助 ELK 堆栈,您能够灵活地定义、存储和可视化日志。此灵活性使您能够从日志中发现新信息,而不会迫使您过早决定使用哪种特定于域的数据模型。
您获得的灵活性是它的一种资产,但伴随灵活性而来的是复杂性。所以该解决方案存在学习曲线。这些技术的不足与学习曲线相关,因为您必须首先理解它们,才能有效地使用它们。但是,阅读本文后,您可能发现这些技术没那么神秘。
请记住,您目前不能对 IBM Container 运行 docker-compose
,这意味着您不能部署完全可组合的 ELK 堆栈。出于这个原因,您需要使用 Docker 构建文件自行从头构建一个堆栈(要获取帮助,请参见参考资料)。不过,在开始针对您的 ELK 需求来设计自己的特殊 Dockerfile 并将它部署到 IBM Container 之前,您需要在您的本地机器上熟悉这些技术。
回页首
由 Docker 支持的 ELK 堆栈用于简化集中化日志的配置和设置。首先安装下面列出的工具。一些工具可能要求您登录到 Bluemix 来获取安装文件:
安装运行 Docker 镜像所需的所有工具后,即可开始配置它。配置过程最初有点复杂,但各部分很快就会一目了然。为了保持本文容易管理,我只展示了如何在 Logstash 中公开一个端口用于 TCP 通信。
请注意,任何人都可将内容发送到该端口,所以,如果您希望构建一个更安全的连接,推荐的选择是结合使用 Lumberjack 协议和 SSL。Logstash 原生支持 Lumberjack,Node.js 也拥有支持 Lumberjack 协议的不错模块。但是,为 Logstash 配置 Lumberjack 和 SSL,以及在 Node.js 应用程序中结合使用 SSL 证书和 Lumberjack 协议,是另一篇文章的介绍主题。
回页首
有两个地方需要配置:
修改文件 ./docker-elk/etc/default/logstash/00_entry.conf:
清单 1. 配置 Logstash
input { tcp { # The port to listen on port => 5000 } lumberjack { # The port to listen on port => 5500 # The paths to your ssl cert and key ssl_certificate => "/etc/pki/tls/certs/logstash-forwarder.crt" ssl_key => "/etc/pki/tls/private/logstash-forwarder.key" # Set this to whatever you want. type => "lumberjack" } syslog { port => 5514 type => syslog } } # NOTE: Do not remove the 'filters' part from the configuration, they were just omitted # from this example # Must use http protocol and specify the host to use Kibana4 output { elasticsearch { protocol => "http" host => "elasticsearch" } }
请注意该软件如何读取通过 TCP 端口 5000 传入的信息,并通过 HTTP 将它推送到本地 Elasticsearch 服务中。可从 官方文档 了解如何更改和配置 Logstash 的不同输入的更多信息。
您需要配置为从 Docker 公开两个端口:
修改来自组合文件 ./docker-elk/docker-compose.yml 的 “elk” 上下文的顶部部分,以包含 ports 部分:
清单 2. 使用 compose 打开正确的端口
elk: extends: file: elk.yml service: elk links: - consul:consul ports: - "5000:5000"
清单 3. 创建容器
sudo docker-compose -f docker-compose.yml up -d
您现在可使用浏览器访问该容器。接下来,在给出可选的额外提示后,我将展示如何使用 Dockerfile 构建自定义镜像并将它部署到 IBM Container 中。
回页首
如果您是高级 Docker 用户且熟悉它,可以看看这些额外提示。将您已构建的自定义 Docker 镜像(单独使用 Dockerfile 构建)部署到 IBM Container 中:
清单 4. 将自定义 Docker 镜像推送到 IBM Container 中进行使用的示例
# NOTE: I'm using my organization name in the examples 'mitu'; you need to use your own # Navigating to correct location cd <custom_image_location> # Login with ICE ice login # Naming the image "logging" for now sudo docker build -t logging . # Tag the image with little help from ICE sudo ice --local tag -f logging:latest registry-ice.ng.bluemix.net/mitu/logging # We next need to push the image into our Bluemix private Docker repository. sudo ice --local push registry-ice.ng.bluemix.net/mitu/logging # Start the IBM Container with our Docker image: # ice run --name <container_name> <namespace>/<image_name> sudo ice run --name logging -p 5000 mitu/logging # To see the container running sudo ice ps
阅读: 从命令行管理单一容器的 IP 地址
回页首
图 1. 创建一个 Cloud Foundry 应用程序
图 2. 选择 SDK for Node.js
有 3 种主要方式来开始开发应用程序:
图 3. 将代码写入 Bluemix
您做出的选择取决于您的个人偏好。我已成功使用所有 3 种开发方法,推荐您尝试每种方法,看看哪种方法最适合您。在此示例中,我使用了 CF 命令行接口。
您创建的微型服务现已在 Bluemix 提供的公共域中运行。继续导航到该 URL 来签出它。只需编写极少量的代码来与 Logstash 通信,无需构建服务:
清单 5. 使用正常的 net 模块来负责 TCP 通信
/*jshint node:true*/ var net = require('net'); var HOST = 'XXX.XXX.XXX.XXX'; // The public IP of your Container (or "localhost"/docker container IP), // if you are testing it on your machine var PORT = 5000; // the port defined in the Logstash configuration var client = new net.Socket(); client.connect(PORT, HOST, function() { console.log('CONNECTED TO: ' + HOST + ':' + PORT); client.write('{ "hello": "world!" }'); });
无需使用原始 TCP 连接,您可能希望通过 Lumberjack 协议发送日志,该协议非常适合此用途。(Lumberjack 需要 SSL 证书才能使用,而且非常安全。)实现 SSL 证书不属于本文的讨论范围,但这里给出了展示其工作原理的一小段代码。
清单 6. 对同一个解决方案使用 Lumberjack 协议
/*jshint node:true*/ var lumberjack = require('lumberjack-protocol'); var fs = require('fs'); var connectionOptions = { host: "XXX.XXX.XXX.XXX", port: 5500, // this is the configured Lumberjack port in the ELK stack ca: [fs.readFileSync('./logstash.crt', { encoding: 'utf-8' })] }; var client = lumberjack.client(connectionOptions, {maxQueueSize: 500}); client.writeDataFrame({"line": "Hello World!"});
您可以按照您下载代码的同一个 “开始编码” 页面上带编号的步骤,使用 CF 部署该微型服务。
回页首
这是首次通过端口 5601 登录到 localhost 上的 Kibana 中时看到的视图。通过在一个容易理解的仪表板上灵活地构建其日志,可以使用 Kibana 来可视化日志状态:
图 4. 包含收到的数据的 Kibana 仪表板示例
回页首
本文不是在创建您自己的集中化日志服务时指导您实现所有功能的完美指南。相反,本文只介绍了您在使用微型服务或分布式架构时可能发现的一些有用技术。我没有深入介绍如何构建自定义的 ELK 堆栈 Docker 镜像,并将它部署在 IBM Container 中。IBM Container 目前无法开箱即用地支持 docker-compose
命令,这意味着您需要在本地运行示例。在以后,当您具有足够自信时,您可以根据您自行构建的自定义 Docker 镜像,将整个解决方案部署到一个 IBM Container 中。然后,借助 ELK 堆栈,您会发现配置一个在 Docker 容器中运行的集中化日志服务非常简单。
您可能在将各部分结合起来时遇到一些小小的阻碍,因为有如此多不同的服务在彼此上运行,所以理解它们可能需要一定的时间。学完本文后,希望您能领悟这些技术提供的可能性,以及您将它们部署在 Bluemix 上的不同方式。