Elasticsearch ۾ ڊگھي مدت جي ڊيٽا اسٽوريج

Elasticsearch ۾ ڊگھي مدت جي ڊيٽا اسٽوريج

منهنجو نالو Igor Sidorenko آهي، مان منتظمين جي ٽيم ۾ هڪ ٽيڪنيڪل ليڊر آهيان، جيڪو ڊوم ڪلڪ جي مڪمل انفراسٽرڪچر کي سنڀاليندو آهي.

مان پنهنجي تجربي کي حصيداري ڪرڻ چاهيان ٿو ورهايل ڊيٽا اسٽوريج کي ترتيب ڏيڻ ۾ Elasticsearch. اسان ڏسنداسين ته نوڊس تي ڪهڙيون سيٽنگون شارڊز جي ورڇ لاءِ ذميوار آهن، ILM ڪيئن ڪم ڪري ٿو ۽ ڪم ڪري ٿو.

اهي جيڪي لاگ سان ڪم ڪن ٿا، هڪ طريقو يا ٻيو، بعد ۾ تجزيو لاء ڊگهي مدت اسٽوريج جي مسئلي کي منهن ڏيڻ. Elasticsearch ۾، اهو خاص طور تي سچ آهي، ڇاڪاڻ ته هر شيء بدقسمتي سان ڪيوٽر جي ڪارڪردگي سان هئي. نسخو 6.6 متعارف ڪرايو ILM ڪارڪردگي. اهو 4 مرحلن تي مشتمل آهي:

  • گرم - انڊيڪس فعال طور تي اپڊيٽ ڪيو پيو وڃي ۽ سوال ڪيو پيو وڃي.
  • گرم - انڊيڪس هاڻي اپڊيٽ نه ڪئي وئي آهي، پر اڃا تائين سوال ڪيو پيو وڃي.
  • ٿڌي - انڊيڪس هاڻي اپڊيٽ نه ڪئي وئي آهي ۽ گهٽ ۾ گهٽ سوال ڪيو ويندو آهي. معلومات اڃا به ڳولهي سگهجي ٿي، پر سوال شايد سست هوندا.
  • حذف ڪريو - انڊيڪس جي ضرورت نه آھي ۽ محفوظ طور تي ختم ڪري سگھجي ٿو.

ڏنو

  • Elasticsearch ڊيٽا گرم: 24 پروسيسر، 128 GB ياداشت، 1,8 TB SSD RAID 10 (8 نوڊس).
  • Elasticsearch Data Warm: 24 پروسيسر، 64 GB ياداشت، 8 TB NetApp SSD پاليسي (4 نوڊس).
  • Elasticsearch Data Cold: 8 پروسيسر، 32 GB ياداشت، 128 TB HDD RAID 10 (4 نوڊس).

گول

اهي سيٽنگون انفرادي آهن، اهو سڀ ڪجهه نوڊس جي جڳهه تي منحصر آهي، انگن اکرن جو تعداد، لاگ، وغيره. اسان وٽ روزانو 2-3 TB ڊيٽا آهي.

  • 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 ذريعي انڊيڪس کي منظم ڪرڻ جي هڪ مثال تي غور ڪريو. اهو هڪ انڊيڪس ٺاهي ٿو ۽ ان تي لاڳو ٿئي ٿو انڊيڪس نموني ۽ ملندڙ ايل ايم ايم.

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. اعلي وزن سان ٽيمپليٽ موجوده ٽيمپليٽ جي پيٽرولن کي ختم ڪري ٿو يا نوان شامل ڪريو.

Elasticsearch ۾ ڊگھي مدت جي ڊيٽا اسٽوريج
Elasticsearch ۾ ڊگھي مدت جي ڊيٽا اسٽوريج

حاصل ڪريو _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-* هڪ اعلي وزن سان ٽيمپليٽ استعمال ڪندي.

Elasticsearch ۾ ڊگھي مدت جي ڊيٽا اسٽوريج
Elasticsearch ۾ ڊگھي مدت جي ڊيٽا اسٽوريج

حاصل ڪريو _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 ۾ ڊگھي مدت جي ڊيٽا اسٽوريج

حاصل ڪريو _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"
          }
        }
      }
    }
  }
}

ٿڌو مرحلو

ئيج (منجمد) - اسان تاريخي ڊيٽا تي سوالن کي بهتر ڪرڻ لاء انڊيڪس کي منجمد ڪريون ٿا.

منجمد انڊيڪس تي ڪيل ڳولها ننڍڙا، وقف ٿيل، سرچ_ٿراٽل ٿريڊ پول استعمال ڪن ٿيون ته ڪن ڪنڪريٽ ڳولها جي تعداد کي ڪنٽرول ڪرڻ لاءِ جيڪي هر نوڊ تي منجمد شارڊز کي مارين ٿيون. هي اضافي ميموري جي مقدار کي محدود ڪري ٿو جيڪا عارضي ڊيٽا جي جوڙجڪ لاءِ گهربل آهي جيڪا منجمد شارڊز سان لاڳاپيل آهي، جنهن جي نتيجي ۾ نوڊس کي وڌيڪ ياداشت جي استعمال کان بچائي ٿو.
منجمد انڊيڪس صرف پڙهڻ لاءِ آهن: توهان انهن ۾ انڊيڪس نٿا ڪري سگهو.
منجمد انڊيڪس تي ڳولها سست ٿيڻ جي اميد رکي ٿي. منجمد انڊيڪس اعلي ڳولها لوڊ لاء ارادو نه آهن. اهو ممڪن آهي ته هڪ منجمد انڊيڪس جي ڳولا مڪمل ٿيڻ ۾ سيڪنڊ يا منٽ وٺي سگھي ٿي، جيتوڻيڪ اهي ساڳيا ڳولها مليس سيڪنڊن ۾ مڪمل ڪيا ويا آهن جڏهن انڊيڪس منجمد نه هئا.

نتيجو

اسان سکيو ته ILM سان ڪم ڪرڻ لاءِ نوڊس ڪيئن تيار ڪيا وڃن، گرم نوڊس جي وچ ۾ شارڊز کي ورهائڻ لاءِ ٽيمپليٽ قائم ڪجي، ۽ زندگيءَ جي سڀني مرحلن تي مشتمل انڊيڪس لاءِ ILM قائم ڪجي.

ڪارآمد لنڪ

جو ذريعو: www.habr.com