[译]使用 Docker 高效管理 Elasticsearch 插件

原文地址:https://www.elastic.co/cn/blog/elasticsearch-docker-plugin-management

原文基于Elasticsearch 2.x,Shield、cloud-aws和bin/plugin都是旧版用法。文末7.13.4示例也是特定版本示例,不能直接套用于当前版本。

如果你正在用容器来运行elasticsearch,那么有一些事项需要注意。在管理有状态服务和守护进程时尤其如此——当将数据持久化在临时容器之外变得很重要时。

在容器中使用 Elasticsearch 插件就是一个例子:这既包括以可重复、可跟踪的方式安装插件,也包括管理插件的配置和数据。

在这篇文章中,我们将探讨一些在Docker和Elasticsearch中实现合理插件管理的选项。

注意:本指南中引用的是 Docker Hub 上的 Elasticsearch 镜像;该镜像的开发和维护与 Elastic, Inc. 无关。

Docker 持久性入门

与版本控制系统中的文件变更类似,修改运行中容器的文件系统会在容器的可写层中留下差异,不会修改原始镜像。停止、重启同一个容器时这些变化仍在,删除并重建容器时则会丢失。需要跨容器保留的数据应另行持久化。

尽管可以利用一些更复杂的存储方案来实现容器持久化,但绑定挂载(bind mount)是 Docker 中最直观的做法。例如,通过将-v /data:/usr/share/elasticsearch/data之类的选项传递给docker run命令,将 Elasticsearch 索引长期保存在/data中来实现的,该命令有效地将Elasticsearch数据存储在主机的(不是容器的)/data 目录。

如果更改是永久性的,也就是说,预计它们不会随着时间的推移而改变,那么把变更固化进 Dockerfile 可能更合理。这两种方法在不同情况下都有用。

管理基础插件

在以下示例中,我将“基础”插件称为不需要许可证或任何其他特殊组件的插件。 像cloud-aws这样简单的插件只需要在系统上放置一些文件就可以工作。

这种情况下,最简单的做法就是用 Dockerfile 扩展镜像来管理插件的安装。 例如:

1
2
3
FROM elasticsearch:2

RUN /usr/share/elasticsearch/bin/plugin install --batch cloud-aws

这个Dockerfile从Docker Hub的维护者提供的Elasticsearch镜像开始,并运行一个简单的插件安装命令。然后可以通过标签构建和引用此镜像:

1
$ docker build -t elasticsearch-aws .

在与 Dockerfile 相同的目录中执行构建,即可得到名为 elasticsearch-aws 的镜像;之后可以在 Docker 命令中引用它来启动新容器,其行为继承自原始镜像。

更复杂的插件

某些插件可能需要额外的文件(例如使用Shield时的证书)才能实现某些功能。上述构建自定义镜像的技术可以处理这些插件的安装,但管理配置是用其它方法处理更好。这有助于保持镜像的通用性以供部署重用,并对敏感信息(secrets)保持更严格的控制。

注意:一些商业插件需要license。在以下示例中,我们仅依赖默认存在的临时试用license。在生产环境中部署时,license 的管理通过 Elasticsearch REST API 进行,它将license信息存储在Elasticsearch的数据路径中。只要您的数据通过卷装载或其他方式适当地持久化,您的license信息就会保存在您的集群中。

示例:Shield

正如Shield安装文档中所述,安装license和shield插件是先决条件,我们可以使用之前的构建派生镜像的策略来实现:

1
2
3
4
FROM elasticsearch:2

RUN /usr/share/elasticsearch/bin/plugin install --batch license
RUN /usr/share/elasticsearch/bin/plugin install --batch shield

构建镜像

1
$ docker build -t elasticsearch-shield .

此时,如果我们将配置目录卷挂载到容器中,Shield 将获取我们的设置。 作为示例配置,请考虑以下目录结构:

1
2
3
4
5
6
7
8
9
10
11
$ tree config
config
├── elasticsearch.yml
├── logging.yml
├── scripts
└── shield
├── roles.yml
├── users
└── users_roles

2 directories, 4 files

logging.yml包含默认日志记录配置。 在elasticsearch.yml中,绑定到通配符 0.0.0.0 确保我们可以访问到容器:

1
2
$ cat elasticsearch.yml
network.host: 0.0.0.0

对于 Shield 配置,我们定义了一个单独的角色admin,以及一个名为“example”且密码为“password”的用户,并将其添加到 admin 角色(您显然需要比这更安全的配置!) :

1
2
3
4
5
6
7
8
9
10
$ cat shield/roles.yml
admin:
cluster: all
indices:
'*':
privileges: all
$ cat shield/users
example:$2a$10$ppZqjFEXgVE3yT/yQPsp4etGMdF4.RFCS9OOGwZGAp0l3lPh4/ALC
$ cat shield/users_roles
admin:example

注意:在此示例中,我们采用 esusers Shield 实用程序生成的密码哈希。

然后我们启动容器,为我们的配置指定挂载卷并公开REST端口:

1
$ docker run -d -p 9200:9200 -v "$PWD/config":/usr/share/elasticsearch/config elasticsearch-shield

Elasticsearch应拒绝未经身份验证的请求,同时放行前面创建的凭据。此时尚未启用TLS,应使用HTTP(原文此处用了HTTPS)。上面的-p 9200:9200通常绑定所有主机地址;仅限本机访问时应写成-p 127.0.0.1:9200:9200。

1
2
3
4
5
6
7
8
9
$ curl -I -XGET http://localhost:9200/_cluster/health
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="shield"
Content-Type: application/json; charset=UTF-8
Content-Length: 389
$ curl -I -XGET -u example:password http://localhost:9200/_cluster/health
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Content-Length: 389

添加 SSL/TLS

与挂载Shield配置文件一样,可以类似地管理SSL和TLS证书。可以遵循Shield SSL/TLS 指南中概述的大部分步骤,但请记住:CONFIG_DIR 是我们运行时挂载进容器的目录路径。 CA和证书管理的全部内容不在本教程的讨论范围内,因此我们在此假设您使用的是正确配置的Javakeystore文件,此处称为 node01.jks。

要暴露 keystore 文件,只需把它放进挂载到容器中的配置目录即可。

1
2
3
4
5
6
7
8
9
10
11
12
$ tree config
config
├── elasticsearch.yml
├── logging.yml
├── node01.jks
├── scripts
└── shield
├── roles.yml
├── users
└── users_roles
$ file config/node01.jks
config/node01.jks: Java KeyStore

按照Shield用户指南,我们启用传输加密:

1
2
3
4
5
6
$ cat config/elasticsearch.yml
network.host: 0.0.0.0
shield.ssl.keystore.path: /usr/share/elasticsearch/config/node01.jks
shield.ssl.keystore.password: password
shield.transport.ssl: true
shield.http.ssl: true

注意:在生产中,您可能希望更严格地控制您的keystore - 在本例中,我们只使用通用密码锁定keystore。

有了keystore文件并启用了SSL,我们可以启动节点并通过HTTPS发出请求(在这种情况下,将 -k 传递给 curl 以绕过自签名证书):

1
2
3
4
5
6
$ docker run -d -p 9200:9200 -v "$PWD/config":/usr/share/elasticsearch/config elasticsearch-shield
87e51d000cc11d63fbedb8a61d58ab1723f4a598b13614272a3b9d7f36a7b223
$ curl -I -XGET -k -u example:password https://localhost:9200/_cluster/health
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Content-Length: 0

当需要在集群中分发keystore文件时,它们可能会由配置管理模块或类似方法进行管理。

注意:在生成将在Docker内运行的节点的证书时,请密切注意将适当的选项传递到-ext选项。DNS名称和IP地址应正确反映节点将用于相互通信的主机名或IP地址。

总结

尽管我们在这篇博文中给出了几个具体示例,但每个部署都是不同的,您应该根据提高环境可靠性、可重复性和安全性的因素来定制您的设置。 一般来说,遵循这些准则应该有助于一个好的插件管理方案:

  • 在Docker镜像中定义最通用的步骤。通过尽早管理插件然后从这些镜像运行容器,您可以避免一遍又一遍地重新运行相同的安装命令。
  • 在挂载卷中维护持久数据。将您的索引数据和插件配置与容器镜像分开存储可确保您的数据尽在掌控,同时容器保持临时(用完即弃)的特性。
  • 测试!在部署任何生产基础设施之前,确保Elasticsearch在Docker中的行为符合预期,尤其是在网络通信(包括单播和IP地址绑定行为)、JVM资源分配和插件功能方面。

新版本示例

1
2
3
4
5
FROM elasticsearch:7.13.4

# RUN ./bin/elasticsearch-plugin install --batch https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.13.4/elasticsearch-analysis-ik-7.13.4.zip
ADD elasticsearch-analysis-ik-7.13.4.zip /usr/share/elasticsearch
RUN ./bin/elasticsearch-plugin install --batch file:///usr/share/elasticsearch/elasticsearch-analysis-ik-7.13.4.zip