Panyimpen data jangka panjang dina Elasticsearch

Panyimpen data jangka panjang dina Elasticsearch

Ngaran abdi Igor Sidorenko, Kami pamimpin teknis dina tim admins anu ngajaga sakabéh infrastruktur Domclick.

Abdi hoyong bagikeun pangalaman abdi dina nyetel neundeun data disebarkeun di Elasticsearch. Urang bakal ningali naon setélan dina titik anu tanggung jawab distribusi beling, kumaha ILM jalan sareng jalanna.

Jalma anu digawekeun ku log, hiji cara atawa sejen, nyanghareupan masalah neundeun jangka panjang pikeun analisis engké. Dina Elasticsearch, ieu hususna leres, sabab sadayana hanjakal sareng fungsionalitas kurator. Vérsi 6.6 ngawanohkeun fungsionalitas ILM. Ieu diwangun ku 4 fase:

  • Panas - Indéks ieu aktip diropéa sareng ditaros.
  • Haneut - Indéks henteu deui diropéa, tapi masih ditaroskeun.
  • Tiis - Indéks henteu deui diropéa sareng jarang ditaroskeun. Inpormasi kedah tetep tiasa dipilarian, tapi patarosan tiasa langkung laun.
  • Hapus - Indéks henteu diperyogikeun deui sareng tiasa dihapus sacara aman.

Dipasihan

  • Elasticsearch Data Hot: 24 prosesor, 128 memori GB, 1,8 TB SSD razia 10 (8 titik).
  • Elasticsearch Data Haneut: 24 prosesor, 64 memori GB, 8 TB NetApp Kawijakan SSD (4 titik).
  • Elasticsearch Data Tiis: 8 prosesor, 32 memori GB, 128 TB HDD razia 10 (4 titik).

tujuan

Setélan ieu individu, éta sadayana gumantung kana tempat dina titik, jumlah indéks, log, jsb. Kami gaduh 2-3 TB data per dinten.

  • 5 poé - Fase panas (8 utama / 1 réplika).
  • 20 poé - Fase haneut (ngaleutikan-indéks 4 utama / 1 réplika).
  • 90 poé - Fase tiis (freeze-indéks 4 utama / 1 réplika).
  • 120 poé - fase Hapus.

Nyetél Elasticsearch

Pikeun ngadistribusikaeun hiji beling sakuliah titik, anjeun peryogi ngan hiji parameter:

  • panas- titik:
    ~]# cat /etc/elasticsearch/elasticsearch.yml | grep attr
    # Add custom attributes to the node:
    node.attr.box_type: hot
  • haneut- titik:
    ~]# cat /etc/elasticsearch/elasticsearch.yml | grep attr
    # Add custom attributes to the node:
    node.attr.box_type: warm
  • tiis- titik:
    ~]# cat /etc/elasticsearch/elasticsearch.yml | grep attr
    # Add custom attributes to the node:
    node.attr.box_type: cold

Nyetél Logstash

Kumaha éta sadayana dianggo sareng kumaha urang nerapkeun fitur ieu? Hayu urang mimitian ku asup log kana Elasticsearch. Aya dua cara:

  1. Logstash nyokot log ti Kafka. Bisa nyokot bersih atawa ngarobah di sisi Anjeun.
  2. Hal sorangan nyerat ka Elasticsearch, contona, server APM.

Pertimbangkeun conto ngatur indéks ngaliwatan Logstash. Éta nyiptakeun indéks sareng nerapkeunana pola indéks sarta pakait 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
    }
}

Setélan kibana

Aya pola dasar anu manglaku ka sadaya indéks énggal. Éta nyetél distribusi indéks panas, jumlah beling, réplika, jsb. Beurat template ditangtukeun ku pilihan order. Témplat anu beuratna langkung luhur nimpa parameter citakan anu tos aya atanapi tambahkeun anu énggal.

Panyimpen data jangka panjang dina Elasticsearch
Panyimpen data jangka panjang dina Elasticsearch

GET_template/standar

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

Lajeng nerapkeun pemetaan ka indexes k8s-ingress-* ngagunakeun citakan anu beuratna leuwih luhur.

Panyimpen data jangka panjang dina Elasticsearch
Panyimpen data jangka panjang dina 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" : { }
  }
}

Saatos nerapkeun sadaya témplat, urang nerapkeun kawijakan ILM sareng mimitian ngawaskeun kahirupan indéks.

Panyimpen data jangka panjang dina Elasticsearch

Panyimpen data jangka panjang dina Elasticsearch

Panyimpen data jangka panjang dina 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" : { }
          }
        }
      }
    }
  }
}

Anu jadi masalah

Aya masalah dina tahap setelan sareng debugging.

Fase panas

Pikeun rotasi indéks anu leres, ayana dina tungtung penting index_name-date-000026 angka format 000001. Aya garis dina kode anu pariksa indéks ngagunakeun ekspresi biasa pikeun ayana angka dina tungtungna. Upami teu kitu, bakal aya kasalahan, euweuh kawijakan bakal dilarapkeun ka indéks, sarta eta bakal salawasna dina fase panas.

Fase haneut

ngurangan (cutoff) - ngurangan jumlah shards, sabab urang boga 4 titik dina fase haneut tur tiis Dokuméntasi ngandung garis handap:

  • Indéksna kedah dibaca wungkul.
  • Salinan unggal beling dina indéks kedah aya dina titik anu sami.
  • Status kaséhatan klaster kudu héjo.

Pikeun prune indéks, Elasticsearch mindahkeun sakabéh beling primér kana hiji titik, duplikat indéks truncated kalawan parameter diperlukeun, lajeng ngahapus nu heubeul. Parameter total_shards_per_node kudu sarua atawa leuwih gede ti jumlah shards utama pikeun pas dina hiji titik. Upami teu kitu, bakal aya bewara sareng beling moal ngalih ka titik anu leres.

Panyimpen data jangka panjang dina Elasticsearch
Panyimpen data jangka panjang dina Elasticsearch

GET / ngaleutikan-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"
          }
        }
      }
    }
  }
}

Fase tiis

ngagiblegkeun (freeze) - Urang freeze indéks pikeun ngaoptimalkeun queries on data sajarah.

Pilarian anu dilakukeun dina indéks beku nganggo threadpool leutik, dedicated, search_throttled pikeun ngadalikeun jumlah pamilarian sakaligus anu pencét beling beku dina unggal titik. Ieu ngabatesan jumlah mémori tambahan anu dipikabutuh pikeun struktur data fana anu pakait sareng beling beku, anu akibatna ngajaga titik tina konsumsi mémori anu kaleuleuwihan.
Indéks beku ngan ukur dibaca: anjeun moal tiasa ngindeks kana éta.
Pilarian dina indéks beku diperkirakeun ngajalankeun lalaunan. indéks beku teu dimaksudkeun pikeun beban pilarian tinggi. Ieu mungkin yen pilarian tina indéks beku butuh sababaraha detik atawa menit pikeun réngsé, sanajan pilarian sarua réngsé dina milliseconds nalika indéks teu beku.

hasil

Urang diajar kumaha carana nyiapkeun titik pikeun gawé bareng ILM, nyetél template pikeun ngadistribusikaeun shards diantara titik panas, tur nyetel ILM pikeun indéks kalayan sagala fase kahirupan.

link mangpaat

sumber: www.habr.com