欢迎访问我的GitHub
这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos
本篇概览
本章是《Docker下ELK三部曲》的第二篇,之前的《Docker下ELK三部曲之一:极速体验》部署了ELK,还有一个web应用可以将日志上报到ELK,然后在Kibana提供的页面查询到了日志,今天我们一起深入细节,看看上述服务是如何实现的;
核心技术点
前一章中,之所以能通过一个docker-compose.yml将整个环境运行起来,所依赖的核心技术点为以下三个docker镜像:
- sebp/elk:这是ELK Server的镜像;
- bolingcavalry/springboot-app-filebeat:我们将web工程做成docker镜像的时候,都以bolingcavalry/springboot-app-filebeat作为基础镜像,这里面集成了filebeat,还有个启动脚本,可以先后启动filebeat和web工程;
- bolingcavalry/elkdemo:这个镜像中有web工程,启动后就相当于启动了web工程,该镜像的本质是将web工程复制到bolingcavalry/springboot-app-filebeat镜像中;
列举所有技术点
我们开门见山,将实现前一章体验用到的技术点列举出来:
- hub.docker.com镜像仓库中的sebp/elk,已集成了Elasticsearch, Logstash, Kibana,创建的容器直接作为ELK的server使用;
- 制作一个镜像,起名为bolingcavalry/springboot-app-filebeat,这里面装好了filebeat,将web应用产生的日志上报到ELK server上去;
- 基于springboot的web工程,在构建的时候使用docker-maven-plugin插件,将web工程制作成一个docker镜像,注意:基础镜像使用步骤2中的bolingcavalry/springboot-app-filebeat;
- 制作docker-compose.yml,将步骤1和步骤3中的镜像配置进来,再配置好link;
- 至此,所有材料就准备完成了,用docker-compose up -d命令即可开始前一章中的体验;
接下来我们将上面几点逐个展开细说;
ELK server
ELK server镜像的tag是622,代表6.2.2版本,下载命令:docker pull sebp/elk:622,有兴趣的同学可以去看一下对应的Dockerfile,地址:https://hub.docker.com/r/sebp/elk/~/dockerfile/
制作带有filebeat服务的基础镜像bolingcavalry/springboot-app-filebeat
制作该镜像的是本文的主要内容,制作前我们列出镜像的功能:
- 装好了JDK;
- 装好了filebeat;
- filebeat有权限将日志上报到ELK server;
- 时区要正确;
- 容器启动后,filebeat自动启动,并且扫描指定路径下的*.log文件;
- filebeat启动后,web应用自动启动,提供web服务,并且将日志输出在filebeat扫描的路径下;
以上就是bolingcavalry/springboot-app-filebeat镜像的所有功能,在编写Dockerfile脚本之前,我们先准备好制作镜像所需的材料;
您可以在GitHub下载这些材料,地址和链接信息如下表所示:
名称 | 链接 | 备注 |
---|---|---|
项目主页 | https://github.com/zq2599/blog_demos | 该项目在GitHub上的主页 |
git仓库地址(https) | https://github.com/zq2599/blog_demos.git | 该项目源码的仓库地址,https协议 |
git仓库地址(ssh) | git@github.com:zq2599/blog_demos.git | 该项目源码的仓库地址,ssh协议 |
这个git项目中有多个目录,本次所需的资源放在 filebeat_springboot_image_files目录下,如下图红框所示:
接下来,将这些材料的来源和加工步骤逐一说清楚,这些是制作镜像的关键;
JDK
不用安装JDK了,直接使用JDK的官方镜像作为基础镜像就好:java:8u111-jdk;
关于filebeat访问ELK的权限
filebeat日志上传到ELK是需要权限的,怎样才能获取权限呢?
请参考官方文档的说明,如下图:
上图红框中是filebeat.yml中的配置信息,要增加ssl节点的配置,并且要指定/etc/pki/tls/certs/目录下的logstash-beats.crt文件,这是个什么文件呢? 绿框中说明了logstash-beats.crt的出处:在elk镜像源码的git仓库中,地址是https://github.com/spujadas/elk-docker;
因此,我们要把logstash-beats.crt文件下载下来,在制作镜像时放在/etc/pki/tls/certs/目录下;
filebeat
在官网下载6.2.2版本,地址:https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-6.2.2-linux-x86_64.tar.gz,下载完毕后解压,然后修改其中的filebeat.yml文件:
- 如下图,enabled设置为true,paths设置为/applog/*.log,今后filebeat就从这个目录下搜集日志,所以我们的web工程中也要把日志输出目录设置成/applog/:
- 如下图,红框中的elkhost,是docker启动时候的link参数,通过elkhost即可访问ELK server,绿框中就是前面提到的,ELK访问权限对应的crt文件路径:
启动filebeat和web应用的脚本:filebeat-springboot-entrypoint.sh
脚本filebeat-springboot-entrypoint.sh,在docker容器启动的时候执行,这样就能让fliebeat和web应用在容器启动后也自动启动了:
代码语言:javascript复制echo "start filebeat now ..."
nohup /opt/filebeat-6.2.2-linux-x86_64/filebeat -e -c /opt/filebeat-6.2.2-linux-x86_64/filebeat.yml >/dev/null 2>&1 &
echo "start springboot jar now ..."
java -jar $1
上述shell脚本先用nohup后台启动filebeat,再用java命令启动基于springboot的jar包,jar包的名字是shell的入参,这里要注意:bolingcavalry/springboot-app-filebeat只是web镜像的基础镜像而已,它并不知道web工程的jar包的名称,所以jar包的名称是在shell脚本被调用的时候,由调用方传入的;
调用方是谁呢?我们在制作web工程的镜像时,可以指定容器启动时执行的shell,此时可以指定这个shell,再把jar包的名字作为参数传入即可;
web工程的镜像怎么制作呢?后面会讲到,先来看看其中调用shell脚本的那一段:
代码语言:javascript复制<!--镜像的FROM,使用bolingcavalry/springboot-app-filebeat:0.0.3-->
<baseImage>bolingcavalry/springboot-app-filebeat:0.0.3</baseImage>
<!--该镜像的容器启动后,直接运行spring boot工程-->
<entryPoint>["sh","/filebeat-springboot-entrypoint.sh","/${project.build.finalName}.jar"]</entryPoint>
如上所示,这是maven工程的pom.xml的一段,baseImage标签指定了基础镜像,entryPoint标签指定了启动容器时要执行的shell命令,jar包的名称是maven项目的名称;
至此,制作镜像bolingcavalry/springboot-app-filebeat所需的材料已经准备完毕,来编写Dockerfile吧;
###bolingcavalry/springboot-app-filebeat镜像的Dockerfile Dockerfile脚本的内容如下,由于每行都加了注释,就不多赘述了:
代码语言:javascript复制# Docker file for filebeat and springboot from bolingcavalry # VERSION 0.0.1
# Author: bolingcavalry
#基础镜像
FROM java:8u111-jdk
#作者
MAINTAINER BolingCavalry <zq2599@gmail.com>
#定义日志文件存放目录,这个要和web应用的日志配置一致
ENV APP_LOG_PATH /applog
#定义证书文件目录,这个要和filebeat.yml的配置一致
ENV FILE_BEAT_CRT_PATH /etc/pki/tls/certs
#定义filebeat文件夹名称
ENV FILE_BEAT_PACKAGE_NAME filebeat-6.2.2-linux-x86_64
#定义证书文件名称
ENV FILE_BEAT_CRT_NAME logstash-beats.crt
#定义启动文件名称
ENV ENTRYPOINT_FILE_NAME filebeat-springboot-entrypoint.sh
#定义时区参数
ENV TZ=Asia/Shanghai
#设置时区
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
#使之生效
RUN . /etc/profile
#创建日志目录文件夹
RUN mkdir $APP_LOG_PATH
#存放证书的文件夹
RUN mkdir -p $FILE_BEAT_CRT_PATH
#从当前目录將证书文件复制到镜像中
COPY ./$FILE_BEAT_CRT_NAME $FILE_BEAT_CRT_PATH/
#从当前目录將filebeat文件复制到镜像中
COPY ./$FILE_BEAT_PACKAGE_NAME /opt/$FILE_BEAT_PACKAGE_NAME
#复制启动文件
COPY ./$ENTRYPOINT_FILE_NAME /$ENTRYPOINT_FILE_NAME
#赋写权限
RUN chmod a x /$ENTRYPOINT_FILE_NAME
如上所述,前面我们准备的材料在脚本都统统用上了;
将filebeat-6.2.2-linux-x86_64 文件夹、Dockerfile文件、filebeat-springboot-entrypoint.sh文件、logstash-beats.crt放在同一目录下,执行以下命令即可将镜像构建成功:
代码语言:javascript复制docker build -t bolingcavalry/springboot-app-filebeat:0.0.3 .
web服务工程所需的基础镜像已经构建成功,接下来我们构建web工程的镜像:bolingcavalry/elkdemo
web工程的镜像
这里的web工程,是个maven构建的springboot工程,是个普通的springmvc服务,您也可以替换成自己想要的工程;
您可以在GitHub下载这个web工程的源码,地址和链接信息如下表所示:
名称 | 链接 | 备注 |
---|---|---|
项目主页 | https://github.com/zq2599/blog_demos | 该项目在GitHub上的主页 |
git仓库地址(https) | https://github.com/zq2599/blog_demos.git | 该项目源码的仓库地址,https协议 |
git仓库地址(ssh) | git@github.com:zq2599/blog_demos.git | 该项目源码的仓库地址,ssh协议 |
这个git项目中有多个目录,本次所需的资源放在elkdemo目录下,如下图红框所示:
接下来简述一下web服务镜像的制作:
- 用maven创建一个springboot的web工程;
- 在目录src/main/resources下增加一个logback.xml文件,用于配置日志有关的参数:
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
<!-- 应用名称 -->
<property name="APP_NAME" value="logtest" />
<!-- 日志输出格式 -->
<property name="ENCODER_PATTERN"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{80} - %msg%n" />
<contextName>${APP_NAME}</contextName>
<!-- 控制台日志:输出全部日志到控制台 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>${ENCODER_PATTERN}</Pattern>
</encoder>
</appender>
<!-- 文件日志:输出全部日志到文件 -->
<appender name="FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/applog/output.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>7</maxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${ENCODER_PATTERN}</pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
</configuration>
如上所示,日志文件的目录设置在/applog/,和filebeat.yml中搜集日志的目录保持一致; 3. 新增HelloController.java用于响应web请求,并且每次收到请求时都会打印一行日志:
代码语言:javascript复制@RestController
public class HelloController {
protected static final Logger logger = LoggerFactory.getLogger(HelloController.class);
@RequestMapping(value="/hello/{username}",method= RequestMethod.GET)
public String hello(@PathVariable String username) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = sdf.format(new Date());
logger.info("execute hello from {} - {}", username, time);
return "hello " username ", " time;
}
}
- pom.xml中,新增一个插件docker-maven-plugin,用于将当前工程构建成的jar文件做成docker镜像文件:
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.12</version>
<!--docker镜像相关的配置信息-->
<configuration>
<!--镜像名,这里用工程名-->
<imageName>bolingcavalry/${project.artifactId}</imageName>
<!--TAG,这里用工程版本号-->
<imageTags>
<imageTag>${project.version}</imageTag>
</imageTags>
<!--镜像的FROM,使用bolingcavalry/springboot-app-filebeat:0.0.3-->
<baseImage>bolingcavalry/springboot-app-filebeat:0.0.3</baseImage>
<!--该镜像的容器启动后,直接运行spring boot工程-->
<entryPoint>["sh","/filebeat-springboot-entrypoint.sh","/${project.build.finalName}.jar"]</entryPoint>
<!--构建镜像的配置信息-->
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
如上所示,web镜像的基础镜像是bolingcavalry/springboot-app-filebeat:0.0.3,启动时执行filebeat-springboot-entrypoint.sh,并且将自己工程的名称作为入参; 5. 在pom.xml文件所在目录执行以下命令,即可编译构建当前工程,并制作成docker镜像:
代码语言:javascript复制mvn clean package -U -DskipTests docker:build
如果您对web工程制作成docker镜像的细节感兴趣,想把自己的web工程做成docker镜像,可以参考《 maven构建docker镜像三部曲》:
- 《maven构建docker镜像三部曲之一:准备环境》;
- 《maven构建docker镜像三部曲之二:编码和构建镜像》;
- 《maven构建docker镜像三部曲之三:推送到远程仓库(内网和阿里云)》;
至此,镜像都已做好,我们再来看看启动他们的docker-compose.yml
docker-compose.yml
代码语言:javascript复制version: '2'
services:
elk:
image: sebp/elk:622
ports:
- "5601:5601"
restart: always
webapp:
image: bolingcavalry/elkdemo:0.0.1-SNAPSHOT
depends_on:
- elk
links:
- elk:elkhost
ports:
- "18080:8080"
restart: always
- ELK server容器的5601端口映射为当前电脑的5601端口,用于访问kibana;
- web应用镜像使用link参数绑定ELK server容器,使用webapp作为域名的地方都会被解析为ELK server容器的IP地址;
- web容器的8080映射为当前电脑的18080端口,访问当前电脑的18080端口即可访问web服务;
整个ELK环境所需的镜像和脚本都做好了,还有一个问题需要注意,否则有可能导致你的filebeat连接ELK server失败;
fliebeat与ELK server的连接问题
下图是filebeat的filebeat.yml文件的内容,红框中的elkhost,是docker启动时候的link参数,在写这个参数的时候要注意两点:
- 可以写成xxxxx的格式,例如:elkhost、abcdef这些都是可以的;
- 不能写成xxxxx.xxxx的格式,例如:elkhost.com、abcdef.com这些都不可以;
具体原因参考官方解释:http://elk-docker.readthedocs.io/#security-considerations,如下图:
简单的说,我们用的那个logstash-beats.crt证书中,限定的域名格式为*,如果一定要使用elkhost.com这样的域名,只能自己制作,然后覆盖ELK server和fliebeat上现有的logstash-beats.crt,制作方式如下图:
至此,制作ELK环境的细节的实战就结束了,您可以用自己的web来实战一番,看看是否能更方便的搜索日志了;
接下来的章节,我们将ELK server和web应用都搬到kubernetes环境上去,这样就更接近生产环境:多个web容器同时运行的时候,查日志不必再登录到每一台上去搜索了;