Mani sauc Igors Sidorenko, esmu tehniskais vadītājs adminu komandā, kas uztur visu Domclick infrastruktūru.
Es vēlos dalīties savā pieredzē par izkliedētās datu krātuves iestatīšanu Elasticsearch. Apskatīsim, kādi mezglu iestatījumi ir atbildīgi par shardu izplatīšanu, kā darbojas un darbojas ILM.
Tie, kas strādā ar apaļkokiem, vienā vai otrā veidā saskaras ar ilgtermiņa uzglabāšanas problēmu vēlākai analīzei. Elasticsearchā tas ir īpaši aktuāli, jo ar kuratora funkcionalitāti viss bija neveiksmīgi. Versijā 6.6 tika ieviesta ILM funkcionalitāte. Tas sastāv no 4 fāzēm:
Karsts — indekss tiek aktīvi atjaunināts un vaicāts.
Silts — indekss vairs netiek atjaunināts, taču joprojām tiek vaicāts.
Auksts — indekss vairs netiek atjaunināts un tiek reti pieprasīts. Informācijai joprojām ir jābūt meklējamai, taču vaicājumi var būt lēnāki.
Dzēst — indekss vairs nav vajadzīgs, un to var droši dzēst.
Lai sadalītu fragmentu pa mezgliem, ir nepieciešams tikai viens parametrs:
karsti-mezgli:
~]# cat /etc/elasticsearch/elasticsearch.yml | grep attr
# Add custom attributes to the node:
node.attr.box_type: hot
Siltie-mezgli:
~]# cat /etc/elasticsearch/elasticsearch.yml | grep attr
# Add custom attributes to the node:
node.attr.box_type: warm
vēsa-mezgli:
~]# cat /etc/elasticsearch/elasticsearch.yml | grep attr
# Add custom attributes to the node:
node.attr.box_type: cold
Logstash iestatīšana
Kā tas viss darbojas un kā mēs ieviesām šo funkciju? Sāksim ar žurnālu iegūšanu Elasticsearch. Ir divi veidi:
Logstash atnes baļķus no Kafkas. Var paņemt tīru vai pārveidot jūsu pusē.
Kaut kas pats raksta uz Elasticsearch, piemēram, APM serveris.
Apsveriet piemēru indeksu pārvaldībai, izmantojot Logstash. Tas izveido indeksu un attiecas uz to indeksa modelis un atbilstošs 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
}
}
Kibana uzstādīšana
Ir bāzes modelis, kas attiecas uz visiem jaunajiem indeksiem. Tas nosaka karsto indeksu sadalījumu, lauskas, kopiju skaitu utt. Veidnes svaru nosaka opcija order. Veidnes ar lielāku svaru ignorē esošos veidņu parametrus vai pievieno jaunus.
GET_veidne/noklusējums
{
"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" : { }
}
}
Pēc tam piemērojiet kartēšanu indeksiem k8s-ingress-* izmantojot veidni ar lielāku svaru.
Pēc visu veidņu lietošanas mēs piemērojam ILM politiku un sākam uzraudzīt indeksu darbības laiku.
IEGŪT _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" : { }
}
}
}
}
}
}
Problēmas
Iestatīšanas un atkļūdošanas posmā radās problēmas.
Karstā fāze
Pareizai indeksu rotācijai klātbūtne beigās ir kritiska index_name-date-000026 formāta skaitļi 000001. Kodā ir rindas, kas pārbauda indeksus, izmantojot regulāru izteiksmi, lai noskaidrotu, vai beigās ir skaitļi. Pretējā gadījumā radīsies kļūda, indeksam netiks piemērotas politikas, un tas vienmēr būs karstajā fāzē.
Siltā fāze
Sarauties (cutoff) - samaziniet šķembu skaitu, jo mums ir 4 mezgli siltajā un aukstajā fāzē. Dokumentācijā ir šādas rindas:
Indeksam ir jābūt tikai lasāmam.
Katras indeksa fragmenta kopijai ir jāatrodas tajā pašā mezglā.
Klastera veselības statusam jābūt zaļam.
Lai apgrieztu indeksu, Elasticsearch pārvieto visus primāros fragmentus uz vienu mezglu, dublē saīsināto indeksu ar nepieciešamajiem parametriem un pēc tam dzēš veco. Parametrs total_shards_per_node ir jābūt vienādam ar vai lielākam par galveno lauskas skaitu, lai tās ietilptu vienā mezglā. Pretējā gadījumā tiks parādīti paziņojumi, un lauskas netiks pārvietotas uz pareizajiem mezgliem.
GET /shrink-k8s-ingress-2020.06.06-000025/_settings
Sasalt (iesaldēt) — mēs iesaldējam indeksu, lai optimizētu vēsturisko datu vaicājumus.
Meklēšanai, kas tiek veikta ar iesaldētajiem indeksiem, tiek izmantots mazs, speciāls, search_throttled pavedienu kopums, lai kontrolētu vienlaicīgu meklējumu skaitu, kas katrā mezglā trāpa iesaldētās lauskas. Tas ierobežo papildu atmiņas apjomu, kas nepieciešams īslaicīgām datu struktūrām, kas atbilst iesaldētajām lauskas, tādējādi aizsargājot mezglus pret pārmērīgu atmiņas patēriņu.
Fiksētie indeksi ir tikai lasāmi: tajos nevar indeksēt.
Paredzams, ka meklēšana iesaldētos indeksos tiks veikta lēni. Iesaldētie indeksi nav paredzēti lielai meklēšanas slodzei. Iespējams, ka iesaldēta indeksa meklēšana var ilgt sekundes vai minūtes, pat ja tā pati meklēšana tika pabeigta milisekundēs, kad indeksi nebija iesaldēti.
Rezultāti
Mēs uzzinājām, kā sagatavot mezglus darbam ar ILM, iestatīt veidni lauskas sadalīšanai starp karstajiem mezgliem un iestatīt ILM indeksam ar visām dzīves fāzēm.