Elasticsearch میں طویل مدتی ڈیٹا اسٹوریج

Elasticsearch میں طویل مدتی ڈیٹا اسٹوریج

میرا نام Igor Sidorenko ہے، میں منتظمین کی ٹیم میں ایک تکنیکی رہنما ہوں جو Domclick کے پورے انفراسٹرکچر کو برقرار رکھتا ہے۔

میں Elasticsearch میں ڈسٹری بیوٹڈ ڈیٹا سٹوریج ترتیب دینے میں اپنا تجربہ شیئر کرنا چاہتا ہوں۔ ہم دیکھیں گے کہ نوڈس پر کون سی ترتیبات شارڈز کی تقسیم کے لیے ذمہ دار ہیں، ILM کیسے کام کرتا ہے اور کام کرتا ہے۔

وہ لوگ جو لاگز کے ساتھ کام کرتے ہیں، کسی نہ کسی طرح، بعد میں تجزیہ کے لیے طویل مدتی اسٹوریج کے مسئلے کا سامنا کرنا پڑتا ہے۔ Elasticsearch میں، یہ خاص طور پر سچ ہے، کیونکہ سب کچھ کیوریٹر کی فعالیت کے ساتھ بدقسمت تھا۔ ورژن 6.6 نے ILM فعالیت کو متعارف کرایا۔ یہ 4 مراحل پر مشتمل ہے:

  • گرم - انڈیکس کو فعال طور پر اپ ڈیٹ اور استفسار کیا جا رہا ہے۔
  • گرم - انڈیکس کو اب اپ ڈیٹ نہیں کیا گیا ہے، لیکن اس سے ابھی بھی استفسار کیا جا رہا ہے۔
  • سرد - انڈیکس کو اب اپ ڈیٹ نہیں کیا گیا ہے اور شاذ و نادر ہی سوال کیا جاتا ہے۔ معلومات کو اب بھی تلاش کے قابل ہونا چاہیے، لیکن سوالات سست ہو سکتے ہیں۔
  • حذف کریں - انڈیکس کی مزید ضرورت نہیں ہے اور اسے محفوظ طریقے سے حذف کیا جاسکتا ہے۔

دیا

  • Elasticsearch Data Hot: 24 پروسیسرز، 128 GB میموری، 1,8 TB SSD RAID 10 (8 نوڈس)۔
  • Elasticsearch Data Warm: 24 پروسیسرز، 64 GB میموری، 8 TB NetApp SSD پالیسی (4 نوڈس)۔
  • Elasticsearch ڈیٹا کولڈ: 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 کے ذریعے اشاریہ جات کے انتظام کی ایک مثال پر غور کریں۔ یہ ایک انڈیکس بناتا ہے اور اس پر لاگو ہوتا ہے۔ انڈیکس پیٹرن اور متعلقہ 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. زیادہ وزن والے ٹیمپلیٹس موجودہ ٹیمپلیٹ پیرامیٹرز کو اوور رائیڈ کرتے ہیں یا نئے شامل کرتے ہیں۔

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/srink-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