Допустим есть некоторый инстанс ElasticSearch который хранит логи от приложения с микро сервисной архитектурой. Каждый день создается новый индекс с логами. Известно что на некоторую дату мониторинг обнаружил повышенную нагрузку на сервер. Задача состоит в том чтобы понять что пошло не так.
Для удобства можно экспортировать URL в переменную
export ES_URL=http://docker:19202
export ES_INDEX=production_log-2019.07.10
export ES_TYPE=logevent
#проверим доступность
curl -X GET $ES_URL
Если не известен точное имя индекса найдем его отобразив все
curl -X GET $ES_URL/_cat/indices?v
#если примерное имя известно
curl -X GET $ES_URL/_cat/indices/log-2019.07*?v
Индекс найден, чтобы понять какие поля есть в индексе получим маппинг этого индекса
curl -X GET $ES_URL/$ES_INDEX/_mappings?pretty
Из маппинга знаем что есть поле содержащее имя сборки fields.AssemblyName попытаемся ответить на вопрос на какой микросервис пришлась нагрузка. для этого агрегируем количество запросов по имени сборки. Так как в маппинге fields это nested документ то запрос
curl -XGET "$ES_URL/$ES_INDEX/_search?pretty" -H 'Content-Type: application/json; charset=UTF-8' -d'
{
"aggs": {
"microservice": {
"nested": {
"path": "fields"
},
"aggs": {
"microservicein": {
"terms": {
"field": "fields.AssemblyName"
}
}
}
}
}
}'
Ответ указывает на то что проблема в микросервисе аутентификации
...
"aggregations" : {
"microservice" : {
"doc_count" : 4062471,
"microservicein" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 27,
"buckets" : [
{
"key" : "AuthServer",
"doc_count" : 3948812
},
{
"key" : "SomeService",
"doc_count" : 58679
},
{
"key" : "UserManagement",
"doc_count" : 33077
},
...
Отфильтруем события этого сервиса и агрегируем их по типу
curl -XGET "$ES_URL/$ES_INDEX/_search?pretty" -H 'Content-Type: application/json; charset=UTF-8' -d'
{
"query": {
"nested": {
"path": "fields",
"query": {
"term": {
"fields.AssemblyName": "AuthServer"
}
}
}
},
"aggs": {
"microservice": {
"terms": {
"field": "level"
}
}
}
}'
Получим распределение
"aggregations" : {
"microservice" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "Debug",
"doc_count" : 3419486
},
{
"key" : "Information",
"doc_count" : 530368
},
{
"key" : "Warning",
"doc_count" : 744
}
]
}
}
Подозрительно много Warning отфильтруем их
curl -XGET "$ES_URL/$ES_INDEX/_search?pretty" -H 'Content-Type: application/json; charset=UTF-8' -d'
{
"query": {
"bool": {
"must": [
{
"term": {
"level": "Warning"
}
},
{
"nested": {
"path": "fields",
"query": {
"term": {
"fields.AssemblyName": "AuthServer"
}
}
}
}
]
}
}
}'
В результате получили Warning которые связаны с локализацией и не представляют интереса. Попытаемся зайти с другой стороны и агрегировать события по пользователям.
curl -XGET "$ES_URL/$ES_INDEX/_search?pretty" -H 'Content-Type: application/json; charset=UTF-8' -d'
{
"query": {
"nested": {
"path": "fields",
"query": {
"term": {
"fields.AssemblyName": "AuthServer"
}
}
}
},
"aggs": {
"microservice": {
"nested": {
"path": "fields"
},
"aggs": {
"microservicein": {
"terms": {
"field": "fields.CompanyId"
}
}
}
}
}
}'
в результате получим id проблемной компании
...
"aggregations" : {
"microservice" : {
"doc_count" : 3955148,
"microservicein" : {
"doc_count_error_upper_bound" : 158,
"sum_other_doc_count" : 29196,
"buckets" : [
{
"key" : "bf34ca49-946a-42c0-a5b1-637e59ef7034",
"doc_count" : 3540355
},
{
"key" : "d04bcd39-076f-4293-b2c7-637e59ef7034",
"doc_count" : 16380
},
{
"key" : "aa225eef-fb63-4f6e-bb02-637e59ef7034",
"doc_count" : 11193
},
...
теперь известна проблемная компания, добавим ее в фильтр
curl -XGET "$ES_URL/$ES_INDEX/_search?pretty" -H 'Content-Type: application/json; charset=UTF-8' -d'
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "fields",
"query": {
"bool": {
"must": [
{
"term": {
"fields.AssemblyName": "AuthServer"
}
},
{
"term": {
"fields.CompanyId": "bf34ca49-946a-42c0-a5b1-637e59ef7034"
}
}
]
}
}
}
}
]
}
}
}'
далее ручным просмотром найдем CorrelationContext и добавим в поиск
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "fields",
"query": {
"bool": {
"must": [
{
"term": {
"fields.AssemblyName": "AuthServer"
}
},
{
"term": {
"fields.CompanyId": "bf34ca49-946a-42c0-a5b1-637e59ef7034"
}
},
{
"term": {
"fields.CorrelationContext": "0HLNR8LB3PKEP:00000001"
}
}
]
}
}
}
}
]
}
}
}
Найдем первый запрос, в нем есть заголовки с информацией
{"Connection":["close"],"Content-Type":["application/x-www-form-urlencoded"],"Accept":["application/json, text/plain, */*"],"Accept-Encoding":["gzip, deflate, br"],"Accept-Language":["ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7"],"Authorization":["Bearer __token was here__"],"Host":["auth"],"Referer":["https://domain.com"],"User-Agent":["Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36"],"Origin":["https://domain.com"],"Content-Length":["164"],"X-real-base-url":["https://domain.com/auth"],"X-Real-IP":["_ip was here_"],"X-Forwarded-For":["_ip was here_"],"X-User-CompanyId":["bf34ca49-946a-42c0-a5b1-637e59ef7034"],"x-request-id":["0HLNR8LB3PKEP:00000001"]}
Расшифровав jwt токен с помощью https://jwt.io/
{
"nbf": 1562732742,
"exp": 1562733642,
"iss": "https://domain.com:443/auth",
"aud": "https://domain.com:443/auth/resources",
"client_id": "angular2client",
"sub": "33d87afa-8a2c-4a08-964a-7c5c08413e44",
"auth_time": 1562731599,
"idp": "local",
"email": "email was here",
"scope": [
"email",
"openid",
"offline_access"
],
"amr": [
"pwd"
]
}
Действия диагностики кластера
curl -XGET "$ES_URL/_cat/health?v"
curl -XGET "$ES_URL/_cat/nodes?v"
curl -XGET "$ES_URL/_cat/shards?v"
curl -XGET "$ES_URL/_cat/allocation?v"
curl -XGET "$ES_URL/_cat/count?v"
curl -XGET "$ES_URL/_cat/indices?v"
curl -XGET "$ES_URL/_cluster/health?level=indices&pretty"
curl -XGET "$ES_URL/_nodes/hot_threads"
Backup и Restore
curl -X PUT \
$ES_URL/_snapshot/backup-repo \
-H 'Content-Type: application/json' \
-d '{
"type": "fs",
"settings":{
"location": "/home/user/backup/"
}
}'
curl -X PUT $ES_URL/_snapshot/backup-repo/snapshot1
curl -X POST $ES_URL/_snapshot/backup-repo/snapshot1/_restore
Работа с шаблонами индекса
curl -X GET $ES_URL/_cat/templates?v&s=name
curl -X DELETE $ES_URL/_template/serilog-events-template
Удалить индекс
curl -X DELETE $ES_URL/$ES_INDEX?pretty
Решение проблемы `403Type: cluster_block_exception Reason: “blocked by: [FORBIDDEN/12/index read-only / allow fix’ возникшей когда кончилось место на диске https://discuss.elastic.co/t/forbidden-12-index-read-only-allow-delete-api/110282/4
curl -X PUT $ES_URL/$ES_INDEX/_settings -H 'Content-Type: application/json' -d '{"index": {"blocks": { "read_only_allow_delete": "false"}}}'
curl -X PUT $ES_URL/_settings -H 'Content-Type: application/json' -d '{"index": {"blocks": { "read_only_allow_delete": "false"}}}'
Работа с документом
# создадим документ
curl -XPUT "$ES_URL/$ES_INDEX/$ES_TYPE/1?pretty" -H 'Content-Type: application/json' -d'{"title": "тест"}'
# извлечем документ с id 1 типа $ES_TYPE из индекса $ES_INDEX
curl -XGET "$ES_URL/$ES_INDEX/$ES_TYPE/1?pretty"
# извлечем только поле title
curl -XGET "$ES_URL/$ES_INDEX/$ES_TYPE/1?_source=title&pretty"
Поиск
curl -XGET "$ES_URL/$ES_INDEX/_search?pretty" -H 'Content-Type: application/json; charset=UTF-8' -d'
{
"size":"10",
"_source": ["message", "@timestamp"],
"sort": [{"@timestamp": "desc"}]
}'
При обновлении при большом количестве индексов может возникнуть ошибка недостачи шардов this action would add [2] total shards, but this cluster currently has [1000]/[1000] maximum shards open
решить ее можно командой
curl -X PUT 10.0.4.14:19200/_cluster/settings -H "Content-Type: application/json" -d '{ "persistent": { "cluster.max_shards_per_node": "3000" } }'