Лабораторная работа 2. etcd 3.6 Запуск: docker compose up -d docker compose ps Состояние кластера и лидер: docker compose exec etcd1 etcdctl \ --endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379 \ endpoint status --write-out=table Запись и линеаризуемое чтение: docker compose exec etcd1 etcdctl --endpoints=http://etcd1:2379 put course raft docker compose exec etcd2 etcdctl --endpoints=http://etcd2:2379 get course Серийное чтение выполняется с флагом --consistency=s: docker compose exec etcd3 etcdctl --endpoints=http://etcd3:2379 \ get course --consistency=s Изоляция третьего узла и возвращение в сеть: docker compose exec etcd1 etcdctl --endpoints=http://etcd1:2379 \ put before-cut visible docker network disconnect distributed-systems-etcd ds-etcd3 docker compose exec etcd3 etcdctl --endpoints=http://127.0.0.1:2379 \ get before-cut Повторяйте предыдущее линеаризуемое чтение без --consistency=s, пока оно не завершится ошибкой: это подтверждает, что изолированный узел уже обнаружил потерю кворума. Только после этого запишите новый ключ в большинство и сравните режимы чтения на изолированном узле: docker compose exec etcd1 etcdctl --endpoints=http://etcd1:2379 \ put after-cut majority docker compose exec etcd3 etcdctl --endpoints=http://127.0.0.1:2379 \ get after-cut docker compose exec etcd3 etcdctl --endpoints=http://127.0.0.1:2379 \ get after-cut --consistency=s Линеаризуемое чтение должно завершиться ошибкой, а серийное — успешно вернуть пустой результат: новый ключ не попал в замершую локальную копию. При слишком ранней записи возможна гонка с самим разрывом сети. Для возвращения узла параметр --alias обязателен: без него контейнер не получит обратно имя etcd3, указанное в конфигурации кластера. docker network connect --alias etcd3 distributed-systems-etcd ds-etcd3 Остановка текущего лидера выполняется после определения его имени: leader_service=etcd2 # замените etcd2 на фактически найденный сервис docker compose stop "$leader_service" docker compose start "$leader_service" Воспроизводимая пауза лидера и новые выборы: В приложенном стенде не переопределены стандартные интервалы etcd: heartbeat около 100 мс, election timeout около 1000 мс. Сначала определите лидера. Затем задайте один из оставшихся сервисов как observer_service и перечислите два неприостановленных endpoint в active_endpoints. Например, если лидер — etcd2: leader_service=etcd2 observer_service=etcd1 active_endpoints=http://etcd1:2379,http://etcd3:2379 docker compose pause "$leader_service" sleep 2 docker compose exec "$observer_service" etcdctl \ --endpoints="$active_endpoints" endpoint status --write-out=table docker compose unpause "$leader_service" docker compose exec "$observer_service" etcdctl \ --endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379 \ endpoint status --write-out=table После паузы дольше election timeout два работающих узла должны выбрать нового лидера. После unpause прежний лидер узнаёт больший терм и остаётся ведомым. Для сравнения повторите опыт с паузой короче election timeout; точный момент реакции зависит также от фазы таймера и времени обработки сообщений. Удаление стенда вместе с учебными данными: docker compose down -v