Docker实战(十五)Docker安装Hive环境

Hive安装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Hive必须运行在Hadoop之上,则需要先安装Hadoop环境,而且还需要MySQL数据库,具体Hadoop安装请参考上一篇文章,我们这里继承上一篇已经安装好的Hadoop镜像
# 下载Hive
$ wget http://apache.mirrors.ionfish.org/hive/hive-1.2.1/apache-hive-1.2.1-bin.tar.gz
# 解压Hive压缩包
$ tar -zxvf apache-hive-1.2.1-bin.tar.gz
# 下载MySQL驱动包
$ wget http://cdn.mysql.com//Downloads/Connector-J/mysql-connector-java-5.1.38.tar.gz
# 解压MySQL驱动压缩包
$ tar -zxvf mysql-connector-java-5.1.38.tar.gz
# 需要修改下面Hive相关的配置文件
Dockerfile文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
############################################
# version : birdben/hive:v1
# desc : 当前版本安装的hive
############################################
# 设置继承自我们创建的 hadoop 镜像
FROM birdben/hadoop:v1
# 下面是一些创建者的基本信息
MAINTAINER birdben (191654006@163.com)
# 设置环境变量,所有操作都是非交互式的
ENV DEBIAN_FRONTEND noninteractive
# 添加 supervisord 的配置文件,并复制配置文件到对应目录下面。(supervisord.conf文件和Dockerfile文件在同一路径)
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# 复制 hive-1.2.1 文件到镜像中(hive-1.2.1 文件夹要和Dockerfile文件在同一路径),这里直接把上一篇Hadoop环境直接用上了
ADD apache-hive-1.2.1-bin /software/hive-1.2.1
# 复制MySQL的驱动包到镜像中
COPY mysql-connector-java-5.1.38/mysql-connector-java-5.1.38-bin.jar /software/hive-1.2.1/lib/mysql-connector-java-5.1.38-bin.jar
# 授权HIVE_HOME路径给admin用户
RUN sudo chown -R admin /software/hive-1.2.1
# 执行supervisord来同时执行多个命令,使用 supervisord 的可执行路径启动服务。
CMD ["/usr/bin/supervisord"]
Dockerfile源文件链接:

https://github.com/birdben/birdDocker/blob/master/hive/Dockerfile

supervisor配置文件内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 配置文件包含目录和进程
# 第一段 supervsord 配置软件本身,使用 nodaemon 参数来运行。
# 第二段包含要控制的 2 个服务。每一段包含一个服务的目录和启动这个服务的命令。
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
[program:metastore]
command=/software/hive-1.2.1/bin/hive --service metastore
[program:hiveserver2]
command=/software/hive-1.2.1/bin/hive --service hiveserver2
配置HIVE_HOME/conf/hive-env.sh(默认不存在,将hive-env.sh.template复制并改名为hive-env.sh)
1
HADOOP_HOME=/software/hadoop-2.7.1
配置HIVE_HOME/conf/hive-log4j.properties(默认不存在,将hive-log4j.properties.template复制并改名为hive-log4j.properties)
配置HIVE_HOME/conf/hdfs-site.xml(默认不存在,将hive-default.xml.template复制并改名为hive-site.xml)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<!-- metastore我的mysql不是在该server上,是在另一台Docker镜像中 -->
<name>hive.metastore.local</name>
<value>false</value>
</property>
<property>
<!-- mysql服务的ip和端口号 -->
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://172.17.0.2:3306/hive</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriveName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>root</value>
</property>
<property>
<!-- hive的仓库目录,需要在HDFS上创建,并修改权限 -->
<name>hive.metastore.warehouse.dir</name>
<value>/hive/warehouse</value>
</property>
<property>
<!-- 运行hive得主机地址及端口,即本机ip和端口号,启动metastore服务 -->
<name>hive.metastore.uris</name>
<value>thrift://Ben:9083</value>
</property>
</configuration>
控制台终端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# 先启动MySQL的Docker容器
$ sudo docker run -p 9999:22 -p 3306:3306 -t -i -v /docker/mysql/data:/software/mysql-5.6.22/data birdben/mysql:v1
# 然后查看MySQL的Docker容器的IP地址,Hive连接MySQL的IP地址需要配置这个IP
$ sudo docker inspect --format '{{.NetworkSettings.IPAddress}}' 34b5ac61b8bd
$ 172.17.0.2
# 构建镜像
$ docker build -t="birdben/hive:v1" .
# 执行已经构件好的镜像,挂载在宿主机器的存储路径也不同,-h设置hostname,Hadoop配置文件需要使用
$ docker run -h Ben -p 9998:22 -p 9083:9083 -p 9000:9000 -p 8088:8088 -p 50020:50020 -p 50070:50070 -p 50075:50075 -p 50090:50090 -t -i 'birdben/hive:v1'
# 然后直接通过ssh远程连接使用admin账号远程登录Hive的Docker容器
$ ssh root@10.211.55.4 -p 9998
# 启动hive shell,发现如下的错误,原因是还没有启动Hadoop,所以hive连接Hadoop时,报错java.net.ConnectException: Call From Ben/172.17.0.3 to Ben:9000 failed on connection exception: java.net.ConnectException: Connection refused;
$ admin@Ben:/$ cd /software/hive-1.2.1/bin
$ admin@Ben:/$ ./hive shell
16/06/25 10:48:40 WARN conf.HiveConf: HiveConf of name hive.metastore.local does not exist
Logging initialized using configuration in file:/software/hive-1.2.1/conf/hive-log4j.properties
Exception in thread "main" java.lang.RuntimeException: java.net.ConnectException: Call From Ben/172.17.0.3 to Ben:9000 failed on connection exception: java.net.ConnectException: Connection refused; For more details see: http://wiki.apache.org/hadoop/ConnectionRefused
# 所以我们先启动Hadoop
# 先初始化namenode
$ admin@Ben:/$ cd /software/hadoop-2.7.1/bin
$ admin@Ben:/software/hadoop-2.7.1/sbin$ ./hdfs namenode -format
# 启动所有服务
admin@Ben:/$ cd /software/hadoop-2.7.1/sbin
admin@Ben:/software/hadoop-2.7.1/sbin$ ./start-all.sh
# 执行jps命令之前需要先把$JAVA_HOME/bin添加到PATH环境变量
admin@Ben:/$ export PATH=/software/jdk7/bin/:$PATH
# 执行jps命令如果能看到下面的6个进程就说明Hadoop启动的没有问题
admin@Ben:/software/hadoop-2.7.1/sbin$ jps
985 Jps
282 DataNode
587 ResourceManager
436 SecondaryNameNode
166 NameNode
691 NodeManager
# 此时重新启动hive shell,就可以成功登录hive了
$ admin@Ben:/$ cd /software/hive-1.2.1/bin
$ admin@Ben:/$ ./hive shell
hive>
hive> show databases;
OK
default
Time taken: 1.323 seconds, Fetched: 1 row(s)
# 注意:这里我是使用了之前的MySQL的Docker镜像,因为之前的MySQL的Docker镜像已经处理了root账号的更改密码和远程登录授权问题,所以这里没有涉及这些问题,具体设置可以参考之前的Docker安装MySQL镜像的文章
# 我们需要预先在mysql中创建一个hive的数据库,因为hive-site.xml是连接到这个hive数据库的,所有的hive元数据都是存在这个hive数据库中的
# 我们在hive中创建新的数据库和表来验证hive的元数据都存储在mysql了
# 在hive中创建一个新的数据库test_hive,test_hive这个数据库会对应mysql中的hive数据库中的DBS表中的一条记录
hive> CREATE DATABASE test_hive;
# 在hive中创建一个新的表test_person,test_person这个表会对应mysql中的hive数据库中的TBLS表中的一条记录
hive> USE test_hive;
hive> CREATE TABLE test_person (id INT,name string) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
# 在hive创建表的时候可能会遇到如下问题,是因为MySQL数据库字符集设置的utf-8导致的
# Specified key was too long; max key length is 767 bytes
# 修改MySQL的hive数据库的字符集为latin1就好用了
$ alter database hive character set latin1;
# 参考:http://blog.163.com/zhangjie_0303/blog/static/990827062013112623615941/
# test_person.txt
1 John
2 Ben
3 Allen
4 Jimmy
5 Will
6 Jackson
# 用scp命令将本地test_person.txt文件传到hive的Docker容器中
$ scp -P 9998 /Users/ben/workspace_git/birdDocker/hive/test_person.txt admin@10.211.55.4:/software/hive-1.2.1/
# 导入数据到test_person.txt到test_person表
hive> LOAD DATA LOCAL INPATH '/software/hive-1.2.1/test_person.txt' OVERWRITE INTO TABLE test_person;
Loading data to table test_hive.test_person
Table test_hive.test_person stats: [numFiles=1, numRows=0, totalSize=45, rawDataSize=0]
OK
Time taken: 2.885 seconds
# 查看test_person表数据
hive> select * from test_person;
OK
1 John
2 Ben
3 Allen
4 Jimmy
5 Will
6 Jackson
Time taken: 0.7 seconds, Fetched: 6 row(s)
# 查看test_hive数据库在HDFS中存储的目录
$ admin@Ben:$ cd /software/hadoop-2.7.1/bin
# 查看HDFS中/hive/warehouse目录下的所有文件,此目录是在hive-site.xml中hive.metastore.warehouse.dir参数配置的路径/hive/warehouse
$ admin@Ben:/software/hadoop-2.7.1/bin$ ./hdfs dfs -ls /hive/warehouse/
Found 1 items
drwxr-xr-x - admin supergroup 0 2016-06-25 11:39 /hive/warehouse/test_hive.db
# 查看test_person表在HDFS中存储的目录
$ admin@Ben:/software/hadoop-2.7.1/bin$ ./hdfs dfs -ls /hive/warehouse/test_hive.db/
Found 1 items
drwxr-xr-x - admin supergroup 0 2016-06-25 11:52 /hive/warehouse/test_hive.db/test_person
# 在深入一层就能看到我们导入的文件test_person.txt了
$ admin@Ben:/software/hadoop-2.7.1/bin$ ./hdfs dfs -ls /hive/warehouse/test_hive.db/test_person/
Found 1 items
-rwxr-xr-x 3 admin supergroup 45 2016-06-25 11:52 /hive/warehouse/test_hive.db/test_person/test_person.txt
# 查看test_person.txt文件里的内容,就是我们导入的内容
$ admin@Ben:/software/hadoop-2.7.1/bin$ ./hdfs dfs -cat /hive/warehouse/test_hive.db/test_person/test_person.txt
1 John
2 Ben
3 Allen
4 Jimmy
5 Will
6 Jackson
# OK,大功告成了,可以回家了 ^_^
test_hive数据库在MySQL的hive数据库中的DBS表中的一条记录

DBS表

test_person表在MySQL的hive数据库中的TBLS表中的一条记录

TBLS表

元数据解析

在MySQL可以查看Hive元数据表,除了DBS和TBLS存储数据库和表的基本信息,其他表的说明见下表:

MySQL的表 说明
BUCKETING_COLS Hive表CLUSTERED BY字段信息(字段名,字段序号)
CDS
COLUMNS_V2 存放表格的字段信息
DATABASE_PARAMS
DBS 存放hive所有数据库信息
FUNCS
FUNC_RU
GLOBAL_PRIVS
PARTITIONS Hive表分区信息(创建时间,具体的分区)
PARTITION_KEYS Hive分区表分区键(名称,类型,comment,序号)
PARTITION_KEY_VALS Hive表分区名(键值,序号)
PARTITION_PARAMS
PART_COL_STATS
ROLES
SDS 所有hive表、表分区所对应的hdfs数据目录和数据格式。
SD_PARAMS
SEQUENCE_TABLE SEQUENCE_TABLE表保存了hive对象的下一个可用ID,如’org.apache.hadoop.hive.metastore.model.MTable’, 21,则下一个新创建的hive表其TBL_ID就是21,同时SEQUENCE_TABLE表中271786被更新为26(这里每次都是+5)。同样,COLUMN,PARTITION等都有相应的记录
SERDES Hive表序列化反序列化使用的类库信息
SERDE_PARAMS 序列化反序列化信息,如行分隔符、列分隔符、NULL的表示字符等
SKEWED_COL_NAMES
SKEWED_COL_VALUE_LOC_MAP
SKEWED_STRING_LIST
SKEWED_STRING_LIST_VALUES
SKEWED_VALUES
SORT_COLS Hive表SORTED BY字段信息(字段名,sort类型,字段序号)
TABLE_PARAMS 表级属性,如是否外部表,表注释等
TAB_COL_STATS
TBLS 所有hive表的基本信息
VERSION

参考文章:

Linux常用命令(二)

scp命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 获取远程服务器上的文件
$ scp -P 2222 root@192.168.1.100:/root/tomcat.tar.gz /home/tomcat.tar.gz
# -P是端口号参数,2222表示更改SSH端口后的端口,如果没有更改SSH端口可以不用添加该参数
# root@192.168.1.100 表示使用root用户登录远程服务器192.168.1.100
# :/root/tomcat.tar.gz 表示远程服务器上的文件
# /home/tomcat.tar.gz 表示保存在本地上的路径和文件名
# 获取远程服务器上的目录
$ scp -P 2222 -r root@192.168.1.100:/root/tomcat/ /home/ben/dev/
# -P是端口号参数,2222表示更改SSH端口后的端口,如果没有更改SSH端口可以不用添加该参数
# -r参数表示递归复制(即复制该目录下面的文件和目录)
# root@192.168.1.100 表示使用root用户登录远程服务器192.168.1.100
# :/root/tomcat/ 表示远程服务器上的目录
# /home/ben/dev/ 表示保存在本地上的路径。
# 将本地文件上传到服务器上
$ scp -P 2222 /home/tomcat.tar.gz root@192.168.1.100:/root/tomcat.tar.gz
# -P是端口号参数,2222表示更改SSH端口后的端口,如果没有更改SSH端口可以不用添加该参数。
# /home/tomcat.tar.gz 表示本地上准备上传文件的路径和文件名
# root@192.168.1.100 表示使用root用户登录远程服务器
# 将本地目录上传到服务器上
$ scp -P 2222 -r /home/tomcat/ root@192.168.1.100:/root/dev/tomcat/
# -P是端口号参数,2222表示更改SSH端口后的端口,如果没有更改SSH端口可以不用添加该参数。
# -r 参数表示递归复制(即复制该目录下面的文件和目录)
# /home/tomcat/表示准备要上传的目录
# root@192.168.1.100 表示使用root用户登录远程服务器192.168.1.100
# :/root/dev/tomcat/ 表示保存在远程服务器上的目录位置。

nc命令

1
2
3
4
5
6
7
8
9
10
# 今天学到了另一种远程传输文件的方式,原来只知道scp,rz/sz
# 远程服务器(目的主机监听)
# 命令格式:nc -l 监听端口<未使用端口> > 要接收的文件名
$ nc -l 9999 > elasticsearch-jdbc-1.7.3.0-dist.zip
# 解释:远程服务器开启一个9999的端口进行监听,并且等待接收elasticsearch-jdbc-1.7.3.0-dist.zip文件
# 本地机器(源主机发起请求)
# 命令格式:nc 目的主机ip 目的端口 < 要发送的文件
$ nc 10.120.10.105 9999 < /Users/ben/Downloads/letv/ES/elasticsearch-jdbc-1.7.3.0-dist.zip
# 解释:本地机器指定远程服务器的ip地址和port端口号将指定的本地文件传送到远程服务器

rz/sz命令

Zmodem(rz/sz命令)一般需要和SSH客户端一起配合使用

下面介绍两种客户端

  1. iterm2(适用Mac环境)
  2. secureCRT(适用Windows环境)

iterm2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1. 安装brew工具
$ brew install lszrz
# 如果没有brew工具,请参考:http://blog.csdn.net/tsxw24/article/details/15500517
2. 下载iterm2-zmodem到/usr/local/bin目录(将两个shell脚本放到/usr/local/bin/目录下然后开始配置)
$ sudo wget https://raw.github.com/mmastrac/iterm2-zmodem/master/iterm2-send-zmodem.sh
$ sudo wget https://raw.github.com/mmastrac/iterm2-zmodem/master/iterm2-recv-zmodem.sh
$ sudo chmod 777 /usr/local/bin/iterm2-*
3. 运行下载的iterm,添加trigger
打开iterm2 --> 同时按command和,键 --> Profiles --> Default --> Advanced --> Triggers的Edit按钮
4. Triggers的设置代码如下
Regular expression: \*\*B0100
Action: Run Silent Coprocess
Parameters: /usr/local/bin/iterm2-send-zmodem.sh
Regular expression: \*\*B00000000000000
Action: Run Silent Coprocess
Parameters: /usr/local/bin/iterm2-recv-zmodem.sh
5. 上传和下载文件和secureCRT方式一样

iterm2

secureCRT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 上传文件
1. 打开secureCRT,通过SSH连到至远程linux主机
2. 键入rz命令
3. 在跳出的窗口选择想要上传的文件
4. 点击ADD后加入传输列表
5. 点击确认以后传送文件
6. 查看状态,一般都是发送正功
7. 查看目录,确定刚才选的文件已经上传成功
# 下载文件
1. 远程连接到linux主机
2. 输入sz fileName
3. 在弹出的窗口中选择保存文件到本地的目录
4. 确定后,等待文件下载完成

参考文章:

Docker实战(十四)Docker安装Hadoop环境

Hadoop安装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 需要提前安装ssh
$ apt-get install ssh
$ apt-get install openssh-server
# 设置免密码登录,生成私钥和公钥
$ ssh-keygen -t rsa -P ""
$ cat ~/.ssh/id_rsa.put >> ~/.ssh/authorized_keys
# 测试是否可以免密码登录
$ ssh localhost
# 下载Hadoop
$ curl -O http://mirrors.cnnic.cn/apache/hadoop/common/hadoop-2.7.1/hadoop-2.7.1.tar.gz
# 解压Hadoop压缩包
$ tar -xf hadoop-2.7.1.tar.gz
Dockerfile文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
############################################
# version : birdben/hadoop:v1
# desc : 当前版本安装的hadoop
############################################
# 设置继承自我们创建的 jdk7 镜像
FROM birdben/jdk7:v1
# 下面是一些创建者的基本信息
MAINTAINER birdben (191654006@163.com)
# 设置环境变量,所有操作都是非交互式的
ENV DEBIAN_FRONTEND noninteractive
# 添加 supervisord 的配置文件,并复制配置文件到对应目录下面。(supervisord.conf文件和Dockerfile文件在同一路径)
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# 设置 hadoop 的环境变量,若读者有其他的环境变量需要设置,也可以在这里添加。
ENV HADOOP_HOME /software/hadoop-2.7.1
ENV PATH ${HADOOP_HOME}/bin:$PATH
# 复制 hadoop-2.7.1 文件到镜像中(hadoop-2.7.1 文件夹要和Dockerfile文件在同一路径)
ADD hadoop-2.7.1 /software/hadoop-2.7.1
# 创建HDFS存储路径
RUN mkdir -p $HADOOP_HOME/hdfs/name
RUN mkdir -p $HADOOP_HOME/hdfs/data
# 授权HADOOP_HOME路径给admin用户
RUN sudo chown -R admin /software/hadoop-2.7.1
# 容器需要开放Hadoop 9000端口
EXPOSE 9000
# 执行supervisord来同时执行多个命令,使用 supervisord 的可执行路径启动服务。
CMD ["/usr/bin/supervisord"]
Dockerfile源文件链接:

https://github.com/birdben/birdDocker/blob/master/hadoop/Dockerfile

supervisor配置文件内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 配置文件包含目录和进程
# 第一段 supervsord 配置软件本身,使用 nodaemon 参数来运行。
# 第二段包含要控制的 2 个服务。每一段包含一个服务的目录和启动这个服务的命令。
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
# 暂时没用使用supervsord启动Hadoop,因为没研究明白如何启动的时候不需要ssh输入密码,即使设置了ENV DEBIAN_FRONTEND noninteractive所有的操作的是非交互的也不好用,所以只能启动Docker容器之后手动再启动Hadoop
# [program:hadoop]
# command=$HADOOP_HOME/bin/hdfs namenode -format
# command=$HADOOP_HOME/sbin/start_all.sh
配置HADOOP_HOME/etc/hadoop/hadoop-env.sh,添加以下内容
1
2
export JAVA_HOME=/software/jdk7
export PATH=$PATH:/software/hadoop-2.7.1/bin
配置HADOOP_HOME/etc/hadoop/yarn-env.sh,添加以下内容
1
export JAVA_HOME=/software/jdk7
配置HADOOP_HOME/etc/hadoop/core-site.xml,这里的Ben是我Docker容器的hostname,读者自行把Ben替换成自己的hostname(下同)
1
2
3
4
5
6
7
8
9
10
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://Ben:9000</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>file:/software/hadoop-2.7.1/tmp</value>
</property>
</configuration>
配置HADOOP_HOME/etc/hadoop/hdfs-site.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<configuration>
<property>
<name>dfs.datanode.ipc.address</name>
<value>Ben:50020</value>
</property>
<property>
<name>dfs.datanode.http.address</name>
<value>Ben:50075</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:/software/hadoop-2.7.1/hdfs/name</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file:/software/hadoop-2.7.1/hdfs/data</value>
</property>
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>Ben:50090</value>
</property>
</configuration>
配置HADOOP_HOME/etc/hadoop/mapred-site.xml,默认不存在,需要自建
1
2
3
4
5
6
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
</configuration>
配置HADOOP_HOME/etc/hadoop/yarn-site.xml
1
2
3
4
5
6
<configuration>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
</configuration>
控制台终端
1
2
3
4
# 构建镜像
$ docker build -t="birdben/hadoop:v1" .
# 执行已经构件好的镜像,挂载在宿主机器的存储路径也不同,-h设置hostname(即上面所说的Docker容器的hostname【Ben】),Hadoop配置文件需要使用
$ docker run -h Ben -p 9999:22 -p 9000:9000 -p 8088:8088 -p 50020:50020 -p 50070:50070 -p 50075:50075 -p 50090:50090 -t -i 'birdben/hadoop:v1'
用SSH登录admin账号启动Hadoop并且查看JPS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# 此时可以通过ssh远程连接Docker容器了
$ ssh root@10.211.55.4 -p 9999
# 先初始化namenode
admin@Ben:/$ cd /software/hadoop-2.7.1/bin
admin@Ben:/software/hadoop-2.7.1/sbin$ ./hdfs namenode -format
# 看到类似下面的信息就说明初始化namenode成功了
16/06/06 03:27:57 INFO namenode.FSNamesystem: Retry cache will use 0.03 of total heap and retry cache entry expiry time is 600000 millis
16/06/06 03:27:57 INFO util.GSet: Computing capacity for map NameNodeRetryCache
16/06/06 03:27:57 INFO util.GSet: VM type = 64-bit
16/06/06 03:27:57 INFO util.GSet: 0.029999999329447746% max memory 889 MB = 273.1 KB
16/06/06 03:27:57 INFO util.GSet: capacity = 2^15 = 32768 entries
16/06/06 03:27:57 INFO namenode.FSImage: Allocated new BlockPoolId: BP-581626940-172.17.0.2-1465183677567
16/06/06 03:27:57 INFO common.Storage: Storage directory /software/hadoop-2.7.1/hdfs/name has been successfully formatted.
16/06/06 03:27:57 INFO namenode.NNStorageRetentionManager: Going to retain 1 images with txid >= 0
16/06/06 03:27:57 INFO util.ExitUtil: Exiting with status 0
16/06/06 03:27:57 INFO namenode.NameNode: SHUTDOWN_MSG:
/************************************************************
SHUTDOWN_MSG: Shutting down NameNode at Ben/172.17.0.2
************************************************************/
# 启动所有服务
admin@Ben:/$ cd /software/hadoop-2.7.1/sbin
admin@Ben:/software/hadoop-2.7.1/sbin$ ./start-all.sh
# 下面的过程就是启动Hadoop的过程,但是始终需要输入ssh的密码,不知道为啥
This script is Deprecated. Instead use start-dfs.sh and start-yarn.sh
Starting namenodes on [Ben]
Ben: Could not create directory '/home/admin/.ssh'.
The authenticity of host 'ben (172.17.0.2)' can't be established.
ECDSA key fingerprint is ae:ec:44:6d:64:48:e8:34:17:33:cf:86:07:20:e3:4d.
Are you sure you want to continue connecting (yes/no)? yes
Ben: Failed to add the host to the list of known hosts (/home/admin/.ssh/known_hosts).
admin@ben's password:
Ben: Could not chdir to home directory /home/admin: No such file or directory
Ben: starting namenode, logging to /software/hadoop-2.7.1/logs/hadoop-admin-namenode-Ben.out
localhost: Could not create directory '/home/admin/.ssh'.
The authenticity of host 'localhost (::1)' can't be established.
ECDSA key fingerprint is ae:ec:44:6d:64:48:e8:34:17:33:cf:86:07:20:e3:4d.
Are you sure you want to continue connecting (yes/no)? yes
localhost: Failed to add the host to the list of known hosts (/home/admin/.ssh/known_hosts).
admin@localhost's password:
localhost: Could not chdir to home directory /home/admin: No such file or directory
localhost: starting datanode, logging to /software/hadoop-2.7.1/logs/hadoop-admin-datanode-Ben.out
Starting secondary namenodes [Ben]
Ben: Could not create directory '/home/admin/.ssh'.
The authenticity of host 'ben (172.17.0.2)' can't be established.
ECDSA key fingerprint is ae:ec:44:6d:64:48:e8:34:17:33:cf:86:07:20:e3:4d.
Are you sure you want to continue connecting (yes/no)? yes
Ben: Failed to add the host to the list of known hosts (/home/admin/.ssh/known_hosts).
admin@ben's password:
Ben: Could not chdir to home directory /home/admin: No such file or directory
Ben: starting secondarynamenode, logging to /software/hadoop-2.7.1/logs/hadoop-admin-secondarynamenode-Ben.out
starting yarn daemons
starting resourcemanager, logging to /software/hadoop-2.7.1/logs/yarn-admin-resourcemanager-Ben.out
localhost: Could not create directory '/home/admin/.ssh'.
The authenticity of host 'localhost (::1)' can't be established.
ECDSA key fingerprint is ae:ec:44:6d:64:48:e8:34:17:33:cf:86:07:20:e3:4d.
Are you sure you want to continue connecting (yes/no)? yes
localhost: Failed to add the host to the list of known hosts (/home/admin/.ssh/known_hosts).
admin@localhost's password:
localhost: Could not chdir to home directory /home/admin: No such file or directory
localhost: starting nodemanager, logging to /software/hadoop-2.7.1/logs/yarn-admin-nodemanager-Ben.out
# 执行jps命令之前需要先把$JAVA_HOME/bin添加到PATH环境变量
admin@Ben:/$ export PATH=/software/jdk7/bin/:$PATH
# 执行jps命令如果能看到下面的6个进程就说明Hadoop启动的没有问题
admin@Ben:/software/hadoop-2.7.1/sbin$ jps
985 Jps
282 DataNode
587 ResourceManager
436 SecondaryNameNode
166 NameNode
691 NodeManager
在Ubuntu宿主机浏览器查看
1
2
3
4
5
# 查看namenode状态:
http://127.0.0.1:50070/
# 查看yarn状态:
http://127.0.0.1:8088/

参考文章:

Docker实战(十三)Docker安装MySQL数据库

基本步骤和之前几篇文章一样,请参考前面的相关文章

Ubuntu安装MySQL安装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
(1)安装编译源码需要的包
sudo apt-get install make cmake gcc g++ bison libncurses5-dev build-essential
(2)下载并解压缩
mysql-5.6.26.tar.gz
tar -zxvf mysql-5.6.26.tar.gz
cd mysql-5.6.26
(3)编译安装
编译配置:
cmake .
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql
-DMYSQL_DATADIR=/usr/local/mysql/data
-DSYSCONFDIR=/etc
-DWITH_INNOBASE_STORAGE_ENGINE=1
-DWITH_ARCHIVE_STORAGE_ENGINE=1
-DWITH_BLACKHOLE_STORAGE_ENGINE=1
-DWITH_PARTITION_STORAGE_ENGINE=1
-DWITH_PERFSCHEMA_STORAGE_ENGINE=1
-DWITHOUT_EXAMPLE_STORAGE_ENGINE=1
-DWITHOUT_FEDERATED_STORAGE_ENGINE=1
-DDEFAULT_CHARSET=utf8
-DDEFAULT_COLLATION=utf8_general_ci
-DWITH_EXTRA_CHARSETS=all
-DENABLED_LOCAL_INFILE=1
-DWITH_READLINE=1
-DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock
-DMYSQL_TCP_PORT=3306
-DMYSQL_USER=mysql
-DCOMPILATION_COMMENT="lq-edition"
-DENABLE_DTRACE=0
-DOPTIMIZER_TRACE=1
-DWITH_DEBUG=1
cmake . -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DMYSQL_DATADIR=/usr/local/mysql/data -DSYSCONFDIR=/etc -DWITH_INNOBASE_STORAGE_ENGINE=1 -DWITH_ARCHIVE_STORAGE_ENGINE=1 -DWITH_BLACKHOLE_STORAGE_ENGINE=1 -DWITH_PARTITION_STORAGE_ENGINE=1 -DWITH_PERFSCHEMA_STORAGE_ENGINE=1 -DWITHOUT_EXAMPLE_STORAGE_ENGINE=1 -DWITHOUT_FEDERATED_STORAGE_ENGINE=1 -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DWITH_EXTRA_CHARSETS=all -DENABLED_LOCAL_INFILE=1 -DWITH_READLINE=1 -DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock -DMYSQL_TCP_PORT=3306 -DMYSQL_USER=mysql -DCOMPILATION_COMMENT="lq-edition" -DENABLE_DTRACE=0 -DOPTIMIZER_TRACE=1 -DWITH_DEBUG=1
参数说明:
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql //安装目录
-DINSTALL_DATADIR=/usr/local/mysql/data //数据库存放目录
-DDEFAULT_CHARSET=utf8     //使用utf8字符
-DDEFAULT_COLLATION=utf8_general_ci //校验字符
-DWITH_EXTRA_CHARSETS=all //安装所有扩展字符集
-DENABLED_LOCAL_INFILE=1    //允许从本地导入数据
编译:
make
安装:
sudo make install
配置MySQL
(1)新建运行Mysql的用户和组
sudo groupadd mysql
sudo useradd -g mysql mysql
登录mysql用户
先修改mysql用户的密码
passwd mysql
(2)设置Mysql安装目录的权限
cd /usr/local/mysql
sudo chown -R mysql:mysql ./
(3)建立配置文件
cp support-files/my-default.cnf /etc/my.cnf
sudo chown mysql:mysql /etc/my.cnf
修改配置文件:
sudo vi /etc/my.cnf
[client]
port = 3306
socket = /usr/local/mysql/data/mysql.sock
[mysqld]
port = 3306
socket = /usr/local/mysql/data/mysql.sock
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
(4)初始化数据库
cd /usr/local/mysql
sudo ./scripts/mysql_install_db --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data/
(5)启动mysql服务
方法1:
直接启动
bin/mysqld_safe &
检查MySQL服务是否启动:
ps -ef |grep mysql
(6)配置环境变量
为了直接调用mysql,需要将mysql的bin目录加入PATH环境变量。
编辑/etc/profile文件:
sudo vim /etc/profile
在文件最后 添加如下两行:
PATH=$PATH:/usr/local/mysql/bin
export PATH
关闭文件,运行下面的命令,让配置立即生效:
source /etc/profile
(7)修改root密码(因为默认密码为空)
$ mysql -u root -p
mysql> UPDATE user SET Password=PASSWORD('你想要的密码') where USER='root';
mysql> FLUSH PRIVILEGES;
(8)授权root账户远程登录
$ mysql -u root -p
mysql> grant ALL PRIVILEGES ON *.* to root@"%" identified by "root" WITH GRANT OPTION;
mysql> FLUSH PRIVILEGES;
Dockerfile文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
############################################
# version : birdben/ubuntu:mysql
# desc : 当前版本安装的MySQL
############################################
# 设置继承自我们创建的 tools 镜像
FROM birdben/ubuntu:tools
# 下面是一些创建者的基本信息
MAINTAINER birdben (191654006@163.com)
# 设置环境变量,所有操作都是非交互式的
ENV DEBIAN_FRONTEND noninteractive
# 添加 supervisord 的配置文件,并复制配置文件到对应目录下面。(supervisord.conf文件和Dockerfile文件在同一路径)
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
RUN echo "export LC_ALL=C"
# 替换ubuntu软件更新的源服务器的sources.list文件
COPY sources.list /etc/apt/sources.list
# 安装升级gcc
RUN sudo rm -rf /var/lib/apt/lists/*
RUN sudo apt-get update
RUN sudo apt-get install -y make cmake gcc g++ bison libncurses5-dev build-essential
# 复制 mysql-5.6.22 文件到镜像中(mysql-5.6.22文件夹要和Dockerfile文件在同一路径)
ADD mysql-5.6.22 /software/downloads/mysql-5.6.22
RUN cd /software/downloads/mysql-5.6.22 && cmake . -DCMAKE_INSTALL_PREFIX=/software/mysql-5.6.22 -DMYSQL_DATADIR=/software/mysql-5.6.22/data -DSYSCONFDIR=/etc -DWITH_INNOBASE_STORAGE_ENGINE=1 -DWITH_ARCHIVE_STORAGE_ENGINE=1 -DWITH_BLACKHOLE_STORAGE_ENGINE=1 -DWITH_PARTITION_STORAGE_ENGINE=1 -DWITH_PERFSCHEMA_STORAGE_ENGINE=1 -DWITHOUT_EXAMPLE_STORAGE_ENGINE=1 -DWITHOUT_FEDERATED_STORAGE_ENGINE=1 -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DWITH_EXTRA_CHARSETS=all -DENABLED_LOCAL_INFILE=1 -DWITH_READLINE=1 -DMYSQL_UNIX_ADDR=/software/mysql-5.6.22/mysql.sock -DMYSQL_TCP_PORT=3306 -DMYSQL_USER=mysql -DCOMPILATION_COMMENT="lq-edition" -DENABLE_DTRACE=0 -DOPTIMIZER_TRACE=1 -DWITH_DEBUG=1 && make && make install
# 添加测试用户mysql,密码mysql,并且将此用户添加到sudoers里
RUN useradd mysql
RUN echo "mysql:mysql" | chpasswd
RUN echo "mysql ALL=(ALL) ALL" >> /etc/sudoers
# 设置Mysql安装目录的权限
RUN cd /software/mysql-5.6.22 && sudo chown -R mysql:mysql ./
# 复制已经准备好的my.cnf文件到Docker容器
COPY my.cnf /etc/my.cnf
RUN sudo chown mysql:mysql /etc/my.cnf
# 初始化数据库
RUN cd /software/mysql-5.6.22 && sudo ./scripts/mysql_install_db --user=mysql --basedir=/software/mysql-5.6.22 --datadir=/software/mysql-5.6.22/data/
# 设置MySQL的环境变量,若读者有其他的环境变量需要设置,也可以在这里添加。
ENV MYSQL_HOME /software/mysql-5.6.22
# (不推荐下面的路径直接建立在Docker虚拟机上,推荐使用volume挂载方式)
# 在宿主机上创建一个数据库目录存储Mysql的数据文件
# sudo mkdir -p /docker/mysql/data
# VOLUME 选项是将本地的目录挂在到容器中 此处要注意:当你运行-v <hostdir>:<Containerdir> 时要确保目录内容相同否则会出现数据丢失
# 对应关系如下
# mysql:/docker/mysql/data
VOLUME ["/software/mysql-5.6.22/data"]
# 容器需要开放MySQL 3306端口
EXPOSE 3306
# 执行supervisord来同时执行多个命令,使用 supervisord 的可执行路径启动服务。
CMD ["/usr/bin/supervisord"]
Dockerfile源文件链接:

https://github.com/birdben/birdDocker/blob/master/mysql/Dockerfile

supervisor配置文件内容
1
2
3
4
5
6
7
8
9
10
11
12
13
# 配置文件包含目录和进程
# 第一段 supervsord 配置软件本身,使用 nodaemon 参数来运行。
# 第二段包含要控制的 2 个服务。每一段包含一个服务的目录和启动这个服务的命令。
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
[program:mysqld]
# 这里使用mysqld_safe &方式启动MySQL服务,但是不知道为什么后面加上&启动MySQL会报错,不加&就能正常启动了,后来看了一遍自己以前安装ES的博客才发现,mysql启动必须改成非daemon启动方式,这样supervisor就可以监控到了,所以要去掉&
command=./software/mysql-5.6.22/bin/mysqld_safe --user=mysql
my.cnf(复制MySQL_HOME/support-files/my-default.cnf文件修改如下)
1
2
3
4
5
6
7
8
[client]
port = 3306
socket = /software/mysql-5.6.22/data/mysql.sock
[mysqld]
port = 3306
socket = /software/mysql-5.6.22/data/mysql.sock
basedir = /software/mysql-5.6.22
datadir = /software/mysql-5.6.22/data
控制台终端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 构建镜像
$ docker build -t="birdben/mysql:v1" .
# 执行已经构件好的镜像
$ docker run -p 9999:22 -p 3306:3306 -t -i -v /docker/mysql/data:/software/mysql-5.6.22/data birdben/mysql:v1
# 可以ssh远程登录,然后登录mysql就大功告成了
$ ssh admin@10.211.55.4 -p 9999
# root账号的默认密码是空
$ cd /software/mysql-5.6.22/bin
$ mysql -u root -p
# 修改root密码(因为默认密码为空)
mysql> use mysql;
mysql> UPDATE user SET Password=PASSWORD('你想要的密码') where USER='root';
mysql> FLUSH PRIVILEGES;
# 授权root账户远程登录,然后就可以通过navicat或者其他客户端工具连接到MySQL服务器了
mysql> grant ALL PRIVILEGES ON *.* to root@"%" identified by "root" WITH GRANT OPTION;
mysql> FLUSH PRIVILEGES;

参考文章

Docker实战(十二)Docker安装ElasticSearch集群环境

ES集群需要配置几个地方,最简单的是配置集群名称和Node名称,其他的基本使用默认值就可以了,下面是elasticsearch.yml配置文件部分属性的用法,可以参考使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# 集群名称,默认为elasticsearch
cluster.name: birdESCluster
# 节点Node名称,ES启动时会自动创建节点名称,默认的是从ES的,但你也可进行配置
node.name: "birdESNode01"
# 是否作为主节点,每个节点都可以被配置成为主节点,默认值为true
node.master: true
# 是否存储数据,即存储索引片段,默认值为true
node.data: true
# master和data同时配置会产生一些奇异的效果:
1) 当master为false,而data为true时,会对该节点产生严重负荷;
2) 当master为true,而data为false时,该节点作为一个协调者;
3) 当master为false,data也为false时,该节点就变成了一个负载均衡器。
你可以通过连接来查看集群状态
http://localhost:9200/_cluster/health
http://localhost:9200/_cluster/nodes
或者使用插件来查看集群状态
http://github.com/lukas-vlcek/bigdesk
http://mobz.github.com/elasticsearch-head
# 设置一个索引的碎片数量,默认值为5
index.number_of_shards: 5
# 设置一个索引可被复制的数量,默认值为1
index.number_of_replicas: 1
# 当你想要禁用公布式时,你可以进行如下设置:
index.number_of_shards: 1
index.number_of_replicas: 0
这两个属性的设置直接影响集群中索引和搜索操作的执行。假设你有足够的机器来持有碎片和复制品,那么可以按如下规则设置这两个值:
1) 拥有更多的碎片可以提升索引执行能力,并允许通过机器分发一个大型的索引;
2) 拥有更多的复制器能够提升搜索执行能力以及集群能力。
对于一个索引来说,number_of_shards只能设置一次,而number_of_replicas可以使用索引更新设置API在任何时候被增加或者减少。
ElasticSearch关注加载均衡、迁移、从节点聚集结果等等。可以尝试多种设计来完成这些功能。
可以连接http://localhost:9200/A/_status来检测索引的状态。
# 配置文件所在的位置,即elasticsearch.yml和logging.yml所在的位置
path.conf: /path/to/conf
# 分配给当前节点的索引数据所在的位置
path.data: /path/to/data
# 可以可选择的包含一个以上的位置,使得数据在文件级别跨越位置,这样在创建时就有更多的自由路径
path.data: /path/to/data1,/path/to/data2
# 日志文件所在位置
path.logs: /path/to/logs
# 临时文件位置
path.work: /path/to/work
# 插件安装位置
path.plugins: /path/to/plugins
# 默认情况下,ElasticSearch使用0.0.0.0地址(也就是说如果这个机子有几个网卡,则ElasticSearch都可以通过这些IP来使用其服务。所以如果我们的服务器有网卡绑定在外网时一定要注意设置ElasticSearch的属性),并为http传输开启9200-9300端口,为节点到节点的通信开启9300-9400端口,也可以自行设置IP地址:
network.bind_host: 192.168.0.1
# publish_host设置其他节点连接此节点的地址,如果不设置的话,则自动获取,publish_host的地址必须为真实地址:
network.publish_host: 192.168.0.1
# bind_host和publish_host可以一起设置:(如果不想外网访问ES,可以设置这个)
network.host: 192.168.0.1
# 可以定制该节点与其他节点交互的端口:
transport.tcp.port: 9300
# 节点间交互时,可以设置是否压缩,转为为不压缩:
transport.tcp.compress: true
# 可以为Http传输监听定制端口:
http.port: 9200
# 设置内容的最大长度:
http.max_content_length: 100mb
# 禁止HTTP
http.enabled: false
# 允许在N个节点启动后恢复过程:
gateway.recover_after_nodes: 1
# 设置初始化恢复过程的超时时间:
gateway.recover_after_time: 5m
# 设置ping其他节点时的超时时间,网络比较慢时可将该值设大:
discovery.zen.ping.timeout: 3s
# 禁止当前节点发现多个集群节点,默认值为true:
discovery.zen.ping.multicast.enabled: false
# 设置新节点被启动时能够发现的主节点列表:
discovery.zen.ping.unicast.hosts: ["10.0.0.28:9300", "10.0.0.28:9500"]
# 设置是否可以通过正则或者_all删除或者关闭索引
action.destructive_requires_name 默认false 允许 可设置true不允许
# 下面是一些查询时的慢日志参数设置
index.search.slowlog.level: TRACE
index.search.slowlog.threshold.query.warn: 10s
index.search.slowlog.threshold.query.info: 5s
index.search.slowlog.threshold.query.debug: 2s
index.search.slowlog.threshold.query.trace: 500ms
index.search.slowlog.threshold.fetch.warn: 1s
index.search.slowlog.threshold.fetch.info: 800ms
index.search.slowlog.threshold.fetch.debug:500ms
index.search.slowlog.threshold.fetch.trace: 200ms
elasticsearch.yml源文件链接:
Dockerfile文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
############################################
# version : birdben/escluster:v1
# desc : 当前版本安装的escluster
############################################
# 设置继承自我们创建的 jdk7 镜像
FROM birdben/jdk7:v1
# 下面是一些创建者的基本信息
MAINTAINER birdben (191654006@163.com)
# 设置环境变量,所有操作都是非交互式的
ENV DEBIAN_FRONTEND noninteractive
# 添加 supervisord 的配置文件,并复制配置文件到对应目录下面。(supervisord.conf文件和Dockerfile文件在同一路径)
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
RUN echo "export LC_ALL=C"
# 设置 ES 的环境变量,若读者有其他的环境变量需要设置,也可以在这里添加。
ENV ES_HOME /software/elasticsearch-1.7.2
# 复制 elasticsearch-1.7.2 文件到镜像中(elasticsearch-1.7.2文件夹要和Dockerfile文件在同一路径)
ADD elasticsearch-1.7.2 /software/elasticsearch-1.7.2
# 挂载/software/elasticsearch-1.7.2/config和/escluster目录
VOLUME ["/software/elasticsearch-1.7.2/config"]
VOLUME ["/escluster"]
# 容器需要开放ES的9200和9300端口
EXPOSE 9200
EXPOSE 9300
# 执行supervisord来同时执行多个命令,使用 supervisord 的可执行路径启动服务。
CMD ["/usr/bin/supervisord"]
Dockerfile源文件链接:

https://github.com/birdben/birdDocker/blob/master/escluster/Dockerfile

supervisor配置文件内容
1
2
3
4
5
6
7
8
9
10
11
12
13
# 配置文件包含目录和进程
# 第一段 supervsord 配置软件本身,使用 nodaemon 参数来运行。
# 第二段包含要控制的 2 个服务。每一段包含一个服务的目录和启动这个服务的命令。
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
# 修改supervisor配置方式如下,修改为不自动重启ES,并且改成非daemon,DFOREGROUND的方式运行,supervisor就可以监控到了
[program:elasticsearch]
command=/bin/bash -c "exec ${ES_HOME}/bin/elasticsearch -DFOREGROUND"
控制台终端
1
2
3
4
5
# 构建镜像
$ docker build -t="birdben/escluster:v1" .
# 执行已经构件好的镜像,这里启动了两个ES的镜像,只是ES的端口号不同,挂载在宿主机器的存储路径也不同
$ docker run -p 9999:22 -p 9200:9200 -p 9300:9300 -v /docker/escluster01:/escluster -v /docker/escluster01/config:/software/elasticsearch-1.7.2/config -t -i 'birdben/escluster:v1'
$ docker run -p 9998:22 -p 9201:9200 -p 9301:9300 -v /docker/escluster02:/escluster -v /docker/escluster02/config:/software/elasticsearch-1.7.2/config -t -i 'birdben/escluster:v1'
访问ElasticSearch集群的插件测试
1
2
3
4
# 访问9201和9201端口都能分别访问
http://10.211.55.4:9200/_plugin/head/
http://10.211.55.4:9201/_plugin/head/
# 在Node1上创建索引会自动同步到Node2上,而且对应的data和logs目录也存储在挂载的目录中
ES集群的访问方式
Java API

Elasticsearch为Java用户提供了两种内置客户端:
需要在项目中引入elasticsearch.jar,这个jar中有两种ES提供的Client

节点客户端 (Node Client)

NodeClient

Instantiating a node based client is the simplest way to get a Client that can execute operations against elasticsearch.

Embedding a node client into your application is the easiest way to connect to an Elasticsearch cluster

Node Client加入ES集群是一个没有数据的Node,就是这个Node不存储任何数据,但是这个Node知道数据存储在ES集群的哪个Node,可以把请求转发到正确的Node上去

注意:

实际上Node Client是在我们的系统,单元测试中启动了一个Embedded ElasticSearch,这个Embedded ElasticSearch是我们不存储任何数据的Node加入ES集群,我们的系统通过它来和ES集群进行通信,最好关闭Embedded Node的http端口(9200端口)防止http请求直接访问,因为Node Client与ES集群Node的通信都是使用的9300端口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import static org.elasticsearch.node.NodeBuilder.*;
// on startup
Node node = nodeBuilder().node();
Client client = node.client();
// on shutdown
node.close();
// 设置ES的集群名称,在Java代码中
Node node = nodeBuilder().clusterName("yourclustername").node();
Client client = node.client();
// 也可以设置cluster.name在/src/main/resources/elasticsearch.yml配置文件
传输客户端 (Transport Client)

TransportClient

The TransportClient connects remotely to an Elasticsearch cluster using the transport module. It does not join the cluster, but simply gets one or more initial transport addresses and communicates with them in round robin fashion on each action (though most actions will probably be “two hop” operations).

Transport Client不会加入集群,只是负责把请求转发给ES集群的Node

Java Client和ES集群通信通过9300端口,使用native ElasticSearch transport protocol, ES集群的Node也使用9300端口进行通信。(如果ES集群的9300端口没有开通,你的Nodes无法构建成一个集群)

注意:Java Client必须和ES集群的Node版本一致(也就是jar包的版本要和ES集群的版本对应一致),否则无法通信

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// on startup
Client client = TransportClient.builder().build()
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("host1"), 9300))
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("host2"), 9300));
// on shutdown
client.close();
// 设置集群名称
Settings settings = Settings.settingsBuilder()
.put("cluster.name", "myClusterName").build();
Client client = TransportClient.builder().settings(settings).build();
//Add transport addresses and do something with the client...
// 也可以设置cluster.name在/src/main/resources/elasticsearch.yml配置文件,如Node Client

注意:addTransportAddress方法

Adds a transport address that will be used to connect to.The Node this transport address represents will be used if its possible to connect to it. If it is unavailable, it will be automatically connected to once it is up.In order to get the list of all the current connected nodes, please see connectedNodes().

当一个ES Node(对应一个transportAddress)不可用时,client会自动发现当前可用的nodes(the current connected nodes),从以下这段代码可知:

TransportClientNodesService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int index = randomNodeGenerator.incrementAndGet();
if (index < 0) {
index = 0;
randomNodeGenerator.set(0);
}
RetryListener<Response> retryListener = new RetryListener<Response>(callback, listener, nodes, index);
try {
callback.doWithNode(nodes.get((index) % nodes.size()), retryListener);
} catch (ElasticsearchException e) {
if (e.unwrapCause() instanceof ConnectTransportException) {
retryListener.onFailure(e);
} else {
throw e;
}
}
RESTFUL API

其他语言都可以使用RESTFUL API通过9200端口和ES进行通信,甚至可以通过命令行使用curl命令

HTTP Request格式

1
2
3
4
5
6
7
8
curl -X<VERB> '<PROTOCOL>://<HOST>/<PATH>?<QUERY_STRING>' -d '<BODY>'
VERB : HTTP方法(GET, POST, PUT, HEAD or DELETE)
PROTOCOL : HTTP 或者 HTTPS协议(如果有一个HTTPS的代理在ES前端)
HOST : ES集群名称或者IP地址
PORT : 端口号运行着ES的HTTP服务,默认是9200
QUERY_STRING : 查询参数(例如:?pretty)
BODY : A JSON-encoded request body

参考文章:

Docker实战(十一)Docker安装ELK环境(二)

日志收集系统架构
日志收集系统架构

日志收集系统架构简介
  • Logstash Agent/Flume:采集各个业务系统的日志,然后发送给Redis/Kafka消息队列。
  • Redis/Kafka:接收用户日志的消息队列,临时存储日志并且起到缓冲的作用,防止日志量上来之后,拖垮Logstash Indexer。
  • Logstash Indexer:做日志解析,统一成JSON输出给Elasticsearch。
  • Elasticsearch:实时日志分析服务的核心技术,一个schemaless,实时的数据存储服务,通过index组织数据,兼具强大的搜索和统计功能。
  • Kibana:基于Elasticsearch的数据可视化组件,超强的数据可视化能力是众多公司选择ELK stack的重要原因。

这里实现的是 ELK + Redis 收集 Nginx 的 access.log
我们这里是把各个组件拆开,模拟每个组件是一个集群,每个集群部署在一台机器上

1.Nginx + Logstash agent
2.Redis
3.Logstash indexer
4.ElasticSearch
5.Kibana

Nginx配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
daemon off;
master_process off;
error_log logs/error.log;
...
http {
include mime.types;
default_type application/octet-stream;
# 设置nginx日志格式,格式的名称logstash
log_format logstash '$http_host $server_addr $remote_addr [$time_local] "$request" $request_body $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_time $upstream_response_time';
# 设置access_log日志输出的文件路径,以及使用的日志格式名称
access_log logs/access.log logstash;
# 以下内容省略
...
}
logstash agent的配置文件logstash.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
input {
file {
type => "nginx_access"
path => ["/usr/local/nginx/logs/access.log"]
}
}
output {
redis {
host => "10.211.55.4"
port => 6379
password => admin
data_type => "list"
key => "logstash:redis"
}
}
注意

这里配置就是往redis队列中塞入日志就行,所以input的来源是Nginx的log文件,output的目标设置为redis,这里redis充当MQ消息队列的作用。

logstash indexer的配置文件logstash.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
input {
redis {
host => "10.211.55.4"
port => 6379
password => admin
data_type => "list"
key => "logstash:redis"
}
}
filter {
grok {
match => [
"message", "%{IPORHOST:http_host} %{IPORHOST:server_ip} %{IPORHOST:client_ip} \[%{HTTPDATE:timestamp}\] \"%{WORD:http_verb} (?:%{PATH:baseurl}\?%{NOTSPACE:params}(?: HTTP/%{NUMBER:http_version})?|%{DATA:raw_http_request})\" (%{NOTSPACE:params})?|- %{NUMBER:http_status_code} (?:%{NUMBER:bytes_read}|-) %{QS:referrer} %{QS:agent} %{NUMBER:time_duration:float} %{NUMBER:time_backend_response:float}"
]
}
kv {
prefix => "params."
field_split => "&"
source => "params"
}
urldecode {
all_fields => true
}
date {
locale => "en"
match => ["timestamp" , "dd/MMM/YYYY:HH:mm:ss Z"]
}
}
output {
elasticsearch {
embedded => false codec => "json" protocol => "http" host => "10.211.55.4" port => 9200 index => "birdlogstash" }
}
注意

logstash indexer的配置文件就比较麻烦了,需要配置的有三个部分

  • input: 负责从redis中获取日志数据
  • filter: 负责对日志数据进行分析和结构化
  • output: 负责将结构化的数据存储进入elasticsearch

这里配置就是从redis队列中获取日志,对日志进行相应地过滤,所以input的来源是Redis的list队列,其中的redis配置当然要和logstash agent的配置一致了。output的目标设置为ES搜索引擎的索引,在通过kibana图形界面化的展示ES的查询索引。

kibana.yml配置文件
1
2
3
# 这里配置Kibana访问ES集群的地址
# The Elasticsearch instance to use for all your queries.
elasticsearch_url: "http://10.211.55.4:9200"
elk_log_agent的Dockerfile文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
############################################
# version : birdben/elk_log_agent:v1
# desc : 当前版本安装的elk_log_agent
############################################
# 设置继承自我们创建的 jdk7 镜像
FROM birdben/jdk7:v1
# 下面是一些创建者的基本信息
MAINTAINER birdben (191654006@163.com)
# 设置环境变量,所有操作都是非交互式的
ENV DEBIAN_FRONTEND noninteractive
# 添加 supervisord 的配置文件,并复制配置文件到对应目录下面。(supervisord.conf文件和Dockerfile文件在同一路径)
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# 设置 LOGSTASH 的环境变量,若读者有其他的环境变量需要设置,也可以在这里添加。
ENV LOGSTASH_HOME /software/logstash-1.5.4
# 复制 logstash-1.5.4 文件到镜像中(logstash-1.5.4 文件夹要和Dockerfile文件在同一路径)
ADD logstash-1.5.4 /software/logstash-1.5.4
# 解决环境问题,否则logstash无法从log文件中采集日志。具体环境: Logstash 1.5, Ubuntu 14.04, Oracle JDK7
RUN ln -s /lib/x86_64-linux-gnu/libcrypt.so.1 /usr/lib/x86_64-linux-gnu/libcrypt.so
# 安装升级gcc
RUN sudo rm -rf /var/lib/apt/lists/*
RUN sudo apt-get update
RUN sudo apt-get -y install \
build-essential
RUN sudo mkdir -p /software/temp
RUN wget http://nginx.org/download/nginx-1.8.0.tar.gz && tar -zxvf nginx-1.8.0.tar.gz -C /software/temp
RUN wget http://zlib.net/zlib-1.2.8.tar.gz && tar -zxvf zlib-1.2.8.tar.gz -C /software/temp
RUN wget http://www.openssl.org/source/openssl-1.0.1q.tar.gz && tar -zxvf openssl-1.0.1q.tar.gz -C /software/temp
RUN wget http://downloads.sourceforge.net/project/pcre/pcre/8.37/pcre-8.37.tar.gz && tar -zxvf pcre-8.37.tar.gz -C /software/temp
RUN cd /software/temp/nginx-1.8.0 && sudo ./configure --sbin-path=/software/nginx-1.8.0/nginx --conf-path=/software/nginx-1.8.0/nginx.conf --pid-path=/software/nginx-1.8.0/nginx.pid --with-http_ssl_module --with-pcre=/software/temp/pcre-8.37 --with-zlib=/software/temp/zlib-1.2.8 --with-openssl=/software/temp/openssl-1.0.1q && sudo make && sudo make install
# 设置nginx是非daemon启动
RUN echo 'daemon off;' >> /software/nginx-1.8.0/nginx.conf
RUN echo 'master_process off;' >> /software/nginx-1.8.0/nginx.conf
RUN echo 'error_log logs/error.log;' >> /software/nginx-1.8.0/nginx.conf
# 设置 NGINX 的环境变量,若读者有其他的环境变量需要设置,也可以在这里添加。
ENV NGINX_HOME /software/nginx-1.8.0
# 挂载/logstash目录
VOLUME ["/logstash"]
# 容器需要开放Nginx 80端口
EXPOSE 80
# 执行supervisord来同时执行多个命令,使用 supervisord 的可执行路径启动服务。
CMD ["/usr/bin/supervisord"]
elk_log_agent的supervisord.conf配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 配置文件包含目录和进程
# 第一段 supervsord 配置软件本身,使用 nodaemon 参数来运行。
# 第二段包含要控制的 2 个服务。每一段包含一个服务的目录和启动这个服务的命令。
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
[program:nginx]
command=/software/nginx-1.8.0/nginx -c /software/nginx-1.8.0/nginx.conf
[program:logstash]
# 指定配置文件时,一定要使用绝对路径,相对路径是不好用的,这个坑已经踩过两次了。。
command=/software/logstash-1.5.4/bin/logstash -f /logstash/logstash_agent.conf
elk_log_agent的控制台终端
1
2
3
4
# 构建镜像
$ docker build -t="birdben/elk_log_agent:v1" .
# 执行已经构件好的镜像
$ docker run -p 9999:22 -p 8888:80 -t -i -v /docker/logstash:/logstash "birdben/elk_log_agent:v1"
logstash的Dockerfile文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
############################################
# version : birdben/logstash:v1
# desc : 当前版本安装的logstash
############################################
# 设置继承自我们创建的 jdk7 镜像
FROM birdben/jdk7:v1
# 下面是一些创建者的基本信息
MAINTAINER birdben (191654006@163.com)
# 设置环境变量,所有操作都是非交互式的
ENV DEBIAN_FRONTEND noninteractive
# 添加 supervisord 的配置文件,并复制配置文件到对应目录下面。(supervisord.conf文件和Dockerfile文件在同一路径)
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# 设置 LOGSTASH 的环境变量,若读者有其他的环境变量需要设置,也可以在这里添加。
ENV LOGSTASH_HOME /software/logstash-1.5.4
# 复制 logstash-1.5.4 文件到镜像中(logstash-1.5.4文件夹要和Dockerfile文件在同一路径)
ADD logstash-1.5.4 /software/logstash-1.5.4
# 解决环境问题,否则logstash无法从log文件中采集日志。具体环境: Logstash 1.5, Ubuntu 14.04, Oracle JDK7
RUN ln -s /lib/x86_64-linux-gnu/libcrypt.so.1 /usr/lib/x86_64-linux-gnu/libcrypt.so
# 挂载/logstash目录
VOLUME ["/logstash"]
# 执行supervisord来同时执行多个命令,使用 supervisord 的可执行路径启动服务。
CMD ["/usr/bin/supervisord"]
logstash的supervisord.conf配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
# 配置文件包含目录和进程
# 第一段 supervsord 配置软件本身,使用 nodaemon 参数来运行。
# 第二段包含要控制的 2 个服务。每一段包含一个服务的目录和启动这个服务的命令。
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
[program:logstash]
# 指定配置文件时,一定要使用绝对路径,相对路径是不好用的,这个坑已经踩过两次了。。
command=/software/logstash-1.5.4/bin/logstash -f /logstash/logstash.conf
logstash的控制台终端
1
2
3
4
# 构建镜像
$ docker build -t="birdben/logstash:v1" .
# 执行已经构件好的镜像
$ docker run -p 9999:22 -t -i -v /docker/logstash:/logstash "birdben/logstash:v1"
kibana的Dockerfile文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
############################################
# version : birdben/kibana:v1
# desc : 当前版本安装的kibana
############################################
# 设置继承自我们创建的 tools 镜像
FROM birdben/tools:v1
# 下面是一些创建者的基本信息
MAINTAINER birdben (191654006@163.com)
# 设置环境变量,所有操作都是非交互式的
ENV DEBIAN_FRONTEND noninteractive
# 添加 supervisord 的配置文件,并复制配置文件到对应目录下面。(supervisord.conf文件和Dockerfile文件在同一路径)
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# 设置 KIBANA 的环境变量,若读者有其他的环境变量需要设置,也可以在这里添加。
ENV KIBANA_HOME /software/kibana-4.1.2
# 复制 kibana-4.1.2 文件到镜像中(kibana-4.1.2文件夹要和Dockerfile文件在同一路径)
ADD kibana-4.1.2 /software/kibana-4.1.2
# 容器需要开放Kibana的5601端口
EXPOSE 5601
# 执行supervisord来同时执行多个命令,使用 supervisord 的可执行路径启动服务。
CMD ["/usr/bin/supervisord"]
kibana的supervisord.conf配置文件
1
2
3
4
5
6
7
8
9
10
11
12
# 配置文件包含目录和进程
# 第一段 supervsord 配置软件本身,使用 nodaemon 参数来运行。
# 第二段包含要控制的 2 个服务。每一段包含一个服务的目录和启动这个服务的命令。
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
[program:kibana]
command=/software/kibana-4.1.2/bin/kibana
kibana的控制台终端
1
2
3
4
# 构建镜像
$ docker build -t="birdben/kibana:v1" .
# 执行已经构件好的镜像
$ docker run -p 9999:22 -p 5601:5601 -t -i "birdben/kibana:v1"
注意

ES和Redis如之前的文章介绍部署即可

验证日志收集

访问Nginx主页,查看access.log中的日志是否按照指定的日志格式输出,之后access.log会被log_agent收集到Redis中,如果log_indexer是可用状态的,就会从Redis中消费掉日志信息,如果log_indexer是不可用的,日志信息就会保存在Redis中。log_indexer从Redis中消费掉日志后,就会在ES中创建相应地索引,最后在Kibana中进行查询显示

参考文章:

Docker实战(十)Docker安装Nginx

安装Nginx可以选择直接使用ubuntu的apt-get install nginx命令来安装,这种安装方式最简单方便,但是Nginx的版本可能是比较老的版本,所以这里我选择编译安装的方式。

Nginx需要依赖下面3个包
  1. gzip 模块需要 zlib 库 ( 下载: http://www.zlib.net/ ) zlib-1.2.8.tar.gz
  2. rewrite 模块需要 pcre 库 ( 下载: http://www.pcre.org/ ) pcre-8.37.tar.gz
  3. ssl 功能需要 openssl 库 ( 下载: http://www.openssl.org/ ) openssl-1.0.1q.tar.gz
编译方式安装Nginx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 下载nginx安装依赖的包
$ wget http://zlib.net/zlib-1.2.8.tar.gz
$ wget http://www.openssl.org/source/openssl-1.0.1q.tar.gz
$ wget http://downloads.sourceforge.net/project/pcre/pcre/8.37/pcre-8.37.tar.gz
$ wget http://nginx.org/download/nginx-1.8.0.tar.gz
# nginx-1.8.0,pcre-8.37,zlib-1.2.8,openssl-1.0.1q这几个解压的文件夹是放在/temp文件夹下,nginx按照的目录是/software/nginx-1.8.0 $ cd /temp/nginx-1.8.0/ $ sudo ./configure --sbin-path=/software/nginx-1.8.0/nginx --conf-path=/software/nginx-1.8.0/nginx.conf --pid-path=/software/nginx-1.8.0/nginx.pid --with-http_ssl_module --with-pcre=/temp/pcre-8.37 --with-zlib=/temp/zlib-1.2.8 --with-openssl=/temp/openssl-1.0.1q
$ sudo make
$ sudo make install
# 检查80端口是否被占用
$ netstat -ano|grep 80
# 启动nginx
$ cd /software/nginx-1.8.0/
$ sudo ./nginx
# 不指定配置文件地址
$ cd /software/nginx-1.8.0
$ ./nginx
# 指定配置文件地址
$ cd /software/nginx-1.8.0
$ ./nginx -c /software/nginx-1.8.0/nginx.conf
# 停止服务
$ sudo kill 'cat /software/nginx-1.8.0/nginx.pid'
# 检测配置文件
$ cd /software/nginx-1.8.0
$ ./nginx -t
# 重新加载配置文件(不停止服务)
$ cd /software/nginx-1.8.0
$ ./nginx -s reload
编译安装Nginx可能会遇到的问题和解决方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 编译安装Nginx的时候需要指定相关参数,否则会遇到下面的问题
./configure: error: the HTTP rewrite module requires the PCRE library. You can either disable the module by using --without-http_rewrite_module option, or install the PCRE library into the system, or build the PCRE library statically from the source with nginx by using --with-pcre=<path> option.
# Nginx编译参数
–prefix #nginx安装目录,默认在/usr/local/nginx
–pid-path #pid问件位置,默认在logs目录
–lock-path #lock问件位置,默认在logs目录
–with-http_ssl_module #开启HTTP SSL模块,以支持HTTPS请求。
–with-http_dav_module #开启WebDAV扩展动作模块,可为文件和目录指定权限
–with-http_flv_module #支持对FLV文件的拖动播放
–with-http_realip_module #支持显示真实来源IP地址
–with-http_gzip_static_module #预压缩文件传前检查,防止文件被重复压缩
–with-http_stub_status_module #取得一些nginx的运行状态
–with-mail #允许POP3/IMAP4/SMTP代理模块
–with-mail_ssl_module #允许POP3/IMAP/SMTP可以使用SSL/TLS
–with-pcre=../pcre-8.11 #注意是未安装的pcre路径
–with-zlib=../zlib-1.2.5 #注意是未安装的zlib路径
–with-debug #允许调试日志
–http-client-body-temp-path #客户端请求临时文件路径
–http-proxy-temp-path #设置http proxy临时文件路径
–http-fastcgi-temp-path #设置http fastcgi临时文件路径
–http-uwsgi-temp-path=/var/tmp/nginx/uwsgi #设置uwsgi 临时文件路径
–http-scgi-temp-path=/var/tmp/nginx/scgi #设置scgi 临时文件路径 # 我用pcre2替代了pcre会遇到如下的问题,最后还是换成pcre
出现了错误:src/core/ngx_regex.h:15:18: fatal error: pcre.h: No such file or directory #include <pcre.h> ^ compilation terminated. make[1]: *** [objs/src/core/nginx.o] Error 1 make[1]: Leaving directory `/home/ben/dev/nginx-1.8.0' make: *** [build] Error 2
# 如果遇到下面的问题最好升级一下gcc
$ sudo rm -rf /var/lib/apt/lists/*
$ apt-get update
configure: error: You need a C++ compiler for C++ support. make[1]: *** [/home/ben/dev/pcre-8.37/Makefile] Error 1 make[1]: Leaving directory `/home/ben/dev/nginx-1.8.0' make: *** [build] Error 2
Dockerfile文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
############################################
# version : birdben/nginx:v1
# desc : 当前版本安装的nginx
############################################
# 设置继承自我们创建的 tools 镜像
FROM birdben/tools:v1
# 下面是一些创建者的基本信息
MAINTAINER birdben (191654006@163.com)
# 设置环境变量,所有操作都是非交互式的
ENV DEBIAN_FRONTEND noninteractive
# 添加 supervisord 的配置文件,并复制配置文件到对应目录下面。(supervisord.conf文件和Dockerfile文件在同一路径)
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# 安装升级gcc
RUN sudo rm -rf /var/lib/apt/lists/*
RUN sudo apt-get update
RUN sudo apt-get -y install \
build-essential
RUN sudo mkdir -p /software/temp
RUN wget http://nginx.org/download/nginx-1.8.0.tar.gz && tar -zxvf nginx-1.8.0.tar.gz -C /software/temp
RUN wget http://zlib.net/zlib-1.2.8.tar.gz && tar -zxvf zlib-1.2.8.tar.gz -C /software/temp
RUN wget http://www.openssl.org/source/openssl-1.0.1q.tar.gz && tar -zxvf openssl-1.0.1q.tar.gz -C /software/temp
RUN wget http://downloads.sourceforge.net/project/pcre/pcre/8.37/pcre-8.37.tar.gz && tar -zxvf pcre-8.37.tar.gz -C /software/temp
RUN cd /software/temp/nginx-1.8.0 && sudo ./configure --sbin-path=/software/nginx-1.8.0/nginx --conf-path=/software/nginx-1.8.0/nginx.conf --pid-path=/software/nginx-1.8.0/nginx.pid --with-http_ssl_module --with-pcre=/software/temp/pcre-8.37 --with-zlib=/software/temp/zlib-1.2.8 --with-openssl=/software/temp/openssl-1.0.1q && sudo make && sudo make install
# 设置nginx是非daemon启动
RUN echo 'daemon off;' >> /software/nginx-1.8.0/nginx.conf
RUN echo 'master_process off;' >> /software/nginx-1.8.0/nginx.conf
RUN echo 'error_log logs/error.log;' >> /software/nginx-1.8.0/nginx.conf
# 设置 NGINX 的环境变量,若读者有其他的环境变量需要设置,也可以在这里添加。
ENV NGINX_HOME /software/nginx-1.8.0
# 容器需要开放Nginx 80端口
EXPOSE 80
# 执行run.sh文件
# CMD ["/run.sh"]
# 执行supervisord来同时执行多个命令,使用 supervisord 的可执行路径启动服务。
CMD ["/usr/bin/supervisord"]
Dockerfile源文件链接:

https://github.com/birdben/birdDocker/blob/master/nginx/Dockerfile

注意
1
2
3
4
5
6
7
8
9
10
11
12
13
# 编译安装Nginx方式构建Docker镜像遇到几个比较坑的问题
1. supervisor无法启动Nginx,必须设置nginx是非daemon启动,这个问题之前安装ES的时候已经遇到过了,因为没有注意还是被这个问题困扰了一段时间。Nginx设置非daemon启动需要在nginx.conf配置文件中设置daemon false即可。
参考文章:
http://comments.gmane.org/gmane.comp.sysutils.supervisor.general/1233
http://nginx.org/en/docs/ngx_core_module.html#daemon
http://serverfault.com/questions/647357/running-and-monitoring-nginx-with-supervisord
http://www.v2ex.com/t/123152
2. 编译安装Nginx时,总是提示lib-dev64相对的版本不匹配,即使执行apt-get -y install build-essential安装gcc也是如此,最终发现是因为之前继承的tools镜像在安装ssh时有改过ubuntu的sourcelist文件,直接继承ubuntu 14.04的镜像就不会有lib-dev64版本不匹配的问题。
参考文章:
http://www.oschina.net/question/220489_160699
http://www.cnblogs.com/linxiong945/p/4180565.html
http://blog.csdn.net/xhz1234/article/details/37044531
Supervisor.conf
1
2
3
4
5
6
7
8
9
10
11
12
# 配置文件包含目录和进程
# 第一段 supervsord 配置软件本身,使用 nodaemon 参数来运行。
# 第二段包含要控制的 2 个服务。每一段包含一个服务的目录和启动这个服务的命令。
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
[program:nginx]
command=/software/nginx-1.8.0/nginx -c /software/nginx-1.8.0/nginx.conf
控制台终端
1
2
3
4
# 构建镜像
docker build -t="birdben/nginx:v1" .
# 执行已经构件好的镜像
docker run -p 9999:22 -p 8888:80 -t -i birdben/nginx:v1
浏览器访问
1
http://10.211.55.4:8888/

参考文章

Docker实战(七)Docker安装MongoDB

大概步骤:
  1. 上传Mongo到宿主机,或者在宿主机中下载
  2. 编写Dockerfile构建镜像
  3. 编写supervisor配置文件
  4. build和run
MongoDB安装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 下载Mongo
$ curl -O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1404-3.0.7.tgz
# 解压Mongo压缩包
$ tar -zxvf mongodb-linux-x86_64-ubuntu1404-3.0.7.tgz
# 重命名一下Mongo的安装目录
$ mv mongodb-linux-x86_64-ubuntu1404-3.0.7/ mongodb-3.0.7
# (不推荐下面的路径直接建立在Docker虚拟机上,推荐使用volume挂载方式)
# 在宿主机上创建一个数据库目录存储Mongo的数据文件
$ sudo mkdir -p /docker/mongo/data
# 在宿主机上创建一个日志目录存储Mongo的Log文件
$ sudo mkdir -p /docker/mongo/log
# 在{MONGO_HOME}下创建一个Mongo启动的配置文件
$ sudo touch mongodb.conf
############# mongodb.conf ################
port=30000
dbpath=/mongo/data
logpath=/mongo/log/mongodb.log
logappend=true
############# mongodb.conf ################
# 启动mongo时,指定config配置文件
$ sudo ./mongod -f ../mongodb.conf
# 参考:
https://docs.mongodb.org/master/tutorial/install-mongodb-on-linux/
http://my.oschina.net/aarongo/blog/349061
Dockerfile文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
############################################
# version : birdben/mongodb:v1
# desc : 当前版本安装的mongodb
############################################
# 设置继承自我们创建的 tools 镜像
FROM birdben/tools:v1
# 下面是一些创建者的基本信息
MAINTAINER birdben (191654006@163.com)
# 设置环境变量,所有操作都是非交互式的
ENV DEBIAN_FRONTEND noninteractive
# 添加 supervisord 的配置文件,并复制配置文件到对应目录下面。(supervisord.conf文件和Dockerfile文件在同一路径)
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# 设置 mongo 的环境变量,若读者有其他的环境变量需要设置,也可以在这里添加。
ENV MONGO_HOME /software/mongodb-3.0.7
ENV LC_ALL C
# 复制 mongodb-3.0.7 文件到镜像中(mongodb-3.0.7 文件夹要和Dockerfile文件在同一路径)
ADD mongodb-3.0.7 /software/mongodb-3.0.7
# VOLUME 选项是将本地的目录挂在到容器中 此处要注意:当你运行-v <hostdir>:<Containerdir> 时要确保目录内容相同否则会出现数据丢失
# 对应关系如下
# mongo:/docker/mongodb
VOLUME ["/mongodb"]
# 容器需要开放Mongo 30000端口
EXPOSE 30000
# 执行supervisord来同时执行多个命令,使用 supervisord 的可执行路径启动服务。
CMD ["/usr/bin/supervisord"]
Dockerfile源文件链接:

https://github.com/birdben/birdDocker/blob/master/mongo/Dockerfile

supervisor配置文件内容
1
2
3
4
5
6
7
8
9
10
11
12
13
# 配置文件包含目录和进程
# 第一段 supervsord 配置软件本身,使用 nodaemon 参数来运行。
# 第二段包含要控制的 2 个服务。每一段包含一个服务的目录和启动这个服务的命令。
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
[program:mongo]
# 注意这里指定的mongodb.conf文件路径,必须是绝对路径
command=/software/mongodb-3.0.7/bin/mongod -f /mongodb/mongodb.conf
控制台终端
1
2
3
4
5
6
7
8
9
10
# 构建镜像
$ docker build -t="birdben/mongodb:v1" .
# 执行已经构件好的镜像
$ docker run -p 9999:22 -p 30000:30000 -t -i -v /docker/mongodb:/mongodb "birdben/mongodb:v1"
# 可以ssh远程登录,然后查看mongo的log是否有变化,然后就大功告成了
$ ssh root@10.211.55.4 -p 9999
$ cd /mongo/log
$ tailf mongodb.log
遇到问题
1
2
3
4
# 如果遇到mongo启动问题Failed global initialization: BadValue Invalid or no user locale set. Please ensure LANG and/or LC_* environment variables are set correctly.
# 需要配置如下的环境变量
export LC_ALL=C

参考文章:

Docker实战(九)Docker安装ELK环境

ELK实际上就是ElasticSearch,Logstash,Kibana的缩写,是日志收集分析的一种解决方案。

  • Elasticsearch一个开源的搜索引擎框架(支持群集架构方式)
  • Logstash集成各种收集日志插件,还是一个比较优秀的正则切割日志工具
  • Kibana一个免费的web应用,支持在web端查看ES的搜索结果

elk是目前比较新也发展比较快的一套数据分析套件,其中Elasticsearch是用来作为存储和查询引擎的,kibana则是位于其之上的一个UI(更偏向于聚合汇总分析),而logstash则是属于ETL工具(数据的提取转换插入)。
在具体的使用过程中,目前觉得logstash算是比较鸡肋的,因为适用的场景有限,而且要扩展必须自己实现。个人建议,如果对es比较熟悉的,完全可以不需要用这个。自己用es加个river插件,那个效果也不错。

ELK简单架构
ELK_Simple

日志收集系统架构整体架构
日志收集系统架构

简单来讲他具体的工作流程就是Logstash agent监控并过滤日志,将过滤后的日志内容发给redis(这里的redis只处理队列不做存储),Logstash index将日志收集在一起交给全文搜索服务ElasticSearch,可以用ElasticSearch进行自定义搜索,通过Kibana来结合 自定义搜索进行页面展示

此外 logstash 的收集方式分为 standalone 和 centralized。
standalone 是所有功能都在一个服务器上面,自发自收,centralized 就是集中收集,一台服务器接收所有shipper(个人理解就是logstash agent)的日志。
其实 logstash本身不分 什么 shipper 和 collector ,只不过就是配置文件不同而已,我们这次按照集中的方式来测试

这里的Logstash分为index和agent两种角色,也可以说是收集方式分为standalone和centralized两种。standalone是所有功能都在一个服务器上面,自发自收,centralized就是集中收集,一台服务器接收所有shipper(个人理解就是logstash agent)的日志。(其实logstash本身不分什么shipper和collector ,只不过就是配置文件不同而已)。Logstash的agent和indexer分开部署,多台agent负责监控、过滤日志,index负责收集日志并将日志交给ElasticSearch做搜索,通过Kibana来结合自定义搜索进行页面展示。Redis实际上是起到了缓冲消峰的作用,否则并发访问量大的时候ES会被拖垮的。使用redis的push和pop做队列,然后有个logstash_indexer来从队列中pop数据分析插入elasticsearch。这样做的好处是可扩展,logstash_agent只需要收集log进入队列即可,比较可能会有瓶颈的log分析使用logstash_indexer来做,而这个logstash_indexer又是可以水平扩展的,我可以在单独的机器上跑多个indexer来进行日志分析存储。

192.168.0.1 logstash index,ElasticSearch,kibana,JDK
192.168.0.2 logstash agent,JDK
192.168.0.3 redis

因为上一篇文章已经写过Docker如何安装ES环境了,这里我们直接继承上一次安装好的Docker镜像,所以重点只介绍Logstash和Kibana的安装,本文只是简单的单机ELK环境,后续会逐步完善ELK+Redis的环境,甚至会把ELK单独拆开三个Docker镜像使用

安装Logstash(本文使用的是logstash的1.5.4版本)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 下载Logstash
$ curl -O https://download.elastic.co/logstash/logstash/logstash-1.5.4.tar.gz
# 解压ES压缩包
$ tar -zxvf logstash-1.5.4.tar.gz
# 在{LOGSTASH_HOME}下新建一个conf目录,在里面新建一个配置文件logstash.conf
$ cd logstash-1.5.4
$ mkdir conf
$ cd conf
# 编辑logstash.conf如下面的配置
$ vi logstash.conf
# 启动logstash
$ cd {LOGSTASH_HOME}/bin/
$ ./logstash -f ../conf/logstash.conf
注意

因为java的默认heap size,回收机制等原因,logstash从1.4.0开始不再使用jar运行方式.

  • 以前方式:
    java -jar logstash-1.3.3-flatjar.jar agent -f logstash.conf
  • 现在方式:
    bin/logstash -f logstash.conf
logstash.conf配置文件
1
2
3
4
5
6
7
8
9
10
11
input {
# 来自控制台 stdin { type => "web" # ES索引的type codec => "json" # 输入格式是json }
# 来自文件 file {
# 文件所在的绝对路径 path => "/software/logstash-1.5.4/test.log"
# ES索引的type type => "system"
# 文件格式是json codec => "json"
# 从文件的什么位置开始采集 start_position => "beginning" } } output {
# 输出到控制台 stdout { codec => rubydebug }
# 输出到ES elasticsearch {
# 不使用logstash内嵌的ES embedded => false codec => "json" protocol => "http" host => "10.211.55.4" port => 9200
# 指定创建的索引名称 index => "birdlogstash" } }
test.log文件内容,放在{LOGSTASH_HOME}目录下
bird hello
bird test
bird bye
1
2
##### 安装Kibana(本文使用的是kibana的4.1.2版本)
# 下载Kibana $ curl -O https://download.elastic.co/kibana/kibana/kibana-4.1.2-linux-x64.tar.gz # 解压ES压缩包 $ tar -zxvf kibana-4.1.2-linux-x64.tar.gz # 重命名一下 $ mv kibana-4.1.2-linux-x64 kibana-4.1.2 # 启动Kibana $ cd {KIBANA_HOME}/bin $ ./kibana # 访问http://192.168.1.120:5601/ 配置一个ElasticSearch索引 # 在logstach里面添加数据
1
2
##### 注意
如果Kibana和ES不在同一台机器上,需要在kibana.yml文件中指定ES集群的地址 # The Elasticsearch instance to use for all your queries. elasticsearch_url: "http://10.211.55.4:9200"
1
2
##### Dockerfile文件
############################################ # version : birdben/elk:v1 # desc : 当前版本安装的elk ############################################ # 设置继承自我们创建的 elasticsearch 镜像 FROM birdben/elasticsearch:v1 # 下面是一些创建者的基本信息 MAINTAINER birdben (191654006@163.com) # 设置环境变量,所有操作都是非交互式的 ENV DEBIAN_FRONTEND noninteractive # 添加 supervisord 的配置文件,并复制配置文件到对应目录下面。(supervisord.conf文件和Dockerfile文件在同一路径) COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf RUN echo "export LC_ALL=C" # 设置 ES 的环境变量,若读者有其他的环境变量需要设置,也可以在这里添加。 ENV LOGSTASH_HOME /software/logstash-1.5.4 ENV KIBANA_HOME /software/kibana-4.1.2 # 复制 logstash-1.5.4, kibana-4.1.2 文件到镜像中(logstash-1.5.4, kibana-4.1.2文件夹要和Dockerfile文件在同一路径) ADD logstash-1.5.4 /software/logstash-1.5.4 ADD kibana-4.1.2 /software/kibana-4.1.2 # 解决环境问题,否则logstash无法从log文件中采集日志。具体环境: Logstash 1.5, Ubuntu 14.04, Oracle JDK7 RUN ln -s /lib/x86_64-linux-gnu/libcrypt.so.1 /usr/lib/x86_64-linux-gnu/libcrypt.so # 挂载/logstash目录 VOLUME ["/logstash"] # 容器需要开放Kibana的5601端口 EXPOSE 5601 # 执行supervisord来同时执行多个命令,使用 supervisord 的可执行路径启动服务。 CMD ["/usr/bin/supervisord"]
1
2
3
4
5
##### Dockerfile源文件链接:
https://github.com/birdben/birdDocker/blob/master/elk/Dockerfile
##### supervisor配置文件内容
# 配置文件包含目录和进程 # 第一段 supervsord 配置软件本身,使用 nodaemon 参数来运行。 # 第二段包含要控制的 2 个服务。每一段包含一个服务的目录和启动这个服务的命令。 [supervisord] nodaemon=true [program:sshd] command=/usr/sbin/sshd -D [program:elasticsearch] command=/bin/bash -c "exec ${ES_HOME}/bin/elasticsearch -DFOREGROUND" [program:logstash] # 指定配置文件时,一定要使用绝对路径,相对路径是不好用的,这个坑已经踩过两次了。。 command=/software/logstash-1.5.4/bin/logstash -f /logstash/logstash.conf [program:kibana] command=/software/kibana-4.1.2/bin/kibana
1
2
##### 注意
# 之前一直在supervisor使用如下配置来启动logstash,但是发现logstash刚启动起来自己就挂了,然后不断的在尝试重启。后来发现是配置文件没有找到,因为使用supervisor来配置服务的命令时,指定配置文件时,一定要使用绝对路径,相对路径是不好用的,这个坑已经踩过两次了。。这里再次鄙视一下自己。。 INFO success: logstash entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) INFO exited: logstash (exit status 1; not expected) INFO spawned: 'logstash' with pid 12 INFO exited: logstash (exit status 1; not expected) INFO spawned: 'logstash' with pid 13 INFO exited: logstash (exit status 1; not expected) INFO gave up: logstash entered FATAL state, too many start retries too quickly # 这里使用supervisorctl status查看supervisor监控的所有服务,就会发现ES没有处于被监控状态 $ supervisorctl status logstash FATAL Exited too quickly (process log may have details) sshd RUNNING pid 6, uptime 0:01:49 elasticsearch RUNNING pid 8, uptime 0:01:49
1
2
3
##### 控制台终端
# 构建镜像 $ docker build -t="birdben/elk:v1" . # 执行已经构件好的镜像 $ docker run -p 9999:22 -p 9200:9200 -p 9300:9300 -p 5601:5601 -t -i -v /docker/logstash:/logstash "birdben/elk:v1"
1
2
##### 测试Logstash
# 这里我们要测试几种方式的logstash输入和输出 logstash启动的参数 -e:代表控制台以字符串的方式输入conf配置 -f:代表指定文件的方式conf配置 ############## logstash从控制台读取 ############## # 只在CMD启动的进程export设置变量,而不是将变量赋值命令写入/etc/profile等脚本里,因此通过ssh方式登录容器获得的shell是没有这个变量的,所以ssh登录要提前设置JAVA_HOME环境变量 $ export JAVA_HOME=/software/jdk7 # 测试运行前端输出 $ {LOGSTASH_HOME}/bin/logstash -e 'input { stdin { } } output { stdout {} }' Logstash startup completed hello 2015-12-20T08:17:06.312Z c7f05b587d11 hello # 也可以使用rubydebug的形式输出到控制台 $ {LOGSTASH_HOME}/bin/logstash -e 'input { stdin { } } output { stdout {codec=>rubydebug} }' Logstash startup completed hello { "message" => "hello", "@version" => "1", "@timestamp" => "2015-12-20T13:35:38.996Z", "host" => "40421a32fbc5" } # 还可以将控制台的输入,输出到ES并且创建对应的索引 $ {LOGSTASH_HOME}/bin/logstash -e 'input { stdin { type => "web" codec => "json" } } output { stdout { codec => rubydebug } elasticsearch { embedded => false codec => "json" protocol => "http" host => "10.211.55.4" port => 9200 } }' Logstash startup completed {"name":"bird"} { "name" => "bird", "@version" => "1", "@timestamp" => "2015-12-20T13:35:38.996Z", "type" => "web", "host" => "40421a32fbc5" } # 执行之后,可以查询ES的索引,会自动创建一个logstash的索引,并且会有一个对应的属性name,它的值是bird $ curl -XPOST 'http://10.211.55.4:9200/_search?pretty' -d '{"query":{"match_all":{}}}' ############## logstash从文件中读取 ############## $ {LOGSTASH_HOME}/bin/logstash -f /logstash/logstash.conf # 从文件中读取日志,可能会遇到下面的问题 NotImplementedError: block device detection unsupported or native support failed to load from org/jruby/RubyFileTest.java:67:in `blockdev?' from (irb):1:in `evaluate' from org/jruby/RubyKernel.java:1107:in `eval' from org/jruby/RubyKernel.java:1507:in `loop' from org/jruby/RubyKernel.java:1270:in `catch' from org/jruby/RubyKernel.java:1270:in `catch' from /home/ubuntu/logstash-1.5.0-rc3/lib/logstash/runner.rb:77:in `run' from org/jruby/RubyProc.java:271:in `call' from /home/ubuntu/logstash-1.5.0-rc3/lib/logstash/runner.rb:131:in `run' from org/jruby/RubyProc.java:271:in `call' from /home/ubuntu/logstash-1.5.0-rc3/vendor/bundle/jruby/1.9/gems/stud-0.0.19/lib/stud/task.rb:12:in `initialize' # 上面的问题原因是环境问题,解决方案是先执行下面的语句,然后在运行logstash ln -s /lib/x86_64-linux-gnu/libcrypt.so.1 /usr/lib/x86_64-linux-gnu/libcrypt.so # 参考文章: https://github.com/elastic/logstash/issues/3127#issuecomment-101068714 # 改好上面的问题之后logstash就会将文件的内容读取并输出到ES,使用下面的语句进行查询,就可以看到之前test.log中的3行记录,被ES创建了3条索引记录 $ curl -XPOST 'http://10.211.55.4:9200/_search?pretty' -d '{"query":{"match_all":{}}}'
1
2
##### 测试Kibana
# 浏览器直接访问 http://10.211.55.4:5601 # 如果ES还没有索引,你需要告诉它你打算探索哪个 Elasticsearch 索引。第一次访问 Kibana 的时候,你会被要求定义一个 index pattern 用来匹配一个或者多个索引名。好了。这就是你需要做的全部工作。以后你还可以随时从 Settings 标签页添加更多的 index pattern。 # 因为我们在Logstash配置了从log文件中读取数据并且输出到ES的索引上,配置文件中已经指定了索引的名称"birdlogstash",这样我们在Kibana只要指定这个索引名称就可以了,同理我们也可以在Logstash中改成按照日期分割的方式,Kibana也可以按照这种方式来配置。 # 指定创建的索引名称 index => "birdlogstash" # 指定创建的索引名称(按照索引类型和日期分割) index => "logstash-%{type}-%{+YYYY.MM.dd}" # 默认情况下,Kibana 会连接运行在 localhost 的 Elasticsearch。要连接其他 Elasticsearch 实例,修改 kibana.yml 里的 Elasticsearch URL,然后重启 Kibana。如何在生产环境下使用 Kibana,阅读生产环境部署章节。 http://kibana.logstash.es/content/kibana/v4/production.html

参考文章:

Docker实战(八)Docker安装ElasticSearch环境

基本步骤和之前几篇文章一样,请参考前面的相关文章

ElasticSearch安装
  • 1.安装ES
  • 2.安装head,bigdesk插件
  • 3.安装ik插件
  • 4.配置ES集群
安装ES(本文使用的是elasticsearch的1.7.2版本)
1
2
3
4
5
6
7
8
# 下载ES
$ curl -O https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch-1.7.2.tar.gz
# 解压ES压缩包
$ tar -zxvf elasticsearch-1.7.2.tar.gz
# 启动ES
$ sudo ./elasticsearch -d
安装head,bigdesk,HQ,kopf插件(可选择安装,建议安装head和bigdesk)
1
2
3
4
5
6
7
8
9
10
11
$ ${ES_HOME}/bin/plugin --install mobz/elasticsearch-head
# 安装完成访问:http://localhost:9200/_plugin/head/
$ ${ES_HOME}/bin/plugin --install lukas-vlcek/bigdesk
# 安装完成访问:http://localhost:9200/_plugin/bigdesk/#nodes
$ ${ES_HOME}/bin/plugin -install royrusso/elasticsearch-HQ
# 安装完成访问:http://localhost:9200/_plugin/HQ/
$ ${ES_HOME}/bin/plugin -install lmenezes/elasticsearch-kopf
# 安装完成访问:http://localhost:9200/_plugin/kopf/#!/cluster
安装ik插件
1
2
3
4
5
6
7
8
9
10
11
# 因为我使用的是老版本的ES,所以ik插件也使用的是对应老版本的
$ git clone https://github.com/medcl/elasticsearch-analysis-ik
$ cd elasticsearch-analysis-ik
$ mvn clean
$ mvn compile
$ mvn package
$ cd target
$ cp elasticsearch-analysis-ik-xxx.jar ${ES_HOME}/plugins/ik/
$ cd elasticsearch-analysis-ik
$ cp config/ik ${ES_HOME}/config/
配置elasticsearch.yml文件,在文件的最后添加下面的配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
index:
analysis:
analyzer:
ik:
alias: [ik_analyzer]
type: org.elasticsearch.index.analysis.IkAnalyzerProvider
ik_max_word:
type: ik
use_smart: false
ik_smart:
type: ik
use_smart: true
index.analysis.analyzer.default.type: ik
index.store.type: niofs
设置ES的内存大小
1
2
3
4
5
6
$ {ES_HOME}/bin
$ vi elasticsearch
# 设置ES的最大内存,最小内存
ES_MIN_MEM=4g
ES_MAX_MEM=4g
注意

如果这里不设置ES的内存大小,后面整合ELK环境的时候,Logstash会无法批量在ES创建索引而报错,具体错误信息如下。所以在ES启动时设置ES的内存大小,建议是实际内存的一半

1
Got error to send bulk of actions: Connection reset {:level=>:error}

这个内存配置不能随便设置,必须根据实际情况进行设置,否则设置之后ES就启动不起来了,报内存溢出的错误,建议尽量不要随意修改此配置

Dockerfile文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
############################################
# version : birdben/elasticsearch:v1
# desc : 当前版本安装的elasticsearch
############################################
# 设置继承自我们创建的 jdk7 镜像
FROM birdben/jdk7:v1
# 下面是一些创建者的基本信息
MAINTAINER birdben (191654006@163.com)
# 设置环境变量,所有操作都是非交互式的
ENV DEBIAN_FRONTEND noninteractive
# 添加 supervisord 的配置文件,并复制配置文件到对应目录下面。(supervisord.conf文件和Dockerfile文件在同一路径)
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
RUN echo "export LC_ALL=C"
# 设置 ES 的环境变量,若读者有其他的环境变量需要设置,也可以在这里添加。
ENV ES_HOME /software/elasticsearch-1.7.2
# 复制 elasticsearch-1.7.2 文件到镜像中(elasticsearch-1.7.2文件夹要和Dockerfile文件在同一路径)
ADD elasticsearch-1.7.2 /software/elasticsearch-1.7.2
# 容器需要开放ES的9200和9300端口
EXPOSE 9200
EXPOSE 9300
# 执行supervisord来同时执行多个命令,使用 supervisord 的可执行路径启动服务。
CMD ["/usr/bin/supervisord"]
Dockerfile源文件链接:

https://github.com/birdben/birdDocker/blob/master/elasticsearch/Dockerfile

supervisor配置文件内容
1
2
3
4
5
6
7
8
9
10
11
12
13
# 配置文件包含目录和进程
# 第一段 supervsord 配置软件本身,使用 nodaemon 参数来运行。
# 第二段包含要控制的 2 个服务。每一段包含一个服务的目录和启动这个服务的命令。
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
# 修改supervisor配置方式如下,修改为不自动重启ES,并且改成非daemon,DFOREGROUND的方式运行,supervisor就可以监控到了
[program:elasticsearch]
command=/bin/bash -c "exec ${ES_HOME}/bin/elasticsearch -DFOREGROUND"
注意supervisor配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 之前一直在supervisor使用如下配置来启动ES,但是仔细观察Docker的控制台输出会发现如下的错误
[program:elasticsearch]
command=/{ES_HOME}/bin/elasticsearch -d
INFO success: elasticsearch entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
INFO exited: elasticsearch (exit status 1; not expected)
INFO spawned: 'elasticsearch' with pid 12
INFO exited: elasticsearch (exit status 1; not expected)
INFO spawned: 'elasticsearch' with pid 13
INFO exited: elasticsearch (exit status 1; not expected)
INFO gave up: elasticsearch entered FATAL state, too many start retries too quickly
# 这里使用supervisorctl status查看supervisor监控的所有服务,就会发现ES没有处于被监控状态
$ supervisorctl status
elasticsearch FATAL Exited too quickly (process log may have details)
sshd RUNNING pid 6, uptime 0:01:49
tomcat RUNNING pid 8, uptime 0:01:49
# 所以这里修改supervisor配置方式如下,修改为不自动重启ES,并且改成非daemon,DFOREGROUND的方式运行,supervisor就可以监控到了
[program:elasticsearch] startsecs = 0 autorestart = false command=/bin/bash -c "exec ${ES_HOME}/bin/elasticsearch -DFOREGROUND"
# 这里说明一下supervisor启动多个服务,要求所有启动的服务都是非daemon的方式启动,否则就会遇到如上的问题,autorestart设置为false只是为了让supervisor启动报错的时候不会重复启动,只要改成非daemon的方式启动ES,可以设置autorestart为true

参考文章

控制台终端
1
2
3
4
# 构建镜像
$ docker build -t="birdben/elasticsearch:v1" .
# 执行已经构件好的镜像
$ docker run -p 9999:22 -p 9200:9200 -p 9300:9300 -t -i 'birdben/elasticsearch:v1'
访问ElasticSearch的插件测试
1
2
http://10.211.55.4:9200/_plugin/head/
http://10.211.55.4:9200/_plugin/bigdesk/#nodes
User索引的mapping
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{
"user": {
"dynamic" : "strict",
"properties": {
"id": {
"type": "string",
"index": "not_analyzed"
},
"name": {
"type": "string",
"index_analyzer": "ik",
"search_analyzer": "ik_smart"
},
"age": {
"type": "integer"
},
"job": {
"type": "string",
"index_analyzer": "ik",
"search_analyzer": "ik_smart"
},
"createTime": {
"type": "long"
}
}
}
}
新建索引测试ik分词
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 尝试创建user索引
$ curl -XPOST 'http://10.211.55.4:9200/user?pretty' -d '@user.json'
# 如果遇到下面的错误,原因是${ES_HOME}/lib/下需要引入httpclient-4.5.jar, httpcore-4.4.1.jar
{
"error" : "IndexCreationException[[user] failed to create index]; nested: NoClassDefFoundError[org/apache/http/client/ClientProtocolException]; nested: ClassNotFoundException[org.apache.http.client.ClientProtocolException]; ",
"status" : 500
}
# 创建索引成功后,查看索引信息
$ curl -XGET 'http://10.211.55.4:9200/_cat/indices?pretty'
green open user 5 1 0 0 970b 575b
# 测试ik分词效果
$ curl -XGET 'http://10.211.55.4:9200/goods/_analyze?analyzer=ik&pretty=true' -d '{"text":"世界如此之大"}'
# 测试ik_smart分词效果
$ curl -XGET 'http://10.211.55.4:9200/user/_analyze?analyzer=ik_smart&pretty=true' -d '{"text":"世界如此之大"}'

参考文章: