
Emri im është Igor Sidorenko dhe jam një drejtues teknik në ekipin e administratorëve që mirëmbajnë të gjithë infrastrukturën e DomClick.
Do të doja të ndaja përvojën time në konfigurimin e ruajtjes së të dhënave të shpërndara në Elasticsearch. Do të shqyrtojmë cilësimet e nyjeve përgjegjëse për shpërndarjen e shard-eve dhe mënyrën se si është strukturuar dhe funksionon ILM.
Kushdo që punon me regjistra përballet në mënyrë të pashmangshme me problemin e ruajtjes afatgjatë për analiza të mëvonshme. Kjo është veçanërisht e rëndësishme në Elasticsearch, pasi funksionaliteti i kuratorit ishte zhgënjyes. Versioni 6.6 prezantoi funksionalitetin ILM. Ai përbëhet nga katër faza:
- I nxehtë — indeksi përditësohet dhe pyetet në mënyrë aktive.
- I ngrohtë - indeksi nuk përditësohet më, por ende i kërkohet informacion.
- I ftohtë — indeksi nuk përditësohet më dhe rrallë kërkohet. Informacioni duhet të jetë ende i kërkueshëm, por pyetjet mund të funksionojnë më ngadalë.
- Fshij - indeksi nuk është më i nevojshëm dhe mund të fshihet në mënyrë të sigurt.
E dhënë
- Elasticsearch Data Hot: 24 procesorë, 128 GB memorie, 1,8 TB SSD RAID 10 (8 nyje).
- Elasticsearch Data Warm: 24 procesorë, 64 GB memorie, 8 TB NetApp SSD Policy (4 nyje).
- Elasticsearch Data Cold: 8 procesorë, memorie 32 GB, 128 TB HDD RAID 10 (4 nyje).
Qëllim
Këto cilësime janë individuale dhe varen nga hapësira në nyje, numri i indekseve, regjistrat, etj. Për ne, kjo është 2-3 TB të dhëna në ditë.
- 5 ditë - Faza e nxehtë (8 kryesore / 1 kopje).
- 20 ditë - Faza e ngrohtë ( 4 kryesore / 1 kopje).
- 90 ditë - Faza e ftohtë ( 4 kryesore / 1 kopje).
- 120 ditë – Faza e fshirjes.
Konfigurimi i Elasticsearch
Për të shpërndarë shard-et nëpër nyje, nevojitet vetëm një parametër:
- nxehtë-nyje:
~]# cat /etc/elasticsearch/elasticsearch.yml | grep attr # Add custom attributes to the node: node.attr.box_type: hot - I ngrohtë-nyje:
~]# cat /etc/elasticsearch/elasticsearch.yml | grep attr # Add custom attributes to the node: node.attr.box_type: warm - Të ftohtë-nyje:
~]# cat /etc/elasticsearch/elasticsearch.yml | grep attr # Add custom attributes to the node: node.attr.box_type: cold
Konfigurimi i Logstash
Si funksionon e gjithë kjo dhe si e zbatuam këtë veçori? Le të fillojmë me marrjen e regjistrave në Elasticsearch. Ka dy mënyra:
- Logstash merr trungje nga Kafka. Mund t'i marrë ato të pastra ose t'i transformojë ato nga brenda.
- Diçka i shkruan vetë Elasticsearch, për shembull, serveri APM.
Le të shohim një shembull të menaxhimit të indeksit nëpërmjet Logstash. Ai krijon një indeks dhe e aplikon atë në dhe përkatëse .
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
}
}
Ngritja e Kibanës
Ekziston një shabllon bazë që zbatohet për të gjitha indekset e reja. Ai përcakton shpërndarjen e indekseve të nxehta, numrin e shard-eve, replikave, etj. Pesha e shabllonit përcaktohet nga opsioni orderShabllonet me pesha më të larta mbivendosin parametrat ekzistues të shabllonit ose shtojnë të rinj.


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" : { }
}
}
Pastaj ne aplikojmë mapimin në indekse k8s-ingress-* duke përdorur një shabllon me një peshë më të lartë.


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" : { }
}
}
Pas aplikimit të të gjitha shablloneve, ne aplikojmë politikën ILM dhe fillojmë monitorimin e jetëgjatësisë së indekseve.



MERR _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" : { }
}
}
}
}
}
}
Problemet
Kishte probleme në fazën e konfigurimit dhe debugging-ut.
Faza e nxehtë
Për rrotullimin e saktë të indeksit, prania e në fund është kritike index_name-date-000026 format numrash 000001Kodi përmban rreshta që kontrollojnë indekset duke përdorur një shprehje të rregullt për numra në fund. Përndryshe, do të ndodhë një gabim, politikat nuk do të zbatohen në indeks dhe ai do të jetë gjithmonë në fazën e nxehtë.
Faza e ngrohtë
Tkurr (krasitje) — zvogëlimi i numrit të copëzave sepse kemi 4 nyje në secilën prej fazave të ngrohta dhe të ftohta. Dokumentacioni përmban rreshtat e mëposhtëm:
- Indeksi duhet të jetë vetëm për lexim.
- Një kopje e çdo shard në indeks duhet të ndodhet në të njëjtin nyje.
- Statusi shëndetësor i klasterit duhet të jetë i gjelbër.
Për të shkurtuar një indeks, Elasticsearch zhvendos të gjitha shard-et primare në një nyje të vetme, dublikon indeksin e shkurtuar me parametrat e kërkuar dhe pastaj fshin atë të vjetrin. Parametri total_shards_per_node duhet të jetë i barabartë ose më i madh se numri i shard-eve kryesore që duhen vendosur në një nyje të vetme. Përndryshe, do të gjenerohen njoftime dhe shard-et nuk do të zhvendosen në nyjet e sakta.


MERR /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"
}
}
}
}
}
}
Faza e ftohtë
Freeze (ngrirje) - ne e ngrijmë indeksin për të optimizuar pyetjet bazuar në të dhënat historike.
Kërkimet e kryera në indekset e ngrira përdorin threadpool-in e vogël, të dedikuar dhe search_throttled për të kontrolluar numrin e kërkimeve të njëkohshme që godasin shard-et e ngrira në secilën nyje. Kjo kufizon sasinë e memories shtesë të nevojshme për strukturat e të dhënave kalimtare që korrespondojnë me shard-et e ngrira, gjë që rrjedhimisht mbron nyjet nga konsumi i tepërt i memories.
Indekset e ngrira janë vetëm për lexim: nuk mund të indeksoni në to.
Kërkimet në indekset e ngrira pritet të ekzekutohen ngadalë. Indekset e ngrira nuk janë të destinuara për ngarkesë të lartë kërkimi. Është e mundur që një kërkim i një indeksi të ngrirë mund të zgjasë sekonda ose minuta për t'u përfunduar, edhe nëse të njëjtat kërkime përfunduan në milisekonda kur indekset nuk ishin të ngrira.
Rezultatet e
Mësuam si të përgatisim nyjet për të punuar me ILM, të konfigurojmë një shabllon për shpërndarjen e shard-eve nëpër nyjet e nxehta dhe të konfigurojmë ILM-in për të indeksuar të gjitha fazat e jetës së tij.
Lidhje të dobishme
Burimi: www.habr.com
