# Динамическое изменение конфигурации

> Поддержка поэтапного изменения конфигурации etcd во время работы

---

Индекс LLMS: [llms.txt](/ru/llms.txt)

---

etcd поддерживает поэтапное изменение конфигурации во время работы, позволяя
обновлять состав кластера без остановки.

Запросы изменения конфигурации обрабатываются только при работающем большинстве
участников. В производственной среде **настоятельно рекомендуется** кластер
размером более двух. Удалять участника из кластера из двух участников небезопасно:
его большинство также равно двум, поэтому ошибка во время удаления может
остановить кластер и потребовать [перезапуска после потери большинства][majority failure].

Архитектура описана в [документе о динамическом изменении конфигурации][runtime-reconf].

## Сценарии реконфигурации {#reconfiguration-use-cases}

В этом разделе рассмотрены распространённые причины изменения конфигурации.
Обычно это сочетания добавления и удаления участников, описанные в разделе
[Операции изменения конфигурации кластера][cluster-reconf].

### Поочерёдная замена или обновление машин {#cycle-or-upgrade-multiple-machines}

Если несколько участников кластера необходимо переместить из-за запланированного обслуживания (обновления аппаратного обеспечения, простоя сети и т. д.), рекомендуется изменять их по одному.

Лидера можно безопасно удалить, но во время выборов возникнет краткий простой.
Если кластер содержит более 50MB данных v2, рекомендуется
[перенести каталог данных участника][member migration].

### Изменение размера кластера {#change-the-cluster-size}

Увеличение размера кластера может повысить [устойчивость к отказам участников][fault tolerance table] и обеспечить лучшую производительность чтения. Поскольку клиенты могут читать из любого участника, увеличение числа участников увеличивает общую пропускную способность сериализуемого чтения.

Уменьшение размера может ускорить запись ценой отказоустойчивости. До фиксации
запись реплицируется большинству участников; меньшее большинство подтверждает её быстрее.

### Заменить сбойную машину {#replace-a-failed-machine}

Машину, отказавшую из-за оборудования, повреждения каталога данных или другой
критической причины, следует заменить как можно скорее. Неудалённый отказавший
участник ухудшает кворум и снижает устойчивость к следующему отказу.

Для замены [удалите участника][remove member], затем [добавьте нового][add member].
Если кластер содержит более 50MB и каталог отказавшего участника доступен,
рекомендуется [перенести его][member migration].

### Перезапуск кластера после потери большинства {#restart-cluster-from-majority-failure}

При потере большинства или изменении IP-адресов всех узлов требуется ручное
восстановление: [создать новый кластер из старых данных][disaster recovery],
принудительно назначить одного участника лидером, затем по одному
[добавить новых участников][add member].

### Восстановление кластера после отказа меньшинства {#recover-cluster-from-minority-failure}

Потеря отдельного участника эквивалентна замене отказавшей машины; см.
[Замена отказавшей машины](/ru/docs/etcd/op-guide/runtime-configuration/#replace-a-failed-machine).

## Операции перенастройки кластера {#cluster-reconfiguration-operations}

Для этих сценариев используются следующие операции.

Перед внесением любых изменений должно быть доступно простое большинство (кворум) участников etcd. Это в сущности то же самое требование для любого вида записи в etcd.

Все изменения в кластере должны выполняться последовательно:

* Чтобы обновить peerURLs одного участника, выполните операцию обновления.
* Чтобы заменить одного исправного участника, удалите старого и добавьте нового.
* Для увеличения с 3 до 5 участников выполните две операции добавления.
* Для уменьшения с 5 до 3 выполните две операции удаления.

Во всех примерах используется поставляемая с etcd утилита `etcdctl`. Чтобы
изменить состав без `etcdctl`, используйте [gRPC API участников v3][member-api-grpc].

### Обновление участника {#update-a-member}

#### Обновление объявляемых клиентских URL {#update-advertise-client-urls}

Чтобы обновить объявляемые клиентские URL участника, перезапустите его с новым значением флага (`--advertise-client-urls`) или переменной окружения (`ETCD_ADVERTISE_CLIENT_URLS`). Участник сам опубликует обновлённые URL. Ошибочно заданный клиентский URL не влияет на работоспособность кластера etcd.

#### Обновление объявляемых URL одноранговых узлов {#update-advertise-peer-urls}

Для обновления объявляемых URL одноранговых узлов сначала явно обновите их с помощью команды member, а затем перезапустите участника. Дополнительное действие необходимо, так как обновление URL одноранговых узлов изменяет конфигурацию кластера и может повлиять на состояние etcd кластера.

Для обновления объявляемых URL сначала найдите ID участника. Список выводится командой `etcdctl`:

```sh
$ etcdctl member list
6e3bd23ae5f1eae0: name=node2 peerURLs=http://localhost:23802 clientURLs=http://127.0.0.1:23792
924e2e83e93f2560: name=node3 peerURLs=http://localhost:23803 clientURLs=http://127.0.0.1:23793
a8266ecf031671f3: name=node1 peerURLs=http://localhost:23801 clientURLs=http://127.0.0.1:23791
```

Пример выполняет `update` участника с ID a8266ecf031671f3 и задаёт peerURLs
`http://10.0.1.10:2380`:

```sh
$ etcdctl member update a8266ecf031671f3 --peer-urls=http://10.0.1.10:2380
Updated member with ID a8266ecf031671f3 in cluster
```

### Удалить участника {#remove-a-member}

Предположим, что идентификатор участника для удаления — a8266ecf031671f3. Используйте команду `remove` для выполнения удаления:

```sh
$ etcdctl member remove a8266ecf031671f3
Removed member a8266ecf031671f3 from cluster
```

Целевой участник остановит себя на этом этапе и выведет сообщение об удалении в журнал:

```
etcd: this member has been permanently removed from the cluster. Exiting.
```

Удалить лидера безопасно, однако кластер будет неактивен до тех пор, пока не будет выбран новый лидер. Этот период составляет обычно сумму тайм-аута выборов и процесса голосования.

### Добавление нового участника {#add-a-new-member}

Добавление участника является двухэтапным процессом:

 * Добавьте участника через [gRPC API участников v3][member-api-grpc] или `etcdctl member add`.
 * Запустите его с новой конфигурацией кластера и обновлённым списком участников (существующие + новый).

`etcdctl` добавляет участника по его [имени][conf-name] и
[объявляемым URL однорангового узла][conf-adv-peer]:

```sh
$ etcdctl member add infra3 --peer-urls=http://10.0.1.13:2380
added member 9bf1b35fc7761a23 to cluster

ETCD_NAME="infra3"
ETCD_INITIAL_CLUSTER="infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380,infra3=http://10.0.1.13:2380"
ETCD_INITIAL_CLUSTER_STATE=existing
```

`etcdctl` уведомил кластер о новом участнике и вывел переменные окружения, необходимые для успешного запуска. Теперь запустите новый процесс etcd с соответствующими флагами для нового участника:

```sh
$ export ETCD_NAME="infra3"
$ export ETCD_INITIAL_CLUSTER="infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380,infra3=http://10.0.1.13:2380"
$ export ETCD_INITIAL_CLUSTER_STATE=existing
$ etcd --listen-client-urls http://10.0.1.13:2379 --advertise-client-urls http://10.0.1.13:2379 --listen-peer-urls http://10.0.1.13:2380 --initial-advertise-peer-urls http://10.0.1.13:2380 --data-dir %data_dir%
```

Новый участник будет функционировать как часть кластера и немедленно начнет синхронизироваться с остальными участниками кластера.

При добавлении нескольких участников настраивайте их по одному и проверяйте
запуск. После добавления участника в кластер из 1 узла кластер не продвигается,
пока новый участник не запустится: для консенсуса теперь нужно большинство из
двух. Пауза длится от `etcdctl member add` до успешного соединения нового участника.

#### Добавление нового участника как обучающегося {#add-a-new-member-as-learner}

Начиная с v3.4 etcd поддерживает добавление обучающегося участника без права голоса.
Мотивацию и дизайн можно найти в [документе по дизайну][design-learner].
Чтобы сделать процесс добавления нового участника безопаснее,
и снизить время простоя кластера при добавлении нового участника, рекомендуется добавлять нового участника в кластер
как обучающегося до тех пор, пока он не синхронизируется. Это можно описать как трехступенчатый процесс:

 * Добавьте нового участника как обучающегося через [gRPC API участников][member-api-grpc] или команду `etcdctl member add --learner`.

 * Запустите нового участника с новой конфигурацией и обновлённым списком участников (существующие + новый).
 Этот шаг не отличается от описанного выше.

 * Повысьте нового добавленного обучающегося до участника с правом голоса через [gRPC API участников][member-api-grpc] или командой `etcdctl member promote`.
Сервер etcd проверяет запрос повышения, чтобы обеспечить безопасность операции.
Только после того как журнал Raft обучающегося участника догонит журнал лидера, обучающийся может быть повышен до участника с правом голоса.
Если обучающийся участник не догнал журнал лидера, запрос на повышение участника завершится ошибкой
(подробнее см. раздел [об ошибках при повышении участника][error cases when promoting a member]).
В этом случае пользователю следует подождать и повторить попытку позже.

В v3.4 сервер etcd ограничивает количество обучающихся участников, которые может иметь кластер, одним. Основное соображение заключается в ограничении дополнительной нагрузки на лидера при распространении данных от лидера к обучающемуся участнику.

Используйте `etcdctl member add` с флагом `--learner` для добавления нового участника в кластер как обучающегося участника.

```sh
$ etcdctl member add infra3 --peer-urls=http://10.0.1.13:2380 --learner
Member 9bf1b35fc7761a23 added to cluster a7ef944b95711739

ETCD_NAME="infra3"
ETCD_INITIAL_CLUSTER="infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380,infra3=http://10.0.1.13:2380"
ETCD_INITIAL_CLUSTER_STATE=existing
```

После запуска нового процесса etcd для нового добавленного обучающегося участника используйте `etcdctl member promote` для повышения обучающегося участника до голосующего участника.
```
$ etcdctl member promote 9bf1b35fc7761a23
Member 9e29bbaa45d74461 promoted in cluster a7ef944b95711739
```

#### Случаи ошибок при добавлении участников {#error-cases-when-adding-members}

В следующем случае новый хост не включается в список перечисленных узлов. Если это новый кластер, узел должен быть добавлен в список исходных участников кластера.

```sh
$ etcd --name infra3 \
  --initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
  --initial-cluster-state existing
etcdserver: assign ids error: the member count is unequal
exit 1
```

В этом примере запуск завершается ошибкой: участник запускается с адресом (10.0.1.14:2380), отличным от зарегистрированного адреса однорангового узла (10.0.1.13:2380):

```sh
$ etcd --name infra4 \
  --initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380,infra4=http://10.0.1.14:2380 \
  --initial-cluster-state existing
etcdserver: assign ids error: unmatched member while checking PeerURLs
exit 1
```

Если etcd начинает использовать данные из директории данных удаленного участника, etcd автоматически завершает работу, если он подключается к любому активному участнику в кластере:

```sh
$ etcd
etcd: this member has been permanently removed from the cluster. Exiting.
exit 1
```

#### Ошибки при добавлении обучающегося участника {#error-cases-when-adding-a-learner-member}

Нельзя добавить обучающегося участника в кластер, если кластер уже имеет 1 обучающегося участника (v3.4).
```
$ etcdctl member add infra4 --peer-urls=http://10.0.1.14:2380 --learner
Error: etcdserver: too many learner members in cluster
```

#### Ошибки при повышении обучающегося участника до участника {#error-cases-when-promoting-a-learner-member}

Обучающегося можно повысить до голосующего участника только после синхронизации с лидером.
```
$ etcdctl member promote 9bf1b35fc7761a23
Error: etcdserver: can only promote a learner member which is in sync with leader
```

Повышение участника, который не является обучающимся, завершится ошибкой.
```
$ etcdctl member promote 9bf1b35fc7761a23
Error: etcdserver: can only promote a learner member
```

Повышение отсутствующего в кластере участника завершится ошибкой.
```
$ etcdctl member promote 12345abcde
Error: etcdserver: member not found
```


### Строгий режим проверки реконфигурации (`-strict-reconfig-check`) {#strict-reconfiguration-check-mode--strict-reconfig-check}

Как описано выше, лучшая практика добавления новых участников заключается в настройке одного участника за раз и проверке того, что он стартует корректно, прежде чем добавлять новых участников. Этот пошаговый подход очень важен, так как если новый участник не настроен правильно (например, URL-адреса одноранговых узлов неверны), кластер может потерять кворум. Потеря кворума происходит, так как новый участник учитывается в кворуме даже если он недоступен из других существующих участников. Также потеря кворума может произойти при проблемах со связностью или при операционных проблемах.

Для предотвращения проблемы etcd предоставляет `-strict-reconfig-check`.
С этим параметром etcd отклоняет изменение конфигурации, если число запущенных
участников станет меньше кворума нового состава.

По умолчанию включено.

[add member]: #add-a-new-member
[cluster-reconf]: #cluster-reconfiguration-operations
[conf-adv-peer]: /ru/docs/etcd/op-guide/configuration#clustering
[conf-name]: /ru/docs/etcd/op-guide/configuration#member
[design-learner]: /ru/docs/etcd/learning/design-learner
[disaster recovery]: /ru/docs/etcd/op-guide/recovery
[error cases when promoting a member]: #error-cases-when-promoting-a-learner-member
[fault tolerance table]: https://etcd.io/docs/v2.3/admin_guide/#fault-tolerance-table
[majority failure]: #restart-cluster-from-majority-failure
[member migration]: https://etcd.io/docs/v2.3/admin_guide/#member-migration
[member-api]: https://etcd.io/docs/v2.3/members_api/
[member-api-grpc]: /ru/docs/etcd/dev-guide/api_reference_v3/
[remove member]: #remove-a-member
[runtime-reconf]: /ru/docs/etcd/op-guide/runtime-reconf-design/
