Skip to content

Commit ac36aa7

Browse files
authored
Resolve Cluster API (#102726)
To improve cross-cluster search user experience, Kibana needs an endpoint that is accessible by arbitrary Kibana dashboard search users and provides: 1. a listing of clusters in scope for a CCS query (based on the index expression and whether there are any indices on each cluster that the Kibana user has access to query). 2. whether that cluster is currently connected to the querying cluster (will it come back as skipped or failed in a CCS search) 3. showing the skip_unavailable setting for those clusters (so you can know whether it will return skipped or failed in a CCS search) 4. the ES version of the cluster Since no single Elasticsearch endpoint provides all of these features, this PR creates a new endpoint `_resolve/cluster` that works along side the existing `_resolve/index` endpoint (and leverages some of its features). Example usage against a cluster with 2 remote clusters configured: GET /_resolve/cluster/*,remote*:bl* Response: { "(local)": { "connected": true, "skip_unavailable": false, "matching_indices": true, "version": { "number": "8.12.0-SNAPSHOT", "build_flavor": "default", "minimum_wire_compatibility_version": "7.17.0", "minimum_index_compatibility_version": "7.0.0" } }, "remote2": { "connected": true, "skip_unavailable": true, "matching_indices": true, "version": { "number": "8.12.0-SNAPSHOT", "build_flavor": "default", "minimum_wire_compatibility_version": "7.17.0", "minimum_index_compatibility_version": "7.0.0" } }, "remote1": { "connected": true, "skip_unavailable": false, "matching_indices": false, "version": { "number": "8.12.0-SNAPSHOT", "build_flavor": "default", "minimum_wire_compatibility_version": "7.17.0", "minimum_index_compatibility_version": "7.0.0" } } } Almost all errors show up as "error" entries in the response. Only the local SecurityException returns a 403 since that happens before the ResolveCluster Transport code kicks in.
1 parent fca3fc8 commit ac36aa7

File tree

25 files changed

+3256
-7
lines changed

25 files changed

+3256
-7
lines changed

docs/changelog/102726.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 102726
2+
summary: Resolve Cluster API
3+
area: Search
4+
type: enhancement
5+
issues: []

docs/reference/indices.asciidoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ index settings, aliases, mappings, and index templates.
2020
* <<indices-rollover-index>>
2121
* <<unfreeze-index-api>>
2222
* <<indices-resolve-index-api>>
23+
* <<indices-resolve-cluster-api>>
2324
* <<indices-downsample-data-stream>>
2425

2526
[discrete]
@@ -130,6 +131,7 @@ include::indices/dangling-indices-list.asciidoc[]
130131
include::indices/open-close.asciidoc[]
131132
include::indices/refresh.asciidoc[]
132133
include::indices/resolve.asciidoc[]
134+
include::indices/resolve-cluster.asciidoc[]
133135
include::indices/rollover-index.asciidoc[]
134136
include::indices/shrink-index.asciidoc[]
135137
include::indices/simulate-index.asciidoc[]
Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
[[indices-resolve-cluster-api]]
2+
=== Resolve cluster API
3+
++++
4+
<titleabbrev>Resolve cluster</titleabbrev>
5+
++++
6+
7+
Resolves the specified index expressions to return information about
8+
each cluster, including the local cluster, if included.
9+
10+
This endpoint is useful before doing a <<modules-cross-cluster-search,{ccs}>> in
11+
order to determine which remote clusters should be included in a search.
12+
13+
You use the same index expression with this endpoint as you would for cross-cluster
14+
search. Index and <<exclude-problematic-clusters,cluster exclusions>> are also supported
15+
with this endpoint.
16+
17+
For each cluster in the index expression, information is returned about:
18+
19+
1. whether the querying ("local") cluster is currently connected to each remote cluster
20+
in the index expression scope
21+
2. whether each remote cluster is configured with `skip_unavailable` as `true` or `false`
22+
3. whether there are any indices, aliases or data streams on that cluster that match
23+
the index expression
24+
4. whether the search is likely to have errors returned when you do the {ccs} (including any
25+
authorization errors if your user does not have permission to query the index)
26+
5. cluster version information, including the Elasticsearch server version
27+
28+
////
29+
[source,console]
30+
--------------------------------
31+
PUT _cluster/settings
32+
{
33+
"persistent": {
34+
"cluster": {
35+
"remote": {
36+
"cluster_one": {
37+
"seeds": [
38+
"35.238.149.1:9300"
39+
],
40+
"skip_unavailable": true
41+
},
42+
"cluster_two": {
43+
"seeds": [
44+
"35.238.149.2:9300"
45+
],
46+
"skip_unavailable": false
47+
}
48+
}
49+
}
50+
}
51+
}
52+
--------------------------------
53+
// TEST[setup:host]
54+
// TEST[s/35.238.149.\d+:930\d+/\${transport_host}/]
55+
////
56+
57+
[source,console]
58+
----
59+
GET /_resolve/cluster/my-index-*,cluster*:my-index-*
60+
----
61+
// TEST[continued]
62+
63+
This will return information about the local cluster and all remotely configured
64+
clusters that start with the alias `cluster*`. Each cluster will return information
65+
about whether it has any indices, aliases or data streams that match `my-index-*`.
66+
67+
[[resolve-cluster-api-request]]
68+
==== {api-request-title}
69+
70+
`GET /_resolve/cluster/<index_expression>`
71+
72+
[[resolve-cluster-api-prereqs]]
73+
==== {api-prereq-title}
74+
75+
* If the {es} {security-features} are enabled, you must have the
76+
`view_index_metadata`, `read`, or `manage` <<privileges-list-indices,index
77+
privilege>> for the target data stream, index, or alias.
78+
79+
[[resolve-cluster-api-path-params]]
80+
==== {api-path-parms-title}
81+
82+
`<index_expression>`::
83+
+
84+
--
85+
(Required, string) Comma-separated name(s) or index pattern(s) of the
86+
indices, aliases, and data streams to resolve, using <<api-multi-index>>.
87+
Resources on <<remote-clusters,remote clusters>> can be specified using the
88+
`<cluster>:<name>` syntax.
89+
--
90+
91+
[[resolve-cluster-api-query-params]]
92+
==== {api-query-parms-title}
93+
94+
include::{es-repo-dir}/rest-api/common-parms.asciidoc[tag=expand-wildcards]
95+
+
96+
Defaults to `open`.
97+
98+
include::{es-repo-dir}/rest-api/common-parms.asciidoc[tag=index-ignore-unavailable]
99+
+
100+
Defaults to `false`.
101+
102+
include::{es-repo-dir}/rest-api/common-parms.asciidoc[tag=allow-no-indices]
103+
+
104+
Defaults to `true`.
105+
106+
`ignore_throttled`::
107+
(Optional, Boolean) If `true`, concrete, expanded or aliased indices are
108+
ignored when frozen. Defaults to `false`.
109+
+
110+
deprecated:[7.16.0]
111+
112+
113+
[discrete]
114+
[[usecases-for-resolve-cluster]]
115+
=== Examples of why this endpoint is useful before doing a {ccs}.
116+
117+
You may want to exclude a cluster or index from a search when:
118+
119+
1. A remote cluster is not currently connected and is configured with `skip_unavailable`=`false`.
120+
Executing a {ccs} under those conditions will cause
121+
<<cross-cluster-search-failures,the entire search to fail>>.
122+
123+
2. A cluster has no matching indices, aliases or data streams for the index expression
124+
(or your user does not have permissions to search them). For example, suppose your
125+
index expression is `logs*,remote1:logs*` and the `remote1` cluster has no indices, aliases or data
126+
streams that match `logs*`. In that case, that cluster will return no results from that cluster if
127+
you include it in a {ccs}.
128+
129+
3. The index expression (combined with any query parameters you specify) will likely cause an exception
130+
to be thrown when you do the search. In these cases, the "error" field in the `_resolve/cluster` response
131+
will be present. (This is also where security/permission errors will be shown.)
132+
133+
4. A remote cluster is an older version that does not support the feature you want to
134+
use in your search.
135+
136+
137+
[[resolve-cluster-api-example]]
138+
==== {api-examples-title}
139+
140+
[source,console]
141+
----
142+
GET /_resolve/cluster/my-index*,clust*:my-index*
143+
----
144+
// TEST[continued]
145+
// TEST[setup:my_index]
146+
147+
The API returns the following response:
148+
149+
[source,console-result]
150+
----
151+
{
152+
"(local)": { <1>
153+
"connected": true,
154+
"skip_unavailable": false,
155+
"matching_indices": true,
156+
"version": {
157+
"number": "8.13.0",
158+
"build_flavor": "default",
159+
"minimum_wire_compatibility_version": "7.17.0",
160+
"minimum_index_compatibility_version": "7.0.0"
161+
}
162+
},
163+
"cluster_one": {
164+
"connected": true, <2>
165+
"skip_unavailable": true, <3>
166+
"matching_indices": true, <4>
167+
"version": {
168+
"number": "8.13.0", <5>
169+
"build_flavor": "default",
170+
"minimum_wire_compatibility_version": "7.17.0",
171+
"minimum_index_compatibility_version": "7.0.0"
172+
}
173+
},
174+
"cluster_two": {
175+
"connected": true,
176+
"skip_unavailable": false,
177+
"matching_indices": true,
178+
"version": {
179+
"number": "8.13.0",
180+
"build_flavor": "default",
181+
"minimum_wire_compatibility_version": "7.17.0",
182+
"minimum_index_compatibility_version": "7.0.0"
183+
}
184+
}
185+
}
186+
----
187+
// TESTRESPONSE[s/"number": "8.13.0"/"number": "$body.$_path"/]
188+
// TESTRESPONSE[s/"minimum_wire_compatibility_version": "7.17.0"/"minimum_wire_compatibility_version": "$body.$_path"/]
189+
// TESTRESPONSE[s/"minimum_index_compatibility_version": "7.0.0"/"minimum_index_compatibility_version": "$body.$_path"/]
190+
191+
<1> Each cluster has its own response section. The cluster you sent the request to is labelled as "(local)".
192+
<2> The querying cluster attempts to make a request to each remote cluster. If successful, `connected`=`true`.
193+
<3> The `skip_unavailable` setting for each remote cluster, as configured on the local cluster.
194+
<4> Indicates whether any index, alias or data stream matches the index expression specified for that cluster.
195+
<5> The Elasticsearch server version.
196+
197+
198+
[discrete]
199+
[[resolve-cluster-api-error-example]]
200+
==== An example showing potential problems with your search set up
201+
202+
The following request shows examples of several reasons why you might want
203+
to change your query to avoid unsuccessful searches.
204+
205+
[source,console]
206+
--------------------------------------------------
207+
GET /_resolve/cluster/not-present,clust*:my-index*,oldcluster:*?ignore_unavailable=false
208+
--------------------------------------------------
209+
// TEST[continued]
210+
// TEST[s/,oldcluster:*//]
211+
212+
[source,console-result]
213+
--------------------------------------------------
214+
{
215+
"(local)": {
216+
"connected": true,
217+
"skip_unavailable": false,
218+
"error": "no such index [not_present]" <1>
219+
},
220+
"cluster_one": {
221+
"connected": true,
222+
"skip_unavailable": true,
223+
"matching_indices": false, <2>
224+
"version": {
225+
"number": "8.13.0",
226+
"build_flavor": "default",
227+
"minimum_wire_compatibility_version": "7.17.0",
228+
"minimum_index_compatibility_version": "7.0.0"
229+
}
230+
},
231+
"cluster_two": {
232+
"connected": false, <3>
233+
"skip_unavailable": false,
234+
"matching_indices": true,
235+
"version": {
236+
"number": "8.13.0",
237+
"build_flavor": "default",
238+
"minimum_wire_compatibility_version": "7.17.0",
239+
"minimum_index_compatibility_version": "7.0.0"
240+
}
241+
},
242+
"oldcluster": { <4>
243+
"connected": true,
244+
"skip_unavailable": false,
245+
"matching_indices": true
246+
}
247+
}
248+
--------------------------------------------------
249+
// TEST[skip: too many illustrative error variations to reproduce]
250+
251+
<1> The local cluster has no index called `not_present` and if you try a search against it
252+
using the specified `ignore_unavailable=false` param, you will get an "no such index" error.
253+
Other types of errors can show up here as well, such as security permission errors when your user does
254+
not have authorization to search the specified index.
255+
<2> The `cluster_one` remote cluster does not have any indices that match the pattern `my-index*`.
256+
That could be due to there being no indices present that match the pattern or that the index
257+
is closed. (You can check this by using the <<indices-resolve-index-api,resolve index>> API.)
258+
<3> The `cluster_two` remote cluster is not connected (the attempt to connect failed). Since this
259+
cluster is marked as `skip_unavailable=false`, you should probably exclude this cluster from the
260+
search by adding `-cluster_two:*` to the search index expression.
261+
<4> The `oldcluster` remote cluster shows that it has matching_indices, but no version information
262+
is included. That means that it is running a version older than when the `_resolve/cluster` API
263+
was added (8.13.0), so you may want to exclude it from your {ccs}. (Note: the endpoint was able to tell
264+
there were matching indices because it fell back to using the <<indices-resolve-index-api,resolve index>>
265+
API.)

0 commit comments

Comments
 (0)