0%

Elasticsearch学习笔记(一)-搭建环境

Elasticsearch目前的发展可谓如日中天,DBEngine上在搜索引擎领域位列第一,作为后来者热度远高于排第二、三的Splunk和Solr。Elasticsearch的创造者叫Shay Banon,最初是因为Lucence的接口使用困难,开发了一个库Compass,让Lucence更好用,2010年Shay Banon对Compass进行重写,把它变成一个高性能的、分布式的服务端软件,取名叫Elasticsearch,并在github开源。这背后还有一个温情的故事,据说起因是为了给新婚老婆写一个菜谱搜索应用,但是最后菜谱应用没有写出来,倒是造就了一个伟大的软件。

Elasticsearch发展非常快,2010年2月发布第一个版本,2012年成立Elastic公司,2014年开始商业化,2018年纽交所上市,在全球股市低迷的背景下上市当天仍大涨94%,创造了开源软件的传奇。而Elastic公司非常的厚道,坚持开源路线,从6.3版本开始将其收费部分x-pack也"开源",x-pack的基础功能终身免费,不需要注册,其中就包括安全方面必须的HTTPS,权限控制等。

今天开始我想通过一系列文章来探索和学习一下ES,第一篇介绍一下ES的基本概念,搭建单节点的ES,通过图形客户端去探索ES的数据结构和操作,通过监控了解ES运行状态,建立对ES总体上的一个认识。

ES简介

image-20200414090725387

ES是基于Apache Lucence的一个开源的,高性能的分布式搜索引擎,Java语言开发,对外提供RESTful接口,使用方便。

ES从6.3版本开始内置支持SQL,当然只支持查询操作,从而降低了学习其特有query DSL的成本,更是让上层基于SQL的应用可以无缝和ES对接。虽然ES越来越像一个数据库,但是它们之间还是有区别的,最显著的一个区别是,ES添加数据不是立刻刷新索引的,有一个刷新间隔,默认1s,所以不会立刻查询到,这就是所谓的近实时,ES强在检索和分析。所以ES和关系数据库的区别像是OLAP和OLTP的区别,适用于不同场景。

ES主要的应用场景,一个是作为应用的前端检索缓存,提高海量数据的检索效率和做一些聚合检索,先从ES检索,然后再从后端存储检索。第二个是日志和监控,以ES为中心,Elastic公司发展起一个生态圈,之前叫ELK,也就是Elasticsearch、Logstash和Kibana,后来加入Beats,名字改成了Elastic Stack。以Kibana为入口,发展到上层的各种分析和可视化应用,包括热门的机器学习。

先理解ES的一些基本概念,可以和关系数据库做一个类比:

  • index:类似关系数据库的表,但是index不需要预先定义schema。
  • document:类似关系数据库的记录,json格式。
  • mapping:也就是类似关系数据的schema了,可以显式定义,也可以添加document时ES自动识别创建。可以指定mapping为严格模式,这样添加数据库就必须严格符合mapping中定义的字段。
  • type:从7.0开始删除了,其实就是mapping的名字,一个index下只有一个type,有点鸡肋。虽然删除了,但是其实内部默认还是有一个type,名字固定是_doc。
  • index template:创建index时自动对index做一些设置,例如index的主分片个数,复制分片个数,mapping字段的类型等等。
  • ilm:也就是index lifecycle management,可以对数据分为Hot,Warm,Cold,Delete四个阶段,可以相应的定义不同的策略。

ES安装

最简单的方式就是用docker来运行。

官方参考文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html

我使用的最新的7.6.2版本,单节点运行时需要指定discovery.type=single-node,以前老的版本是不需要的。

1
docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.6.2

为了后续配置方面可以把配置文件放到host机器上,然后mount到容器。

1
docker run -d --name es -p 9200:9200 -p 9300:9300  -v $(pwd)/elasticsearch.docker.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /etc/localtime:/etc/localtime elasticsearch:7.6.2

这里加入-v /etc/localtime:/etc/localtime是为了将容器的时间和host保持一致,后面再讲为什么。

配置文件elasticsearch.docker.yml如下。

1
2
3
cluster.name: "es_cluster"
network.host: 0.0.0.0
discovery.type: single-node

从上面命令看到ES暴露2个端口,9200用于提供RESTful接口,9300端口提供TCP的内部协议通信,9300对外的访问在7.0标识为Deprecated,只有集群内部之间仍通过9300通信。

通过curl就可以很方便的操作ES。

1
curl http://127.0.0.1:9200

返回如下内容表示ES启动正常。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"name" : "903d9b3ecb97",
"cluster_name" : "es_cluster",
"cluster_uuid" : "zV0tEFQ4TgqtyzsabtzMMg",
"version" : {
"number" : "7.6.2",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
"build_date" : "2020-03-26T06:34:37.794943Z",
"build_snapshot" : false,
"lucene_version" : "8.4.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}

图形客户端

推荐一个图形客户端dejavu,使用reactjs开发,相比常用的elasticsearch-head插件更加现代化一些,功能也丰富一些,对于探索ES非常有帮助。

为了解决跨站访问问题,需要修改ES的配置如下,其中http.cors.allow-origin也可以指定为具体的地址,也就是dejavu的地址,例如http://localhost:1358。

1
2
3
4
5
6
7
cluster.name: "es_cluster"
network.host: 0.0.0.0
discovery.type: single-node
http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-headers: X-Requested-With,X-Auth-Token,Content-Type,Content-Length,Authorization
http.cors.allow-credentials: true

然后重启一下ES。

dejavu也支持docker运行。

1
docker run -d --name=es-ui -p 1358:1358 -d appbaseio/dejavu

访问http://localhost:1358即可使用。

image-20200414143846241

输入ES地址和index名(*表示所有)就可以开始读取和操作document和mapping。目前不支持index tempalte,ILM策略等。

需要注意如果ES是空的是连接不上的,必须至少有一个index。

监控

ES最常用的场景是用于监控和分析,对ES自身的监控自然也不在话下。ES本生提供了丰富的监控指标,结合Kibana可以将他们可视化。通过监控可以让我们更了解ES内部的细节。

Kibana安装

官方文档:https://www.elastic.co/guide/en/kibana/7.6/docker.html

同样使用docker运行:

1
docker run -d --link es:elasticsearch -p 5601:5601 -v $(pwd)/kibana.docker.yml:/usr/share/kibana/config/kibana.yml -v /etc/localtime:/etc/localtime --name kibana kibana:7.6.2

–link可以在kibana容器中通过http://elasticsearch:9200访问ES。

配置文件kibana.docker.yml如下。

1
2
3
4
server.name: kibana
server.host: "0"
elasticsearch.hosts: [ "http://elasticsearch:9200" ]
xpack.monitoring.ui.container.elasticsearch.enabled: true

kibana中对ES的监控是在Stack Monitoring功能中,其中也包含对Kibana,Logstash及Beats的监控。

image-20200414145927599

数据采集有两种方式,通过Metricbeat采集或内部采集,官方推荐前者:

image-20200414150035168

时区问题

先说遇到的一个问题,从Kibana查询最近一个小时的数据会发现查询不到,但是采集是正常的,也可以看到监控的index已经有数据了。

问题原因是访问kibana的机器是用的本地时间,而ES、Kibana运行的机器是UTC时间。需要把ES运行的机器改成本地时间。ES是运行在容器中的,问题就变成了怎么修改容器的时区。答案就是先改Host的,然后让容器和Host保持一致。我是用的centos,以下是centos的修改方法。

1
2
3
sudo timedatectl set-timezone Asia/Shanghai
sudo hwclock --localtime -w
sudo timedatectl set-ntp yes

ES的容器基础镜像也是centos,所以运行容器的时候加上-v /etc/localtime:/etc/localtime即可。

通过内部采集

官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.6/monitoring-production.html

先来看第一种方式,非常简单,通过kibana图形界面就可以操作。

image-20200414161133787

点击Turn on monitoring就可以了,Kibana会帮我们将ES的xpack.monitoring.collection.enabled设为true,你也可以通过Kibana的Dev Tools中的Console自己修改,是一样的效果:

1
2
3
4
5
6
PUT _cluster/settings
{
"persistent": {
"xpack.monitoring.collection.enabled": true
}
}

另外有几个参数也很重要,它们默认是true的,如果它们任意一个为false,那么也无法监控。

  • xpack.monitoring.enabled:决定是否启用监控

  • xpack.monitoring.elasticsearch.collection.enabled:决定是否采集elasticsearch

内部采集是Kibana默认通过local exporter保存在被监控ES集群中,index名为.monitoring-*,例如对kibana的采集数据的index形如.monitorning-kibana-7-2020.04.13,每天一个。

通过Metricbeat采集

官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.6/configuring-metricbeat.html

这是官方推荐的方式,两种方式二选一。

首先同样需要ES的xpack.monitoring.collection.enabled设置为true,为了禁用内部采集将xpack.monitoring.elasticsearch.collection.enabled设置为false。

然后安装Metricbeat,官方文档:https://www.elastic.co/guide/en/beats/metricbeat/7.6/running-on-docker.html

同样用Docker运行,分两步,第一步是setup过程,主要是初始化一些数据。

1
2
3
4
docker run --rm --link kibana:kibana --link es:elasticsearch \
docker.elastic.co/beats/metricbeat:7.6.2 \
setup -E setup.kibana.host=kibana:5601 \
-E output.elasticsearch.hosts=["elasticsearch:9200"]

第二步启动Metricbeat。

1
2
3
4
5
6
7
8
9
docker run -d --link es:elasticsearch \
--name=metricbeat \
--user=root \
--volume="$(pwd)/metricbeat.docker.yml:/usr/share/metricbeat/metricbeat.yml:ro" \
--volume="/var/run/docker.sock:/var/run/docker.sock:ro" \
--volume="/sys/fs/cgroup:/hostfs/sys/fs/cgroup:ro" \
--volume="/proc:/hostfs/proc:ro" \
--volume="/:/hostfs:ro" \
docker.elastic.co/beats/metricbeat:7.6.2 metricbeat

这里可能会遇到一个问题。

1
Exiting: error loading config file: config file ("metricbeat.yml") must be owned by the user identifier (uid=0) or root

或者:

1
Exiting: error loading config file: config file ("metricbeat.yml") can only be writable by the owner but the permissions are "-rw-rw-r--" (to fix the permissions use: 'chmod go-w /usr/share/metricbeat/metricbeat.yml')

原因参考:https://www.elastic.co/guide/en/beats/libbeat/5.3/config-file-permissions.html#config-file-permissions

因为在host中我是用的non-root用户uid1000,到容器里面的uid1000是metricbeat用户,但是beats要求配置文件必须是root拥有并且权限为0644。解决办法是把metricbeat.docker.yml的owner改成root。

1
2
sudo chown root metricbeat.docker.yml
sudo chmod 0644 metricbeat.docker.yml

配置文件metricbeat.docker.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
metricbeat.config:
modules:
path: ${path.config}/modules.d/*.yml
# Reload module configs as they change:
reload.enabled: false

metricbeat.autodiscover:
providers:
- type: docker
hints.enabled: true

metricbeat.modules:
- module: elasticsearch
metricsets:
- ccr
- enrich
- cluster_stats
- index
- index_recovery
- index_summary
- ml_job
- node_stats
- shard
period: 10s
hosts: ["http://elasticsearch:9200"]
#username: "user"
#password: "secret"
xpack.enabled: true

processors:
- add_cloud_metadata: ~

output.elasticsearch:
hosts: '${ELASTICSEARCH_HOSTS:elasticsearch:9200}'
username: '${ELASTICSEARCH_USERNAME:}'
password: '${ELASTICSEARCH_PASSWORD:}'

用dejavu可以查看到metricbeat写入的index形如.monitoring-es-7-mb-2020.04.13,也是每天一个。

img

回到Kibana的Stack Monitoring可以查看到ES和Kibana的监控了,其中ES是通过Metricbeat采集的数据,而Kibana是通过第一种方式内部采集的。

image-20200414171354181

-------------本文结束感谢您的阅读-------------