Elasticsearch 可以作为 Docker 镜像使用。 www.docker.elastic.co 上提供了所有已发布的 Docker 图像和标签的列表。 源文件在 Github 中。此软件包包含免费和订阅功能。 开始 30 天试用以试用所有功能。
从 Elasticsearch 8.0 开始,默认启用安全性。 启用安全性后,Elastic Stack 安全功能需要对传输网络层进行 TLS 加密,否则你的集群将无法启动。
安装 Docker Desktop 或 Docker Engine
为你的操作系统安装适当的 Docker 应用程序。
注意:确保为 Docker 分配至少 4GiB 的内存。 在 Docker Desktop 中,你可以在首选项 (macOS) 或设置 (Windows) 的高级选项卡上配置资源使用。
拉取 Elasticsearch Docker 镜像
获取 Elasticsearch for Docker 就像针对 Elastic Docker 注册表发出 docker pull 命令一样简单:
docker pull docker.elastic.co/elasticsearch/elasticsearch:8.8.0
$ docker pull docker.elastic.co/elasticsearch/elasticsearch:8.8.0
8.8.0: Pulling from elasticsearch/elasticsearch
16c1e5ae78fc: Already exists
2a63fecd431d: Pull complete
c709fa6210ed: Pull complete
89732bc75041: Pull complete
a47052f8e9bf: Pull complete
7f91ecd93209: Pull complete
af03b547f578: Pull complete
8931370f2a7b: Pull complete
ab2e468d9ee0: Pull complete
5a44f6d27aab: Pull complete
Digest: sha256:9aaa38551b4d9e655c54d9dc6a1dad24ee568c41952dc8cf1d4808513cfb5f65
Status: Downloaded newer image for docker.elastic.co/elasticsearch/elasticsearch:8.8.0
docker.elastic.co/elasticsearch/elasticsearch:8.8.0
可选:验证 Elasticsearch Docker 镜像签名
虽然这是可选的,但我们强烈建议你验证下载的 Docker 映像中包含的签名,以确保映像有效。
Elastic 镜像使用 Sigstore 项目的一部分 Cosign 进行签名。Cosign 支持在 OCI 注册表中进行容器签名、验证和存储。
为你的操作系统安装适当的 Cosign 应用程序。
Elasticsearch v8.8.0 的容器镜像签名验证如下:
wget https://artifacts.elastic.co/cosign.pub
cosign verify --key cosign.pub docker.elastic.co/elasticsearch/elasticsearch:8.8.0
该命令以 JSON 格式打印检查结果和签名负载:
Verification for docker.elastic.co/elasticsearch/elasticsearch:{version} --
The following checks were performed on each of these signatures:
- The cosign claims were validated
- Existence of the claims in the transparency log was verified offline
- The signatures were verified against the specified public key
现在你已经验证了 Elasticsearch Docker 镜像签名,你可以启动单节点或多节点集群。
使用 Docker 启动单节点集群
如果你在 Docker 容器中启动单节点 Elasticsearch 集群,系统会自动为你启用和配置安全性。 首次启动 Elasticsearch 时,会自动进行以下安全配置:
- 为传输层和 HTTP 层生成证书和密钥。
- 传输层安全性 (TLS) 配置设置写入 elasticsearch.yml。
- 为 elastic 用户生成密码。
- 为 Kibana 生成注册令牌。
然后你可以启动 Kibana 并输入注册令牌,该令牌的有效期为 30 分钟。 此令牌自动应用 Elasticsearch 集群的安全设置,使用 kibana_system 用户向 Elasticsearch 进行身份验证,并将安全配置写入 kibana.yml。
以下命令启动用于开发或测试的单节点 Elasticsearch 集群。
1)为 Elasticsearch 和 Kibana 创建一个新的 docker 网络
docker network create elastic
提示:如果你已经存在某个网络,你可以使用 docker network rm <network_name> 来删除命名为 network_name 的网络。
$ docker network create elastic
3f510dc3fb931d808c98365b5126dbdda0e8aede4bb503f1f5aeeb8802bdfeb9
2)在 Docker 中启动 Elasticsearch。 为 elastic 用户生成密码并输出到终端,加上用于注册 Kibana 的注册令牌。
docker run -e ES_JAVA_OPTS="-Xms1g -Xmx1g" --name es01 --net elastic -p 9200:9200 -p 9300:9300 -it docker.elastic.co/elasticsearch/elasticsearch:8.8.0
提示:你可能需要在终端中向后滚动一点才能查看密码和注册令牌
3)复制生成的密码和注册令牌并将它们保存在安全位置。 这些值仅在你首次启动 Elasticsearch 时显示。
注意:如果需要重置 elastic 用户或其他内置用户的密码,请运行 elasticsearch-reset-password 工具。 该工具位于 Docker 容器的 Elasticsearch /bin 目录中。 例如:
docker exec -it es01 /usr/share/elasticsearch/bin/elasticsearch-reset-password
4)将 http_ca.crt 安全证书从 Docker 容器复制到本地计算机。
docker cp es01:/usr/share/elasticsearch/config/certs/http_ca.crt .
$ pwd
/Users/liuxg/tmp/certs
$ docker cp es01:/usr/share/elasticsearch/config/certs/http_ca.crt .
$ ls
http_ca.crt
5)打开一个新终端,并使用从 Docker 容器复制的 http_ca.crt 文件进行经过身份验证的调用,以验证你是否可以连接到 Elasticsearch 集群。 出现提示时输入弹性用户的密码。
curl --cacert http_ca.crt -u elastic https://localhost:9200
$ curl --cacert http_ca.crt -u elastic https://localhost:9200
Enter host password for user 'elastic':
{
"name" : "2ea501480d1a",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "xL5JbUBqTN6_-7dUYSSazw",
"version" : {
"number" : "8.8.0",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "c01029875a091076ed42cdb3a41c10b1a9a5a20f",
"build_date" : "2023-05-23T17:16:07.179039820Z",
"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"
}
我们从上面的 Elasticsearch 启动的窗口中拷贝过来 elastic 超级用户的密码。如果你能看到上面的输出,那么贡献你。你已经成功地在你的电脑上运行起来 Elasticsearch!
添加额外的节点
首次启动 Elasticsearch 时,安装过程默认配置单节点集群。 此过程还会生成注册令牌并将其打印到你的终端。 如果你希望节点加入现有集群,请使用生成的注册令牌启动新节点。
生成注册令牌:
注册令牌的有效期为 30 分钟。 如果你需要生成新的注册令牌,请在现有节点上运行 elasticsearch-create-enrollment-token 工具。 该工具位于 Docker 容器的 Elasticsearch bin 目录中。
例如,在现有的 es01 节点上运行以下命令,为新的 Elasticsearch 节点生成注册令牌:
docker exec -it es01 /usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token -s node
1)在启动第一个节点的终端中,复制生成的注册令牌以添加新的 Elasticsearch 节点。
2)在你的新节点上,启动 Elasticsearch 并包含生成的注册令牌。
docker run -e ENROLLMENT_TOKEN="<token>" -e ES_JAVA_OPTS="-Xms1g -Xmx1g" --name es02 --net elastic -it docker.elastic.co/elasticsearch/elasticsearch:8.8.0
我们在第一个节点的终端中可以看到如下的信息:
Elasticsearch 现在配置为加入现有集群。我们可以使用如下的命令来检查现有的 nodes:
curl --cacert http_ca.crt -u elastic https://localhost:9200/_cat/nodes
$ pwd
/Users/liuxg/tmp/certs
$ ls
http_ca.crt
$ curl --cacert http_ca.crt -u elastic https://localhost:9200/_cat/nodes
Enter host password for user 'elastic':
172.18.0.2 13 16 0 0.07 0.13 0.15 cdfhilmrstw * 8904985c21d9
172.18.0.3 48 16 0 0.07 0.13 0.15 cdfhilmrstw - f8a062a42e48
从上面的输出中,我们可以看到集群中有两个节点了。
设置 JVM 堆大小
如果你遇到在第二个节点启动时运行第一个节点的容器退出的问题,请显式设置 JVM 堆大小的值。 要手动配置堆大小,请在启动每个节点时包含 ES_JAVA_OPTS 变量并设置 -Xms 和 -Xmx 的值。 例如,以下命令启动节点 es02 并将最小和最大 JVM 堆大小设置为 1 GB:
docker run -e ES_JAVA_OPTS="-Xms1g -Xmx1g" -e ENROLLMENT_TOKEN="<token>" --name es02 -p 9201:9200 --net elastic -it docker.elastic.co/elasticsearch/elasticsearch:8.8.0
在上面,我们的示例中已经这么做了。在我做练习时,没有定义这个参数,结果就退出了。
下一步
你现在已经设置了测试 Elasticsearch 环境。 在开始认真开发或使用 Elasticsearch 投入生产之前,请查看下面在生产环境中在 Docker 中运行 Elasticsearch 时要应用的要求和建议。
安全证书和密钥
安装 Elasticsearch 时,会在 Elasticsearch 配置目录中生成以下证书和密钥,用于将 Kibana 实例连接到你的安全 Elasticsearch 集群并加密节点间通信。 此处列出这些文件以供参考。
http_ca.crt
用于为此 Elasticsearch 集群的 HTTP 层签署证书的 CA 证书。
http.p12
包含此节点的 HTTP 层的密钥和证书的密钥库。
tranport.p12
包含集群中所有节点的传输层密钥和证书的密钥库。
http.p12 和 transport.p12 是受密码保护的 PKCS#12 密钥库。 Elasticsearch 将这些密钥库的密码存储为安全设置。 要检索密码以便你可以检查或更改密钥库内容,请使用 bin/elasticsearch-keystore 工具。
使用以下命令检索 http.p12 的密码:
bin/elasticsearch-keystore show xpack.security.http.ssl.keystore.secure_password
使用以下命令检索 transport.p12 的密码:
bin/elasticsearch-keystore show xpack.security.transport.ssl.keystore.secure_password
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f8a062a42e48 docker.elastic.co/elasticsearch/elasticsearch:8.8.0 "/bin/tini -- /usr/l…" 50 minutes ago Up 50 minutes 9200/tcp, 9300/tcp es02
8904985c21d9 docker.elastic.co/elasticsearch/elasticsearch:8.8.0 "/bin/tini -- /usr/l…" 52 minutes ago Up 52 minutes 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp es01
$ docker exec -it es01 /bin/bash
elasticsearch@8904985c21d9:~$ ls
LICENSE.txt NOTICE.txt README.asciidoc bin config data jdk lib logs modules plugins
elasticsearch@8904985c21d9:~$ cd bin/
elasticsearch@8904985c21d9:~/bin$ cd ..
elasticsearch@8904985c21d9:~$ bin/elasticsearch-keystore show xpack.security.http.ssl.keystore.secure_password
pKee5zKnR6mq32YCFGsBew
elasticsearch@8904985c21d9:~$ bin/elasticsearch-keystore show xpack.security.transport.ssl.keystore.secure_password
Ca7GGTq9Qo2PgGWgPbc6Dg
elasticsearch@8904985c21d9:~$
使用 Docker Compose 启动多节点集群
要在启用安全性的 Docker 中启动和运行多节点 Elasticsearch 集群和 Kibana,你可以使用 Docker Compose。
此配置提供了一种启动安全集群的简单方法,你可以在使用多台主机构建分布式部署之前将其用于开发。
先决条件
为你的操作系统安装适当的 Docker 应用程序。
如果你在 Linux 上运行,请安装 Docker Compose。
注意:确保至少为 Docker 分配了 4GB 内存。 在 Docker Desktop 中,你可以在首选项 (macOS) 或设置 (Windows) 的高级选项卡上配置资源使用。
准备环境
在新的空目录中创建以下配置文件。 这些文件也可以从 GitHub 上的 elasticsearch 存储库中获得。
.env
.env 文件设置运行 docker-compose.yml 配置文件时使用的环境变量。 确保使用 ELASTIC_PASSWORD 和 KIBANA_PASSWORD 变量为 elastic 和 kibana_system 用户指定强密码。 这些变量由 docker-compose.yml 文件引用。
重要:你的密码必须是字母数字,并且不能包含特殊字符,例如! 或者 @。 docker-compose.yml 文件中包含的 bash 脚本仅对字母数字字符起作用。
# Password for the 'elastic' user (at least 6 characters)
ELASTIC_PASSWORD=
# Password for the 'kibana_system' user (at least 6 characters)
KIBANA_PASSWORD=
# Version of Elastic products
STACK_VERSION=8.8.0
# Set the cluster name
CLUSTER_NAME=docker-cluster
# Set to 'basic' or 'trial' to automatically start the 30-day trial
LICENSE=basic
#LICENSE=trial
# Port to expose Elasticsearch HTTP API to the host
ES_PORT=9200
#ES_PORT=127.0.0.1:9200
# Port to expose Kibana to the host
KIBANA_PORT=5601
#KIBANA_PORT=80
# Increase or decrease based on the available host memory (in bytes)
MEM_LIMIT=1073741824
# Project namespace (defaults to the current folder name if not set)
#COMPOSE_PROJECT_NAME=myproject
docker-compose.yml
这个 docker-compose.yml 文件创建了一个启用身份验证和网络加密的三节点安全 Elasticsearch 集群,以及一个安全连接到它的 Kibana 实例。
暴露端口:此配置在所有网络接口上公开端口 9200。 由于 Docker 处理端口的方式,未绑定到 localhost 的端口使你的 Elasticsearch 集群可公开访问,可能会忽略任何防火墙设置。 如果你不想将端口 9200 暴露给外部主机,请将 .env 文件中的 ES_PORT 值设置为类似于 127.0.0.1:9200 的值。 Elasticsearch 将只能从主机本身访问。
version: "2.2"
services:
setup:
image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
volumes:
- certs:/usr/share/elasticsearch/config/certs
user: "0"
command: >
bash -c '
if [ x${ELASTIC_PASSWORD} == x ]; then
echo "Set the ELASTIC_PASSWORD environment variable in the .env file";
exit 1;
elif [ x${KIBANA_PASSWORD} == x ]; then
echo "Set the KIBANA_PASSWORD environment variable in the .env file";
exit 1;
fi;
if [ ! -f config/certs/ca.zip ]; then
echo "Creating CA";
bin/elasticsearch-certutil ca --silent --pem -out config/certs/ca.zip;
unzip config/certs/ca.zip -d config/certs;
fi;
if [ ! -f config/certs/certs.zip ]; then
echo "Creating certs";
echo -ne \
"instances:\n"\
" - name: es01\n"\
" dns:\n"\
" - es01\n"\
" - localhost\n"\
" ip:\n"\
" - 127.0.0.1\n"\
" - name: es02\n"\
" dns:\n"\
" - es02\n"\
" - localhost\n"\
" ip:\n"\
" - 127.0.0.1\n"\
" - name: es03\n"\
" dns:\n"\
" - es03\n"\
" - localhost\n"\
" ip:\n"\
" - 127.0.0.1\n"\
> config/certs/instances.yml;
bin/elasticsearch-certutil cert --silent --pem -out config/certs/certs.zip --in config/certs/instances.yml --ca-cert config/certs/ca/ca.crt --ca-key config/certs/ca/ca.key;
unzip config/certs/certs.zip -d config/certs;
fi;
echo "Setting file permissions"
chown -R root:root config/certs;
find . -type d -exec chmod 750 \{\} \;;
find . -type f -exec chmod 640 \{\} \;;
echo "Waiting for Elasticsearch availability";
until curl -s --cacert config/certs/ca/ca.crt https://es01:9200 | grep -q "missing authentication credentials"; do sleep 30; done;
echo "Setting kibana_system password";
until curl -s -X POST --cacert config/certs/ca/ca.crt -u "elastic:${ELASTIC_PASSWORD}" -H "Content-Type: application/json" https://es01:9200/_security/user/kibana_system/_password -d "{\"password\":\"${KIBANA_PASSWORD}\"}" | grep -q "^{}"; do sleep 10; done;
echo "All done!";
'
healthcheck:
test: ["CMD-SHELL", "[ -f config/certs/es01/es01.crt ]"]
interval: 1s
timeout: 5s
retries: 120
es01:
depends_on:
setup:
condition: service_healthy
image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
volumes:
- certs:/usr/share/elasticsearch/config/certs
- esdata01:/usr/share/elasticsearch/data
ports:
- ${ES_PORT}:9200
environment:
- node.name=es01
- cluster.name=${CLUSTER_NAME}
- cluster.initial_master_nodes=es01,es02,es03
- discovery.seed_hosts=es02,es03
- ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
- bootstrap.memory_lock=true
- xpack.security.enabled=true
- xpack.security.http.ssl.enabled=true
- xpack.security.http.ssl.key=certs/es01/es01.key
- xpack.security.http.ssl.certificate=certs/es01/es01.crt
- xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
- xpack.security.transport.ssl.enabled=true
- xpack.security.transport.ssl.key=certs/es01/es01.key
- xpack.security.transport.ssl.certificate=certs/es01/es01.crt
- xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt
- xpack.security.transport.ssl.verification_mode=certificate
- xpack.license.self_generated.type=${LICENSE}
mem_limit: ${MEM_LIMIT}
ulimits:
memlock:
soft: -1
hard: -1
healthcheck:
test:
[
"CMD-SHELL",
"curl -s --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",
]
interval: 10s
timeout: 10s
retries: 120
es02:
depends_on:
- es01
image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
volumes:
- certs:/usr/share/elasticsearch/config/certs
- esdata02:/usr/share/elasticsearch/data
environment:
- node.name=es02
- cluster.name=${CLUSTER_NAME}
- cluster.initial_master_nodes=es01,es02,es03
- discovery.seed_hosts=es01,es03
- bootstrap.memory_lock=true
- xpack.security.enabled=true
- xpack.security.http.ssl.enabled=true
- xpack.security.http.ssl.key=certs/es02/es02.key
- xpack.security.http.ssl.certificate=certs/es02/es02.crt
- xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
- xpack.security.transport.ssl.enabled=true
- xpack.security.transport.ssl.key=certs/es02/es02.key
- xpack.security.transport.ssl.certificate=certs/es02/es02.crt
- xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt
- xpack.security.transport.ssl.verification_mode=certificate
- xpack.license.self_generated.type=${LICENSE}
mem_limit: ${MEM_LIMIT}
ulimits:
memlock:
soft: -1
hard: -1
healthcheck:
test:
[
"CMD-SHELL",
"curl -s --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",
]
interval: 10s
timeout: 10s
retries: 120
es03:
depends_on:
- es02
image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
volumes:
- certs:/usr/share/elasticsearch/config/certs
- esdata03:/usr/share/elasticsearch/data
environment:
- node.name=es03
- cluster.name=${CLUSTER_NAME}
- cluster.initial_master_nodes=es01,es02,es03
- discovery.seed_hosts=es01,es02
- bootstrap.memory_lock=true
- xpack.security.enabled=true
- xpack.security.http.ssl.enabled=true
- xpack.security.http.ssl.key=certs/es03/es03.key
- xpack.security.http.ssl.certificate=certs/es03/es03.crt
- xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
- xpack.security.transport.ssl.enabled=true
- xpack.security.transport.ssl.key=certs/es03/es03.key
- xpack.security.transport.ssl.certificate=certs/es03/es03.crt
- xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt
- xpack.security.transport.ssl.verification_mode=certificate
- xpack.license.self_generated.type=${LICENSE}
mem_limit: ${MEM_LIMIT}
ulimits:
memlock:
soft: -1
hard: -1
healthcheck:
test:
[
"CMD-SHELL",
"curl -s --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",
]
interval: 10s
timeout: 10s
retries: 120
kibana:
depends_on:
es01:
condition: service_healthy
es02:
condition: service_healthy
es03:
condition: service_healthy
image: docker.elastic.co/kibana/kibana:${STACK_VERSION}
volumes:
- certs:/usr/share/kibana/config/certs
- kibanadata:/usr/share/kibana/data
ports:
- ${KIBANA_PORT}:5601
environment:
- SERVERNAME=kibana
- ELASTICSEARCH_HOSTS=https://es01:9200
- ELASTICSEARCH_USERNAME=kibana_system
- ELASTICSEARCH_PASSWORD=${KIBANA_PASSWORD}
- ELASTICSEARCH_SSL_CERTIFICATEAUTHORITIES=config/certs/ca/ca.crt
mem_limit: ${MEM_LIMIT}
healthcheck:
test:
[
"CMD-SHELL",
"curl -s -I http://localhost:5601 | grep -q 'HTTP/1.1 302 Found'",
]
interval: 10s
timeout: 10s
retries: 120
volumes:
certs:
driver: local
esdata01:
driver: local
esdata02:
driver: local
esdata03:
driver: local
kibanadata:
driver: local
在启用和配置安全性的情况下启动集群
1)修改 .env 文件并为 ELASTIC_PASSWORD 和 KIBANA_PASSWORD 变量输入强密码值。
注意:你必须使用 ELASTIC_PASSWORD 值才能与集群进一步交互。 KIBANA_PASSWORD 值仅在配置 Kibana 时在内部使用。
2)创建并启动三节点 Elasticsearch 集群和 Kibana 实例:
docker-compose up -d
3)部署开始后,打开浏览器并导航至 http://localhost:5601 以访问 Kibana,你可以在其中加载示例数据并与集群交互。
停止并删除部署
要停止集群,请运行 docker-compose down。 当你使用 docker-compose up 重新启动集群时,Docker 卷中的数据将被保留和加载。
docker-compose down
要在停止集群时删除网络、容器和卷,请指定 -v 选项:
docker-compose down -v
下一步
你现在已经设置了测试 Elasticsearch 环境。 在开始认真开发或使用 Elasticsearch 投入生产之前,请查看下面在生产环境中在 Docker 中运行 Elasticsearch 时要应用的要求和建议。
在生产环境中使用 Docker 镜像
在生产中的 Docker 中运行 Elasticsearch 时,以下要求和建议适用。
将 vm.max_map_count 设置为至少 262144
vm.max_map_count 内核设置必须至少设置为 262144 才能用于生产。
如何设置 vm.max_map_count 取决于你的平台。
Linux
要查看 vm.max_map_count 设置的当前值,请运行:
grep vm.max_map_count /etc/sysctl.conf
vm.max_map_count=262144
要在实时系统上应用设置,请运行:
sysctl -w vm.max_map_count=262144
要永久更改 vm.max_map_count 设置的值,请更新 /etc/sysctl.conf 中的值。
适用于 Mac 的 macOS 和 Docker
vm.max_map_count 设置必须在 xhyve 虚拟机中设置:
1)从命令行运行:
screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty
2)按 enter 并使用 sysctl 配置 vm.max_map_count:
sysctl -w vm.max_map_count=262144
3)要退出屏幕会话,请键入 Ctrl a d。
Windows 和 macOS 与 Docker 桌面
vm.max_map_count 设置必须通过 docker-machine 设置:
docker-machine ssh
sudo sysctl -w vm.max_map_count=262144
带有 Docker Desktop WSL 2 后端的 Windows
在 Elasticsearch 容器正确启动之前,必须在 “docker-desktop” WSL 实例中设置 vm.max_map_count 设置。 有多种方法可以执行此操作,具体取决于你的 Windows 版本和 WSL 版本。
如果你在 Windows 10 版本 22H2 之前,或者如果你在 Windows 10 版本 22H2 使用内置版本的 WSL,则必须在每次启动 Elasticsearch 容器之前重新启动 Docker 时手动设置它,或者(如果你这样做 不希望在每次重新启动时都这样做)你必须全局设置每个 WSL2 实例以更改 vm.max_map_count。 这是因为这些版本的 WSL 无法正确处理 /etc/sysctl.conf 文件。
要在每次重新启动时手动设置它,你必须在每次重新启动 Docker 时在命令提示符或 PowerShell 窗口中运行以下命令:
wsl -d docker-desktop -u root
sysctl -w vm.max_map_count=262144
如果你使用的是这些版本的 WSL,并且不想在每次重新启动 Docker 时都运行这些命令,则可以通过修改 %USERPROFILE%\.wslconfig 来全局更改具有此设置的每个 WSL 发行版,如下所示:
[wsl2]
kernelCommandLine = "sysctl.vm.max_map_count=262144"
这将导致所有 WSL2 VM 在启动时分配该设置。
如果你使用的是 Windows 11 或 Windows 10 版本 22H2 并且安装了 Microsoft Store 版本的 WSL,则可以修改 “docker-desktop” WSL 分发版中的 /etc/sysctl.conf,可能使用如下命令:
wsl -d docker-desktop -u root
vi /etc/sysctl.conf
并附加一行内容如下:
vm.max_map_count = 262144
配置文件必须是 elasticsearch 用户可读的
默认情况下,Elasticsearch 使用 uid:gid 1000:0 作为用户 elasticsearch 在容器内运行。
重要:一个例外是 Openshift,它使用任意分配的用户 ID 运行容器。 Openshift 提供 gid 设置为 0 的持久卷,无需任何调整即可工作。
如果你正在绑定挂载本地目录或文件,则它必须可被 elasticsearch 用户读取。 此外,此用户必须具有对配置、数据和日志目录的写入权限(Elasticsearch 需要对配置目录的写入权限,以便它可以生成密钥库)。 一个好的策略是授予组访问本地目录的 gid 0。
例如,通过绑定挂载准备一个用于存储数据的本地目录:
mkdir esdatadir
chmod g+rwx esdatadir
chgrp 0 esdatadir
你还可以使用自定义 UID 和 GID 运行 Elasticsearch 容器。 你必须确保文件权限不会阻止 Elasticsearch 执行。 你可以使用以下两个选项之一:
- 绑定挂载 config、data 和 logs 目录。 如果你打算安装插件并且不想创建自定义 Docker 映像,则还必须绑定挂载插件目录。
- 将 --group-add 0 命令行选项传递给 docker run。 这可确保运行 Elasticsearch 的用户也是容器内根 (GID 0) 组的成员。
增加 nofile 和 nproc 的 ulimits
增加的 nofile 和 nproc 的 ulimits 必须可用于 Elasticsearch 容器。 验证 Docker 守护进程的 init system 将它们设置为可接受的值。
要检查 ulimits 的 Docker 守护程序默认值,请运行:
docker run --rm docker.elastic.co/elasticsearch/elasticsearch:{version} /bin/bash -c 'ulimit -Hn && ulimit -Sn && ulimit -Hu && ulimit -Su'
如果需要,在守护进程中调整它们或按容器覆盖它们。 例如,使用 docker run 时,设置:
--ulimit nofile=65535:65535
禁用 swapping
为了性能和节点稳定性,需要禁用 swapping。 有关执行此操作的方法的信息,请参阅 disable swapping。
如果你选择 bootstrap.memory_lock: true 方法,你还需要在 Docker 守护进程中定义 memlock: true ulimit,或者如上面展示的示例 compose 文件中所示为容器明确设置。 使用 docker run 时,你可以指定:
-e "bootstrap.memory_lock=true" --ulimit memlock=-1:-1
随机化已发布的端口
该镜像公开了 TCP 端口 9200 和 9300。对于生产集群,建议使用 --publish-all 随机化已发布的端口,除非你为每个主机固定一个容器。
手动设置堆大小
默认情况下,Elasticsearch 根据节点的角色和节点容器可用的总内存自动调整 JVM 堆的大小。 对于大多数生产环境,我们建议使用此默认大小。 如果需要,你可以通过手动设置 JVM 堆大小来覆盖默认大小。
要在生产环境中手动设置堆大小,请在 /usr/share/elasticsearch/config/jvm.options.d 下绑定一个 JVM 选项文件,其中包含你所需的堆大小设置。
对于测试,你还可以使用 ES_JAVA_OPTS 环境变量手动设置堆大小。 例如,要使用 16GB,请指定 -e
ES_JAVA_OPTS="-Xms16g -Xmx16g" 与 docker 运行。 ES_JAVA_OPTS 变量覆盖所有其他 JVM 选项。 我们不建议在生产中使用 ES_JAVA_OPTS。 上面的 docker-compose.yml 文件将堆大小设置为 512MB。
将部署固定到特定映像版本
将你的部署固定到特定版本的 Elasticsearch Docker 映像。 例如 docker.elastic.co/elasticsearch/elasticsearch:8.8.0。
始终绑定数据卷
出于以下原因,你应该使用绑定在 /usr/share/elasticsearch/data 上的卷:
- 如果容器被杀死,你的 Elasticsearch 节点的数据不会丢失
- Elasticsearch 对 I/O 敏感,而 Docker 存储驱动程序不适合快速 I/O
- 它允许使用高级 Docker 卷插件
避免使用 loop-lvm 模式
如果你正在使用 devicemapper 存储驱动程序,请不要使用默认的 loop-lvm 模式。 配置 docker-engine 以使用 direct-lvm。
集中你的日志
考虑使用不同的日志记录驱动程序来集中你的日志。 另请注意,默认的 json 文件日志记录驱动程序并不非常适合生产使用。
使用 Docker 配置 Elasticsearch
当你在 Docker 中运行时,Elasticsearch 配置文件从 /usr/share/elasticsearch/config/ 加载。
要使用自定义配置文件,你可以将文件绑定安装在镜像中的配置文件之上。
你可以使用 Docker 环境变量设置单独的 Elasticsearch 配置参数。 上面示例组合文件和单节点示例使用此方法。 你可以直接使用设置名称作为环境变量名称。 如果你不能这样做,例如因为你的编排平台禁止在环境变量名称中使用句点,那么你可以通过如下转换设置名称来使用替代样式。
- 将设置名称更改为大写
- 前缀为 ES_SETTING_
- 通过复制转义任何下划线 (_)
- 将所有句点 (.) 转换为下划线 (_)
例如,-e bootstrap.memory_lock=true 变为 -e ES_SETTING_BOOTSTRAP_MEMORY__LOCK=true。
你可以使用文件的内容来设置 ELASTIC_PASSWORD 或 KEYSTORE_PASSWORD 环境变量的值,方法是在环境变量名称后加上 _FILE。 这对于将密码(例如密码)传递给 Elasticsearch 而无需直接指定它们很有用。
例如,要从文件设置 Elasticsearch 引导程序密码,你可以绑定挂载文件并将 ELASTIC_PASSWORD_FILE 环境变量设置为挂载位置。 如果将密码文件挂载到 /run/secrets/bootstrapPassword.txt,请指定:
-e ELASTIC_PASSWORD_FILE=/run/secrets/bootstrapPassword.txt
你可以覆盖图像的默认命令,以将 Elasticsearch 配置参数作为命令行选项传递。 例如:
docker run <various parameters> bin/elasticsearch -Ecluster.name=mynewclustername
虽然绑定安装配置文件通常是生产中的首选方法,但你也可以创建包含你的配置的自定义 Docker 映像。
挂载 Elasticsearch 配置文件
创建自定义配置文件并将它们绑定挂载到 Docker 映像中的相应文件上。 例如,要使用 docker run 绑定挂载 custom_elasticsearch.yml,请指定:
-v full_path_to/custom_elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
如果绑定挂载自定义 elasticsearch.yml 文件,请确保它包含 network.host: 0.0.0.0 设置。 此设置可确保节点可访问 HTTP 和传输流量,前提是其端口已公开。 Docker 镜像的内置 elasticsearch.yml 文件默认包含此设置。
重要:容器使用 uid:gid 1000:0 作为用户 elasticsearch 运行 Elasticsearch。 绑定挂载的主机目录和文件必须可以被该用户访问,数据和日志目录必须可以被该用户写入。
创建加密的 Elasticsearch 密钥库
默认情况下,Elasticsearch 会自动生成用于安全设置的密钥库文件。 此文件经过混淆但未加密。
要使用密码加密你的安全设置并让它们在容器外保留,请使用 docker run 命令手动创建密钥库。 命令必须:
- 绑定挂载 config 目录。 该命令将在此目录中创建一个 elasticsearch.keystore 文件。 为避免错误,请勿直接绑定挂载 elasticsearch.keystore 文件。
- 使用带有 create -p 选项的 elasticsearch-keystore 工具。 系统将提示你输入密钥库的密码。
例如:
docker run -it --rm \
-v full_path_to/config:/usr/share/elasticsearch/config \
docker.elastic.co/elasticsearch/elasticsearch:8.8.0 \
bin/elasticsearch-keystore create -p
你还可以使用 docker run 命令添加或更新密钥库中的安全设置。 系统将提示你输入设置值。 如果密钥库已加密,系统还会提示你输入密钥库密码。
docker run -it --rm \
-v full_path_to/config:/usr/share/elasticsearch/config \
docker.elastic.co/elasticsearch/elasticsearch:8.8.0 \
bin/elasticsearch-keystore \
add my.secure.setting \
my.other.secure.setting
如果你已经创建了密钥库并且不需要更新它,则可以直接绑定挂载 elasticsearch.keystore 文件。你可以使用 KEYSTORE_PASSWORD 环境变量在启动时向容器提供密钥库密码。 例如,docker run 命令可能有以下选项:
-v full_path_to/config/elasticsearch.keystore:/usr/share/elasticsearch/config/elasticsearch.keystore
-e KEYSTORE_PASSWORD=mypassword
使用自定义 Docker 镜像
在某些环境中,准备包含你的配置的自定义映像可能更有意义。 实现此目的的 Dockerfile 可能非常简单:
FROM docker.elastic.co/elasticsearch/elasticsearch:8.8.0
COPY --chown=elasticsearch:elasticsearch elasticsearch.yml /usr/share/elasticsearch/config/
然后你可以构建并运行镜像:
docker build --tag=elasticsearch-custom .
docker run -ti -v /usr/share/elasticsearch/data elasticsearch-custom
一些插件需要额外的安全权限。 你必须通过以下方式明确接受它们:
- 在运行 Docker 映像时附加 tty,并在出现提示时允许权限。
- 通过将 --batch 标志添加到插件安装命令来检查安全权限并接受它们(如果适用)。
有关更多信息,请参阅插件管理。
排查 Elasticsearch 的 Docker 错误
以下是使用 Docker 运行 Elasticsearch 时解决常见错误的方法。
elasticsearch.keystore 是一个目录
Exception in thread "main" org.elasticsearch.bootstrap.BootstrapException: java.io.IOException: Is a directory: SimpleFSIndexInput(path="/usr/share/elasticsearch/config/elasticsearch.keystore") Likely root cause: java.io.IOException: Is a directory
与密钥库相关的 docker run 命令试图直接绑定挂载不存在的 elasticsearch.keystore 文件。 如果你使用 -v 或 --volume 标志挂载一个不存在的文件,Docker 会创建一个同名目录。
要解决此错误:
- 删除 config 目录下的 elasticsearch.keystore 目录。
- 更新 -v 或 --volume 标志以指向配置目录路径而不是密钥库文件的路径。 有关示例,请参阅创建加密的 Elasticsearch 密钥库。
- 重试该命令。
elasticsearch.keystore: Device or resource busy
Exception in thread "main" java.nio.file.FileSystemException: /usr/share/elasticsearch/config/elasticsearch.keystore.tmp -> /usr/share/elasticsearch/config/elasticsearch.keystore: Device or resource busy
docker run 命令尝试在直接绑定挂载 elasticsearch.keystore 文件时更新密钥库。 要更新密钥库,容器需要访问配置目录中的其他文件,例如 keystore.tmp。
要解决此错误:
- 更新 -v 或 --volume 标志以指向配置目录路径而不是密钥库文件的路径。 有关示例,请参阅创建加密的 Elasticsearch 密钥库。
- 重试该命令。