① Elasticsearch 搭建
- Elasticsearch是一个实时的分布式搜索和分析引擎。下面简称es,它可以帮助你用前所未有的速度去处理大规模数据。
它可以用于全文搜索,结构化搜索以及分析,当然你也可以将这三者进行组合。
附带Elasticsearch: 权威指南(中文)一. 拉取es镜像
本次使用版本5.6,在服务器终端,执行:docker pull elasticsearch:5.6
二. 创建各个节点的配置文件和设置JVM线程数限制数量
1. 创建配置文件
es一般是集群使用,本次会在一台测试服务器上搭建三个es节点,每个节点需要一个配置文件在/disk1/elasticsearch/config/ 路径下创建3个文件夹es-node1、es-node2、es-node3,每个文件夹上分别创建每个节点对应的配置文件:es-node1.yml、es-node2.yml、 es-node3.yml
es-node1.yml
#集群名称
cluster.name: elasticsearch-cluster
#本node节点的名称
node.name: es-node1
#设置可以访问的ip,可以是ipv4或ipv6的,默认为0.0.0.0,这里全部设置通过
network.bind_host: 0.0.0.0
#设置其它结点和该结点交互的ip地址,如果不设置它会自动判断,值必须是个真实的ip地址
network.publish_host: 127.0.0.1
#设置对外服务的http端口,默认为9200
http.port: 8201
#设置节点之间交互的tcp端口,默认是9300
transport.tcp.port: 8301
#是否允许跨域REST请求
http.cors.enabled: true
#允许 REST 请求来自何处
http.cors.allow-origin: "*"
#是否可以为主节点。这个属性表示节点是否具有成为主节点的资格注意
node.master: true
#这个属性表示节点是否存储数据
node.data: true
#设置集群列表
discovery.zen.ping.unicast.hosts: ["127.0.0.1:8301","127.0.0.1:8302","127.0.0.1:8303"]
#配置当前集群中最少的主节点数,防止脑裂。
discovery.zen.minimum_master_nodes: 2
es-node2.yml
cluster.name: elasticsearch-cluster
node.name: es-node2
network.bind_host: 0.0.0.0
network.publish_host: 127.0.0.1
http.port: 8202
transport.tcp.port: 8302
http.cors.enabled: true
http.cors.allow-origin: "*"
node.master: true
node.data: true
discovery.zen.ping.unicast.hosts: ["127.0.0.1:8301","127.0.0.1:8302","127.0.0.1:8303"]
discovery.zen.minimum_master_nodes: 2
es-node3.yml
cluster.name: elasticsearch-cluster
node.name: es-node3
network.bind_host: 0.0.0.0
network.publish_host: 127.0.0.1
http.port: 8203
transport.tcp.port: 8303
http.cors.enabled: true
http.cors.allow-origin: "*"
node.master: true
node.data: true
discovery.zen.ping.unicast.hosts: ["127.0.0.1:8301","127.0.0.1:8302","127.0.0.1:8303"]
discovery.zen.minimum_master_nodes: 2
三个配置其实就是端口和节点名称略有不同,如果不搭集群,只用单个es配置可以删除discovery.zen.ping.unicast.hosts和discovery.zen.minimum_master_nodes
2. 调高JVM线程数限制数量
一般启动时会报错:ootstrap checks failed max virtual memory areas vm.max_map_count [65530] likely too low, increase to at least [262144] 这时候就应该修改配置sysctl.conf
vim /etc/sysctl.conf
加入下面内容:
vm.max_map_count=262144
启动配置:
sysctl -p
三. 启动es集群容器
实际就是启动docker镜像,执行下面命令:
docker run -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -d -p 8201:8201 -p 8301:8301 -v /disk1/elasticsearch/config/es-node1/es-node1.yml:/usr/share/elasticsearch/config/elasticsearch.yml --name ES01 elasticsearch:5.6
docker run -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -d -p 8202:8202 -p 8302:8302 -v /disk1/elasticsearch/config/es-node2/es-node2.yml:/usr/share/elasticsearch/config/elasticsearch.yml --name ES02 elasticsearch:5.6
docker run -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -d -p 8203:8203 -p 8303:8303 -v /disk1/elasticsearch/config/es-node3/es-node3.yml:/usr/share/elasticsearch/config/elasticsearch.yml --name ES03 elasticsearch:5.6
说明一下es的默认端口:
9200端口:ES节点和外部通讯使用,是http协议的RESTful接口
9300端口ES节点之间通讯使用,是tcp通讯端口,集群间和TCPClient都走的它
ps:设置-e ES_JAVA_OPTS="-Xms512m -Xmx512m" 是因为/etc/elasticsearch/jvm.options 默认jvm最大最小内存是2G,也可以直接进去容器修改配置(-Xms512m #总堆空间的初始大小,主要是改这里和下面的参数,所占大小尽量大。 -Xmx512m #总堆空间的最大大小,如我们是64G的内存初始就是32G,官网推荐最多是物理内存的一半)启动容器后可用docker stats命令查看
四. 验证是否搭建成功
1. 在浏览器地址栏访问http://127.0.0.1:8201/_cat/nodes?pretty 查看节点状态
127.0.0.1 32 99 6 1.00 1.44 1.52 mdi - es-node1
127.0.0.1 81 99 6 1.00 1.44 1.52 mdi * es-node2
127.0.0.1 58 99 6 1.00 1.44 1.52 mdi - es-node3
PS:节点名称带\表示为主节点*
不带任何参数表示访问单独节点:http://127.0.0.1:8201
2.使用elasticsearch-head前端框架
拉取镜像
docker pull mobz/elasticsearch-head:5
启动容器
docker run -d -p 8400:9100 --name es-manager mobz/elasticsearch-head:5
浏览器访问http://127.0.0.1:8400/ 输入http://127.0.0.1:8201/ 连接
五. 添加ik分词器插件
es自带分词对中文会进行每个字的拆分,不太合适,所以一般会安装中文分词插件。这里使用的是 ik,ik分词器有两个分词策略,分别为ik_smart 和 ik_max_word
k_max_word: 会将文本做最细粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,中华人民,中华,华人,人民共和国,人民,人,民,共和国,共和,和,国国,国歌”,会穷尽各种可能的组合;
ik_smart: 会做最粗粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,国歌”。
安装分词器需要根据es版本选择对应版本,有两种方法安装:
1.在线下载安装:
进入es容器内部目录
//这里ES01为容器名字也可以改为对应的CONTAINER ID docker exec -it ES01 /bin/bash
在线安装
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v5.6.16/elasticsearch-analysis-ik-5.6.16.zip
退出容器并重启指定容器
exit docker restart ES01
2.离线安装:
先去下载对应版本的zip,解压复制到容器的/usr/share/elasticsearch/plugins,再重启es
ps:采取第一种方法时重启报错,提示版本号不一致,故我这边采取第二种方法
3.检查:
在创建index和type后(下面有说明),添加数据可以查看分词效果
$ curl -X GET 'http://127.0.0.1:8201/project/_analyze?field=content&text=我爱中国'
如果不是每个字都拆开说明不是使用默认分词器
② Elasticsearch 使用
一. 基本概念
使用es前需要理解一下基本概念:
1.Node 与 Cluster
es 本质上是一个分布式数据库,允许多台服务器协同工作,每台服务器可以运行多个 Elastic 实例。 单个 Elastic 实例称为一个节点(node)。一组节点构成一个集群(cluster)。
2.Index
Elastic 数据管理的顶层单位就叫做 Index(索引)。类型等同于传统的关系型数据库的名称。每个 Index (即数据库)的名字必须是小写。
3.Type
类型是索引内部的逻辑分区(category/partition),然而其意义完全取决于用户需求。类型等同于传统的关系型数据库的表
4.Document
Index 里面单条的记录称为 Document(文档)。基于JSON格式进行表示,类型等同于传统的关系型数据库的列
5.Mapping
Mapping 是定义document,其包含的字段,字段存储,字段类型和索引
6.Shard
Shard是分片:因为 ES 是个分布式的搜索引擎, 所以索引通常都会分解成不同部分, 而这些分布在不同节点的数据就是分片,默认为5
6.Replica
Replica是副本:ES 默认为一个索引创建 5 个主分片, 并分别为其创建一个副本分片. 也就是说每个索引都由 5 个主分片成本, 而每个主分片都相应的有一个 copy。
Elastic 6.x 版只允许每个 Index 包含一个 Type,7.x 版将会彻底移除 Type。
二. 增删改查
ps:第二点主要介绍用API进行增删改查,一般不会重点使用,而是把es集成到springboot中代码进行增删改查
es提供基于restful风格的API接口来进行增删改查
1.新建一个Index和Type
新建一个 Index,指定需要分词的字段。这一步根据数据结构而异,下面的命令只针对本文。基本上,凡是需要搜索的中文字段,都要单独设置一下。
$ curl -X PUT 'http://127.0.0.1:8201/project' -d '
{
"mappings": {
"tb_elasticsearch_test": {
"properties": {
"id": {
"type": "long"
},
"number": {
"type": "float"
},
"createTime": {
"type": "long"
},
"updateTime": {
"type": "long"
},
"content": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
},
"elaseicsearchTestId": {
"type": "long"
}
}
}
}
}'
上面代码中,首先新建一个名称为project的 Index,里面有一个名称为tb_elasticsearch_test的 Type。tb_elasticsearch_test有六个字段。 相当于创建数据库和表,其他操作只需更改方法类型(GET,PUT,DELETE,POST)
1.新建一个Document(插入一条数据)
向指定的 /Index/Type 发送 PUT 请求,就可以在 Index 里面新增一条记录。比如,向/project/tb_elasticsearch_test发送请求,就可以新增一条记录。
$ curl -X PUT 'http://127.0.0.1:8201/project/tb_elasticsearch_test/1' -d '
{
"id": 1,
"elasticsearchTestId": 1,
"content": null,
"number": 0.05,
"createTime": 1555059048000,
"updateTime": 1555059050000
}'
服务器返回的 JSON 对象,会给出 Index、Type、Id、Version 等信息
{
"_index":"project",
"_type":"tb_elasticsearch_test",
"_id":"1",
"_version":1,
"result":"created",
"_shards":{"total":2,"successful":1,"failed":0},
"created":true
}
此时请求路径指定了id,/project/tb_elasticsearch_test/1,如不指定 Id,这时要改成 POST 请求,_id字段就是一个随机字符串。
2.查询一条数据
向指定的 /Index/Type 发送 GET 请求
$ curl 'http://127.0.0.1:8201/project/tb_elasticsearch_test/1?pretty=true'
pretty=true表示以易读的格式返回。 返回的数据中,found字段true表示查询成功,查不到数据,found字段就是false,_source字段返回原始记录。
{
"_index" : "project",
"_type" : "tb_elasticsearch_test",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : {
"id" : 1,
"elasticsearchTestId" : 1,
"content" : null,
"number" : 0.05,
"createTime" : 1555059048000,
"updateTime" : 1555059050000
}
}
3.更新数据
向指定的 /Index/Type/id 发送 PUT 请求
$ curl -X PUT 'http://127.0.0.1:8201/project/tb_elasticsearch_test/1' -d '
{
"id": 1,
"elasticsearchTestId": 1,
"content": "aaa",
"number": 0.06,
"createTime": 1555059048000,
"updateTime": 1555059050000
}'
返回
{
"_index": "project",
"_type": "tb_elasticsearch_test",
"_id": "1",
"_version": 2,
"result": "updated",
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"created": false
}
4.删除一条记录
删除记录就是发出 DELETE 请求。
$ curl -X DELETE 'http://127.0.0.1:8201/project/tb_elasticsearch_test/1'
返回
{
"found": true,
"_index": "project",
"_type": "tb_elasticsearch_test",
"_id": "1",
"_version": 3,
"result": "deleted",
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
}
}
5.简单查询
检测集群时候健康:GET /_cat/health?v
- 绿色表示一切正常, 黄色表示所有的数据可用但是部分副本还没有分配,红色表示部分数据因为某些原因不可用.
获取集群的节点列表:GET /_cat/nodes?v
列出所有索引:GET /_cat/indices?v
- 更多cat API
/_cat/allocation # 返回分片分配和磁盘使用的信息 /_cat/shards # 返回关于分片的信息 /_cat/shards/{index} /_cat/master # 返回当选主节点信息 /_cat/nodes # 返回集群拓扑相关信息 /_cat/tasks /_cat/indices # 返回所有索引信息 /_cat/indices/{index} /_cat/segments # 索引段包括分片布局的API信息 /_cat/segments/{index} /_cat/count # 为所有索引返回文档个数的信息 /_cat/count/{index} /_cat/recovery # 返回还原过程的视图 /_cat/recovery/{index} /_cat/health # 集群健康度 /_cat/pending_tasks # 正在等待执行任务信息 /_cat/aliases # 返回有关别名信息 /_cat/aliases/{alias} /_cat/thread_pool #集群范围内的线程池统计信息 /_cat/thread_pool/{thread_pools} /_cat/plugins # 插件信息 /_cat/fielddata # 字段数据信息使用堆内存 /_cat/fielddata/{fields} /_cat/nodeattrs # 输出显示自定义节点属性 /_cat/repositories # 输出集群中注册快照存储库 /_cat/snapshots/{repository} # 输出属于指定仓库的快照信息 /_cat/templates # 输出当前正在存在的模板信
- 更多cat API
匹配索引中所有的数据:POST /Index/Type/_search
{ "query": { "match_all": {} }, "sort": { "id": { "order": "desc" } }, "from": 0, "size": 10 }
返回指定的字段(id和number):POST /Index/Type/_search
{ "query": { "match_all": {} }, "_source": [ "id", "number" ] }
返回content中包含测试的所有数据:POST /Index/Type/_search
{ "query": { "match": { "content": "测试" } } }
match:match会被分词
term:term不分词,完全匹配
match_phrase会被分词且需要必须包含所有分词
multi_match两多个字段进行匹配如:
{
"query": {
"multi_match": {
"query": "测试",
"fields": [
"content",
"number"
],
"tie_breaker": 0.3
}
}
}
三. springboot集成es
1.添加依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
2.配置文件添加:
和es配置文件对应
spring:
data:
elasticsearch:
cluster-name: elasticsearch-cluster
cluster-nodes: 127.0.0.1:8301,127.0.0.1:8302,127.0.0.1:8303
repositories:
enabled: true
3.创建对应实体类:
创建ElasticsearchTestEntity.class并添加注解@Document(indexName = "project", type = "tb_elasticsearch_test")
import lombok.Data;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import javax.persistence.Id;
import java.math.BigDecimal;
import java.util.Date;
@Document(indexName = "project", type = "tb_elasticsearch_test")
@Data
public class ElasticsearchTestEntity {
@Id //主键只能叫id,@Id注解加上后,在Elasticsearch里相应于该列就是主键了,在查询时就可以直接用主键查询
private Integer id;
private Integer elasticsearchTestId;
@Field(searchAnalyzer = "ik_max_word", analyzer = "ik_max_word", type = FieldType.Text)
private String content;
private BigDecimal number = BigDecimal.ZERO;
private Date createTime = new Date();
private Date updateTime = new Date();
}
@Document注解里面的几个属性,类比mysql
- indexName –> 索引库的名称,建议以项目的名称命名,就相当于数据库DB
- type –> 类型,建议以实体的名称命名Table ,就相当于数据库中的表table
- Document –> row 就相当于某一个具体对象
Ⅰ @Document注解
String indexName();//索引库的名称,建议以项目的名称命名
String type() default "";//类型,建议以实体的名称命名
short shards() default 5;//默认分区数
short replicas() default 1;//每个分区默认的备份数
String refreshInterval() default "1s";//刷新间隔
String indexStoreType() default "fs";//索引文件存储类型
Ⅱ @Field注解
public @interface Field {
FieldType type() default FieldType.Auto;#自动检测属性的类型
FieldIndex index() default FieldIndex.analyzed;#默认情况下分词
DateFormat format() default DateFormat.none;
boolean fileddata() default false;#默认不把字段数据全部读取到内存中进行操作
String pattern() default "";
boolean store() default false;#默认情况下不存储原文
String searchAnalyzer() default "";#指定字段搜索时使用的分词器
String indexAnalyzer() default "";#指定字段建立索引时指定的分词器
String[] ignoreFields() default {};#如果某个字段需要被忽略
boolean includeInParent() default false;
}
重点说明一下type中的text和keyword 一般用于字符串类型
- text:存储数据时候,会自动分词,并生成索引,text不能用来排序,除非设置fileddata为true
- keyword:存储数据时候,不会分词建立索引
Ⅲ @MultiField注解
该字段使用text时如果进行分组查询,会根据分词后的内容分组,而不是完整的内容分组,如:想用“国泰君安”聚合,结果使用“国泰”,“君安”聚合 如果想要根据所有内容分组,就需要用@MultiField,把内容改为:
import lombok.Data;
import org.springframework.data.elasticsearch.annotations.*;
import javax.persistence.Id;
import java.math.BigDecimal;
import java.util.Date;
@Document(indexName = "project", type = "tb_elasticsearch_test")
@Data
public class ElasticsearchTestEntity {
@Id
private Integer id;
private Integer elasticsearchTestId;
@MultiField(
mainField = @Field(searchAnalyzer = "ik_max_word", analyzer = "ik_max_word", type = FieldType.Text, fielddata = true),
otherFields = {@InnerField(suffix = "raw", type = FieldType.Keyword)})
private String content;
private BigDecimal number = BigDecimal.ZERO;
private Date createTime = new Date();
private Date updateTime = new Date();
}
这样需要分词列名可以使用content,不需要分词时列名可以使用content.raw
*ps:字段的分词器创建不能更改,所以需要考虑清楚使用哪种分词器
4.创建es对应DAO:
和jpa基本类型,继承ElasticsearchRepository接口
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.data.jpa.repository.Modifying;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Optional;
public interface ElasticsearchTestEntityDao extends ElasticsearchRepository<ElasticsearchTestEntity, Integer> {
Page<ElasticsearchTestEntity> findByContent(String content, Pageable pageable);
Page<ElasticsearchTestEntity> findByCreateTimeBetween(Date startTime, Date endTime, Pageable pageable);
Page<ElasticsearchTestEntity> findByNumber(BigDecimal Number, Pageable pageable);
Page<ElasticsearchTestEntity> findByContentOrNumber(String content, BigDecimal number, Pageable pageable);
Optional<ElasticsearchTestEntity> findByElasticsearchTestId(Integer elasticsearchTestId);
@Modifying
int deleteByElasticsearchTestId(Integer elasticsearchTestId);
}
5.根据reporitory的简单增删改查:
这个方法和操作jpa中的普通的方法没什么区别,就是普通的增删改查。 通过自带方法就可以进行简单查询
<S extends T> S save(S var1);
<S extends T> Iterable<S> saveAll(Iterable<S> var1);
Optional<T> findById(ID var1);
boolean existsById(ID var1);
Iterable<T> findAll();
Iterable<T> findAllById(Iterable<ID> var1);
long count();
void deleteById(ID var1);
void delete(T var1);
void deleteAll(Iterable<? extends T> var1);
void deleteAll();
ps:es插入新信息时,实体类中的主键id是需要填写,不能通过es自动生成(通过API可以自动生成随机id)不填写会以id为null插入信息
6.es的高级复杂查询:
例子可以查看项目模板(project-templet)
四.es集成search-guard安全插件:
1.安装search-guard安全插件:
- 进入es容器内部目录
//这里ES01为容器名字也可以改为对应的CONTAINER ID docker exec -it ES01 /bin/bash
- 安装search-guard安全插件:
//版本号对应es版本号 bin/elasticsearch-plugin install -b com.floragunn:search-guard-5:5.6.16-19.3
- 等待下载完成后自动安装,出现下面语句说明已经安装成功 ```
Installed search-guard-5
后面每个es都需要安装该插件,不一一演示
2.生成证书文件
Ⅰ search-guard证书有3种类型:
- Client certificates(客户端证书)
- Admin certificates(管理员证书)
- Node certificates(节点证书)
客户端证书是TLS证书,用在es 客户端,支持rest client和transport client ; 管理员证书也是客户端证书。客户端证书如果在es配置文件elasticsearch.yml中增加了如下配置,就变成了管理员证书,例如javaapi是客户端证书, 配置完才可以给springboot使用,可以配置多个:
search-guard配置包括用户,角色,权限等。search-guard提供了sgadmin脚本工具,来往es写入search-guard配置信息。searchguard.authcz.admin_dn: - CN=javaapi,OU=javaapi,O=client,L=Test, C=DE - CN=test,OU=client,O=client,L=Test, C=DE
节点证书用在es节点。保证es节点之间通信安全。节点证书没有权限限制,即每个操作都是允许的。也不能针对节点证书配置权限。
Ⅱ 证书生成工具
需要使用search-guard-ssl中的脚本生成各种证书
#git clone https://github.com/floragunncom/search-guard-ssl.git
#cd search-guard-ssl/example-pki-scripts
example-pki-scripts目录下有这几个脚本文件:
gen_client_node_cert.sh 创建客户端证书
可以修改证书发行者信息if [ -z "$DN" ]; then DN="CN=$CLIENT_NAME, OU=client, O=client, L=Test, C=DE" fi
其中:CN=名字与姓氏,OU=组织单位名称,O=组织名称,L=城市或区域名 称,ST=州或省份名称,C=单位的两字母国家代码, 对应es配置文件elasticsearch.yml中的searchguard.authcz.admin_dn 如:CN=javaapi,OU=client,O=client,L=Test,C=DE
可以修改证书的有效期"$BIN_PATH" -genkey \ -alias $CLIENT_NAME \ -keystore $CLIENT_NAME-keystore.jks \ -keyalg RSA \ -keysize 2048 \ -sigalg SHA256withRSA \ -validity 712 \ -keypass $KS_PASS \ -storepass $KS_PASS \ -dname "$DN"
其中validity为有效期,单位是天
gen_node_cert.sh 创建节点证书
可以修改证书发行者信息和修改证书的有效期,与gen_client_node_cert.sh相等gen_root_ca.sh 创建根证书
etc/root-ca.conf 根证书配置
etc/signing-ca.conf 签名证书配置
etc/root-ca.conf 和 etc/signing-ca.conf 需要配置相同信息: ```
0.domainComponent = "www.test.com” 域名 1.domainComponent = "www.test.com" 域名 organizationName = "Test" 组织名称 organizationalUnitName = "Test Root CA" 组织单位名称 commonName = "Test Root CA" 通用名称
* example.sh 生成证书脚本
修改为
#!/bin/bash OPENSSL_VER="$(openssl version)"
if [[ $OPENSSL_VER == *"0.9"* ]]; then echo "Your OpenSSL version is too old: $OPENSSL_VER" echo "Please install version 1.0.1 or later" exit -1 else echo "Your OpenSSL version is: $OPENSSL_VER" fi
set -e ./clean.sh
第一个参数为CA根证书密码,第二个参数为TS密码(truststore,信任证书密码)
./gen_root_ca.sh aaccbb 123456
生成节点证书: 第一个参数为节点编号,第二个参数为keystore文件密码,第三个参数为CA根证书密码。
此处我们只生成三个节点证书
./gen_node_cert.sh 1 123456 aaccbb && ./gen_node_cert.sh 2 123456 aaccbb && ./gen_node_cert.sh 3 123456 aaccbb
生成客户端证书: 第一个参数为客户端名称, 第二个参数为keystore文件名称,第三个参数为CA根证书名称。
生成一个javaapi访问的客户端证书,用于springboot访问es
./gen_client_node_cert.sh javaapi 123456 aaccbb
rm -f ./tmp
然后运行脚本后会在该文件夹生成很多的证书:我们主要需要:
* truststore.jks 根证书
* javaapi-keystore.jks 客户端证书,该证书将会配置到es配置文件,做为管理员证书
* node-1-keystore.jks,node-2-keystore.jks,node-3-keystore.jks 3个节点证书
##### Ⅲ 设置es配置
把生成的truststore.jks和javaapi-keystore.jks上传到/disk1/elasticsearch/config/;
各个节点的证书也分别上传到对应的配置文件夹:/disk1/elasticsearch/config/es-node1/;
把管理员证书和根证书和对应的节点证书分别复制到各个es的配置文件夹中:/usr/share/elasticsearch/config/
ES01 docker cp /disk1/elasticsearch/config/truststore.jks ES01:/usr/share/elasticsearch/config/ docker cp /disk1/elasticsearch/config/es-node1/node-1-keystore.jks ES01:/usr/share/elasticsearch/config/ docker cp /disk1/elasticsearch/config/javaapi-keystore.jks ES01:/usr/share/elasticsearch/config/
ES02 docker cp /disk1/elasticsearch/config/truststore.jks ES02:/usr/share/elasticsearch/config/ docker cp /disk1/elasticsearch/config/es-node2/node-2-keystore.jks ES02:/usr/share/elasticsearch/config/ docker cp /disk1/elasticsearch/config/javaapi-keystore.jks ES02:/usr/share/elasticsearch/config/
ES03 docker cp /disk1/elasticsearch/config/truststore.jks ES03:/usr/share/elasticsearch/config/ docker cp /disk1/elasticsearch/config/es-node3/node-3-keystore.jks ES03:/usr/share/elasticsearch/config/ docker cp /disk1/elasticsearch/config/javaapi-keystore.jks ES03:/usr/share/elasticsearch/config/
各个es的配置文件中添加:
###### es-node1.yml
http.cors.allow-headers: Authorization,X-Requested-With,Content-Length,Content-Type
配置节点间通信证书,节点间通信使用TLS是强制的
searchguard.ssl.transport.keystore_filepath: node-1-keystore.jks searchguard.ssl.transport.keystore_password: 123456 searchguard.ssl.transport.truststore_filepath: truststore.jks searchguard.ssl.transport.truststore_password: 123456
设置不校验hostname
searchguard.ssl.transport.enforce_hostname_verification: false searchguard.ssl.transport.resolve_hostname: false
#配置restful为https访问,此处配置了head插件无法访问,所以一个节点不配置https,用于给head访问,剩下的配置https searchguard.ssl.http.enabled: false searchguard.ssl.http.keystore_filepath: node-1-keystore.jks searchguard.ssl.http.keystore_password: 123456 searchguard.ssl.http.truststore_filepath: truststore.jks searchguard.ssl.http.truststore_password: 123456
配置管理员证书DN
searchguard.authcz.admin_dn:
- CN=javaapi,OU=client,O=client,L=Test, C=DE
###### es-node2.yml
http.cors.allow-headers: Authorization,X-Requested-With,Content-Length,Content-Type
# 配置节点间通信证书,节点间通信使用TLS是强制的
searchguard.ssl.transport.keystore_filepath: node-2-keystore.jks
searchguard.ssl.transport.keystore_password: 123456
searchguard.ssl.transport.truststore_filepath: truststore.jks
searchguard.ssl.transport.truststore_password: 123456
# 设置不校验hostname
searchguard.ssl.transport.enforce_hostname_verification: false
searchguard.ssl.transport.resolve_hostname: false
searchguard.ssl.http.enabled: true
searchguard.ssl.http.keystore_filepath: node-2-keystore.jks
searchguard.ssl.http.keystore_password: 123456
searchguard.ssl.http.truststore_filepath: truststore.jks
searchguard.ssl.http.truststore_password: 123456
# 配置管理员证书DN
searchguard.authcz.admin_dn:
- CN=javaapi,OU=client,O=client,L=Test, C=DE
es-node3.yml
http.cors.allow-headers: Authorization,X-Requested-With,Content-Length,Content-Type
# 配置节点间通信证书,节点间通信使用TLS是强制的
searchguard.ssl.transport.keystore_filepath: node-3-keystore.jks
searchguard.ssl.transport.keystore_password: 123456
searchguard.ssl.transport.truststore_filepath: truststore.jks
searchguard.ssl.transport.truststore_password: 123456
# 设置不校验hostname
searchguard.ssl.transport.enforce_hostname_verification: false
searchguard.ssl.transport.resolve_hostname: false
searchguard.ssl.http.enabled: true
searchguard.ssl.http.keystore_filepath: node-3-keystore.jks
searchguard.ssl.http.keystore_password: 123456
searchguard.ssl.http.truststore_filepath: truststore.jks
searchguard.ssl.http.truststore_password: 123456
# 配置管理员证书DN
searchguard.authcz.admin_dn:
- CN=javaapi,OU=client,O=client,L=Test, C=DE
重启es:
docker restart ES01 ES02 ES03
最后进入各个es内部将search-guard配置写入到es
1 docker exec -it ES01 /bin/bash
2 cd plugins/search-guard-5/tools/
//添加权限
3 chmod +x *.sh
//-p 8301 对应elasticsearch transport连接的端口号
//-cn test 为elasticsearch 集群名称 cluster.name
//以后每次调整searchguard 用户,角色和权限都需要执行一次写入search-guard配置操作;
//写入search-guard配置不需要重启Elasticsearch;
4 ./sgadmin.sh -cn elasticsearch-cluster -p 8301 -cd ../sgconfig -ks ../../../config/javaapi-keystore.jks -kspass 123456 -ts ../../../config/truststore.jks -tspass 123456 -nhnv
现在访问随意一个节点的地址http://127.0.0.1:8201/,发现需要输入密码才能访问,输入默认账号和密码:admin,才能访问
Ⅳ search-guard配置文件
searchguard 主要有5个配置文件在plugins/search-guard-5/sgconfig 下:
sg_config.yml:主配置文件不需要做改动。
sg_internal_users.yml:本地用户文件,定义用户密码以及对应的权限。
sg_roles.yml:角色权限配置文件
sg_roles_mapping.yml:定义用户角色的映射关系
sg_action_groups.yml:定义权限组:
可以修改对应的配置文件进行修改账号、角色信息
五.遇到的问题:
1.项目中如果有用到redis,springboot启动时会报错:java.lang.IllegalStateException: availableProcessors is already set to [4], rejecting [4]
主要是netty冲突
Ⅰ springboot中添加es配置类:
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
@Configuration
public class ElasticSearchConfig {
@PostConstruct
void init() {
System.setProperty("es.set.netty.runtime.available.processors", "false");
}
}
Ⅱ 启动方法添加
System.setProperty("es.set.netty.runtime.available.processors", "false");:
@EnableSwagger2
@SpringBootApplication
public class CmsApplication {
public static void main(String[] args) {
System.setProperty("es.set.netty.runtime.available.processors", "false");
SpringApplication.run(CmsApplication.class, args);
}
}
ps:有时第一个方法可以有时第二个方法可以,原因还在排查中
2.springboot启动报错:NoNodeAvailableException[None of the configured nodes are available: [{#transport#-1}{192.111.222.5}{192.111.222.5:9300}]]
es配置文件添加network.host: 0.0.0.0(网上有说改为本地ip有说改为0.0.0.0)
3.es启动时形成不了集群:not enough master nodes discovered during pinging (found [[Candidate{node={my_node_name}{jRy-sXoCRP6bywdHcptjcA}{9uIaSSb7SEWx4AP6R_crTw}{192.168.58.147}{192.168.58.147:9300}, clusterStateVersion=-1}]], but needed [2]), pinging again
Ⅰ es配置文件中,node.master都设置为true
Ⅱ docker映射的端口设为相等(防止找不到相应的es节点)
4. 途中打开防火墙又关闭防火墙 docker启动容器报错:docker: Error response from daemon: driver failed programming external connectivity on endpoint
原因是docker服务启动时定义的自定义链DOCKER被防火墙清掉,学英语重启docker服务及可重新生成自定义链DOCKER,systmctl restart docker 重启docker,再重启容器
参考的网站: