跨集群查询

跨集群搜索(cross-cluster search)使你可以针对一个或多个远程集群运行单个搜索请求。 例如,你可以使用跨集群搜索来筛选和分析存储在不同数据中心的集群中的日志数据。

ES 跨集群搜索 Cross-cluster search (CCS)_elasticsearch

环境准备

角色

IP

系统

dev

172.16.122.244

CentOS 7.9

prod

172.16.122.245

CentOS 7.9

ES 软件下载地址 https://elasticsearch.cn/download,我使用的版本是 7.13。

wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.13.0-x86_64.rpm
wget https://artifacts.elastic.co/downloads/kibana/kibana-7.13.2-x86_64.rpm
软件安装配置
rpm -ivh elasticsearch-7.13.0-x86_64.rpm
rpm -ivh kibana-7.13.2-x86_64.rpm
ES 集群配置

dev 集群配置 /etc/elasticsearch/elasticsearch.yml

cluster.name: dev
node.name: dev-1
network.host: 0.0.0.0
discovery.type: single-node

prod 集群配置 /etc/elasticsearch/elasticsearch.yml

cluster.name: prod
node.name: prod-1
network.host: 0.0.0.0
discovery.type: single-node

kibana 配置添加如下 /etc/kibana/kibana.yml

server.host: "0.0.0.0"

启动集群

systemctl restart elasticsearch
systemctl restart kibana

ES 集群访问使用 IP:9200,Kibana 集群访问 IP:5601。

[root@iZ0xignxv65xzl2gq5x8t4Z ~]# curl localhost:9200
{
  "name" : "dev-1",
  "cluster_name" : "dev",
  "cluster_uuid" : "k45zaOJASSGHos3hnVFePw",
  "version" : {
    "number" : "7.13.0",
    "build_flavor" : "default",
    "build_type" : "rpm",
    "build_hash" : "5ca8591c6fcdb1260ce95b08a8e023559635c6f3",
    "build_date" : "2021-05-19T22:22:26.081971330Z",
    "build_snapshot" : false,
    "lucene_version" : "8.8.2",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

ES 跨集群搜索 Cross-cluster search (CCS)_elasticsearch_02

配置跨集群搜索

注册 remote cluster

以下 cluster update settings API请求添加了两个远程集群:dev 和 prod,可以在其中一个集群配置,每个集群都配置一下。

PUT _cluster/settings
{
  "persistent": {
    "cluster": {
      "remote": {
        "dev": {
          "seeds": [
            "172.16.122.244:9300"
          ],
          "transport.compress": true,
          "skip_unavailable": true
        },
        "prod": {
          "seeds": [
            "172.16.122.245:9300"
          ],
          "transport.compress": true,
          "skip_unavailable": true
        }
      }
    }
  }
}

Elasticsearch 中有两种重要的网络通信机制需要了解:

  • HTTP 9200:用于 HTTP 通信绑定的地址和端口,这是 Elasticsearch REST API 公开的方式
  • transport 9300:用于集群内节点之间的内部通信

在 Kibana 的 Dev Tools 里面执行上面的请求。

ES 跨集群搜索 Cross-cluster search (CCS)_搜索_03

我们看到右边有一个告警,提示集群没有进行任何安全认证,不安全,这个我们后面再进行处理,先看下下目前跨集群查询的情况。

我们接下来使用如下的命令来检查我们的连接状态:

GET _remote/info

我们可以看到如下的响应信息:

{
  "prod" : {
    "connected" : true,
    "mode" : "sniff",
    "seeds" : [
      "172.16.122.245:9300"
    ],
    "num_nodes_connected" : 1,
    "max_connections_per_cluster" : 3,
    "initial_connect_timeout" : "30s",
    "skip_unavailable" : true
  },
  "dev" : {
    "connected" : true,
    "mode" : "sniff",
    "seeds" : [
      "172.16.122.244:9300"
    ],
    "num_nodes_connected" : 1,
    "max_connections_per_cluster" : 3,
    "initial_connect_timeout" : "30s",
    "skip_unavailable" : true
  }
}

它表明我们的连接是成功的。

这个时候我们在 prod kibana 中创建如下的 users 索引:

POST _bulk
{"index":{"_index":"users","_id":1}}
{"user":"张三","message":"今儿天气不错啊,出去转转去","uid":2,"age":20,"city":"北京","province":"北京","country":"中国","address":"中国北京市海淀区","location":{"lat":"39.970718","lon":"116.325747"}, "DOB": "1999-04-01"}
{"index":{"_index":"users","_id":2}}
{"user":"老刘","message":"出发,下一站云南!","uid":3,"age":22,"city":"北京","province":"北京","country":"中国","address":"中国北京市东城区台基厂三条3号","location":{"lat":"39.904313","lon":"116.412754"}, "DOB": "1997-04-01"}
{"index":{"_index":"users","_id":3}}
{"user":"李四","message":"happy birthday!","uid":4,"age":25,"city":"北京","province":"北京","country":"中国","address":"中国北京市东城区","location":{"lat":"39.893801","lon":"116.408986"}, "DOB": "1994-04-01"}
{"index":{"_index":"users","_id":4}}
{"user":"老贾","message":"123,gogogo","uid":5,"age":30,"city":"北京","province":"北京","country":"中国","address":"中国北京市朝阳区建国门","location":{"lat":"39.718256","lon":"116.367910"}, "DOB": "1989-04-01"}
{"index":{"_index":"users","_id":5}}
{"user":"老王","message":"Happy BirthDay My Friend!","uid":6,"age":26,"city":"北京","province":"北京","country":"中国","address":"中国北京市朝阳区国贸","location":{"lat":"39.918256","lon":"116.467910"}, "DOB": "1993-04-01"}
{"index":{"_index":"users","_id":6}}
{"user":"老吴","message":"好友来了都今天我生日,好友来了,什么 birthday happy 就成!","uid":7,"age":28,"city":"上海","province":"上海","country":"中国","address":"中国上海市闵行区","location":{"lat":"31.175927","lon":"121.383328"}, "DOB": "1991-04-01"}

我们可以在 prod kibana 中通过如下的命令来检查 users 索引是否已经被成功创建:

GET _cat/indices
green  open .kibana_7.13.2_001              1jXL4B6hQzePkxZCFLj0Gw 1 0 27    9   2.1mb   2.1mb
green  open .apm-custom-link                HyHW7sA5RMWBSfXTAl51hQ 1 0  0    0    208b    208b
green  open .kibana-event-log-7.13.2-000001 nyUtNHamSqCppZkT9IvLLA 1 0  1    0   5.6kb   5.6kb
green  open .apm-agent-configuration        XMHcg6sFQfKcHZFr_o34Bw 1 0  0    0    208b    208b
green  open .kibana_task_manager_7.13.2_001 Qdlj4I-mRLqg_1_AobYEQA 1 0 10 2278 345.9kb 345.9kb
yellow open users                           kSt0onMUToKyawJ0S_y19A 1 1  6    0  12.2kb  12.2kb

在上面,我们可以看到我们已经成功地在 prod 上创建了 users 索引,那么我们怎么在 dev 上对这个进行搜索呢?

我们在 dev kibana 里,打入如下的命令:

GET prod:users/_search

ES 跨集群搜索 Cross-cluster search (CCS)_elasticsearch_04

从上面我们可以看出来,我们可以对位于 prod 的 users 索引进行搜索。

如果你配置了多个 remote 索引,你可以使用如下的方法来进行搜索:

GET *:users/_search

在这里,我们使用 *:users 来表示所有 remote cluster里含有 users 的集群。

配置索引模式

我们通过 API 的方式可以进行跨集群查询了,那我们可以在 dev kibana 上面配置索引模式进行查询。

ES 跨集群搜索 Cross-cluster search (CCS)_elastic_05

也可以输入 prod:users,配置特定 remote cluster 的索引。

ES 跨集群搜索 Cross-cluster search (CCS)_elasticsearch_06

至此跨集群查询配置完成了,也可以设置互相查询。

安全配置

ES 跨集群搜索 Cross-cluster search (CCS)_搜索_07

配置集群间安全认证9300

跨集群搜索启用跨多个集群的联合搜索。 将跨集群搜索与受保护集群一起使用时,所有集群都必须启用 Elasticsearch 安全功能。必须允许本地群集(用于启动跨群集搜索的群集)连接到远程群集,这意味着用于签署本地群集的 SSL/TLS 密钥的 CA 必须受到远程群集的信任。

用户身份验证是在本地群集上执行的,并且用户和用户的角色(role)将传递到远程群集。 远程集群会根据其本地角色定义检查用户的角色,以确定允许用户访问哪些索引。

在对安全的 Elasticsearch 集群使用跨集群复制或跨集群搜索之前,请完成以下配置任务:

  1. Enable the Elasticsearch security features on every node in each connected cluster by setting xpack.security.enabled to true in elasticsearch.yml. Refer to the Elasticsearch security settings.
  2. Configure Transport Layer Security (TLS) on every node to encrypt internode traffic and authenticate nodes in the local cluster with nodes in all remote clusters. Refer to set up basic security for the Elastic Stack for the required steps to configure security.

此过程使用相同的 CA 为所有节点生成证书。或者,您可以将来自本地集群的证书添加为每个远程集群中的可信 CA。您还必须将来自远程集群的证书添加为本地集群上的受信任 CA。使用同一个 CA 为所有节点生成证书可简化此任务。

首先创建 CA 证书。

/usr/share/elasticsearch/bin/elasticsearch-certutil ca

通过 CA 证书创建集群证书,我们这里所有节点统一使用一个证书,也可以给证书设置一个密码。

/usr/share/elasticsearch/bin/elasticsearch-certutil cert --ca elastic-stack-ca.p12

证书生成在了 elasticsearch 的家目录下面。

[root@iZ0xignxv65xzl2gq5x8t4Z ~]# ll /usr/share/elasticsearch/
total 620
drwxr-xr-x  2 root root   4096 Feb 22 15:56 bin
-rw-------  1 root root   3596 Feb 23 11:40 elastic-certificates.p12
-rw-------  1 root root   2672 Feb 23 11:37 elastic-stack-ca.p12
drwxr-xr-x  9 root root   4096 Feb 22 15:56 jdk
drwxr-xr-x  3 root root   4096 Feb 22 15:56 lib
-rw-r--r--  1 root root   3860 May 20  2021 LICENSE.txt
drwxr-xr-x 60 root root   4096 Feb 22 15:56 modules
-rw-rw-r--  1 root root 594096 May 20  2021 NOTICE.txt
drwxr-xr-x  2 root root   4096 May 20  2021 plugins
-rw-r--r--  1 root root   2710 May 20  2021 README.asciidoc

把证书elastic-certificates.p12 copy 到所有节点的 /etc/elasticsearch 目录下面,并添加读的权限。

chmod +r /usr/share/elasticsearch/elastic-certificates.p12
mv /usr/share/elasticsearch/elastic-certificates.p12 /etc/elasticsearch

然后再所有的节点的配置文件 elasticsearch.yml 增加如下配置:

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

因为证书设置了密码,我们需要添加证书密码的配置。

cd /usr/share/elasticsearch/
./bin/elasticsearch-keystore add xpack.security.transport.ssl.keystore.secure_password
./bin/elasticsearch-keystore add xpack.security.transport.ssl.truststore.secure_password

然后重启服务即可。

systemctl restart elasticsearch
配置集群安全认证9200

目前集群节点之间通信已经使用了 TLS 加密,但是 kibana 连接 ES 还是没有进行任何认证,我们这里配置用户密码的认证。

首先在 elasticsearch.yml 里面新增如下配置,开启用户认证:

xpack.security.enabled: true

然后重启集群。

为集群配置内置用户密码。

# 自动创建密码
./bin/elasticsearch-setup-passwords auto
# 手动指定密码
./bin/elasticsearch-setup-passwords interactive

当我们再次访问 9200 端口的时候,就已经报错了,需要认证,同样的 kibana 连接集群也需要认证。

修改 kibana 的配置文件,新增如下配置:

elasticsearch.username: "kibana_system"
elasticsearch.password: "123456"

重启 kibana,登录账户密码即可。

参考文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html#_prerequisites_10

https://www.elastic.co/guide/en/elasticsearch/reference/7.17/modules-cross-cluster-search.html#ccs-remote-cluster-setup

https://www.elastic.co/guide/en/kibana/8.5/settings.html#server-publicBaseUrl

https://www.elastic.co/guide/en/elasticsearch/reference/8.6/remote-clusters-security.html

ES 跨集群搜索 Cross-cluster search (CCS)_elasticsearch_08