elasticsearch 安装使用及常见错误集锦

环境信息

  • Centos7 3.10.0-1062.9.1.el7
  • elasticsearch 8.8.2

elasticsearch 下载

elasticsearch 下载页面

安装 elasticsearch

wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.8.2-linux-x86_64.tar.gz
tar -xzf elasticsearch-8.8.2-linux-x86_64.tar.gz
cd elasticsearch-8.8.2/

启动

./bin/elasticsearch

首次启动 Elasitcsearch 时,安全特性默认被启用,以下的安全选项会自动配置: [2]

  • 认证鉴权功能会被启用,并且会为默认的超级用户 elastic 产生一个密码
  • 生成 TLS 证书,并配置证书以启用 TLS 功能
  • 为 Kibana 产生一个 enrollment key,有效期 30 分钟

要以 daemon 的形式运行 Elasticsearch,使用 -d 选项,使用 -p 选项将 PID 记录到一个文件里面

./bin/elasticsearch -d -p pid

RPM 安装 Elasticsearch 官方参考文档不同版本具有不同的配置,根据版本选择对应配置

$ rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch

$ cat /etc/yum.repos.d/elasticsearch.repo
[elasticsearch]
name=Elasticsearch repository for 8.x packages
baseurl=https://artifacts.elastic.co/packages/8.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=0
autorefresh=1
type=rpm-md

$ yum install --enablerepo=elasticsearch elasticsearch

配置文件示例

elasticsearch.yml
cluster.name: es-cluster1
node.name: es-cluster1-node1
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch

# 多网卡情况下,建议指定 IP 地址,以防止集群使用网络不通的 IP。如果需要监听多个 IP 地址,使用配置 network.host: ["127.0.0.1", "192.168.1.1"]
network.host: 0.0.0.0
http.port: 9200

discovery.seed_hosts: ["172.31.26.116", "172.31.19.164", "172.31.21.3"]
cluster.initial_master_nodes: ["es-cluster1-node1", "es-cluster1-node2", "es-cluster1-node3"]

xpack.security.enabled: false
xpack.security.enrollment.enabled: false
xpack.security.transport.ssl.enabled: false
xpack.security.http.ssl.enabled: false

加入节点到集群

默认情况下,只有同一个主机上的节点才能在 没有其他配置的情况下 加入到集群。如果要让另一个主机上的节点加入到新启动的节点的集群中,需要更改配置,首先要修改 Elasticsearch 的监听地址,确保另一台主机能连接它(不是默认监听的 localhost[2]

加入开启了安全功能的集群

要将新节点加入到开启了安全功能的集群,首先要创建一个 enrollment token。在集群中的任一节点上执行以下命令,创建 enrollment token

bin/elasticsearch-create-enrollment-token -s node

要加入集群的节点上,使用以下命令启动 Elasticsearch,使用 --enrollment-token 传递 enrollment token

bin/elasticsearch --enrollment-token <enrollment-token>

新节点上的 Elasticsearch 会自动在 config/certs 下面生成证书和 Key

常见错误

Elasticsearch 启动失败

Caused by: java.io.IOException: failed to read [id:2, file:/var/lib/elasticsearch/nodes/0/_state/node-2.st]

启动报错,手动执行启动程序

su - elasticsearch -c /usr/share/elasticsearch/bin/elasticsearch

启动报错:

[2023-03-30T16:20:28,458][WARN ][o.e.b.ElasticsearchUncaughtExceptionHandler] [node-1] uncaught exception in thread [main]
org.elasticsearch.bootstrap.StartupException: ElasticsearchException[java.io.IOException: failed to read [id:2, file:/var/lib/elasticsearch/nodes/0/_state/node-2.st]]; nested: IOException[failed to read [id:2, file:/var/lib/elasticsearch/nodes/0/_state/node-2.st]]; nested: XContentParseException[[-1:36] [node_meta_data] unknown field [node_version], parser not found];
at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:163) ~[elasticsearch-6.8.23.jar:6.8.23]
at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:150) ~[elasticsearch-6.8.23.jar:6.8.23]
at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:86) ~[elasticsearch-6.8.23.jar:6.8.23]
at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:124) ~[elasticsearch-cli-6.8.23.jar:6.8.23]
at org.elasticsearch.cli.Command.main(Command.java:90) ~[elasticsearch-cli-6.8.23.jar:6.8.23]
at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:116) ~[elasticsearch-6.8.23.jar:6.8.23]
at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:93) ~[elasticsearch-6.8.23.jar:6.8.23]
Caused by: org.elasticsearch.ElasticsearchException: java.io.IOException: failed to read [id:2, file:/var/lib/elasticsearch/nodes/0/_state/node-2.st]

问题原因

系统安装过其他版本的 elasticsearch,卸载后重新安装,报这个错误,可能是因为版本之间的数据不兼容,重新卸载 elasticsearch,并删除以下数据,重新安装

yum remove elasticsearch

rm -rf /etc/elasticsearch/
rm -rf /var/lib/elasticsearch/
rm -rf /usr/share/elasticsearch

yum install -y elasticsearch-8.8.23.rpm

bootstrap check failure

Elasticsearch 启动报错:

validation exception
[1] bootstrap checks failed. You must address the points described in the following [1] lines before starting Elasticsearch.
bootstrap check failure [1] of [1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

错误原因 是因为 vm.max_map_count 的值过低。这个值是系统限制,控制了单个进程可以拥有的虚拟内存区域的最大数量

使用以下命令修改此值,要持久化配置,需要写入内核配置文件 /etc/sysctl.conf

sysctl -w vm.max_map_count=262144

bootstrap check failure

Elasticsearch 启动报错:

node validation exception
[1] bootstrap checks failed. You must address the points described in the following [1] lines before starting Elasticsearch.
bootstrap check failure [1] of [1]: Transport SSL must be enabled if security is enabled. Please set [xpack.security.transport.ssl.enabled] to [true] or disable security by setting [xpack.security.enabled] to [false]

安全配置不全,如果无需安全相关配置,使用以下配置关闭

elasticsearch.yml
xpack.security.enabled: false

keystore password was incorrect

Elasticsearch 启动失败,检查日志,报错如下

Caused by: org.elasticsearch.common.ssl.SslConfigException: cannot read configured [PKCS12] keystore (as a truststore) [/etc/elasticsearch/certs/elastic-certificates.p12] - this is usually caused by an incorrect password; (a keystore password was provided)
at org.elasticsearch.common.ssl.SslFileUtil.ioException(SslFileUtil.java:56) ~[?:?]
at org.elasticsearch.common.ssl.StoreTrustConfig.readKeyStore(StoreTrustConfig.java:98) ~[?:?]
at org.elasticsearch.common.ssl.StoreTrustConfig.createTrustManager(StoreTrustConfig.java:82) ~[?:?]
at org.elasticsearch.xpack.core.ssl.SSLService.createSslContext(SSLService.java:476) ~[?:?]
at java.util.HashMap.computeIfAbsent(HashMap.java:1228) ~[?:?]
at org.elasticsearch.xpack.core.ssl.SSLService.lambda$loadSslConfigurations$11(SSLService.java:615) ~[?:?]
... 23 more
Caused by: java.io.IOException: keystore password was incorrect

问题原因 Elasticsearch 启用了安全特性,但是获取到的 TSL/SSL 证书及密钥的解密密码不对。例如以下安全相关配置中,节点之间通信使用了安全认证(xpack.security.transport.ssl.enabled: true),以及对应证书(certs/elastic-certificates.p12),本示例此证书未加密,没有解密密码。如果 Elasticsearch 启动时使用了解密的密码不为空或错误,可能导致此错误。

/etc/elasticsearch/elasticsearch.yml
xpack.security.enabled: true
xpack.security.enrollment.enabled: false
xpack.security.http.ssl.enabled: false

xpack.security.transport.ssl:
enabled: true
verification_mode: certificate
keystore.path: certs/elastic-certificates.p12
truststore.path: certs/elastic-certificates.p12

Elasticsearch 解密证书使用的密码默认在 /etc/elasticsearch/elasticsearch.keystore。密码使用以下命令更新,如果密码为空,直接使用 Enter 键即可。

# elasticsearch-keystore add xpack.security.transport.ssl.keystore.secure_password
Setting xpack.security.transport.ssl.keystore.secure_password already exists. Overwrite? [y/N]y
Enter value for xpack.security.transport.ssl.keystore.secure_password:

# elasticsearch-keystore add xpack.security.transport.ssl.truststore.secure_password
Setting xpack.security.transport.ssl.truststore.secure_password already exists. Overwrite? [y/N]y
Enter value for xpack.security.transport.ssl.truststore.secure_password:

如果要更新客户端使用的证书(xpack.security.http.ssl)解码密码,使用以下命令

elasticsearch-keystore add xpack.security.http.ssl.keystore.secure_password

elasticsearch-keystore add xpack.security.http.ssl.truststore.secure_password

AccessDeniedException

Elasticsearch 服务启动失败,检查日志内容如下

Caused by: org.elasticsearch.common.ssl.SslConfigException: not permitted to read the [PKCS12] keystore (as a truststore) file [/etc/elasticsearch/certs/elastic-certificates.p12]
at org.elasticsearch.common.ssl.SslFileUtil.accessDenied(SslFileUtil.java:77) ~[?:?]
at org.elasticsearch.common.ssl.SslFileUtil.ioException(SslFileUtil.java:40) ~[?:?]
at org.elasticsearch.common.ssl.StoreTrustConfig.readKeyStore(StoreTrustConfig.java:98) ~[?:?]
at org.elasticsearch.common.ssl.StoreTrustConfig.createTrustManager(StoreTrustConfig.java:82) ~[?:?]
at org.elasticsearch.xpack.core.ssl.SSLService.createSslContext(SSLService.java:476) ~[?:?]
at java.util.HashMap.computeIfAbsent(HashMap.java:1228) ~[?:?]
at org.elasticsearch.xpack.core.ssl.SSLService.lambda$loadSslConfigurations$11(SSLService.java:615) ~[?:?]
... 23 more
Caused by: java.nio.file.AccessDeniedException: /etc/elasticsearch/certs/elastic-certificates.p12

从日志可知,问题原因为配置文件无权限读取

# ll /etc/elasticsearch/certs/
total 32
-rw-------. 1 root root 3596 Jul 27 16:04 elastic-certificates.p12
-rw-------. 1 root root 2672 Jul 27 16:01 elastic-stack-ca.p12
-rw-rw----. 1 root elasticsearch 1915 Jul 20 14:56 http_ca.crt
-rw-rw----. 1 root elasticsearch 10189 Jul 20 14:56 http.p12
-rw-rw----. 1 root elasticsearch 5838 Jul 20 14:56 transport.p12

执行以下命令,修改配置路径权限

chmod 660 /etc/elasticsearch/certs/*
chown root:elasticsearch /etc/elasticsearch/certs/*

配置相关问题

Empty reply from server

参考 官方文档中的安装方式安装运行 Elasticsearch。使用以下请求测试 Elasticsearch 是否启动成功

$ curl 'http://localhost:9200/?pretty'
curl: (52) Empty reply from server

查看 Elasticsearch 日志

$ tail elasticsearch.log 
[2023-07-18T01:12:10,126][WARN ][o.e.h.n.Netty4HttpServerTransport] [b5f96e32c638] received plaintext http traffic on an https channel, closing connection Netty4HttpChannel{localAddress=/127.0.0.1:9200, remoteAddress=/127.0.0.1:58504}
[2023-07-18T01:12:19,317][WARN ][o.e.h.n.Netty4HttpServerTransport] [b5f96e32c638] received plaintext http traffic on an https channel, closing connection Netty4HttpChannel{localAddress=/127.0.0.1:9200, remoteAddress=/127.0.0.1:38916}

根据日志中显示的信息可知,curl: (52) Empty reply from server 是因为 Elasticsearch 服务配置为使用了 HTTPS,而客户端请求使用的是 HTTP 明文传输,为了确保安全性,Elasticsearch 服务关闭了这些在 HTTPS 通道上的 HTTP 请求。针对此问题,可以参考以下解决方法

  • 客户端使用 HTTPS 请求,并配置跳过证书认证
    $ curl -k 'https://localhost:9200/?pretty'
    {
    "error" : {
    "root_cause" : [
    {
    "type" : "security_exception",
    "reason" : "missing authentication credentials for REST request [/?pretty]",
    "header" : {
    "WWW-Authenticate" : [
    "Basic realm=\"security\" charset=\"UTF-8\"",
    "Bearer realm=\"security\"",
    "ApiKey"
    ]
    }
    }
    ],
    "type" : "security_exception",
    "reason" : "missing authentication credentials for REST request [/?pretty]",
    "header" : {
    "WWW-Authenticate" : [
    "Basic realm=\"security\" charset=\"UTF-8\"",
    "Bearer realm=\"security\"",
    "ApiKey"
    ]
    }
    },
    "status" : 401
    }

  • 关闭 Elasticsearch 的 HTTPS,使用 HTTP 通信
    修改配置文件 elasticsearch.yml,重启 Elasticsearch 服务后使用 HTTP 请求,相关配置说明参考
    elasticsearch.yml
    xpack.security.enabled: false   # 改为 false

    xpack.security.enrollment.enabled: false # 改为 false

    xpack.security.http.ssl:
    enabled: false # 改为 false
    keystore.path: certs/http.p12
    xpack.security.transport.ssl:
    enabled: false # 改为 false
    verification_mode: certificate
    keystore.path: certs/transport.p12
    truststore.path: certs/transport.p12

    重新使用 HTTP 请求,即可得到响应
    $ curl 'http://localhost:9200/?pretty'
    {
    "error" : {
    "root_cause" : [
    {
    "type" : "security_exception",
    "reason" : "missing authentication credentials for REST request [/?pretty]",
    "header" : {
    "WWW-Authenticate" : [
    "Basic realm=\"security\" charset=\"UTF-8\"",
    "ApiKey"
    ]
    }
    }
    ],
    "type" : "security_exception",
    "reason" : "missing authentication credentials for REST request [/?pretty]",
    "header" : {
    "WWW-Authenticate" : [
    "Basic realm=\"security\" charset=\"UTF-8\"",
    "ApiKey"
    ]
    }
    },
    "status" : 401
    }

其他问题

missing authentication credentials for REST request

请求 Elasticsearch 时,返回以下错误: missing authentication credentials for REST request

$ curl 'http://localhost:9200/?pretty'
{
"error" : {
"root_cause" : [
{
"type" : "security_exception",
"reason" : "missing authentication credentials for REST request [/?pretty]",
"header" : {
"WWW-Authenticate" : [
"Basic realm=\"security\" charset=\"UTF-8\"",
"ApiKey"
]
}
}
],
"type" : "security_exception",
"reason" : "missing authentication credentials for REST request [/?pretty]",
"header" : {
"WWW-Authenticate" : [
"Basic realm=\"security\" charset=\"UTF-8\"",
"ApiKey"
]
}
},
"status" : 401
}

这个错误表示尝试在 Elasticsearch 上执行一个需要身份验证的请求,但没有提供正确的凭据。Elasticsearch 需要进行身份验证才能访问相关的端点。

有两种常见的身份验证方式可以使用:基本身份验证(Basic Authentication)API 密钥(API Key)。根据响应头部的提示,你可以使用其中一种方式来提供正确的身份验证凭据。

  • 基本身份验证(Basic Authentication)

    对于基本身份验证,可以在 URL 请求中包含用户名和密码,例如:

    curl -u username:password 'http://localhost:9200/?pretty'
  • API 密钥(API Key)

    对于 API 密钥身份验证,你需要将 API 密钥放置在请求的头部。

    curl -H 'Authorization: ApiKey YOUR_API_KEY' 'http://localhost:9200/?pretty'

  • 关闭身份验证
    要关闭 Elasticsearch 的身份认证功能,需要修改配置文件 elasticsearch.yml,修改以下配置,关闭认证功能

    elasticsearch.yml
    xpack.security.enabled: false

    重启 Elasticsearch 后重新请求

    $ curl 'http://localhost:9200/?pretty'
    {
    "name" : "b5f96e32c638",
    "cluster_name" : "elasticsearch",
    "cluster_uuid" : "UAiC0qVVT-Ov4nJFvoE1HA",
    "version" : {
    "number" : "8.8.2",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "98e1271edf932a480e4262a471281f1ee295ce6b",
    "build_date" : "2023-06-26T05:16:16.196344851Z",
    "build_snapshot" : false,
    "lucene_version" : "9.6.0",
    "minimum_wire_compatibility_version" : "7.17.0",
    "minimum_index_compatibility_version" : "7.0.0"
    },
    "tagline" : "You Know, for Search"
    }

application/x-www-form-urlencoded

$ curl -X PUT 'localhost:9200/blogs' -d '{"settings": {"number_of_shards": 3, "number_of_replicas": 1}}'
{"error":"Content-Type header [application/x-www-form-urlencoded] is not supported","status":406}

错误原因 没有在 curl 命令中指定正确的内容类型。解决方法为 使用 -H 参数来设置正确的内容类型为 application/json

$ curl -X PUT 'localhost:9200/blogs' -H "Content-Type: application/json" -d '{"settings": {"number_of_shards": 3, "number_of_replicas": 1}}'
{"acknowledged":true,"shards_acknowledged":true,"index":"blogs"}

write index for data stream

直接删除索引失败

$ curl -XDELETE localhost:9200/.ds-logs-generic-default-2023.07.21-000001
{
"error" : {
"root_cause" : [
{
"type" : "illegal_argument_exception",
"reason" : "index [.ds-logs-generic-default-2023.07.21-000001] is the write index for data stream [logs-generic-default] and cannot be deleted"
}
],
"type" : "illegal_argument_exception",
"reason" : "index [.ds-logs-generic-default-2023.07.21-000001] is the write index for data stream [logs-generic-default] and cannot be deleted"
},
"status" : 400
}

主要报错信息 index [.ds-logs-generic-default-2023.07.21-000001] is the write index for data stream [logs-generic-default] and cannot be deleted

问题原因 data stream (数据流) 是 Elasticsearch 中用于管理时间序列数据的功能,它会自动创建和管理多个索引,包括索引写入和滚动索引data stream (数据流) 有一个或者多个写入索引,用于实际写入和索引数据。由于数据流是一种时间序列的数据存储方式,不应该直接删除写入索引如果想要删除一个数据流,应该通过删除整个数据流来实现,而不是单独的删除写入索引

要删除一个 data stream (数据流),参考以下 API

$ curl -XDELETE localhost:9200/_data_stream/logs-generic-default
{"acknowledged":true}

参考链接

官方文档

脚注