From 3629dbc54d5dcb1d9913411aa818543deb10b594 Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Sun, 7 Apr 2024 00:38:22 +0300 Subject: [PATCH] Plug the new PG combinator into monitor --- docs/config/monitor.en.md | 9 ++++ docs/config/monitor.ru.md | 9 ++++ docs/config/pool.en.md | 65 +++++++++++++++++++++++++++ docs/config/pool.ru.md | 71 ++++++++++++++++++++++++++++- docs/config/src/monitor.yml | 9 ++++ docs/usage/cli.en.md | 2 + docs/usage/cli.ru.md | 2 + mon/dsl_pgs.js | 26 ++++++++++- mon/mon.js | 90 +++++++++++++++++++++++++++++++++++-- mon/simple_pgs.js | 20 +++------ mon/test-parse-dsl.js | 14 ++++++ src/cli.cpp | 3 ++ src/cli_pool_cfg.cpp | 65 ++++++++++++++++++++++++++- 13 files changed, 362 insertions(+), 23 deletions(-) diff --git a/docs/config/monitor.en.md b/docs/config/monitor.en.md index a2583ca7..c91bde56 100644 --- a/docs/config/monitor.en.md +++ b/docs/config/monitor.en.md @@ -15,6 +15,7 @@ These parameters only apply to Monitors. - [mon_stats_timeout](#mon_stats_timeout) - [osd_out_time](#osd_out_time) - [placement_levels](#placement_levels) +- [use_old_pg_combinator](#use_old_pg_combinator) ## etcd_mon_ttl @@ -77,3 +78,11 @@ values. Smaller priority means higher level in tree. For example, levels are always predefined and can't be removed. If one of them is not present in the configuration, then it is defined with the default priority (100 for "host", 101 for "osd"). + +## use_old_pg_combinator + +- Type: boolean +- Default: false + +Use the old PG combination generator which doesn't support [level_placement](pool.en.md#level_placement) +and [raw_placement](pool.en.md#raw_placement) for pools which don't use this features. diff --git a/docs/config/monitor.ru.md b/docs/config/monitor.ru.md index 9adab5da..5d36860e 100644 --- a/docs/config/monitor.ru.md +++ b/docs/config/monitor.ru.md @@ -15,6 +15,7 @@ - [mon_stats_timeout](#mon_stats_timeout) - [osd_out_time](#osd_out_time) - [placement_levels](#placement_levels) +- [use_old_pg_combinator](#use_old_pg_combinator) ## etcd_mon_ttl @@ -78,3 +79,11 @@ OSD перед обновлением агрегированной статис "host" и "osd" являются предопределёнными и не могут быть удалены. Если один из них отсутствует в конфигурации, он доопределяется с приоритетом по умолчанию (100 для уровня "host", 101 для "osd"). + +## use_old_pg_combinator + +- Тип: булево (да/нет) +- Значение по умолчанию: false + +Использовать старый генератор комбинаций PG, не поддерживающий [level_placement](pool.ru.md#level_placement) +и [raw_placement](pool.ru.md#raw_placement) для пулов, которые не используют данные функции. diff --git a/docs/config/pool.en.md b/docs/config/pool.en.md index d442e648..fb7fb12f 100644 --- a/docs/config/pool.en.md +++ b/docs/config/pool.en.md @@ -32,6 +32,8 @@ Parameters: - [pg_minsize](#pg_minsize) - [pg_count](#pg_count) - [failure_domain](#failure_domain) +- [level_placement](#level_placement) +- [raw_placement](#raw_placement) - [max_osd_combinations](#max_osd_combinations) - [block_size](#block_size) - [bitmap_granularity](#bitmap_granularity) @@ -209,6 +211,69 @@ never put on OSDs in the same failure domain (for example, on the same host). So failure domain specifies the unit which failure you are protecting yourself from. +## level_placement + +- Type: string + +Additional failure domain rules, applied in conjuction with failure_domain. +Must be specified in the following form: + +`=, =, ...` + +Sequence should be exactly [pg_size](#pg_size) character long. Each character +corresponds to an OSD in the PG of this pool. Equal characters mean that +corresponding items of the PG should be placed into the same placement tree +item at this level. Different characters mean that items should be placed into +different items. + +For example, if you want a EC 4+2 pool and you want every 2 chunks to be stored +in its own datacenter and you also want each chunk to be stored on a different +host, you should set `level_placement` to `dc=112233 host=123456`. + +Or you can set `level_placement` to `dc=112233` and leave `failure_domain` empty, +because `host` is the default `failure_domain` and it will be applied anyway. + +Without this rule, it may happen that 3 chunks will be stored on OSDs in the +same datacenter, and the data will become inaccessibly if that datacenter goes +down in this case. + +Of course, you should group your hosts into datacenters before applying the rule +by setting [placement_levels](monitor.en.md#placement_levels) to something like +`{"dc":90,"host":100,"osd":110}` and add DCs to [node_placement](#placement-tree), +like `{"dc1":{"level":"dc"},"host1":{"parent":"dc1"},...}`. + +## raw_placement + +- Type: string + +Raw PG placement rules, specified in the form of a DSL (domain-specific language). +Use only if you really know what you're doing :) + +DSL specification: + +``` +dsl := item | item ("\n" | ",") items +item := "any" | rules +rules := rule | rule rules +rule := level operator arg +level := /\w+/ +operator := "!=" | "=" | ">" | "?=" +arg := value | "(" values ")" +values := value | value "," values +value := item_ref | constant_id +item_ref := /\d+/ +constant_id := /"([^"]+)"/ +``` + +"?=" operator means "preferred". I.e. `dc ?= "meow"` means "prefer datacenter meow +for this chunk, but put into another dc if it's unavailable". + +Examples: + +- Simple 3 replicas with failure_domain=host: `any, host!=1, host!=(1,2)` +- EC 4+2 in 3 DC: `any, dc=1 host!=1, dc!=1, dc=3 host!=3, dc!=(1,3), dc=5 host!=5` +- 1 replica in fixed DC + 2 in random DCs: `dc?=meow, dc!=1, dc!=(1,2)` + ## max_osd_combinations - Type: integer diff --git a/docs/config/pool.ru.md b/docs/config/pool.ru.md index 44abb707..a4ad09c3 100644 --- a/docs/config/pool.ru.md +++ b/docs/config/pool.ru.md @@ -31,6 +31,8 @@ - [pg_minsize](#pg_minsize) - [pg_count](#pg_count) - [failure_domain](#failure_domain) +- [level_placement](#level_placement) +- [raw_placement](#raw_placement) - [max_osd_combinations](#max_osd_combinations) - [block_size](#block_size) - [bitmap_granularity](#bitmap_granularity) @@ -161,7 +163,7 @@ OSD, PG деактивируется на чтение и запись. Иным Для примера, разница между pg_minsize 2 и 1 в реплицированном пуле с 3 копиями данных (pg_size=3), проявляется следующим образом: - Если 2 сервера отключаются при pg_minsize=2, пул становится неактивным и - остаётся неактивным в течение [osd_out_time](monitor.en.md#osd_out_time) + остаётся неактивным в течение [osd_out_time](monitor.ru.md#osd_out_time) (10 минут), после чего монитор назначает другие OSD/серверы на замену, пул поднимается и начинает восстанавливать недостающие копии данных. Соответственно, если OSD на замену нет - то есть, если у вас всего 3 сервера с OSD и 2 из них @@ -169,7 +171,7 @@ OSD, PG деактивируется на чтение и запись. Иным или не добавите хотя бы 1 сервер (или не переключите failure_domain на "osd"). - Если 2 сервера отключаются при pg_minsize=1, ввод-вывод лишь приостанавливается на короткое время, до тех пор, пока монитор не поймёт, что OSD отключены - (что занимает 5-10 секунд при стандартном [etcd_report_interval](osd.en.md#etcd_report_interval)). + (что занимает 5-10 секунд при стандартном [etcd_report_interval](osd.ru.md#etcd_report_interval)). После этого ввод-вывод восстанавливается, но новые данные временно пишутся всего в 1 копии. Когда же проходит osd_out_time, монитор точно так же назначает другие OSD на замену выбывшим и пул начинает восстанавливать копии данных. @@ -211,6 +213,71 @@ PG в Vitastor эферемерны, то есть вы можете менят Иными словами, домен отказа - это то, от отказа чего вы защищаете себя избыточным хранением. +## level_placement + +- Тип: строка + +Правила дополнительных доменов отказа, применяемые вместе с failure_domain. +Должны задаваться в следующем виде: + +`<уровень>=<последовательность символов>, <уровень2>=<последовательность2>, ...` + +Каждая `<последовательность>` должна состоять ровно из [pg_size](#pg_size) символов. +Каждый символ соответствует одному OSD (размещению одной части PG) этого пула. +Одинаковые символы означают, что соответствующие части размещаются в один и тот же +узел дерева OSD на заданном `<уровне>`. Разные символы означают, что части +размещаются в разные узлы. + +Например, если вы хотите сделать пул EC 4+2 и хотите поместить каждые 2 части +данных в свой датацентр, и также вы хотите, чтобы каждая часть размещалась на +другом хосте, то вы должны задать `level_placement` равным `dc=112233 host=123456`. + +Либо вы просто можете задать `level_placement` равным `dc=112233` и оставить +`failure_domain` пустым, т.к. `host` это его значение по умолчанию и оно также +применится автоматически. + +Без этого правила может получиться так, что в одном из датацентров окажется +3 части данных одной PG и данные окажутся недоступными при временном отключении +этого датацентра. + +Естественно, перед установкой правила вам нужно сгруппировать ваши хосты в +датацентры, установив [placement_levels](monitor.ru.md#placement_levels) во что-то +типа `{"dc":90,"host":100,"osd":110}` и добавив датацентры в [node_placement](#дерево-размещения), +примерно так: `{"dc1":{"level":"dc"},"host1":{"parent":"dc1"},...}`. + +## raw_placement + +- Type: string + +Низкоуровневые правила генерации PG в форме DSL (доменно-специфичного языка). +Используйте, только если действительно знаете, зачем вам это надо :) + +Спецификация DSL: + +``` +dsl := item | item ("\n" | ",") items +item := "any" | rules +rules := rule | rule rules +rule := level operator arg +level := /\w+/ +operator := "!=" | "=" | ">" | "?=" +arg := value | "(" values ")" +values := value | value "," values +value := item_ref | constant_id +item_ref := /\d+/ +constant_id := /"([^"]+)"/ +``` + +Оператор "?=" означает "предпочитаемый". Т.е. `dc ?= "meow"` означает "предпочитать +датацентр meow для этой части данных, но разместить её в другом датацентре, если +meow недоступен". + +Примеры: + +- Простые 3 реплики с failure_domain=host: `any, host!=1, host!=(1,2)` +- EC 4+2 в 3 датацентрах: `any, dc=1 host!=1, dc!=1, dc=3 host!=3, dc!=(1,3), dc=5 host!=5` +- 1 копия в фиксированном ДЦ + 2 в других ДЦ: `dc?=meow, dc!=1, dc!=(1,2)` + ## max_osd_combinations - Тип: целое число diff --git a/docs/config/src/monitor.yml b/docs/config/src/monitor.yml index caf335e3..83a93ef0 100644 --- a/docs/config/src/monitor.yml +++ b/docs/config/src/monitor.yml @@ -63,3 +63,12 @@ "host" и "osd" являются предопределёнными и не могут быть удалены. Если один из них отсутствует в конфигурации, он доопределяется с приоритетом по умолчанию (100 для уровня "host", 101 для "osd"). +- name: use_old_pg_combinator + type: bool + default: false + info: | + Use the old PG combination generator which doesn't support [level_placement](pool.en.md#level_placement) + and [raw_placement](pool.en.md#raw_placement) for pools which don't use this features. + info_ru: | + Использовать старый генератор комбинаций PG, не поддерживающий [level_placement](pool.ru.md#level_placement) + и [raw_placement](pool.ru.md#raw_placement) для пулов, которые не используют данные функции. diff --git a/docs/usage/cli.en.md b/docs/usage/cli.en.md index 41ed6f47..a53b1f72 100644 --- a/docs/usage/cli.en.md +++ b/docs/usage/cli.en.md @@ -269,6 +269,8 @@ Optional parameters: | `--block_size 128k` | Put pool only on OSDs with this data block size | | `--bitmap_granularity 4k` | Put pool only on OSDs with this logical sector size | | `--immediate_commit none` | Put pool only on OSDs with this or larger immediate_commit (none < small < all) | +| `--level_placement ` | Use additional failure domain rules (example: "dc=112233") | +| `--raw_placement ` | Specify raw PG generation rules ([details](../config/pool.en.md#raw_placement)) | | `--primary_affinity_tags tags` | Prefer to put primary copies on OSDs with all specified tags | | `--scrub_interval