సాగే శోధనలో దీర్ఘకాలిక డేటా నిల్వ

సాగే శోధనలో దీర్ఘకాలిక డేటా నిల్వ

నా పేరు ఇగోర్ సిడోరెంకో, నేను డొమ్‌క్లిక్ యొక్క మొత్తం మౌలిక సదుపాయాలను నిర్వహించే నిర్వాహకుల బృందంలో సాంకేతిక నాయకుడిని.

నేను సాగే శోధనలో పంపిణీ చేయబడిన డేటా నిల్వను సెటప్ చేయడంలో నా అనుభవాన్ని పంచుకోవాలనుకుంటున్నాను. ముక్కల పంపిణీకి నోడ్‌లలో ఏ సెట్టింగ్‌లు బాధ్యత వహిస్తాయో, ILM ఎలా పనిచేస్తుంది మరియు పని చేస్తుందో మేము పరిశీలిస్తాము.

లాగ్‌లతో పనిచేసే వారు, ఒక మార్గం లేదా మరొకటి, తరువాత విశ్లేషణ కోసం దీర్ఘకాలిక నిల్వ సమస్యను ఎదుర్కొంటారు. సాగే శోధనలో, ఇది ప్రత్యేకంగా వర్తిస్తుంది, ఎందుకంటే క్యూరేటర్ కార్యాచరణతో ప్రతిదీ దురదృష్టకరం. వెర్షన్ 6.6 ILM కార్యాచరణను పరిచయం చేసింది. ఇది 4 దశలను కలిగి ఉంటుంది:

  • హాట్ - ఇండెక్స్ చురుకుగా నవీకరించబడుతోంది మరియు ప్రశ్నించబడుతోంది.
  • వెచ్చగా - ఇండెక్స్ అప్‌డేట్ చేయబడదు, కానీ ఇంకా ప్రశ్నించబడుతోంది.
  • కోల్డ్ - ఇండెక్స్ అప్‌డేట్ చేయబడదు మరియు అరుదుగా ప్రశ్నించబడుతుంది. సమాచారం ఇప్పటికీ శోధించదగినదిగా ఉండాలి, కానీ ప్రశ్నలు నెమ్మదిగా ఉండవచ్చు.
  • తొలగించు - సూచిక ఇకపై అవసరం లేదు మరియు సురక్షితంగా తొలగించబడుతుంది.

ఇచ్చిన

  • సాగే శోధన డేటా హాట్: 24 ప్రాసెసర్‌లు, 128 GB మెమరీ, 1,8 TB SSD RAID 10 (8 నోడ్స్).
  • సాగే శోధన డేటా వార్మ్: 24 ప్రాసెసర్‌లు, 64 GB మెమరీ, 8 TB NetApp SSD పాలసీ (4 నోడ్‌లు).
  • సాగే శోధన డేటా కోల్డ్: 8 ప్రాసెసర్‌లు, 32 GB మెమరీ, 128 TB HDD RAID 10 (4 నోడ్‌లు).

లక్ష్యం

ఈ సెట్టింగులు వ్యక్తిగతమైనవి, ఇవన్నీ నోడ్‌లలోని స్థలం, సూచికల సంఖ్య, లాగ్‌లు మొదలైన వాటిపై ఆధారపడి ఉంటాయి. మాకు రోజుకు 2-3 TB డేటా ఉంటుంది.

  • 5 రోజులు - హాట్ ఫేజ్ (8 ప్రధాన / 1 ప్రతిరూపం).
  • 20 రోజులు - వెచ్చని దశ (కుదించు-సూచిక 4 ప్రధాన / 1 ప్రతిరూపం).
  • 90 రోజులు - చల్లని దశ (ఫ్రీజ్-ఇండెక్స్ 4 ప్రధాన / 1 ప్రతిరూపం).
  • 120 రోజులు - దశను తొలగించండి.

సాగే శోధనను సెటప్ చేస్తోంది

నోడ్‌ల అంతటా షార్డ్‌ను పంపిణీ చేయడానికి, మీకు ఒక పరామితి మాత్రమే అవసరం:

  • హాట్- నోడ్స్:
    ~]# 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

లాగ్‌స్టాష్‌ని సెటప్ చేస్తోంది

ఇవన్నీ ఎలా పని చేస్తాయి మరియు మేము ఈ లక్షణాన్ని ఎలా అమలు చేసాము? సాగే శోధనలోకి లాగ్‌లను పొందడం ద్వారా ప్రారంభిద్దాం. రెండు మార్గాలు ఉన్నాయి:

  1. లాగ్‌స్టాష్ కాఫ్కా నుండి లాగ్‌లను పొందుతుంది. శుభ్రంగా తీయవచ్చు లేదా మీ వైపుకు మార్చవచ్చు.
  2. ఏదో దానంతట అదే ఎలాస్టిక్ సెర్చ్‌కి వ్రాస్తుంది, ఉదాహరణకు, APM సర్వర్.

లాగ్‌స్టాష్ ద్వారా సూచికలను నిర్వహించడానికి ఒక ఉదాహరణను పరిగణించండి. ఇది ఒక సూచికను సృష్టిస్తుంది మరియు దానికి వర్తిస్తుంది సూచిక నమూనా మరియు సంబంధిత 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
    }
}

కిబానా సెటప్

అన్ని కొత్త ఇండెక్స్‌లకు వర్తించే ఆధార నమూనా ఉంది. ఇది హాట్ ఇండెక్స్‌ల పంపిణీ, షార్డ్‌ల సంఖ్య, ప్రతిరూపాలు మొదలైనవాటిని సెట్ చేస్తుంది. టెంప్లేట్ యొక్క బరువు ఎంపిక ద్వారా నిర్ణయించబడుతుంది order. అధిక బరువు ఉన్న టెంప్లేట్‌లు ఇప్పటికే ఉన్న టెంప్లేట్ పారామితులను భర్తీ చేస్తాయి లేదా కొత్త వాటిని జోడిస్తాయి.

సాగే శోధనలో దీర్ఘకాలిక డేటా నిల్వ
సాగే శోధనలో దీర్ఘకాలిక డేటా నిల్వ

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

ఆపై సూచికలకు మ్యాపింగ్‌ను వర్తింపజేయండి k8s-ingress-* అధిక బరువుతో టెంప్లేట్‌ని ఉపయోగించడం.

సాగే శోధనలో దీర్ఘకాలిక డేటా నిల్వ
సాగే శోధనలో దీర్ఘకాలిక డేటా నిల్వ

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 విధానాన్ని వర్తింపజేస్తాము మరియు సూచికల జీవితాన్ని పర్యవేక్షించడం ప్రారంభిస్తాము.

సాగే శోధనలో దీర్ఘకాలిక డేటా నిల్వ

సాగే శోధనలో దీర్ఘకాలిక డేటా నిల్వ

సాగే శోధనలో దీర్ఘకాలిక డేటా నిల్వ

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 ఒక నోడ్‌పై సరిపోయేలా ప్రధాన ముక్కల సంఖ్యకు సమానంగా లేదా అంతకంటే ఎక్కువ ఉండాలి. లేకపోతే, నోటిఫికేషన్‌లు ఉంటాయి మరియు ముక్కలు సరైన నోడ్‌లకు తరలించబడవు.

సాగే శోధనలో దీర్ఘకాలిక డేటా నిల్వ
సాగే శోధనలో దీర్ఘకాలిక డేటా నిల్వ

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

చల్లని దశ

ఫ్రీజ్ (ఫ్రీజ్) - చారిత్రక డేటాపై ప్రశ్నలను ఆప్టిమైజ్ చేయడానికి మేము సూచికను స్తంభింపజేస్తాము.

స్తంభింపచేసిన సూచికలపై చేసే శోధనలు చిన్న, అంకితమైన, శోధన_థ్రోటెల్డ్ థ్రెడ్‌పూల్‌ని ఉపయోగించి ప్రతి నోడ్‌లో స్తంభింపచేసిన షార్డ్‌లను తాకిన ఏకకాలిక శోధనల సంఖ్యను నియంత్రించవచ్చు. ఇది స్తంభింపచేసిన షార్డ్‌లకు సంబంధించిన తాత్కాలిక డేటా స్ట్రక్చర్‌లకు అవసరమైన అదనపు మెమరీ మొత్తాన్ని పరిమితం చేస్తుంది, తత్ఫలితంగా అధిక మెమరీ వినియోగం నుండి నోడ్‌లను రక్షిస్తుంది.
ఘనీభవించిన సూచికలు చదవడానికి మాత్రమే: మీరు వాటిని ఇండెక్స్ చేయలేరు.
స్తంభింపచేసిన సూచికలపై శోధనలు నెమ్మదిగా అమలు చేయబడతాయని భావిస్తున్నారు. ఘనీభవించిన సూచికలు అధిక శోధన లోడ్ కోసం ఉద్దేశించబడలేదు. స్తంభింపచేసిన సూచిక యొక్క శోధన పూర్తి కావడానికి సెకన్లు లేదా నిమిషాలు పట్టే అవకాశం ఉంది, సూచికలు స్తంభింపజేయనప్పుడు అదే శోధనలు మిల్లీసెకన్లలో పూర్తయినప్పటికీ.

ఫలితాలు

మేము ILMతో పని చేయడానికి నోడ్‌లను ఎలా సిద్ధం చేయాలో నేర్చుకున్నాము, హాట్ నోడ్‌ల మధ్య షార్డ్‌లను పంపిణీ చేయడానికి ఒక టెంప్లేట్‌ను సెటప్ చేయండి మరియు జీవితంలోని అన్ని దశలతో కూడిన సూచిక కోసం ILMని సెటప్ చేయండి.

ఉపయోగకరమైన లింకులు

మూలం: www.habr.com