集群的一些概念
集群
一個(gè)集群cluster由一個(gè)或者多個(gè)節(jié)點(diǎn)組成,具有相同的cluster.name,協(xié)同工作,分項(xiàng)數(shù)據(jù)和負(fù)載。當(dāng)有新的節(jié)點(diǎn)加入或者刪除了一個(gè)節(jié)點(diǎn)時(shí),集群回感知到并能夠平衡數(shù)據(jù)。ElasticSearch中可以監(jiān)控很多信息,有一個(gè)最重要的就是集群健康。集群健康有三個(gè)狀態(tài):green(所有主要分片和復(fù)制分片都可用),yellow(所有主要分片可用,但不是所有復(fù)制分片都可用),red(不是所有的主要分片都可用)。
節(jié)點(diǎn)
一個(gè)節(jié)點(diǎn)node就是一個(gè)ElasticSearch的實(shí)例。 集群中的一個(gè)節(jié)點(diǎn)會(huì)被選舉為主節(jié)點(diǎn)master,它將臨時(shí)管理集群級(jí)別的一些變更,譬如新建或者刪除索引、增加或者移除節(jié)點(diǎn)等等。主節(jié)點(diǎn)不參與文檔級(jí)別的變更或者搜索,所以不會(huì)成為集群的瓶頸。任何節(jié)點(diǎn)都可以成為主節(jié)點(diǎn)。 用戶能夠與集群中的任何節(jié)點(diǎn)通信,包括主節(jié)點(diǎn)。每一個(gè)節(jié)點(diǎn)都知道文檔存在于哪個(gè)節(jié)點(diǎn)上,可以轉(zhuǎn)發(fā)請(qǐng)求到相應(yīng)的節(jié)點(diǎn)上。
分片
一個(gè)分片shard是一個(gè)最小級(jí)別的工作單元,es把一個(gè)完整的索引分成多個(gè)分片。僅保存了索引中所有數(shù)據(jù)的一部分。 分片就是一個(gè)Lucene實(shí)例,并且它本身就是一個(gè)完整的搜索引擎。 文檔存儲(chǔ)在分片中,并且在分片中被索引,但是程序不會(huì)直接與分片通信,而是與索引通信。
Replicas分片:代表索引副本。es可以設(shè)置多個(gè)索引的副本,副本的作用是提高了系統(tǒng)的容錯(cuò)性。當(dāng)某個(gè)節(jié)點(diǎn)的分片損壞或者丟失的時(shí)候可以從副本中恢復(fù)。還可以提高查詢搜索效率,es會(huì)自動(dòng)對(duì)搜索請(qǐng)求進(jìn)行負(fù)載均衡。
Elasticsearch配置參數(shù)說(shuō)明
| 參數(shù) | 說(shuō)明 |
|---|---|
| cluster.name: ES | ES集群名稱,同一個(gè)集群內(nèi)的所有節(jié)點(diǎn)集群名稱必須保持一致 |
| node.name: slave2 | ES集群內(nèi)的節(jié)點(diǎn)名稱,同一個(gè)集群內(nèi)的節(jié)點(diǎn)名稱要具備唯一性 |
| node.master: true | 允許節(jié)點(diǎn)是否可以成為一個(gè)master節(jié)點(diǎn),ES是默認(rèn)集群中的第一臺(tái)機(jī)器成為master,如果這臺(tái)機(jī)器停止就會(huì)重新選舉 |
| node.data: false | 允許該節(jié)點(diǎn)存儲(chǔ)索引數(shù)據(jù)(默認(rèn)開啟) |
| path.data: | ES是搜索引擎,會(huì)創(chuàng)建文檔,建立索引,此路徑是索引的存放目錄.可以指定多個(gè)存儲(chǔ)位置 |
| path.logs: | elasticsearch專門的日志存儲(chǔ)位置 |
| bootstrap.memory_lock: true | 在ES運(yùn)行起來(lái)后鎖定ES所能使用的堆內(nèi)存大小,鎖定內(nèi)存大小一般為可用內(nèi)存的一半左右;鎖定內(nèi)存后就不會(huì)使用交換分區(qū)。如果不打開此項(xiàng),當(dāng)系統(tǒng)物理內(nèi)存空間不足,ES將使用交換分區(qū),ES如果使用交換分區(qū),那么ES的性能將會(huì)變得很差 |
| network.host: 0.0.0.0 | es的HTTP端口和集群通信端口就會(huì)監(jiān)聽在此地址上 |
| network.tcp.no_delay: true | 是否啟用tcp無(wú)延遲,true為啟用tcp不延遲,默認(rèn)為false啟用tcp延遲 |
| truenetwork.tcp.keep_alive: true | 是否啟用TCP保持活動(dòng)狀態(tài),默認(rèn)為true |
| network.tcp.reuse_address: true | 是否應(yīng)該重復(fù)使用地址。默認(rèn)true,在Windows機(jī)器上默認(rèn)為false |
| network.tcp.send_buffer_size: 128mb | tcp發(fā)送緩沖區(qū)大小,默認(rèn)不設(shè)置 |
| _buffer_size: 128mb | tcp接收緩沖區(qū)大小,默認(rèn)不設(shè)置 |
| transport.tcp.port: 9301 | 設(shè)置集群節(jié)點(diǎn)通信的TCP端口,默認(rèn)就是9300 |
| transport.tcp.compress: true | 設(shè)置是否壓縮TCP傳輸時(shí)的數(shù)據(jù),默認(rèn)為false |
| http.max_content_length: 200mb | 設(shè)置http請(qǐng)求內(nèi)容的最大容量,默認(rèn)是100mb |
| http.cors.enabled: true | 是否開啟跨域訪問(wèn) |
| http.cors.allow-origin: "*" | 開啟跨域訪問(wèn)后的地址限制,*表示無(wú)限制 |
| http.port: 9201 | 定義ES對(duì)外調(diào)用的http端口,默認(rèn)是9200 |
| discovery.zen.ping.unicast.hosts: ["127.0.0.1:9301","127.0.0.1:9302","127.0.0.1:9303"] | 在Elasticsearch7.0版本已被移除,配置錯(cuò)誤。寫入候選主節(jié)點(diǎn)的設(shè)備地址,來(lái)開啟服務(wù)時(shí)就可以被選為主節(jié)點(diǎn)。默認(rèn)主機(jī)列表只有127.0.0.1和IPV6的本機(jī)回環(huán)地址。上面是書寫格式,discover意思為發(fā)現(xiàn),zen是判定集群成員的協(xié)議,unicast是單播的意思,ES5.0版本之后只支持單播的方式來(lái)進(jìn)行集群間的通信,hosts為主機(jī) |
| discovery.zen.minimum_master_nodes: 2 | 在Elasticsearch7.0版本已被移除,配置無(wú)效,為了避免腦裂,集群的最少節(jié)點(diǎn)數(shù)量為,集群的總節(jié)點(diǎn)數(shù)量除以2加一 |
| discovery.zen.fd.ping_timeout: 120s | 在Elasticsearch7.0版本已被移除,配置無(wú)效。探測(cè)超時(shí)時(shí)間,默認(rèn)是3秒,我們這里填120秒是為了防止網(wǎng)絡(luò)不好的時(shí)候ES集群發(fā)生腦裂現(xiàn)象 |
| discovery.zen.fd.ping_retries: 6 | 在Elasticsearch7.0版本已被移除,配置無(wú)效。探測(cè)次數(shù),如果每次探測(cè)90秒,連續(xù)探測(cè)超過(guò)六次,則認(rèn)為節(jié)點(diǎn)該節(jié)點(diǎn)已脫離集群,默認(rèn)為3次 |
| discovery.zen.fd.ping_interval: 15s | 在Elasticsearch7.0版本已被移除,配置無(wú)效。節(jié)點(diǎn)每隔15秒向master發(fā)送一次心跳,證明自己和master還存活,默認(rèn)為1秒太頻繁 |
| discovery.seed_hosts: ["127.0.0.1:9301","127.0.0.1:9302 | Elasticsearch7新增參數(shù),寫入候選主節(jié)點(diǎn)的設(shè)備地址,來(lái)開啟服務(wù)時(shí)就可以被選為主節(jié)點(diǎn),由discovery.zen.ping.unicast.hosts:參數(shù)改變而來(lái) |
| cluster.initial_master_nodes: ["127.0.0.1:9301","127.0.0.1:9302"] | Elasticsearch7新增參數(shù),寫入候選主節(jié)點(diǎn)的設(shè)備地址,來(lái)開啟服務(wù)時(shí)就可以被選為主節(jié)點(diǎn) |
| cluster.fault_detection.leader_check.interval: 15s | Elasticsearch7新增參數(shù),設(shè)置每個(gè)節(jié)點(diǎn)在選中的主節(jié)點(diǎn)的檢查之間等待的時(shí)間。默認(rèn)為1秒 |
| discovery.cluster_formation_warning_timeout: 30s | Elasticsearch7新增參數(shù),啟動(dòng)后30秒內(nèi),如果集群未形成,那么將會(huì)記錄一條警告信息,警告信息未master not fount開始,默認(rèn)為10秒 |
| cluster.join.timeout: 30s | Elasticsearch7新增參數(shù),節(jié)點(diǎn)發(fā)送請(qǐng)求加入集群后,在認(rèn)為請(qǐng)求失敗后,再次發(fā)送請(qǐng)求的等待時(shí)間,默認(rèn)為60秒 |
| cluster.publish.timeout: 90s | Elasticsearch7新增參數(shù),設(shè)置主節(jié)點(diǎn)等待每個(gè)集群狀態(tài)完全更新后發(fā)布到所有節(jié)點(diǎn)的時(shí)間,默認(rèn)為30秒 |
| cluster.routing.allocation.cluster_concurrent_rebalance: 32 | 集群內(nèi)同時(shí)啟動(dòng)的數(shù)據(jù)任務(wù)個(gè)數(shù),默認(rèn)是2個(gè) |
| cluster.routing.allocation.node_concurrent_recoveries: 32 | 添加或刪除節(jié)點(diǎn)及負(fù)載均衡時(shí)并發(fā)恢復(fù)的線程個(gè)數(shù),默認(rèn)4個(gè) |
| cluster.routing.allocation.node_initial_primaries_recoveries: 32 | 初始化數(shù)據(jù)恢復(fù)時(shí),并發(fā)恢復(fù)線程的個(gè)數(shù),默認(rèn)4個(gè) |
分析主docker-compose文件
詳細(xì)docker-compose文件請(qǐng)見文章末尾附件
elasticsearch主節(jié)點(diǎn)

discovery.zen.minimum_master_nodes=2設(shè)置最新主節(jié)點(diǎn)數(shù),有助于防止腦裂node.name=elasticsearch指定節(jié)點(diǎn)名字cluster.name=es-docker-cluster指定集群名字discovery.seed_hosts=es02,es03寫入除自己以外的候選主節(jié)點(diǎn)的設(shè)備地址,來(lái)開啟服務(wù)時(shí)就可以被選為主節(jié)點(diǎn)cluster.initial_master_nodes=elasticsearch,es02,es03寫入全部的候選主節(jié)點(diǎn)的設(shè)備地址,來(lái)開啟服務(wù)時(shí)就可以被選為主節(jié)點(diǎn)bootstrap.memory_lock=true在ES運(yùn)行起來(lái)后鎖定ES所能使用的堆內(nèi)存大小,鎖定內(nèi)存大小一般為可用內(nèi)存的一半左右;鎖定內(nèi)存后就不會(huì)使用交換分區(qū)。如果不打開此項(xiàng),當(dāng)系統(tǒng)物理內(nèi)存空間不足,ES將使用交換分區(qū),ES如果使用交換分區(qū),那么ES的性能將會(huì)變得很差
從節(jié)點(diǎn)es02:

從節(jié)點(diǎn)es03:

重啟docker-compose
建議down掉之前的docker-compose,再up開啟,防止restart容器前,需要修改 elasticsearch容器內(nèi)的elasticsearch.yml文件

docker-compose up后訪問(wèn)http://localhost:9200/使用谷歌的Elasticsearch Head插件,可觀察到主節(jié)點(diǎn)和從節(jié)點(diǎn)信息

- 粗框是
主節(jié)點(diǎn),細(xì)框是從節(jié)點(diǎn)
image.png
附件:
主docker-compose.yml文件
version: "3.2"
services:
elasticsearch: #主節(jié)點(diǎn)master
image: docker.elastic.co/elasticsearch/elasticsearch:7.4.2
container_name: elasticsearch
networks:
- "elk-net"
ports:
- "9200:9200"
environment:
- discovery.zen.minimum_master_nodes=2 #設(shè)置最新主節(jié)點(diǎn)數(shù),有助于防止 腦裂
- node.name=elasticsearch #指定節(jié)點(diǎn)名字
- cluster.name=es-docker-cluster #指定集群名字
- discovery.seed_hosts=es02,es03 #寫入除自己以外的候選主節(jié)點(diǎn)的設(shè)備地址,來(lái)開啟服務(wù)時(shí)就可以被選為主節(jié)點(diǎn)
- cluster.initial_master_nodes=elasticsearch,es02,es03 #寫入全部的候選主節(jié)點(diǎn)的設(shè)備地址,來(lái)開啟服務(wù)時(shí)就可以被選為主節(jié)點(diǎn)
- bootstrap.memory_lock=true #在ES運(yùn)行起來(lái)后鎖定ES所能使用的堆內(nèi)存大小,鎖定內(nèi)存大小一般為可用內(nèi)存的一半左右;鎖定內(nèi)存后就不會(huì)使用交換分區(qū)。如果不打開此項(xiàng),當(dāng)系統(tǒng)物理內(nèi)存空間不足,ES將使用交換分區(qū),ES如果使用交換分區(qū),那么ES的性能將會(huì)變得很差
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
#- cluster.initial_master_nodes=single-node
# - discovery.type=single-node
es02: #從節(jié)點(diǎn)
image: docker.elastic.co/elasticsearch/elasticsearch:7.4.2
container_name: es02
networks:
- "elk-net"
# ports: #不用設(shè)定端口,自動(dòng)生成即可
# - "9200:9200"
environment:
- discovery.zen.minimum_master_nodes=2
- node.name=es02
- cluster.name=es-docker-cluster
- discovery.seed_hosts=elasticsearch,es03
- cluster.initial_master_nodes=elasticsearch,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms1024m -Xmx1024m"
ulimits:
memlock:
soft: -1
hard: -1
es03: #從節(jié)點(diǎn)
image: docker.elastic.co/elasticsearch/elasticsearch:7.4.2
container_name: es03
networks:
- "elk-net"
# ports:
# - "9200:9200"
environment:
- discovery.zen.minimum_master_nodes=2
- node.name=es03
- cluster.name=es-docker-cluster
- discovery.seed_hosts=elasticsearch,es02
- cluster.initial_master_nodes=elasticsearch,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
filebeat:
image: docker.elastic.co/beats/filebeat:7.4.2
volumes:
- type: bind
source: "/home/ELK/filebeat/2018.log"
target: "/2018.log"
- type: bind
source: "/home/ELK/filebeat/filebeat.yml"
target: "/usr/share/filebeat/filebeat.yml"
networks:
- "elk-net"
depends_on:
- "logstash"
logstash:
image: docker.elastic.co/logstash/logstash:7.4.2
container_name: logstash
volumes:
- type: bind
source: "/home/ELK/filebeat/2018.log"
target: "/2018.log"
- type: bind
source: "/home/ELK/logstash/logstash_stdout.conf"
target: "/usr/share/logstash/pipeline/logstash.conf"
networks:
- "elk-net"
kibanna:
image: docker.elastic.co/kibana/kibana:7.4.2
networks:
- "elk-net"
ports:
- "5601:5601"
depends_on:
- "elasticsearch"
networks:
elk-net:
-
logstash_stdout.conf文件
input {
beats {
port => 5044
host => "0.0.0.0"
}
}
#output {
# stdout { codec => rubydebug }
#}
#filter {
# grok {
# match => { "message" => "%{COMBINEDAPACHELOG}"}
# }
# geoip {
# source => "clientip"
# }
#}
filter {
if ([fileset][module] == "nginx") {
if ([fileset][name] == "access") {
grok {
match => { "message" => ["%{IPORHOST:[nginx][access][remote_ip]} - %{DATA:[nginx][access][user_name]} \[%{HTTPDATE:[nginx][access][time]}\] \"%{WORD:[nginx][access][method]} %{DATA:[nginx][access][url]} HTTP/%{NUMBER:[nginx][access][http_version]}\" %{NUMBER:[nginx][access][response_code]} %{NUMBER:[nginx][access][body_sent][bytes]} \"%{DATA:[nginx][access][referrer]}\" \"%{DATA:[nginx][access][agent]}\""] }
remove_field => "message"
}
mutate {
add_field => { "read_timestamp" => "%{@timestamp}" }
}
date {
match => [ "[nginx][access][time]", "dd/MMM/YYYY:H:m:s Z" ]
remove_field => "[nginx][access][time]"
}
useragent {
source => "[nginx][access][agent]"
target => "[nginx][access][user_agent]"
remove_field => "[nginx][access][agent]"
}
geoip {
source => "[nginx][access][remote_ip]"
target => "[nginx][access][geoip]"
}
}
else if [fileset][name] == "error" {
grok {
match => { "message" => ["%{DATA:[nginx][error][time]} \[%{DATA:[nginx][error][level]}\] %{NUMBER:[nginx][error][pid]}#%{NUMBER:[nginx][error][tid]}: (\*%{NUMBER:[nginx][error][connection_id]} )?%{GREEDYDATA:[nginx][error][message]}"] }
remove_field => "message"
}
mutate {
rename => { "@timestamp" => "read_timestamp" }
}
date {
match => [ "[nginx][error][time]", "YYYY/MM/dd H:m:s" ]
remove_field => "[nginx][error][time]"
}
}
}
}
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
manage_template => false
index => "%{[@metadata][beat]}-%{[@metadata][version]}-%{+YYYY.MM.dd}"
}
# stdout { codec => rubydebug } # 假如有問(wèn)題,可以打開此行進(jìn)行調(diào)試
}

