Нигоҳдории дарозмуддати маълумот дар Elasticsearch

Нигоҳдории дарозмуддати маълумот дар Elasticsearch

Номи ман Игор Сидоренко, ман роҳбари техникии як гурӯҳи маъмурон ҳастам, ки тамоми инфрасохтори Домкликро дар ҳолати корӣ нигоҳ медоранд.

Ман мехоҳам таҷрибаи худро дар ташкили нигаҳдории додаҳои тақсимшуда дар Elasticsearch мубодила кунам. Мо бубинем, ки кадом танзимотҳо дар гиреҳҳо барои тақсими пардаҳо масъуланд, ILM чӣ гуна сохтор ва кор мекунад.

Онҳое, ки бо гузоришҳо кор мекунанд, ин ё он роҳ бо мушкилоти нигоҳдории дарозмуддат барои таҳлили минбаъда дучор меоянд. Ин махсусан дар Elasticsearch дуруст аст, зеро фаъолияти куратор хеле ғамангез буд. Дар версияи 6.6, функсияи ILM пайдо шуд. Он аз 4 марҳила иборат аст:

  • Hot - Индекс фаъолона нав карда мешавад ва дархост карда мешавад.
  • Гарм - индекс дигар нав карда намешавад, аммо то ҳол дархост карда мешавад.
  • Сард - Индекс дигар нав карда намешавад ва хеле кам дархост карда мешавад. Маълумот бояд то ҳол ҷустуҷӯшаванда бошад, аммо дархостҳо метавонанд сусттар бошанд.
  • Нест кардан — Индекс дигар лозим нест ва онро бехатар нест кардан мумкин аст.

дода шудааст

  • Elasticsearch Data Hot: 24 протсессор, 128 ГБ хотира, 1,8 TB SSD RAID 10 (8 гиреҳ).
  • Elasticsearch Data Warm: 24 протсессор, 64 ГБ хотира, 8 TB Policy NetApp SSD (4 гиреҳ).
  • Elasticsearch Data Cold: 8 протсессори, 32 ГБ хотира, 128 TB HDD RAID 10 (4 гиреҳ).

Мақсад

Ин танзимот инфиродӣ мебошанд, ҳамааш аз фазои гиреҳҳо, шумораи индексҳо, гузоришҳо ва ғайра вобаста аст. Барои мо ин 2-3 ТБ маълумот дар як рӯз аст.

  • 5 рӯз - Марҳилаи гарм (8 асосӣ / 1 нусха).
  • 20 рӯз - Марҳилаи гарм (шохиси коҳиш 4 асосӣ / 1 нусха).
  • 90 рӯз - Марҳилаи сард (индекси яхбандӣ 4 асосӣ / 1 нусха).
  • 120 рӯз - Нобуд кардани марҳила.

Насб кардани Elasticsearch

Барои тақсим кардани пораҳо дар байни гиреҳҳо, ба шумо танҳо як параметр лозим аст:

  • гарм- гиреҳҳо:
    ~]# cat /etc/elasticsearch/elasticsearch.yml | grep attr
    # Add custom attributes to the node:
    node.attr.box_type: hot
  • гарм- гиреҳҳо:
    ~]# cat /etc/elasticsearch/elasticsearch.yml | grep attr
    # Add custom attributes to the node:
    node.attr.box_type: warm
  • хунук- гиреҳҳо:
    ~]# cat /etc/elasticsearch/elasticsearch.yml | grep attr
    # Add custom attributes to the node:
    node.attr.box_type: cold

Насб кардани Logstash

Ин ҳама чӣ гуна кор мекунад ва мо ин функсияро чӣ гуна амалӣ кардем? Биёед бо ворид кардани гузоришҳо ба Elasticsearch оғоз кунем. Ду роҳ вуҷуд дорад:

  1. Logstash гузоришҳоро аз Кафка мегирад. Метавонад дар паҳлӯи худ тоза ё табдил диҳад.
  2. Чизе худро ба Elasticsearch менависад, масалан, сервери APM.

Биёед мисоли идоракунии индексҳоро тавассути Logstash дида бароем. Он индекс эҷод мекунад ва татбиқ мекунад Шаблон индекс ва мувофиқ ILM.

k8s-ingress.conf

input {
    kafka {
        bootstrap_servers => "node01, node02, node03"
        topics => ["ingress-k8s"]
        decorate_events => false
        codec => "json"
    }
}

filter {
    ruby {
        path => "/etc/logstash/conf.d/k8s-normalize.rb"
    }
    if [log] =~ "[warn]" or [log] =~ "[error]" or [log] =~ "[notice]" or [log] =~ "[alert]" {
        grok {
            match => { "log" => "%{DATA:[nginx][error][time]} [%{DATA:[nginx][error][level]}] %{NUMBER:[nginx][error][pid]}#%{NUMBER:[nginx][error][tid]}: *%{NUMBER:[nginx][error][connection_id]} %{DATA:[nginx][error][message]}, client: %{IPORHOST:[nginx][error][remote_ip]}, server: %{DATA:[nginx][error][server]}, request: "%{WORD:[nginx][error][method]} %{DATA:[nginx][error][url]} HTTP/%{NUMBER:[nginx][error][http_version]}", (?:upstream: "%{DATA:[nginx][error][upstream][proto]}://%{DATA:[nginx][error][upstream][host]}:%{DATA:[nginx][error][upstream][port]}/%{DATA:[nginx][error][upstream][url]}", )?host: "%{DATA:[nginx][error][host]}"(?:, referrer: "%{DATA:[nginx][error][referrer]}")?" }
            remove_field => "log"
        }
    }
    else {
        grok {
            match => { "log" => "%{IPORHOST:[nginx][access][host]} - [%{IPORHOST:[nginx][access][remote_ip]}] - %{DATA:[nginx][access][remote_user]} [%{HTTPDATE:[nginx][access][time]}] "%{WORD:[nginx][access][method]} %{DATA:[nginx][access][url]} HTTP/%{NUMBER:[nginx][access][http_version]}" %{NUMBER:[nginx][access][response_code]} %{NUMBER:[nginx][access][bytes_sent]} "%{DATA:[nginx][access][referrer]}" "%{DATA:[nginx][access][agent]}" %{NUMBER:[nginx][access][request_lenght]} %{NUMBER:[nginx][access][request_time]} [%{DATA:[nginx][access][upstream][name]}] (?:-|%{IPORHOST:[nginx][access][upstream][addr]}:%{NUMBER:[nginx][access][upstream][port]}) (?:-|%{NUMBER:[nginx][access][upstream][response_lenght]}) %{DATA:[nginx][access][upstream][response_time]} %{DATA:[nginx][access][upstream][status]} %{DATA:[nginx][access][request_id]}" }
            remove_field => "log"
        }
    }
}
output {
    elasticsearch {
        id => "k8s-ingress"
        hosts => ["node01", "node02", "node03", "node04", "node05", "node06", "node07", "node08"]
        manage_template => true # включаем управление шаблонами
        template_name => "k8s-ingress" # имя применяемого шаблона
        ilm_enabled => true # включаем управление ILM
        ilm_rollover_alias => "k8s-ingress" # alias для записи в индексы, должен быть уникальным
        ilm_pattern => "{now/d}-000001" # шаблон для создания индексов, может быть как "{now/d}-000001" так и "000001"
        ilm_policy => "k8s-ingress" # политика прикрепляемая к индексу
        index => "k8s-ingress-%{+YYYY.MM.dd}" # название создаваемого индекса, может содержать %{+YYYY.MM.dd}, зависит от ilm_pattern
    }
}

Танзими Kibana

Шаблони асосӣ мавҷуд аст, ки ба ҳама индексҳои нав дахл дорад. Он тақсимоти индексҳои гарм, шумораи пораҳо, репликаҳо ва ғайраро муқаррар мекунад. Вазни шаблон бо вариант муайян карда мешавад order. Шаблонҳои дорои вазнҳои баландтар параметрҳои мавҷудаи қолабро бекор мекунанд ё навро илова мекунанд.

Нигоҳдории дарозмуддати маълумот дар Elasticsearch
Нигоҳдории дарозмуддати маълумот дар Elasticsearch

GET_шаблон/пешфарз

{
  "default" : {
    "order" : -1, # вес шаблона
    "version" : 1,
    "index_patterns" : [
      "*" # применяем ко всем индексам
    ],
    "settings" : {
      "index" : {
        "codec" : "best_compression", # уровень сжатия
        "routing" : {
          "allocation" : {
            "require" : {
              "box_type" : "hot" # распределяем только по горячим нодам
            },
            "total_shards_per_node" : "8" # максимальное количество шардов на ноду от одного индекса
          }
        },
        "refresh_interval" : "5s", # интервал обновления индекса
        "number_of_shards" : "8", # количество шардов
        "auto_expand_replicas" : "0-1", # количество реплик на ноду от одного индекса
        "number_of_replicas" : "1" # количество реплик
      }
    },
    "mappings" : {
      "_meta" : { },
      "_source" : { },
      "properties" : { }
    },
    "aliases" : { }
  }
}

Сипас харитасозӣ ба индексҳо татбиқ кунед k8s-ingress-* бо истифода аз қолаби дорои вазни баландтар.

Нигоҳдории дарозмуддати маълумот дар Elasticsearch
Нигоҳдории дарозмуддати маълумот дар Elasticsearch

GET _template/k8s-ingress

{
  "k8s-ingress" : {
    "order" : 100,
    "index_patterns" : [
      "k8s-ingress-*"
    ],
    "settings" : {
      "index" : {
        "lifecycle" : {
          "name" : "k8s-ingress",
          "rollover_alias" : "k8s-ingress"
        },
        "codec" : "best_compression",
        "routing" : {
          "allocation" : {
            "require" : {
              "box_type" : "hot"
            }
          }
        },
        "number_of_shards" : "8",
        "number_of_replicas" : "1"
      }
    },
    "mappings" : {
      "numeric_detection" : false,
      "_meta" : { },
      "_source" : { },
      "dynamic_templates" : [
        {
          "all_fields" : {
            "mapping" : {
              "index" : false,
              "type" : "text"
            },
            "match" : "*"
          }
        }
      ],
      "date_detection" : false,
      "properties" : {
        "kubernetes" : {
          "type" : "object",
          "properties" : {
            "container_name" : {
              "type" : "keyword"
            },
            "container_hash" : {
              "index" : false,
              "type" : "keyword"
            },
            "host" : {
              "type" : "keyword"
            },
            "annotations" : {
              "type" : "object",
              "properties" : {
                "value" : {
                  "index" : false,
                  "type" : "text"
                },
                "key" : {
                  "index" : false,
                  "type" : "keyword"
                }
              }
            },
            "docker_id" : {
              "index" : false,
              "type" : "keyword"
            },
            "pod_id" : {
              "type" : "keyword"
            },
            "labels" : {
              "type" : "object",
              "properties" : {
                "value" : {
                  "type" : "keyword"
                },
                "key" : {
                  "type" : "keyword"
                }
              }
            },
            "namespace_name" : {
              "type" : "keyword"
            },
            "pod_name" : {
              "type" : "keyword"
            }
          }
        },
        "@timestamp" : {
          "type" : "date"
        },
        "nginx" : {
          "type" : "object",
          "properties" : {
            "access" : {
              "type" : "object",
              "properties" : {
                "agent" : {
                  "type" : "text"
                },
                "response_code" : {
                  "type" : "integer"
                },
                "upstream" : {
                  "type" : "object",
                  "properties" : {
                    "port" : {
                      "type" : "keyword"
                    },
                    "name" : {
                      "type" : "keyword"
                    },
                    "response_lenght" : {
                      "type" : "integer"
                    },
                    "response_time" : {
                      "index" : false,
                      "type" : "text"
                    },
                    "addr" : {
                      "type" : "keyword"
                    },
                    "status" : {
                      "index" : false,
                      "type" : "text"
                    }
                  }
                },
                "method" : {
                  "type" : "keyword"
                },
                "http_version" : {
                  "type" : "keyword"
                },
                "bytes_sent" : {
                  "type" : "integer"
                },
                "request_lenght" : {
                  "type" : "integer"
                },
                "url" : {
                  "type" : "text",
                  "fields" : {
                    "keyword" : {
                      "type" : "keyword"
                    }
                  }
                },
                "remote_user" : {
                  "type" : "text"
                },
                "referrer" : {
                  "type" : "text"
                },
                "remote_ip" : {
                  "type" : "ip"
                },
                "request_time" : {
                  "format" : "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis||dd/MMM/YYYY:H:m:s Z",
                  "type" : "date"
                },
                "host" : {
                  "type" : "keyword"
                },
                "time" : {
                  "format" : "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis||dd/MMM/YYYY:H:m:s Z",
                  "type" : "date"
                }
              }
            },
            "error" : {
              "type" : "object",
              "properties" : {
                "server" : {
                  "type" : "keyword"
                },
                "upstream" : {
                  "type" : "object",
                  "properties" : {
                    "port" : {
                      "type" : "keyword"
                    },
                    "proto" : {
                      "type" : "keyword"
                    },
                    "host" : {
                      "type" : "keyword"
                    },
                    "url" : {
                      "type" : "text",
                      "fields" : {
                        "keyword" : {
                          "type" : "keyword"
                        }
                      }
                    }
                  }
                },
                "method" : {
                  "type" : "keyword"
                },
                "level" : {
                  "type" : "keyword"
                },
                "http_version" : {
                  "type" : "keyword"
                },
                "pid" : {
                  "index" : false,
                  "type" : "integer"
                },
                "message" : {
                  "type" : "text"
                },
                "tid" : {
                  "index" : false,
                  "type" : "keyword"
                },
                "url" : {
                  "type" : "text",
                  "fields" : {
                    "keyword" : {
                      "type" : "keyword"
                    }
                  }
                },
                "referrer" : {
                  "type" : "text"
                },
                "remote_ip" : {
                  "type" : "ip"
                },
                "connection_id" : {
                  "index" : false,
                  "type" : "keyword"
                },
                "host" : {
                  "type" : "keyword"
                },
                "time" : {
                  "format" : "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis||dd/MMM/YYYY:H:m:s Z",
                  "type" : "date"
                }
              }
            }
          }
        },
        "log" : {
          "type" : "text"
        },
        "@version" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "ignore_above" : 256,
              "type" : "keyword"
            }
          }
        },
        "eventtime" : {
          "type" : "float"
        }
      }
    },
    "aliases" : { }
  }
}

Пас аз татбиқи ҳама қолабҳо, мо сиёсати ILM-ро истифода мебарем ва ба мониторинги ҳаёти индексҳо шурӯъ мекунем.

Нигоҳдории дарозмуддати маълумот дар Elasticsearch

Нигоҳдории дарозмуддати маълумот дар Elasticsearch

Нигоҳдории дарозмуддати маълумот дар Elasticsearch

GET _ilm/policy/k8s-ingress

{
  "k8s-ingress" : {
    "version" : 14,
    "modified_date" : "2020-06-11T10:27:01.448Z",
    "policy" : {
      "phases" : {
        "warm" : { # теплая фаза
          "min_age" : "5d", # срок жизни индекса после ротации до наступления теплой фазы
          "actions" : {
            "allocate" : {
              "include" : { },
              "exclude" : { },
              "require" : {
                "box_type" : "warm" # куда перемещаем индекс
              }
            },
            "shrink" : {
              "number_of_shards" : 4 # обрезание индексов, т.к. у нас 4 ноды
            }
          }
        },
        "cold" : { # холодная фаза
          "min_age" : "25d", # срок жизни индекса после ротации до наступления холодной фазы
          "actions" : {
            "allocate" : {
              "include" : { },
              "exclude" : { },
              "require" : {
                "box_type" : "cold" # куда перемещаем индекс
              }
            },
            "freeze" : { } # замораживаем для оптимизации
          }
        },
        "hot" : { # горячая фаза
          "min_age" : "0ms",
          "actions" : {
            "rollover" : {
              "max_size" : "50gb", # максимальный размер индекса до ротации (будет х2, т.к. есть 1 реплика)
              "max_age" : "1d" # максимальный срок жизни индекса до ротации
            },
            "set_priority" : {
              "priority" : 100
            }
          }
        },
        "delete" : { # фаза удаления
          "min_age" : "120d", # максимальный срок жизни после ротации перед удалением
          "actions" : {
            "delete" : { }
          }
        }
      }
    }
  }
}

Масъалаҳо

Дар марҳилаи танзим ва ислоҳкунӣ мушкилот вуҷуд доштанд.

Марҳилаи гарм

Барои гардиши дурусти индексҳо, ҳузур дар охири index_name-date-000026 рақамҳои формат 000001. Дар код сатрҳо мавҷуданд, ки индексҳоро бо истифода аз ифодаи муқаррарии рақамҳо дар охири тафтиш мекунанд. Дар акси ҳол, хатогӣ рӯй медиҳад, сиёсатҳо ба индекс татбиқ карда намешаванд ва он ҳамеша дар марҳилаи гарм хоҳад буд.

Марҳилаи гарм

Шаффоф (буридан) - кам кардани шумораи пораҳо, зеро мо дар марҳилаҳои гарм ва хунук 4 гиреҳ дорем Дар ҳуҷҷатҳо сатрҳои зерин мавҷуданд:

  • Индекс бояд танҳо барои хондан бошад.
  • Нусхаи ҳар як пораи индекс бояд дар як гиреҳ ҷойгир бошад.
  • Ҳолати саломатии кластер бояд сабз бошад.

Барои буридани индекс, Elasticsearch ҳамаи пораҳои ибтидоиро ба як гиреҳ интиқол медиҳад, индекси буридашударо бо параметрҳои зарурӣ такрор мекунад ва сипас кӯҳнаро нест мекунад. Параметр total_shards_per_node бояд ба шумораи пораҳои асосӣ баробар ё бештар бошад, то онҳо дар як гиреҳ мувофиқ бошанд. Дар акси ҳол, огоҳиҳо пайдо мешаванд ва пораҳо ба гиреҳҳои зарурӣ намегузаранд.

Нигоҳдории дарозмуддати маълумот дар Elasticsearch
Нигоҳдории дарозмуддати маълумот дар Elasticsearch

GET /shrink-k8s-ingress-2020.06.06-000025/_settings

{
  "shrink-k8s-ingress-2020.06.06-000025" : {
    "settings" : {
      "index" : {
        "refresh_interval" : "5s",
        "auto_expand_replicas" : "0-1",
        "blocks" : {
          "write" : "true"
        },
        "provided_name" : "shrink-k8s-ingress-2020.06.06-000025",
        "creation_date" : "1592225525569",
        "priority" : "100",
        "number_of_replicas" : "1",
        "uuid" : "psF4MiFGQRmi8EstYUQS4w",
        "version" : {
          "created" : "7060299",
          "upgraded" : "7060299"
        },
        "lifecycle" : {
          "name" : "k8s-ingress",
          "rollover_alias" : "k8s-ingress",
          "indexing_complete" : "true"
        },
        "codec" : "best_compression",
        "routing" : {
          "allocation" : {
            "initial_recovery" : {
              "_id" : "_Le0Ww96RZ-o76bEPAWWag"
            },
            "require" : {
              "_id" : null,
              "box_type" : "cold"
            },
            "total_shards_per_node" : "8"
          }
        },
        "number_of_shards" : "4",
        "routing_partition_size" : "1",
        "resize" : {
          "source" : {
            "name" : "k8s-ingress-2020.06.06-000025",
            "uuid" : "gNhYixO6Skqi54lBjg5bpQ"
          }
        }
      }
    }
  }
}

Марҳилаи сард

Ях кун (ях кардан) - мо индексро барои оптимизатсияи дархостҳо дар асоси маълумоти таърихӣ ях мекунем.

Ҷустуҷӯҳое, ки дар шохисҳои яхкардашуда анҷом дода мешаванд, риштаи хурди бахшидашуда, search_throttled-ро барои назорат кардани шумораи ҷустуҷӯҳои ҳамзамон, ки ба ҳар як гиреҳ зарбаҳои яхкардашуда задаанд, истифода мебаранд. Ин миқдори хотираи иловагиро барои сохторҳои муваққатии додаҳои мувофиқи пораҳои яхкардашуда маҳдуд мекунад, ки дар натиҷа гиреҳҳоро аз истеъмоли аз ҳад зиёди хотира муҳофизат мекунад.
Индексҳои яхкардашуда танҳо барои хондан мебошанд: шумо наметавонед ба онҳо индексатсия кунед.
Интизор меравад, ки ҷустуҷӯҳо дар индексҳои яхкардашуда оҳиста иҷро шаванд. Индексҳои яхкардашуда барои сарбории баланди ҷустуҷӯ пешбинӣ нашудаанд. Эҳтимол аст, ки ҷустуҷӯи индекси яхкардашуда метавонад сонияҳо ё дақиқаҳоро дар бар гирад, ҳатто агар ҳамон ҷустуҷӯҳо дар миллисонияҳо, вақте ки индексҳо яхбандӣ нашудаанд, анҷом дода шаванд.

Натиҷаҳо

Мо омӯхтем, ки чӣ гуна гиреҳҳоро барои кор бо ILM омода кунем, қолаби тақсими пардаҳо дар байни гиреҳҳои гармро таъсис диҳем ва ILM-ро барои индекс бо тамоми марҳилаҳои ҳаёт танзим кардем.

Пайвандҳои муфид

Манбаъ: will.com