Di Elasticsearch de hilanîna daneya demdirêj

Di Elasticsearch de hilanîna daneya demdirêj

Navê min Igor Sidorenko ye, ez di tîmek rêvebiran de pêşengek teknîkî me ku tevahiya binesaziya Domklik di rewşa xebatê de diparêze.

Ez dixwazim ezmûna xwe ya di sazkirina hilanîna daneya belavkirî de li Elasticsearch parve bikim. Em ê binihêrin ka kîjan mîhengên li ser girêkan ji bo belavkirina şûşeyan berpirsiyar in, ILM çawa hatî çêkirin û kar dike.

Yên ku bi têketin re dixebitin bi rengekî din bi pirsgirêka hilanîna dirêj-dirêj re ji bo analîzên paşîn re rû bi rû ne. Ev bi taybetî di Elasticsearch-ê de rast e ji ber ku fonksiyona parêzgerê xemgîn bûye. Di guhertoya 6.6 de, fonksiyona ILM xuya bû. Ew ji 4 qonaxan pêk tê:

  • Germ — Indeks bi awayekî aktîf tê nûvekirin û pirsîn.
  • Germ - îndeks êdî nayê nûve kirin, lê hîn jî tê pirsîn.
  • Sar - Indeks êdî nayê nûve kirin û kêm caran tê pirsîn. Pêdivî ye ku agahdarî hîn jî were lêgerîn, lê dibe ku pirs hêdîtir bin.
  • Jêbirin - Pîvan êdî ne hewce ye û dikare bi ewlehî were jêbirin.

dayîn

  • Elasticsearch Data Hot: 24 pêvajo, 128 GB bîra, 1,8 TB SSD RAID 10 (8 nod).
  • Daneyên Elasticsearch Germ: 24 pêvajo, 64 GB bîra, 8 TB Siyaseta NetApp SSD (4 nod).
  • Elasticsearch Data Cold: 8 pêvajo, 32 GB bîra, 128 TB HDD RAID 10 (4 nod).

Armanc

Van mîhengan ferdî ne, ew hemî bi cîhê li ser girêkan, hejmara pêvekan, têketin û hwd ve girêdayî ye. Ji bo me ev rojane 2-3 TB dane ye.

  • 5 roj - Qonaxa germ (8 serekî / 1 replica).
  • 20 roj - Qonaxa germ (biçûk-indeks 4 sereke / 1 replica).
  • 90 roj - Qonaxa sar (cemidandin-index 4 sereke / 1 replica).
  • 120 roj - Qonaxa jêbirin.

Sazkirina Elasticsearch

Ji bo belavkirina perçeyan di nav girêkan de, hûn tenê yek pîvanek hewce ne:

  • germ-girêdan:
    ~]# cat /etc/elasticsearch/elasticsearch.yml | grep attr
    # Add custom attributes to the node:
    node.attr.box_type: hot
  • Germ-girêdan:
    ~]# cat /etc/elasticsearch/elasticsearch.yml | grep attr
    # Add custom attributes to the node:
    node.attr.box_type: warm
  • Sarma-girêdan:
    ~]# cat /etc/elasticsearch/elasticsearch.yml | grep attr
    # Add custom attributes to the node:
    node.attr.box_type: cold

Sazkirina Logstash

Ev hemî çawa dixebite û me ev fonksiyon çawa pêk anî? Ka em bi girtina têketinên nav Elasticsearch dest pê bikin. Du rê hene:

  1. Logstash têketinên Kafka distîne. Dikare li tenişta xwe paqij hilde an veguherîne.
  2. Tiştek xwe ji Elasticsearch re dinivîse, mînakî, serverek APM.

Ka em li mînakek birêvebirina indexan bi riya Logstash binêrin. Indeksek çêdike û tê sepandin şablonê index û têkildar 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
    }
}

Sazkirina Kibana

Şablonek bingehîn heye ku ji bo hemî navnîşên nû derbas dibe. Ew dabeşkirina navnîşên germ, hejmara şûşeyan, kopiyan, hwd destnîşan dike. Giraniya şablonê ji hêla vebijarkê ve tê destnîşankirin order. Şablonên bi giraniya wan zêdetir parametreyên şablonê yên heyî li ber xwe didin an jî yên nû lê zêde dikin.

Di Elasticsearch de hilanîna daneya demdirêj
Di Elasticsearch de hilanîna daneya demdirêj

GET_şablon/default

{
  "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" : { }
  }
}

Dûv re nexşeyê li ser indexan bicîh bikin k8s-ingress-* bikaranîna şablonê bi giraniya bilind.

Di Elasticsearch de hilanîna daneya demdirêj
Di Elasticsearch de hilanîna daneya demdirêj

GET _şablon/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" : { }
  }
}

Piştî sepandina hemî şablonan, em polîtîkaya ILM bicîh dikin û dest bi şopandina jiyana îndeksan dikin.

Di Elasticsearch de hilanîna daneya demdirêj

Di Elasticsearch de hilanîna daneya demdirêj

Di Elasticsearch de hilanîna daneya demdirêj

GET _ilm/polîtîka/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" : { }
          }
        }
      }
    }
  }
}

Pirsgirêkên

Di qonaxa sazkirin û rakirinê de pirsgirêk hebûn.

Qonaxa germ

Ji bo zivirîna rast a indexan, hebûna li dawiya index_name-date-000026 hejmarên formatê 000001. Di kodê de xêz hene ku bi karanîna birêkûpêkek birêkûpêk ji bo jimareyan di dawiyê de indexan kontrol dikin. Wekî din, dê xeletiyek çêbibe, polîtîka li ser îndeksê neyê sepandin û dê her dem di qonaxa germ de be.

Qonaxa germ

Hedimîn (birrîn) - kêmkirina hejmara şikestiyan, ji ber ku di qonaxên germ û sar de 4 girêkên me hene.

  • Indeks divê tenê-xwendin be.
  • Pêdivî ye ku kopiyek ji her perçeyek di navnîşanê de li ser heman girêkê bimîne.
  • Divê rewşa tenduristiya komê kesk be.

Ji bo xêzkirina îndeksekê, Elasticsearch hemî şûşeyên seretayî ber bi yek girêkekê ve diguhezîne, pêveka birêkûpêk bi pîvanên pêwîst dubare dike, û dûv re ya kevin jê dike. Parametre total_shards_per_node Ji bo ku ew li ser yek girêkekê bi cih bibin divê ji hejmara qertafên sereke wekhev an mezintir be. Wekî din, dê agahdarî hebin û perçe dê neçin girêkên pêwîst.

Di Elasticsearch de hilanîna daneya demdirêj
Di Elasticsearch de hilanîna daneya demdirêj

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"
          }
        }
      }
    }
  }
}

Qonaxa sar

Qerisandin (cemidandin) - em îndeksê dicemidînin da ku li ser bingeha daneyên dîrokî pirsan xweşbîn bikin.

Lêgerînên ku li ser nîşaneyên cemidî têne kirin, threadpoolek piçûk, veqetandî, search_throttled bikar tînin da ku hejmara lêgerînên hevdem ên ku li ser her girêkek qeşagirtî dixin kontrol bikin. Ev mîqdara bîranîna zêde ya ku ji bo strukturên daneya derbasbûyî yên ku bi perçeyên cemidî re têkildar in, sînordar dike, ku di encamê de girêkan li hember vexwarina bîranîna zêde diparêze.
Nîşaneyên cemidî tenê-xwendewar in: hûn nekarin nav wan navnîş bikin.
Li bendê ye ku lêgerînên li ser nîşaneyên cemidî hêdî hêdî werin meşandin. Nîşaneyên cemidî ji bo barkirina lêgerîna bilind nayên armanc kirin. Mimkun e ku lêgerîna pêdekek qeşagirtî çirkeyan an hûrdeman bigire heya ku temam bibe, her çend heman lêgerîn di milî çirkeyan de biqede dema ku îndeks nehatine cemidandin.

Encam

Em fêr bûn ku meriv çawa girêkan ji bo xebata bi ILM-ê re amade dike, ji bo belavkirina şûşeyan di nav girêkên germ de şablonek saz dike, û ILM-ê ji bo pêvekek bi hemî qonaxên jiyanê ve mîheng kir.

Girêdanên bikarhêner

Source: www.habr.com

Ji bo malperên bi parastina DDoS, serverên VPS VDS mêvandariya pêbawer bikirin 🔥 Hostinga malperê ya pêbawer bi parastina DDoS, serverên VPS VDS bikirin | ProHoster