Перейти к содержанию

1 - Обновление кластеров etcd и приложений

Список документации по обновлению кластеров etcd и приложений

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

Политика обновления

Перед обновлением обратите внимание, что etcd поддерживает только следующие два случая обновления:

  • Обновление патча: обновление между выпусками патча в рамках одной минорной версии (e.g. 3.7.0 - 3.7.1).
  • Минорное обновление: обновление по одной минорной версии за раз (e.g. 3.6 - 3.7). Обновления, пропускающие минорную версию, не поддерживаются и, скорее всего, завершатся неудачно. Обновитесь до последней версии патча перед обновлением до следующей минорной версии.

Обновление кластера etcd v3.x

Обновление с etcd v2.3

2 - Обновление etcd с v3.5 до v3.6

Процессы, контрольные списки и примечания по обновлению etcd с v3.5 до v3.6

В общем случае переход с etcd v3.5 на v3.6 можно выполнить как скользящее обновление без простоя:

  • поочерёдно останавливать процессы etcd v3.5 и заменять их процессами etcd v3.6
  • после запуска всех процессов v3.6 кластеру становятся доступны новые возможности v3.6

До начала обновления прочитайте оставшуюся часть руководства и подготовьтесь.

Контрольные списки обновления

Обновление 3.5

Важно

Перед обновлением до 3.6 убедитесь, что все участники 3.5 обновлены до 3.5.32 или более поздней версии . Корректирующие выпуски с 3.5.24 по 3.5.26 устраняют несколько потенциальных препятствий обновлению; в 3.5.32 добавлен --v2-deprecation=write-only-skip-check, а etcdutl check v2store расширен для проверки не только снимка v2, но и записей WAL.

Хранилище V2

Примечание

Если флаг --enable-v2 не настроен или равен false, дальнейшие действия не требуются.

Если --enable-v2 настроен, выполните etcdutl check v2store, чтобы проверить наличие в v2store пользовательских данных, не относящихся к составу кластера. Если таких данных нет, флаг можно безопасно удалить. В противном случае обратитесь к руководству по миграции v2 .

Добавленные флаги

+etcd --discovery-token ''
+etcd --discovery-endpoints ''
+etcd --discovery-dial-timeout '2s'
+etcd --discovery-request-timeout '5s'
+etcd --discovery-keepalive-time '2s'
+etcd --discovery-keepalive-timeout '6s'
+etcd --discovery-insecure-transport 'true'
+etcd --discovery-insecure-skip-tls-verify 'false'
+etcd --discovery-cert ''
+etcd --discovery-key ''
+etcd --discovery-cacert ''
+etcd --discovery-user ''
+etcd --discovery-password ''
+etcd --feature-gates
+etcd --log-format

Удалённые флаги

-etcd --enable-v2
-etcd --experimental-enable-v2v3
-etcd --proxy
-etcd --proxy-failure-wait
-etcd --proxy-refresh-interval
-etcd --proxy-dial-timeout
-etcd --proxy-write-timeout
-etcd --proxy-read-timeout

Устаревшие флаги

Флаг etcd --experimental-bootstrap-defrag-threshold-megabytes объявлен устаревшим.


-etcd --experimental-bootstrap-defrag-threshold-megabytes

+etcd --bootstrap-defrag-threshold-megabytes

Флаг etcd --experimental-compaction-batch-limit объявлен устаревшим.


-etcd --experimental-compaction-batch-limit

+etcd --compaction-batch-limit

Флаг etcd --experimental-compact-hash-check-time объявлен устаревшим.


-etcd --experimental-compact-hash-check-time

+etcd --compact-hash-check-time

Флаг etcd --experimental-compaction-sleep-interval объявлен устаревшим.


-etcd --experimental-compaction-sleep-interval

+etcd --compaction-sleep-interval

Флаг etcd --experimental-corrupt-check-time объявлен устаревшим.


-etcd --experimental-corrupt-check-time

+etcd --corrupt-check-time

Флаг etcd --experimental-enable-distributed-tracing объявлен устаревшим.


-etcd --experimental-enable-distributed-tracing

+etcd --enable-distributed-tracing

Флаг etcd --experimental-distributed-tracing-address объявлен устаревшим.


-etcd --experimental-distributed-tracing-address

+etcd --distributed-tracing-address

Флаг etcd --experimental-distributed-tracing-instance-id объявлен устаревшим.


-etcd --experimental-distributed-tracing-instance-id

+etcd --distributed-tracing-instance-id

Флаг etcd --experimental-distributed-tracing-sampling-rate объявлен устаревшим.


-etcd --experimental-distributed-tracing-sampling-rate

+etcd --distributed-tracing-sampling-rate

Флаг etcd --experimental-distributed-tracing-service-name объявлен устаревшим.


-etcd --experimental-distributed-tracing-service-name

+etcd --distributed-tracing-service-name

Флаг etcd --experimental-downgrade-check-time объявлен устаревшим.


-etcd --experimental-downgrade-check-time

+etcd --downgrade-check-time

Флаг etcd --experimental-max-learners объявлен устаревшим.


-etcd --experimental-max-learners

+etcd --max-learners

Флаг etcd --experimental-memory-mlock объявлен устаревшим.


-etcd --experimental-memory-mlock

+etcd --memory-mlock

Флаг etcd --experimental-peer-skip-client-san-verification объявлен устаревшим.


-etcd --experimental-peer-skip-client-san-verification

+etcd --peer-skip-client-san-verification

Флаг etcd --experimental-snapshot-catchup-entries объявлен устаревшим.


-etcd --experimental-snapshot-catchup-entries

+etcd --snapshot-catchup-entries

Флаг etcd --experimental-warning-apply-duration объявлен устаревшим.


-etcd --experimental-warning-apply-duration

+etcd --warning-apply-duration

Флаг etcd --experimental-warning-unary-request-duration объявлен устаревшим.


-etcd --experimental-warning-unary-request-duration

+etcd --warning-unary-request-duration

Флаг etcd --experimental-watch-progress-notify-interval объявлен устаревшим.


-etcd --experimental-watch-progress-notify-interval

+etcd --watch-progress-notify-interval

Эквивалентные флаги функций v3.5

эквивалентный флаг функции для etcd --experimental-compact-hash-check-enabled=true


-etcd --experimental-compact-hash-check-enabled=true

+etcd --feature-gates=CompactHashCheck=true

эквивалентный флаг функции для etcd --experimental-initial-corrupt-check=true


-etcd --experimental-initial-corrupt-check=true

+etcd --feature-gates=InitialCorruptCheck=true

эквивалентный флаг функции для etcd --experimental-enable-lease-checkpoint=true


-etcd --experimental-enable-lease-checkpoint=true

+etcd --feature-gates=LeaseCheckpoint=true

эквивалентный флаг функции для etcd --experimental-enable-lease-checkpoint-persist=true


-etcd --experimental-enable-lease-checkpoint-persist=true

+etcd --feature-gates=LeaseCheckpointPersist=true

эквивалентный флаг функции для etcd --experimental-stop-grpc-service-on-defrag=true


-etcd --experimental-stop-grpc-service-on-defrag=true

+etcd --feature-gates=StopGRPCServiceOnDefrag=true

эквивалентный флаг функции для etcd --experimental-txn-mode-write-with-shared-buffer=false


-etcd --experimental-txn-mode-write-with-shared-buffer=false

+etcd --feature-gates=TxnModeWriteWithSharedBuffer=false

Флаги с новыми значениями по умолчанию

Исходное значение флага по умолчанию etcd --snapshot-count=100000


-etcd --snapshot-count=100000

+etcd --snapshot-count=10000

Исходное значение флага по умолчанию etcd --v2-deprecation='not-yet'


-etcd --v2-deprecation='not-yet'

+etcd --v2-deprecation='write-only'

Исходное значение флага по умолчанию etcd --discovery-fallback='proxy'


-etcd --discovery-fallback='proxy'

+etcd --discovery-fallback='exit'

Различия в метриках Prometheus

# metrics added in v3.6
+etcd_network_known_peers
+etcd_server_feature_enabled

Контрольные списки обновления сервера

Требования к обновлению

Для обновления существующего развёртывания etcd до v3.6 работающий кластер должен иметь версию v3.5 или более позднюю. Если версия старше v3.5, перед переходом на v3.6 обновитесь до v3.5 .

Кроме того, для плавного скользящего обновления работающий кластер должен быть исправен. Перед продолжением проверьте его работоспособность командой etcdctl endpoint health.

Подготовка

Перед обновлением etcd обязательно протестируйте зависящие от него службы в промежуточном окружении, прежде чем развёртывать обновление в рабочем окружении.

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

Смешанные версии

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

Откат

Перед обновлением кластера etcd создайте и загрузите его резервную копию снимка . При необходимости снимок позволяет восстановить состояние кластера до обновления. Если во время обновления возникнут проблемы, сначала следует определить и устранить их первопричину. Пока кластер находится в состоянии смешанных версий и хотя бы один участник остаётся на v3.5, можно либо заменить двоичный файл или образ старой версией v3.5, либо непосредственно восстановить кластер из снимка. В таком смешанном состоянии кластер продолжает работать как кластер v3.5, что позволяет откатиться без формальной процедуры понижения версии.

Однако после обновления всех участников до v3.6 кластер считается полностью обновлённым, и откат заменой двоичных файлов больше невозможен. В этом случае восстановиться можно только из снимка, сделанного перед обновлением. Чтобы вернуться к исходной версии после полного обновления, необходимо следовать официальному руководству по понижению версии, обеспечивая согласованность и предотвращая повреждение данных.

Процедура обновления

В этом примере показано обновление работающего на локальной машине кластера etcd v3.5 из 3 участников.

Шаг 1: проверка требований к обновлению

Кластер исправен и использует v3.5.x?

etcdctl --endpoints=localhost:2379,localhost:22379,localhost:32379 endpoint health
<<COMMENT
localhost:2379 is healthy: successfully committed proposal: took = 2.555774ms
localhost:32379 is healthy: successfully committed proposal: took = 2.631133ms
localhost:22379 is healthy: successfully committed proposal: took = 3.020958ms
COMMENT

curl http://localhost:2379/version
<<COMMENT
{"etcdserver":"3.5.18","etcdcluster":"3.5.0"}
COMMENT

curl http://localhost:22379/version
<<COMMENT
{"etcdserver":"3.5.18","etcdcluster":"3.5.0"}
COMMENT

curl http://localhost:32379/version
<<COMMENT
{"etcdserver":"3.5.18","etcdcluster":"3.5.0"}
COMMENT

Шаг 2: загрузка резервной копии снимка с лидера

Загрузите резервную копию снимка , чтобы обеспечить путь понижения версии при возникновении проблем.

Лидер etcd гарантированно содержит последние данные приложения, поэтому снимок следует получать с лидера:

curl -sL http://localhost:2379/metrics | grep etcd_server_is_leader
<<COMMENT
# HELP etcd_server_is_leader Whether or not this member is a leader. 1 if is, 0 otherwise.
# TYPE etcd_server_is_leader gauge
etcd_server_is_leader 1
COMMENT

curl -sL http://localhost:22379/metrics | grep etcd_server_is_leader
<<COMMENT
etcd_server_is_leader 0
COMMENT

curl -sL http://localhost:32379/metrics | grep etcd_server_is_leader
<<COMMENT
etcd_server_is_leader 0
COMMENT

etcdctl --endpoints=localhost:2379 snapshot save backup.db
<<COMMENT
{"level":"info","ts":"2025-03-01T04:34:10.336768+0530","caller":"snapshot/v3_snapshot.go:65","msg":"created temporary db file","path":"backup.db.part"}
{"level":"info","ts":"2025-03-01T04:34:10.342373+0530","logger":"client","caller":"v3@v3.5.18/maintenance.go:212","msg":"opened snapshot stream; downloading"}
{"level":"info","ts":"2025-03-01T04:34:10.342433+0530","caller":"snapshot/v3_snapshot.go:73","msg":"fetching snapshot","endpoint":"localhost:2379"}
{"level":"info","ts":"2025-03-01T04:34:10.346482+0530","logger":"client","caller":"v3@v3.5.18/maintenance.go:220","msg":"completed snapshot read; closing"}
{"level":"info","ts":"2025-03-01T04:34:10.348801+0530","caller":"snapshot/v3_snapshot.go:88","msg":"fetched snapshot","endpoint":"localhost:2379","size":"20 kB","took":"now"}
{"level":"info","ts":"2025-03-01T04:34:10.348933+0530","caller":"snapshot/v3_snapshot.go:97","msg":"saved","path":"backup.db"}
Snapshot saved at backup.db
COMMENT

Шаг 3: остановка одного существующего сервера etcd

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

{"level":"info","ts":"2025-03-01T04:31:50.654520+0530","caller":"etcdserver/server.go:2676","msg":"cluster version is updated","cluster-version":"3.5"}
{"level":"info","ts":"2025-03-01T04:34:10.345927+0530","caller":"v3rpc/maintenance.go:130","msg":"sending database snapshot to client","total-bytes":20480,"size":"20 kB"}
{"level":"info","ts":"2025-03-01T04:34:10.346094+0530","caller":"v3rpc/maintenance.go:170","msg":"sending database sha256 checksum to client","total-bytes":20480,"checksum-size":32}
{"level":"info","ts":"2025-03-01T04:34:10.346108+0530","caller":"v3rpc/maintenance.go:179","msg":"successfully sent database snapshot to client","total-bytes":20480,"size":"20 kB","took":"now"}
^C
{"level":"info","ts":"2025-03-01T04:35:01.443045+0530","caller":"osutil/interrupt_unix.go:64","msg":"received signal; shutting down","signal":"interrupt"}
{"level":"info","ts":"2025-03-01T04:35:01.443088+0530","caller":"embed/etcd.go:408","msg":"closing etcd server","name":"node1","data-dir":"/tmp/etcd-node1","advertise-peer-urls":["http://127.0.0.1:2380"],"advertise-client-urls":["http://127.0.0.1:2379"]}
{"level":"info","ts":"2025-03-01T04:35:01.443417+0530","caller":"etcdserver/server.go:1503","msg":"leadership transfer starting","local-member-id":"bf9071f4639c75cc","current-leader-member-id":"bf9071f4639c75cc","transferee-member-id":"91bc3c398fb3c146"}
{"level":"info","ts":"2025-03-01T04:35:01.443441+0530","logger":"raft","caller":"etcdserver/zap_raft.go:77","msg":"bf9071f4639c75cc [term 2] starts to transfer leadership to 91bc3c398fb3c146"}
{"level":"info","ts":"2025-03-01T04:35:01.443455+0530","logger":"raft","caller":"etcdserver/zap_raft.go:77","msg":"bf9071f4639c75cc sends MsgTimeoutNow to 91bc3c398fb3c146 immediately as 91bc3c398fb3c146 already has up-to-date log"}
{"level":"warn","ts":"2025-03-01T04:35:01.443517+0530","caller":"embed/serve.go:179","msg":"stopping insecure grpc server due to error","error":"accept tcp 127.0.0.1:2379: use of closed network connection"}
{"level":"warn","ts":"2025-03-01T04:35:01.443548+0530","caller":"embed/serve.go:181","msg":"stopped insecure grpc server due to error","error":"accept tcp 127.0.0.1:2379: use of closed network connection"}
{"level":"info","ts":"2025-03-01T04:35:01.445536+0530","logger":"raft","caller":"etcdserver/zap_raft.go:77","msg":"bf9071f4639c75cc [term: 2] received a MsgVote message with higher term from 91bc3c398fb3c146 [term: 3]"}
{"level":"info","ts":"2025-03-01T04:35:01.445556+0530","logger":"raft","caller":"etcdserver/zap_raft.go:77","msg":"bf9071f4639c75cc became follower at term 3"}
{"level":"info","ts":"2025-03-01T04:35:01.445565+0530","logger":"raft","caller":"etcdserver/zap_raft.go:77","msg":"bf9071f4639c75cc [logterm: 2, index: 12, vote: 0] cast MsgVote for 91bc3c398fb3c146 [logterm: 2, index: 12] at term 3"}
{"level":"info","ts":"2025-03-01T04:35:01.445572+0530","logger":"raft","caller":"etcdserver/zap_raft.go:77","msg":"raft.node: bf9071f4639c75cc lost leader bf9071f4639c75cc at term 3"}
{"level":"info","ts":"2025-03-01T04:35:01.446773+0530","logger":"raft","caller":"etcdserver/zap_raft.go:77","msg":"raft.node: bf9071f4639c75cc elected leader 91bc3c398fb3c146 at term 3"}
{"level":"info","ts":"2025-03-01T04:35:01.544062+0530","caller":"etcdserver/server.go:1520","msg":"leadership transfer finished","local-member-id":"bf9071f4639c75cc","old-leader-member-id":"bf9071f4639c75cc","new-leader-member-id":"91bc3c398fb3c146","took":"100.640374ms"}
{"level":"info","ts":"2025-03-01T04:35:01.544160+0530","caller":"rafthttp/peer.go:330","msg":"stopping remote peer","remote-peer-id":"91bc3c398fb3c146"}
{"level":"warn","ts":"2025-03-01T04:35:01.544956+0530","caller":"rafthttp/stream.go:286","msg":"closed TCP streaming connection with remote peer","stream-writer-type":"stream MsgApp v2","remote-peer-id":"91bc3c398fb3c146"}
{"level":"info","ts":"2025-03-01T04:35:01.544984+0530","caller":"rafthttp/stream.go:294","msg":"stopped TCP streaming connection with remote peer","stream-writer-type":"stream MsgApp v2","remote-peer-id":"91bc3c398fb3c146"}
{"level":"warn","ts":"2025-03-01T04:35:01.545050+0530","caller":"rafthttp/stream.go:286","msg":"closed TCP streaming connection with remote peer","stream-writer-type":"stream Message","remote-peer-id":"91bc3c398fb3c146"}
{"level":"info","ts":"2025-03-01T04:35:01.545065+0530","caller":"rafthttp/stream.go:294","msg":"stopped TCP streaming connection with remote peer","stream-writer-type":"stream Message","remote-peer-id":"91bc3c398fb3c146"}
{"level":"info","ts":"2025-03-01T04:35:01.545099+0530","caller":"rafthttp/pipeline.go:85","msg":"stopped HTTP pipelining with remote peer","local-member-id":"bf9071f4639c75cc","remote-peer-id":"91bc3c398fb3c146"}
{"level":"warn","ts":"2025-03-01T04:35:01.545156+0530","caller":"rafthttp/stream.go:421","msg":"lost TCP streaming connection with remote peer","stream-reader-type":"stream MsgApp v2","local-member-id":"bf9071f4639c75cc","remote-peer-id":"91bc3c398fb3c146","error":"context canceled"}
{"level":"warn","ts":"2025-03-01T04:35:01.545178+0530","caller":"rafthttp/peer_status.go:66","msg":"peer became inactive (message send to peer failed)","peer-id":"91bc3c398fb3c146","error":"failed to read 91bc3c398fb3c146 on stream MsgApp v2 (context canceled)"}
{"level":"info","ts":"2025-03-01T04:35:01.545199+0530","caller":"rafthttp/stream.go:442","msg":"stopped stream reader with remote peer","stream-reader-type":"stream MsgApp v2","local-member-id":"bf9071f4639c75cc","remote-peer-id":"91bc3c398fb3c146"}
{"level":"warn","ts":"2025-03-01T04:35:01.545246+0530","caller":"rafthttp/stream.go:421","msg":"lost TCP streaming connection with remote peer","stream-reader-type":"stream Message","local-member-id":"bf9071f4639c75cc","remote-peer-id":"91bc3c398fb3c146","error":"context canceled"}
{"level":"info","ts":"2025-03-01T04:35:01.545263+0530","caller":"rafthttp/stream.go:442","msg":"stopped stream reader with remote peer","stream-reader-type":"stream Message","local-member-id":"bf9071f4639c75cc","remote-peer-id":"91bc3c398fb3c146"}
{"level":"info","ts":"2025-03-01T04:35:01.545272+0530","caller":"rafthttp/peer.go:335","msg":"stopped remote peer","remote-peer-id":"91bc3c398fb3c146"}
{"level":"info","ts":"2025-03-01T04:35:01.545282+0530","caller":"rafthttp/peer.go:330","msg":"stopping remote peer","remote-peer-id":"fd422379fda50e48"}
{"level":"warn","ts":"2025-03-01T04:35:01.545307+0530","caller":"rafthttp/stream.go:286","msg":"closed TCP streaming connection with remote peer","stream-writer-type":"stream MsgApp v2","remote-peer-id":"fd422379fda50e48"}
{"level":"info","ts":"2025-03-01T04:35:01.545328+0530","caller":"rafthttp/stream.go:294","msg":"stopped TCP streaming connection with remote peer","stream-writer-type":"stream MsgApp v2","remote-peer-id":"fd422379fda50e48"}
{"level":"warn","ts":"2025-03-01T04:35:01.545359+0530","caller":"rafthttp/stream.go:286","msg":"closed TCP streaming connection with remote peer","stream-writer-type":"stream Message","remote-peer-id":"fd422379fda50e48"}
{"level":"info","ts":"2025-03-01T04:35:01.545379+0530","caller":"rafthttp/stream.go:294","msg":"stopped TCP streaming connection with remote peer","stream-writer-type":"stream Message","remote-peer-id":"fd422379fda50e48"}
{"level":"info","ts":"2025-03-01T04:35:01.545410+0530","caller":"rafthttp/pipeline.go:85","msg":"stopped HTTP pipelining with remote peer","local-member-id":"bf9071f4639c75cc","remote-peer-id":"fd422379fda50e48"}
{"level":"warn","ts":"2025-03-01T04:35:01.545467+0530","caller":"rafthttp/stream.go:421","msg":"lost TCP streaming connection with remote peer","stream-reader-type":"stream MsgApp v2","local-member-id":"bf9071f4639c75cc","remote-peer-id":"fd422379fda50e48","error":"context canceled"}
{"level":"warn","ts":"2025-03-01T04:35:01.545485+0530","caller":"rafthttp/peer_status.go:66","msg":"peer became inactive (message send to peer failed)","peer-id":"fd422379fda50e48","error":"failed to read fd422379fda50e48 on stream MsgApp v2 (context canceled)"}
{"level":"info","ts":"2025-03-01T04:35:01.545504+0530","caller":"rafthttp/stream.go:442","msg":"stopped stream reader with remote peer","stream-reader-type":"stream MsgApp v2","local-member-id":"bf9071f4639c75cc","remote-peer-id":"fd422379fda50e48"}
{"level":"warn","ts":"2025-03-01T04:35:01.545560+0530","caller":"rafthttp/stream.go:421","msg":"lost TCP streaming connection with remote peer","stream-reader-type":"stream Message","local-member-id":"bf9071f4639c75cc","remote-peer-id":"fd422379fda50e48","error":"context canceled"}
{"level":"info","ts":"2025-03-01T04:35:01.545577+0530","caller":"rafthttp/stream.go:442","msg":"stopped stream reader with remote peer","stream-reader-type":"stream Message","local-member-id":"bf9071f4639c75cc","remote-peer-id":"fd422379fda50e48"}
{"level":"info","ts":"2025-03-01T04:35:01.545592+0530","caller":"rafthttp/peer.go:335","msg":"stopped remote peer","remote-peer-id":"fd422379fda50e48"}
{"level":"warn","ts":"2025-03-01T04:35:01.545669+0530","caller":"rafthttp/http.go:413","msg":"failed to find remote peer in cluster","local-member-id":"bf9071f4639c75cc","remote-peer-id-stream-handler":"bf9071f4639c75cc","remote-peer-id-from":"91bc3c398fb3c146","cluster-id":"59a05384c9b79ee"}
{"level":"warn","ts":"2025-03-01T04:35:01.545698+0530","caller":"rafthttp/http.go:413","msg":"failed to find remote peer in cluster","local-member-id":"bf9071f4639c75cc","remote-peer-id-stream-handler":"bf9071f4639c75cc","remote-peer-id-from":"fd422379fda50e48","cluster-id":"59a05384c9b79ee"}
{"level":"warn","ts":"2025-03-01T04:35:01.545732+0530","caller":"rafthttp/http.go:413","msg":"failed to find remote peer in cluster","local-member-id":"bf9071f4639c75cc","remote-peer-id-stream-handler":"bf9071f4639c75cc","remote-peer-id-from":"91bc3c398fb3c146","cluster-id":"59a05384c9b79ee"}
{"level":"warn","ts":"2025-03-01T04:35:01.545765+0530","caller":"rafthttp/http.go:413","msg":"failed to find remote peer in cluster","local-member-id":"bf9071f4639c75cc","remote-peer-id-stream-handler":"bf9071f4639c75cc","remote-peer-id-from":"fd422379fda50e48","cluster-id":"59a05384c9b79ee"}
{"level":"info","ts":"2025-03-01T04:35:01.549658+0530","caller":"embed/etcd.go:613","msg":"stopping serving peer traffic","address":"127.0.0.1:2380"}
{"level":"info","ts":"2025-03-01T04:35:02.550532+0530","caller":"embed/etcd.go:618","msg":"stopped serving peer traffic","address":"127.0.0.1:2380"}
{"level":"info","ts":"2025-03-01T04:35:02.550561+0530","caller":"embed/etcd.go:410","msg":"closed etcd server","name":"node1","data-dir":"/tmp/etcd-node1","advertise-peer-urls":["http://127.0.0.1:2380"],"advertise-client-urls":["http://127.0.0.1:2379"]}

Шаг 4: перезапуск сервера etcd с той же конфигурацией

Перезапустите сервер etcd с прежней конфигурацией, но с новым двоичным файлом etcd.

-etcd-old --name ${name} \
+etcd-new --name ${name} \
  --data-dir /path/to/${name}.etcd \
  --listen-client-urls http://localhost:2379 \
  --advertise-client-urls http://localhost:2379 \
  --listen-peer-urls http://localhost:2380 \
  --initial-advertise-peer-urls http://localhost:2380 \
  --initial-cluster s1=http://localhost:2380,s2=http://localhost:22380,s3=http://localhost:32380 \
  --initial-cluster-token tkn \
  --initial-cluster-state new

Новый etcd v3.6 опубликует свои сведения в кластере. На этом этапе кластер всё ещё работает по протоколу v3.5 — наименьшей общей версии.

{"level":"info","ts":"2025-03-01T04:40:36.828+0530","caller":"api/capability.go:76","msg":"enabled capabilities for version","cluster-version":"3.5"}

{"level":"info","ts":"2025-03-01T04:40:36.889+0530","caller":"membership/cluster.go:539","msg":"updated cluster version","cluster-id":"59a05384c9b79ee","local-member-id":"bf9071f4639c75cc","from":"3.0","to":"3.5"}

{"level":"info","ts":"2025-03-01T04:40:36.828+0530","caller":"api/capability.go:76","msg":"enabled capabilities for version","cluster-version":"3.5"}

{"level":"info","ts":"2025-03-01T04:40:36.894+0530","caller":"etcdserver/server.go:1686","msg":"published local member to cluster through raft","local-member-id":"bf9071f4639c75cc","local-member-attributes":"{Name:node1 ClientURLs:[http://127.0.0.1:2379]}","cluster-id":"59a05384c9b79ee","publish-timeout":"7s"}

Убедитесь, что сначала каждый участник, а затем весь кластер становятся исправными с новым двоичным файлом etcd v3.6:

etcdctl endpoint health --endpoints=localhost:2379,localhost:22379,localhost:32379
<<COMMENT
localhost:2379 is healthy: successfully committed proposal: took = 1.704998ms
localhost:22379 is healthy: successfully committed proposal: took = 2.331754ms
localhost:32379 is healthy: successfully committed proposal: took = 2.490705ms
COMMENT

До обновления всего кластера необновлённые участники будут записывать в журнал подобные предупреждения.

Это ожидаемо и прекратится после обновления всех участников кластера etcd до v3.6:

{"level":"warn","ts":"2025-03-01T04:40:37.545960+0530","caller":"etcdserver/cluster_util.go:189","msg":"leader found higher-versioned member","local-member-version":"3.5.18","remote-member-id":"bf9071f4639c75cc","remote-member-version":"3.6.0-alpha.0"}

Шаг 5: повторение шага 3 и шага 4 для остальных участников

После обновления всех участников кластер сообщит об успешном переходе на v3.6:

Участник 1:

{"level":"info","ts":"2025-03-01T04:58:32.375+0530","caller":"etcdserver/server.go:2149","msg":"updating cluster version using v3 API","from":"3.5","to":"3.6"} {"level":"info","ts":"2025-03-01T04:58:32.377+0530","caller":"etcdserver/server.go:2164","msg":"cluster version is updated","cluster-version":"3.6"}

Участник 2:

{"level":"info","ts":"2025-03-01T04:58:32.377+0530","caller":"membership/cluster.go:539","msg":"updated cluster version","cluster-id":"59a05384c9b79ee","local-member-id":"91bc3c398fb3c146","from":"3.5","to":"3.6"}

Участник 3:

{"level":"info","ts":"2025-03-01T04:58:32.377+0530","caller":"membership/cluster.go:539","msg":"updated cluster version","cluster-id":"59a05384c9b79ee","local-member-id":"fd422379fda50e48","from":"3.5","to":"3.6"}

endpoint health --endpoints=localhost:2379,localhost:22379,localhost:32379
<<COMMENT
localhost:2379 is healthy: successfully committed proposal: took = 492.834µs
localhost:22379 is healthy: successfully committed proposal: took = 1.015025ms
localhost:32379 is healthy: successfully committed proposal: took = 1.853077ms
COMMENT

curl http://localhost:2379/version
<<COMMENT
{"etcdserver":"3.6.0-alpha.0","etcdcluster":"3.6.0"}
COMMENT

curl http://localhost:22379/version
<<COMMENT
{"etcdserver":"3.6.0-alpha.0","etcdcluster":"3.6.0"}
COMMENT

curl http://localhost:32379/version
<<COMMENT
{"etcdserver":"3.6.0-alpha.0","etcdcluster":"3.6.0"}
COMMENT

3 - Обновление etcd с 3.4 до 3.5

Процессы, контрольные списки и примечания по обновлению etcd с 3.4 до 3.5

В общем случае переход с etcd 3.4 на 3.5 можно выполнить как скользящее обновление без простоя:

  • поочерёдно останавливать процессы etcd v3.4 и заменять их процессами etcd v3.5
  • после запуска всех процессов v3.5 кластеру становятся доступны новые возможности v3.5

До начала обновления прочитайте оставшуюся часть руководства и подготовьтесь.

Контрольные списки обновления

Предупреждение

При миграции с v2 без данных v3 сервер etcd v3.2+ аварийно завершается, если etcd восстанавливается из существующих снимков, но файл v3 ETCD_DATA_DIR/member/snap/db отсутствует. Это происходит, когда сервер был перенесён с v2 и ранее не содержал данных v3. Такое поведение также предотвращает случайную потерю данных v3 (например, если файл db перемещён). etcd требует, чтобы после миграции на v3 работа продолжалась только при наличии данных v3. Не обновляйтесь до более новых версий v3, пока сервер v3.0 не содержит данные v3.

Предупреждение

Если в кластере включена аутентификация, скользящее обновление с 3.4 или более ранней версии не поддерживается, поскольку 3.5 изменяет формат относящихся к аутентификации записей WAL .

Основные нарушающие совместимость изменения в 3.5.

Устаревшая метрика Prometheus etcd_debugging_mvcc_db_total_size_in_bytes

Чтобы стимулировать мониторинг хранилища etcd, в v3.5 метрика Prometheus etcd_debugging_mvcc_db_total_size_in_bytes переведена в etcd_mvcc_db_total_size_in_bytes. В v3.5 метрика etcd_debugging_mvcc_db_total_size_in_bytes полностью объявлена устаревшей.

-etcd_debugging_mvcc_db_total_size_in_bytes
+etcd_mvcc_db_total_size_in_bytes

Обратите внимание: метрики пространства имён etcd_debugging_* помечены как экспериментальные. По мере улучшения руководства по мониторингу дополнительные метрики могут становиться стабильными.

Устаревшая метрика Prometheus etcd_debugging_mvcc_put_total

Чтобы стимулировать мониторинг хранилища etcd, в v3.5 метрика Prometheus etcd_debugging_mvcc_put_total переведена в etcd_mvcc_put_total. В v3.5 метрика etcd_debugging_mvcc_put_total полностью объявлена устаревшей.

-etcd_debugging_mvcc_put_total
+etcd_mvcc_put_total

Обратите внимание: метрики пространства имён etcd_debugging_* помечены как экспериментальные. По мере улучшения руководства по мониторингу дополнительные метрики могут становиться стабильными.

Устаревшая метрика Prometheus etcd_debugging_mvcc_delete_total

Чтобы стимулировать мониторинг хранилища etcd, в v3.5 метрика Prometheus etcd_debugging_mvcc_delete_total переведена в etcd_mvcc_delete_total. В v3.5 метрика etcd_debugging_mvcc_delete_total полностью объявлена устаревшей.

-etcd_debugging_mvcc_delete_total
+etcd_mvcc_delete_total

Обратите внимание: метрики пространства имён etcd_debugging_* помечены как экспериментальные. По мере улучшения руководства по мониторингу дополнительные метрики могут становиться стабильными.

Устаревшая метрика Prometheus etcd_debugging_mvcc_txn_total

Чтобы стимулировать мониторинг хранилища etcd, в v3.5 метрика Prometheus etcd_debugging_mvcc_txn_total переведена в etcd_mvcc_txn_total. В v3.5 метрика etcd_debugging_mvcc_txn_total полностью объявлена устаревшей.

-etcd_debugging_mvcc_txn_total
+etcd_mvcc_txn_total

Обратите внимание: метрики пространства имён etcd_debugging_* помечены как экспериментальные. По мере улучшения руководства по мониторингу дополнительные метрики могут становиться стабильными.

Устаревшая метрика Prometheus etcd_debugging_mvcc_range_total

Чтобы стимулировать мониторинг хранилища etcd, в v3.5 метрика Prometheus etcd_debugging_mvcc_range_total переведена в etcd_mvcc_range_total. В v3.5 метрика etcd_debugging_mvcc_range_total полностью объявлена устаревшей.

-etcd_debugging_mvcc_range_total
+etcd_mvcc_range_total

Обратите внимание: метрики пространства имён etcd_debugging_* помечены как экспериментальные. По мере улучшения руководства по мониторингу дополнительные метрики могут становиться стабильными.

Устаревший etcd --logger capnslog

Для поддержки нескольких направлений вывода и структурированного ведения журнала v3.4 по умолчанию использует --logger=zap.

etcd --logger=capnslog объявлен устаревшим в v3.5, а теперь по умолчанию используется --logger=zap.

-etcd --logger=capnslog
+etcd --logger=zap --log-outputs=stderr

+# to write logs to stderr and a.log file at the same time
+etcd --logger=zap --log-outputs=stderr,a.log

В v3.4 добавлена поддержка etcd --logger=zap для структурированного ведения журнала и нескольких направлений вывода. Основная цель — содействовать автоматизированному мониторингу etcd вместо просмотра серверных журналов уже после начала сбоя. В дальнейшем etcd будет записывать как можно меньше сообщений, а его мониторинг с помощью метрик и оповещений станет проще. etcd --logger=capnslog будет объявлен устаревшим в v3.5.

Устаревший etcd --log-output

Для поддержки нескольких направлений вывода журнала в v3.4 etcd --log-output переименован в --log-outputs .

etcd --log-output объявлен устаревшим в v3.5.

-etcd --log-output=stderr
+etcd --log-outputs=stderr

Устаревший флаг etcd --debug (теперь --log-level=debug)

Флаг etcd --debug объявлен устаревшим.

-etcd --debug
+etcd --log-level debug

Устаревший etcd --log-package-levels

Флаг etcd --log-package-levels для capnslog объявлен устаревшим.

Теперь по умолчанию используется etcd --logger=zap.

-etcd --log-package-levels 'etcdmain=CRITICAL,etcdserver=DEBUG'
+etcd --logger=zap --log-outputs=stderr

Устаревшая конечная точка [CLIENT-URL]/config/local/log

Конечная точка /config/local/log, как и флаг etcd --log-package-levels, объявляется устаревшей в v3.5.

-$ curl http://127.0.0.1:2379/config/local/log -XPUT -d '{"Level":"DEBUG"}'
-# debug logging enabled

Изменённые конечные точки HTTP шлюза gRPC (устаревшая /v3beta)

До

curl -L http://localhost:2379/v3beta/kv/put \
  -X POST -d '{"key": "Zm9v", "value": "YmFy"}'

После

curl -L http://localhost:2379/v3/kv/put \
  -X POST -d '{"key": "Zm9v", "value": "YmFy"}'

/v3beta удалена в выпуске 3.5.

Контрольные списки обновления сервера

Требования к обновлению

Для обновления существующего развёртывания etcd до 3.5 работающий кластер должен иметь версию 3.4 или более позднюю. Если версия старше 3.4, перед переходом на 3.5 обновитесь до 3.4 .

Кроме того, для плавного скользящего обновления работающий кластер должен быть исправен. Перед продолжением проверьте его работоспособность командой etcdctl endpoint health.

Подготовка

Перед обновлением etcd обязательно протестируйте зависящие от него службы в промежуточном окружении, прежде чем развёртывать обновление в рабочем окружении.

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

Смешанные версии

Во время обновления кластер etcd поддерживает участников разных версий и работает по протоколу наименьшей общей версии. Кластер считается обновлённым только после обновления всех участников до 3.5. Участники etcd согласуют между собой общую версию кластера, которая определяет сообщаемую версию и поддерживаемые возможности.

Ограничения

Примечание: это ограничение не относится к кластеру, содержащему только данные v3 и не содержащему данные v2.

Если кластер обслуживает набор данных v2 объёмом более 50MB, каждому только что обновлённому участнику может потребоваться до двух минут, чтобы догнать существующий кластер. Для оценки общего объёма данных проверьте размер недавнего снимка. Иными словами, безопаснее всего ждать 2 минуты между обновлениями участников.

При значительно большем общем объёме данных, 100MB или более, этот однократный процесс может занять ещё больше времени. Администраторы столь крупных кластеров etcd могут перед обновлением обратиться к команде etcd за рекомендациями по процедуре.

Понижение версии

После обновления всех участников до v3.5 кластер также переходит на v3.5, и понижение версии из этого завершённого состояния невозможно. Однако пока хотя бы один участник остаётся на v3.4, кластер и его операции имеют версию “v3.4”, а из смешанного состояния можно вернуться к использованию двоичного файла etcd v3.4 на всех участниках.

Загрузите резервную копию снимка , чтобы сохранить возможность понижения версии кластера даже после полного обновления.

Процедура обновления

В этом примере показано обновление работающего на локальной машине кластера etcd v3.4 из 3 участников.

Шаг 1: проверка требований к обновлению

Кластер исправен и использует v3.4.x?

etcdctl --endpoints=localhost:2379,localhost:22379,localhost:32379 endpoint health
<<COMMENT
localhost:2379 is healthy: successfully committed proposal: took = 2.118638ms
localhost:22379 is healthy: successfully committed proposal: took = 3.631388ms
localhost:32379 is healthy: successfully committed proposal: took = 2.157051ms
COMMENT

curl http://localhost:2379/version
<<COMMENT
{"etcdserver":"3.4.0","etcdcluster":"3.4.0"}
COMMENT

curl http://localhost:22379/version
<<COMMENT
{"etcdserver":"3.4.0","etcdcluster":"3.4.0"}
COMMENT

curl http://localhost:32379/version
<<COMMENT
{"etcdserver":"3.4.0","etcdcluster":"3.4.0"}
COMMENT

Шаг 2: загрузка резервной копии снимка с лидера

Загрузите резервную копию снимка , чтобы обеспечить путь понижения версии при возникновении проблем.

Лидер etcd гарантированно содержит последние данные приложения, поэтому снимок следует получать с лидера:

curl -sL http://localhost:2379/metrics | grep etcd_server_is_leader
<<COMMENT
# HELP etcd_server_is_leader Whether or not this member is a leader. 1 if is, 0 otherwise.
# TYPE etcd_server_is_leader gauge
etcd_server_is_leader 1
COMMENT

curl -sL http://localhost:22379/metrics | grep etcd_server_is_leader
<<COMMENT
etcd_server_is_leader 0
COMMENT

curl -sL http://localhost:32379/metrics | grep etcd_server_is_leader
<<COMMENT
etcd_server_is_leader 0
COMMENT

etcdctl --endpoints=localhost:2379 snapshot save backup.db
<<COMMENT
{"level":"info","ts":1526585787.148433,"caller":"snapshot/v3_snapshot.go:109","msg":"created temporary db file","path":"backup.db.part"}
{"level":"info","ts":1526585787.1485257,"caller":"snapshot/v3_snapshot.go:120","msg":"fetching snapshot","endpoint":"localhost:2379"}
{"level":"info","ts":1526585787.1519694,"caller":"snapshot/v3_snapshot.go:133","msg":"fetched snapshot","endpoint":"localhost:2379","took":0.003502721}
{"level":"info","ts":1526585787.1520295,"caller":"snapshot/v3_snapshot.go:142","msg":"saved","path":"backup.db"}
Snapshot saved at backup.db
COMMENT

Шаг 3: остановка одного существующего сервера etcd

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

{"level":"info","ts":1526587281.2001143,"caller":"etcdserver/server.go:2249","msg":"updating cluster version","from":"3.0","to":"3.4"}
{"level":"info","ts":1526587281.2010646,"caller":"membership/cluster.go:473","msg":"updated cluster version","cluster-id":"7dee9ba76d59ed53","local-member-id":"7339c4e5e833c029","from":"3.0","from":"3.4"}
{"level":"info","ts":1526587281.2012327,"caller":"api/capability.go:76","msg":"enabled capabilities for version","cluster-version":"3.4"}
{"level":"info","ts":1526587281.2013083,"caller":"etcdserver/server.go:2272","msg":"cluster version is updated","cluster-version":"3.4"}



^C{"level":"info","ts":1526587299.0717514,"caller":"osutil/interrupt_unix.go:63","msg":"received signal; shutting down","signal":"interrupt"}
{"level":"info","ts":1526587299.0718873,"caller":"embed/etcd.go:285","msg":"closing etcd server","name":"s1","data-dir":"/tmp/etcd/s1","advertise-peer-urls":["http://localhost:2380"],"advertise-client-urls":["http://localhost:2379"]}
{"level":"info","ts":1526587299.0722554,"caller":"etcdserver/server.go:1341","msg":"leadership transfer starting","local-member-id":"7339c4e5e833c029","current-leader-member-id":"7339c4e5e833c029","transferee-member-id":"729934363faa4a24"}
{"level":"info","ts":1526587299.0723994,"caller":"raft/raft.go:1107","msg":"7339c4e5e833c029 [term 3] starts to transfer leadership to 729934363faa4a24"}
{"level":"info","ts":1526587299.0724802,"caller":"raft/raft.go:1113","msg":"7339c4e5e833c029 sends MsgTimeoutNow to 729934363faa4a24 immediately as 729934363faa4a24 already has up-to-date log"}
{"level":"info","ts":1526587299.0737045,"caller":"raft/raft.go:797","msg":"7339c4e5e833c029 [term: 3] received a MsgVote message with higher term from 729934363faa4a24 [term: 4]"}
{"level":"info","ts":1526587299.0737681,"caller":"raft/raft.go:656","msg":"7339c4e5e833c029 became follower at term 4"}
{"level":"info","ts":1526587299.073831,"caller":"raft/raft.go:882","msg":"7339c4e5e833c029 [logterm: 3, index: 9, vote: 0] cast MsgVote for 729934363faa4a24 [logterm: 3, index: 9] at term 4"}
{"level":"info","ts":1526587299.0738947,"caller":"raft/node.go:312","msg":"raft.node: 7339c4e5e833c029 lost leader 7339c4e5e833c029 at term 4"}
{"level":"info","ts":1526587299.0748374,"caller":"raft/node.go:306","msg":"raft.node: 7339c4e5e833c029 elected leader 729934363faa4a24 at term 4"}
{"level":"info","ts":1526587299.1726425,"caller":"etcdserver/server.go:1362","msg":"leadership transfer finished","local-member-id":"7339c4e5e833c029","old-leader-member-id":"7339c4e5e833c029","new-leader-member-id":"729934363faa4a24","took":0.100389359}
{"level":"info","ts":1526587299.1728148,"caller":"rafthttp/peer.go:333","msg":"stopping remote peer","remote-peer-id":"b548c2511513015"}
{"level":"warn","ts":1526587299.1751974,"caller":"rafthttp/stream.go:291","msg":"closed TCP streaming connection with remote peer","stream-writer-type":"stream MsgApp v2","remote-peer-id":"b548c2511513015"}
{"level":"warn","ts":1526587299.1752589,"caller":"rafthttp/stream.go:301","msg":"stopped TCP streaming connection with remote peer","stream-writer-type":"stream MsgApp v2","remote-peer-id":"b548c2511513015"}
{"level":"warn","ts":1526587299.177348,"caller":"rafthttp/stream.go:291","msg":"closed TCP streaming connection with remote peer","stream-writer-type":"stream Message","remote-peer-id":"b548c2511513015"}
{"level":"warn","ts":1526587299.1774004,"caller":"rafthttp/stream.go:301","msg":"stopped TCP streaming connection with remote peer","stream-writer-type":"stream Message","remote-peer-id":"b548c2511513015"}
{"level":"info","ts":1526587299.177515,"caller":"rafthttp/pipeline.go:86","msg":"stopped HTTP pipelining with remote peer","local-member-id":"7339c4e5e833c029","remote-peer-id":"b548c2511513015"}
{"level":"warn","ts":1526587299.1777067,"caller":"rafthttp/stream.go:436","msg":"lost TCP streaming connection with remote peer","stream-reader-type":"stream MsgApp v2","local-member-id":"7339c4e5e833c029","remote-peer-id":"b548c2511513015","error":"read tcp 127.0.0.1:34636->127.0.0.1:32380: use of closed network connection"}
{"level":"info","ts":1526587299.1778402,"caller":"rafthttp/stream.go:459","msg":"stopped stream reader with remote peer","stream-reader-type":"stream MsgApp v2","local-member-id":"7339c4e5e833c029","remote-peer-id":"b548c2511513015"}
{"level":"warn","ts":1526587299.1780295,"caller":"rafthttp/stream.go:436","msg":"lost TCP streaming connection with remote peer","stream-reader-type":"stream Message","local-member-id":"7339c4e5e833c029","remote-peer-id":"b548c2511513015","error":"read tcp 127.0.0.1:34634->127.0.0.1:32380: use of closed network connection"}
{"level":"info","ts":1526587299.1780987,"caller":"rafthttp/stream.go:459","msg":"stopped stream reader with remote peer","stream-reader-type":"stream Message","local-member-id":"7339c4e5e833c029","remote-peer-id":"b548c2511513015"}
{"level":"info","ts":1526587299.1781602,"caller":"rafthttp/peer.go:340","msg":"stopped remote peer","remote-peer-id":"b548c2511513015"}
{"level":"info","ts":1526587299.1781986,"caller":"rafthttp/peer.go:333","msg":"stopping remote peer","remote-peer-id":"729934363faa4a24"}
{"level":"warn","ts":1526587299.1802843,"caller":"rafthttp/stream.go:291","msg":"closed TCP streaming connection with remote peer","stream-writer-type":"stream MsgApp v2","remote-peer-id":"729934363faa4a24"}
{"level":"warn","ts":1526587299.1803446,"caller":"rafthttp/stream.go:301","msg":"stopped TCP streaming connection with remote peer","stream-writer-type":"stream MsgApp v2","remote-peer-id":"729934363faa4a24"}
{"level":"warn","ts":1526587299.1824749,"caller":"rafthttp/stream.go:291","msg":"closed TCP streaming connection with remote peer","stream-writer-type":"stream Message","remote-peer-id":"729934363faa4a24"}
{"level":"warn","ts":1526587299.18255,"caller":"rafthttp/stream.go:301","msg":"stopped TCP streaming connection with remote peer","stream-writer-type":"stream Message","remote-peer-id":"729934363faa4a24"}
{"level":"info","ts":1526587299.18261,"caller":"rafthttp/pipeline.go:86","msg":"stopped HTTP pipelining with remote peer","local-member-id":"7339c4e5e833c029","remote-peer-id":"729934363faa4a24"}
{"level":"warn","ts":1526587299.1827736,"caller":"rafthttp/stream.go:436","msg":"lost TCP streaming connection with remote peer","stream-reader-type":"stream MsgApp v2","local-member-id":"7339c4e5e833c029","remote-peer-id":"729934363faa4a24","error":"read tcp 127.0.0.1:51482->127.0.0.1:22380: use of closed network connection"}
{"level":"info","ts":1526587299.182845,"caller":"rafthttp/stream.go:459","msg":"stopped stream reader with remote peer","stream-reader-type":"stream MsgApp v2","local-member-id":"7339c4e5e833c029","remote-peer-id":"729934363faa4a24"}
{"level":"warn","ts":1526587299.1830168,"caller":"rafthttp/stream.go:436","msg":"lost TCP streaming connection with remote peer","stream-reader-type":"stream Message","local-member-id":"7339c4e5e833c029","remote-peer-id":"729934363faa4a24","error":"context canceled"}
{"level":"warn","ts":1526587299.1831107,"caller":"rafthttp/peer_status.go:65","msg":"peer became inactive","peer-id":"729934363faa4a24","error":"failed to read 729934363faa4a24 on stream Message (context canceled)"}
{"level":"info","ts":1526587299.1831737,"caller":"rafthttp/stream.go:459","msg":"stopped stream reader with remote peer","stream-reader-type":"stream Message","local-member-id":"7339c4e5e833c029","remote-peer-id":"729934363faa4a24"}
{"level":"info","ts":1526587299.1832306,"caller":"rafthttp/peer.go:340","msg":"stopped remote peer","remote-peer-id":"729934363faa4a24"}
{"level":"warn","ts":1526587299.1837125,"caller":"rafthttp/http.go:424","msg":"failed to find remote peer in cluster","local-member-id":"7339c4e5e833c029","remote-peer-id-stream-handler":"7339c4e5e833c029","remote-peer-id-from":"b548c2511513015","cluster-id":"7dee9ba76d59ed53"}
{"level":"warn","ts":1526587299.1840093,"caller":"rafthttp/http.go:424","msg":"failed to find remote peer in cluster","local-member-id":"7339c4e5e833c029","remote-peer-id-stream-handler":"7339c4e5e833c029","remote-peer-id-from":"b548c2511513015","cluster-id":"7dee9ba76d59ed53"}
{"level":"warn","ts":1526587299.1842315,"caller":"rafthttp/http.go:424","msg":"failed to find remote peer in cluster","local-member-id":"7339c4e5e833c029","remote-peer-id-stream-handler":"7339c4e5e833c029","remote-peer-id-from":"729934363faa4a24","cluster-id":"7dee9ba76d59ed53"}
{"level":"warn","ts":1526587299.1844475,"caller":"rafthttp/http.go:424","msg":"failed to find remote peer in cluster","local-member-id":"7339c4e5e833c029","remote-peer-id-stream-handler":"7339c4e5e833c029","remote-peer-id-from":"729934363faa4a24","cluster-id":"7dee9ba76d59ed53"}
{"level":"info","ts":1526587299.2056687,"caller":"embed/etcd.go:473","msg":"stopping serving peer traffic","address":"127.0.0.1:2380"}
{"level":"info","ts":1526587299.205819,"caller":"embed/etcd.go:480","msg":"stopped serving peer traffic","address":"127.0.0.1:2380"}
{"level":"info","ts":1526587299.2058413,"caller":"embed/etcd.go:289","msg":"closed etcd server","name":"s1","data-dir":"/tmp/etcd/s1","advertise-peer-urls":["http://localhost:2380"],"advertise-client-urls":["http://localhost:2379"]}

Шаг 4: перезапуск сервера etcd с той же конфигурацией

Перезапустите сервер etcd с прежней конфигурацией, но с новым двоичным файлом etcd.

-etcd-old --name s1 \
+etcd-new --name s1 \
  --data-dir /tmp/etcd/s1 \
  --listen-client-urls http://localhost:2379 \
  --advertise-client-urls http://localhost:2379 \
  --listen-peer-urls http://localhost:2380 \
  --initial-advertise-peer-urls http://localhost:2380 \
  --initial-cluster s1=http://localhost:2380,s2=http://localhost:22380,s3=http://localhost:32380 \
  --initial-cluster-token tkn \
  --initial-cluster-state new

Новый etcd v3.5 опубликует свои сведения в кластере. На этом этапе кластер всё ещё работает по протоколу v3.4 — наименьшей общей версии.

{"level":"info","ts":1526586617.1647713,"caller":"membership/cluster.go:485","msg":"set initial cluster version","cluster-id":"7dee9ba76d59ed53","local-member-id":"7339c4e5e833c029","cluster-version":"3.0"}

{"level":"info","ts":1526586617.1648536,"caller":"api/capability.go:76","msg":"enabled capabilities for version","cluster-version":"3.0"}

{"level":"info","ts":1526586617.1649303,"caller":"membership/cluster.go:473","msg":"updated cluster version","cluster-id":"7dee9ba76d59ed53","local-member-id":"7339c4e5e833c029","from":"3.0","from":"3.4"}

{"level":"info","ts":1526586617.1649797,"caller":"api/capability.go:76","msg":"enabled capabilities for version","cluster-version":"3.4"}

{"level":"info","ts":1526586617.2107732,"caller":"etcdserver/server.go:1770","msg":"published local member to cluster through raft","local-member-id":"7339c4e5e833c029","local-member-attributes":"{Name:s1 ClientURLs:[http://localhost:2379]}","request-path":"/0/members/7339c4e5e833c029/attributes","cluster-id":"7dee9ba76d59ed53","publish-timeout":7}

Убедитесь, что сначала каждый участник, а затем весь кластер становятся исправными с новым двоичным файлом etcd v3.5:

etcdctl endpoint health --endpoints=localhost:2379,localhost:22379,localhost:32379
<<COMMENT
localhost:32379 is healthy: successfully committed proposal: took = 2.337471ms
localhost:22379 is healthy: successfully committed proposal: took = 1.130717ms
localhost:2379 is healthy: successfully committed proposal: took = 2.124843ms
COMMENT

До обновления всего кластера необновлённые участники будут записывать в журнал подобные предупреждения.

Это ожидаемо и прекратится после обновления всех участников кластера etcd до v3.5:

:41.942121 W | etcdserver: member 7339c4e5e833c029 has a higher version 3.5.0
:45.945154 W | etcdserver: the local etcd version 3.4.0 is not up-to-date

Шаг 5: повторение шага 3 и шага 4 для остальных участников

После обновления всех участников кластер сообщит об успешном переходе на 3.5:

Участник 1:

{"level":"info","ts":1526586949.0920913,"caller":"api/capability.go:76","msg":"enabled capabilities for version","cluster-version":"3.5"} {"level":"info","ts":1526586949.0921566,"caller":"etcdserver/server.go:2272","msg":"cluster version is updated","cluster-version":"3.5"}

Участник 2:

{"level":"info","ts":1526586949.092117,"caller":"membership/cluster.go:473","msg":"updated cluster version","cluster-id":"7dee9ba76d59ed53","local-member-id":"729934363faa4a24","from":"3.4","from":"3.5"} {"level":"info","ts":1526586949.0923078,"caller":"api/capability.go:76","msg":"enabled capabilities for version","cluster-version":"3.5"}

Участник 3:

{"level":"info","ts":1526586949.0921423,"caller":"membership/cluster.go:473","msg":"updated cluster version","cluster-id":"7dee9ba76d59ed53","local-member-id":"b548c2511513015","from":"3.4","from":"3.5"} {"level":"info","ts":1526586949.0922918,"caller":"api/capability.go:76","msg":"enabled capabilities for version","cluster-version":"3.5"}

endpoint health --endpoints=localhost:2379,localhost:22379,localhost:32379
<<COMMENT
localhost:2379 is healthy: successfully committed proposal: took = 492.834µs
localhost:22379 is healthy: successfully committed proposal: took = 1.015025ms
localhost:32379 is healthy: successfully committed proposal: took = 1.853077ms
COMMENT

curl http://localhost:2379/version
<<COMMENT
{"etcdserver":"3.5.0","etcdcluster":"3.5.0"}
COMMENT

curl http://localhost:22379/version
<<COMMENT
{"etcdserver":"3.5.0","etcdcluster":"3.5.0"}
COMMENT

curl http://localhost:32379/version
<<COMMENT
{"etcdserver":"3.5.0","etcdcluster":"3.5.0"}
COMMENT

4 - Обновление etcd с 3.3 до 3.4

Процессы, контрольные списки и примечания по обновлению etcd с 3.3 до 3.4

В общем случае переход с etcd 3.3 на 3.4 можно выполнить как скользящее обновление без простоя:

  • поочерёдно останавливать процессы etcd v3.3 и заменять их процессами etcd v3.4
  • после запуска всех процессов v3.4 кластеру становятся доступны новые возможности v3.4

До начала обновления прочитайте оставшуюся часть руководства и подготовьтесь.

Контрольные списки обновления

Предупреждение

При миграции с v2 без данных v3 сервер etcd v3.2+ аварийно завершается, если etcd восстанавливается из существующих снимков, но файл v3 ETCD_DATA_DIR/member/snap/db отсутствует. Это происходит, когда сервер был перенесён с v2 и ранее не содержал данных v3. Такое поведение также предотвращает случайную потерю данных v3 (например, если файл db перемещён). etcd требует, чтобы после миграции на v3 работа продолжалась только при наличии данных v3. Не обновляйтесь до более новых версий v3, пока сервер v3.0 не содержит данные v3.

Основные нарушающие совместимость изменения в 3.4.

Использование ETCDCTL_API=3 etcdctl по умолчанию

Теперь ETCDCTL_API=3 используется по умолчанию.

etcdctl set foo bar
Error: unknown command "set" for "etcdctl"

-etcdctl set foo bar
+ETCDCTL_API=2 etcdctl set foo bar
bar

ETCDCTL_API=3 etcdctl put foo bar
OK

-ETCDCTL_API=3 etcdctl put foo bar
+etcdctl put foo bar

Использование etcd --enable-v2=false по умолчанию

Теперь etcd --enable-v2=false используется по умолчанию.

Это означает, что без явного etcd --enable-v2=true сервер etcd v3.4 не обслуживает запросы API v2.

Если использовался API v2, обязательно включите API v2 в v3.4:

-etcd
+etcd --enable-v2=true

Остальные API HTTP продолжат работать (например, [CLIENT-URL]/metrics, [CLIENT-URL]/health и шлюз gRPC v3).

Устаревшие флаги etcd --ca-file и etcd --peer-ca-file

Флаги --ca-file и --peer-ca-file устарели; они объявлены устаревшими начиная с v2.1.

Обратите внимание: задание этого параметра автоматически включает аутентификацию по клиентскому сертификату независимо от значения --client-cert-auth.

-etcd --ca-file ca-client.crt
+etcd --trusted-ca-file ca-client.crt
-etcd --peer-ca-file ca-peer.crt
+etcd --peer-trusted-ca-file ca-peer.crt

Устаревшая ошибка grpc.ErrClientConnClosing

grpc.ErrClientConnClosing объявлена устаревшей в gRPC >= 1.10 .

import (
+	"go.etcd.io/etcd/clientv3"

	"google.golang.org/grpc"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
)

_, err := kvc.Get(ctx, "a")
-if err == grpc.ErrClientConnClosing {
+if clientv3.IsConnCanceled(err) {

// or
+s, ok := status.FromError(err)
+if ok {
+  if s.Code() == codes.Canceled

Требование grpc.WithBlock для клиентского подключения

Новый клиентский балансировщик использует асинхронный разрешитель для передачи конечных точек функции подключения gRPC. Поэтому клиенту v3.4 требуется параметр подключения grpc.WithBlock, чтобы дождаться установления нижележащего соединения.

import (
	"time"
	"go.etcd.io/etcd/clientv3"
+	"google.golang.org/grpc"
)

+// "grpc.WithBlock()" to block until the underlying connection is up
ccfg := clientv3.Config{
  Endpoints:            []string{"localhost:2379"},
  DialTimeout:          time.Second,
+ DialOptions:          []grpc.DialOption{grpc.WithBlock()},
  DialKeepAliveTime:    time.Second,
  DialKeepAliveTimeout: 500 * time.Millisecond,
}

Объявление метрики Prometheus etcd_debugging_mvcc_db_total_size_in_bytes устаревшей

Чтобы стимулировать мониторинг хранилища etcd, в v3.4 метрика Prometheus etcd_debugging_mvcc_db_total_size_in_bytes переведена в etcd_mvcc_db_total_size_in_bytes.

Для обратной совместимости etcd_debugging_mvcc_db_total_size_in_bytes всё ещё предоставляется в v3.4. В v3.5 она будет полностью объявлена устаревшей.

-etcd_debugging_mvcc_db_total_size_in_bytes
+etcd_mvcc_db_total_size_in_bytes

Обратите внимание: метрики пространства имён etcd_debugging_* помечены как экспериментальные. По мере улучшения руководства по мониторингу дополнительные метрики могут становиться стабильными.

Объявление метрики Prometheus etcd_debugging_mvcc_put_total устаревшей

Чтобы стимулировать мониторинг хранилища etcd, в v3.4 метрика Prometheus etcd_debugging_mvcc_put_total переведена в etcd_mvcc_put_total.

Для обратной совместимости etcd_debugging_mvcc_put_total всё ещё предоставляется в v3.4. В v3.5 она будет полностью объявлена устаревшей.

-etcd_debugging_mvcc_put_total
+etcd_mvcc_put_total

Обратите внимание: метрики пространства имён etcd_debugging_* помечены как экспериментальные. По мере улучшения руководства по мониторингу дополнительные метрики могут становиться стабильными.

Объявление метрики Prometheus etcd_debugging_mvcc_delete_total устаревшей

Чтобы стимулировать мониторинг хранилища etcd, в v3.4 метрика Prometheus etcd_debugging_mvcc_delete_total переведена в etcd_mvcc_delete_total.

Для обратной совместимости etcd_debugging_mvcc_delete_total всё ещё предоставляется в v3.4. В v3.5 она будет полностью объявлена устаревшей.

-etcd_debugging_mvcc_delete_total
+etcd_mvcc_delete_total

Обратите внимание: метрики пространства имён etcd_debugging_* помечены как экспериментальные. По мере улучшения руководства по мониторингу дополнительные метрики могут становиться стабильными.

Объявление метрики Prometheus etcd_debugging_mvcc_txn_total устаревшей

Чтобы стимулировать мониторинг хранилища etcd, в v3.4 метрика Prometheus etcd_debugging_mvcc_txn_total переведена в etcd_mvcc_txn_total.

Для обратной совместимости etcd_debugging_mvcc_txn_total всё ещё предоставляется в v3.4. В v3.5 она будет полностью объявлена устаревшей.

-etcd_debugging_mvcc_txn_total
+etcd_mvcc_txn_total

Обратите внимание: метрики пространства имён etcd_debugging_* помечены как экспериментальные. По мере улучшения руководства по мониторингу дополнительные метрики могут становиться стабильными.

Объявление метрики Prometheus etcd_debugging_mvcc_range_total устаревшей

Чтобы стимулировать мониторинг хранилища etcd, в v3.4 метрика Prometheus etcd_debugging_mvcc_range_total переведена в etcd_mvcc_range_total.

Для обратной совместимости etcd_debugging_mvcc_range_total всё ещё предоставляется в v3.4. В v3.5 она будет полностью объявлена устаревшей.

-etcd_debugging_mvcc_range_total
+etcd_mvcc_range_total

Обратите внимание: метрики пространства имён etcd_debugging_* помечены как экспериментальные. По мере улучшения руководства по мониторингу дополнительные метрики могут становиться стабильными.

Объявление флага etcd --log-output устаревшим (теперь --log-outputs)

Для поддержки нескольких направлений вывода журнала etcd --log-output переименован в --log-outputs . etcd --logger=capnslog не поддерживает несколько направлений вывода.

etcd --log-output будет объявлен устаревшим в v3.5. etcd --logger=capnslog будет объявлен устаревшим в v3.5.

-etcd --log-output=stderr
+etcd --log-outputs=stderr

+# to write logs to stderr and a.log file at the same time
+# only "--logger=zap" supports multiple writers
+etcd --logger=zap --log-outputs=stderr,a.log

В v3.4 добавлена поддержка etcd --logger=zap --log-outputs=stderr для структурированного ведения журнала и нескольких направлений вывода. Основная цель — содействовать автоматизированному мониторингу etcd вместо просмотра серверных журналов уже после начала сбоя. В дальнейшем etcd будет записывать как можно меньше сообщений, а его мониторинг с помощью метрик и оповещений станет проще. etcd --logger=capnslog будет объявлен устаревшим в v3.5.

Изменение типа поля log-outputs в etcd --config-file на []string

Поскольку log-outputs (прежнее имя поля — log-output) теперь принимает несколько получателей, тип поля log-outputs в файле конфигурации YAML etcd необходимо изменить на []string, как показано ниже:

 # Specify 'stdout' or 'stderr' to skip journald logging even when running under systemd.
-log-output: default
+log-outputs: [default]

Переименование embed.Config.LogOutput в embed.Config.LogOutputs

Для поддержки нескольких направлений вывода embed.Config.LogOutput переименован в embed.Config.LogOutputs , а тип embed.Config.LogOutput изменён с string на []string .

import "github.com/coreos/etcd/embed"

cfg := &embed.Config{Debug: false}
-cfg.LogOutput = "stderr"
+cfg.LogOutputs = []string{"stderr"}

В v3.5 capnslog объявляется устаревшим

В v3.5 флаг etcd --log-package-levels для capnslog будет объявлен устаревшим; по умолчанию будет использоваться etcd --logger=zap --log-outputs=stderr. В v3.5 конечная точка [CLIENT-URL]/config/local/log будет объявлена устаревшей.

-etcd
+etcd --logger zap

Объявление флага etcd --debug устаревшим (теперь --log-level=debug)

В v3.4 флаг etcd --debug объявлен устаревшим. Вместо него используйте etcd --log-level=debug.

-etcd --debug
+etcd --logger zap --log-level debug

Устаревшее поле pkg/transport.TLSInfo.CAFile

Поле pkg/transport.TLSInfo.CAFile объявлено устаревшим.

import "github.com/coreos/etcd/pkg/transport"

tlsInfo := transport.TLSInfo{
    CertFile: "/tmp/test-certs/test.pem",
    KeyFile: "/tmp/test-certs/test-key.pem",
-   CAFile: "/tmp/test-certs/trusted-ca.pem",
+   TrustedCAFile: "/tmp/test-certs/trusted-ca.pem",
}
tlsConfig, err := tlsInfo.ClientConfig()
if err != nil {
    panic(err)
}

Изменение embed.Config.SnapCount на embed.Config.SnapshotCount

Для согласованности с именем флага etcd --snapshot-count поле embed.Config.SnapCount переименовано в embed.Config.SnapshotCount:

import "github.com/coreos/etcd/embed"

cfg := embed.NewConfig()
-cfg.SnapCount = 100000
+cfg.SnapshotCount = 100000

Изменение etcdserver.ServerConfig.SnapCount на etcdserver.ServerConfig.SnapshotCount

Для согласованности с именем флага etcd --snapshot-count поле etcdserver.ServerConfig.SnapCount переименовано в etcdserver.ServerConfig.SnapshotCount:

import "github.com/coreos/etcd/etcdserver"

srvcfg := etcdserver.ServerConfig{
-  SnapCount: 100000,
+  SnapshotCount: 100000,

Изменение сигнатур функций в пакете wal

Сигнатуры функций wal изменены для поддержки структурированного средства ведения журнала.

import "github.com/coreos/etcd/wal"
+import "go.uber.org/zap"

+lg, _ = zap.NewProduction()

-wal.Open(dirpath, snap)
+wal.Open(lg, dirpath, snap)

-wal.OpenForRead(dirpath, snap)
+wal.OpenForRead(lg, dirpath, snap)

-wal.Repair(dirpath)
+wal.Repair(lg, dirpath)

-wal.Create(dirpath, metadata)
+wal.Create(lg, dirpath, metadata)

Изменение типа IntervalTree в пакете pkg/adt

Теперь pkg/adt.IntervalTree определён как interface.

import (
    "fmt"

    "go.etcd.io/etcd/pkg/adt"
)

func main() {
-    ivt := &adt.IntervalTree{}
+    ivt := adt.NewIntervalTree()

Устаревший embed.Config.SetupLogging

embed.Config.SetupLogging удалён для предотвращения неверной конфигурации журналирования; теперь она настраивается автоматически.

import "github.com/coreos/etcd/embed"

cfg := &embed.Config{Debug: false}
-cfg.SetupLogging()

Изменённые конечные точки HTTP шлюза gRPC (/v3beta заменена на /v3)

До

curl -L http://localhost:2379/v3beta/kv/put \
  -X POST -d '{"key": "Zm9v", "value": "YmFy"}'

После

curl -L http://localhost:2379/v3/kv/put \
  -X POST -d '{"key": "Zm9v", "value": "YmFy"}'

Запросы к конечным точкам /v3beta перенаправляются на /v3, а /v3beta будет удалена в выпуске 3.5.

Устаревшие теги образов контейнеров

Теги образов latest и дополнительной версии объявлены устаревшими:

-docker pull gcr.io/etcd-development/etcd:latest
+docker pull gcr.io/etcd-development/etcd:v3.4.0

-docker pull gcr.io/etcd-development/etcd:v3.4
+docker pull gcr.io/etcd-development/etcd:v3.4.0

-docker pull gcr.io/etcd-development/etcd:v3.4
+docker pull gcr.io/etcd-development/etcd:v3.4.1

-docker pull gcr.io/etcd-development/etcd:v3.4
+docker pull gcr.io/etcd-development/etcd:v3.4.2

Контрольные списки обновления сервера

Требования к обновлению

Для обновления существующего развёртывания etcd до 3.4 работающий кластер должен иметь версию 3.3 или более позднюю. Если версия старше 3.3, перед переходом на 3.4 обновитесь до 3.3 .

Кроме того, для плавного скользящего обновления работающий кластер должен быть исправен. Перед продолжением проверьте его работоспособность командой etcdctl endpoint health.

Подготовка

Перед обновлением etcd обязательно протестируйте зависящие от него службы в промежуточном окружении, прежде чем развёртывать обновление в рабочем окружении.

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

Смешанные версии

Во время обновления кластер etcd поддерживает участников разных версий и работает по протоколу наименьшей общей версии. Кластер считается обновлённым только после обновления всех участников до 3.4. Участники etcd согласуют между собой общую версию кластера, которая определяет сообщаемую версию и поддерживаемые возможности.

Ограничения

Примечание: это ограничение не относится к кластеру, содержащему только данные v3 и не содержащему данные v2.

Если кластер обслуживает набор данных v2 объёмом более 50MB, каждому только что обновлённому участнику может потребоваться до двух минут, чтобы догнать существующий кластер. Для оценки общего объёма данных проверьте размер недавнего снимка. Иными словами, безопаснее всего ждать 2 минуты между обновлениями участников.

При значительно большем общем объёме данных, 100MB или более, этот однократный процесс может занять ещё больше времени. Администраторы столь крупных кластеров etcd могут перед обновлением обратиться к команде etcd за рекомендациями по процедуре.

Понижение версии

После обновления всех участников до v3.4 кластер также переходит на v3.4, и понижение версии из этого завершённого состояния невозможно. Однако пока хотя бы один участник остаётся на v3.3, кластер и его операции имеют версию “v3.3”, а из смешанного состояния можно вернуться к использованию двоичного файла etcd v3.3 на всех участниках.

Загрузите резервную копию снимка , чтобы сохранить возможность понижения версии кластера даже после полного обновления.

Процедура обновления

В этом примере показано обновление работающего на локальной машине кластера etcd v3.3 из 3 участников.

Шаг 1: проверка требований к обновлению

Кластер исправен и использует v3.3.x?

etcdctl --endpoints=localhost:2379,localhost:22379,localhost:32379 endpoint health
<<COMMENT
localhost:2379 is healthy: successfully committed proposal: took = 2.118638ms
localhost:22379 is healthy: successfully committed proposal: took = 3.631388ms
localhost:32379 is healthy: successfully committed proposal: took = 2.157051ms
COMMENT

curl http://localhost:2379/version
<<COMMENT
{"etcdserver":"3.3.5","etcdcluster":"3.3.0"}
COMMENT

curl http://localhost:22379/version
<<COMMENT
{"etcdserver":"3.3.5","etcdcluster":"3.3.0"}
COMMENT

curl http://localhost:32379/version
<<COMMENT
{"etcdserver":"3.3.5","etcdcluster":"3.3.0"}
COMMENT

Шаг 2: загрузка резервной копии снимка с лидера

Загрузите резервную копию снимка , чтобы обеспечить путь понижения версии при возникновении проблем.

Лидер etcd гарантированно содержит последние данные приложения, поэтому снимок следует получать с лидера:

curl -sL http://localhost:2379/metrics | grep etcd_server_is_leader
<<COMMENT
# HELP etcd_server_is_leader Whether or not this member is a leader. 1 if is, 0 otherwise.
# TYPE etcd_server_is_leader gauge
etcd_server_is_leader 1
COMMENT

curl -sL http://localhost:22379/metrics | grep etcd_server_is_leader
<<COMMENT
etcd_server_is_leader 0
COMMENT

curl -sL http://localhost:32379/metrics | grep etcd_server_is_leader
<<COMMENT
etcd_server_is_leader 0
COMMENT

etcdctl --endpoints=localhost:2379 snapshot save backup.db
<<COMMENT
{"level":"info","ts":1526585787.148433,"caller":"snapshot/v3_snapshot.go:109","msg":"created temporary db file","path":"backup.db.part"}
{"level":"info","ts":1526585787.1485257,"caller":"snapshot/v3_snapshot.go:120","msg":"fetching snapshot","endpoint":"localhost:2379"}
{"level":"info","ts":1526585787.1519694,"caller":"snapshot/v3_snapshot.go:133","msg":"fetched snapshot","endpoint":"localhost:2379","took":0.003502721}
{"level":"info","ts":1526585787.1520295,"caller":"snapshot/v3_snapshot.go:142","msg":"saved","path":"backup.db"}
Snapshot saved at backup.db
COMMENT

Шаг 3: остановка одного существующего сервера etcd

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

10.237579 I | etcdserver: updating the cluster version from 3.0 to 3.3
10.238315 N | etcdserver/membership: updated the cluster version from 3.0 to 3.3
10.238451 I | etcdserver/api: enabled capabilities for version 3.3


^C21.192174 N | pkg/osutil: received interrupt signal, shutting down...
21.192459 I | etcdserver: 7339c4e5e833c029 starts leadership transfer from 7339c4e5e833c029 to 729934363faa4a24
21.192569 I | raft: 7339c4e5e833c029 [term 8] starts to transfer leadership to 729934363faa4a24
21.192619 I | raft: 7339c4e5e833c029 sends MsgTimeoutNow to 729934363faa4a24 immediately as 729934363faa4a24 already has up-to-date log
WARNING: 2018/05/17 12:45:21 grpc: addrConn.resetTransport failed to create client transport: connection error: desc = "transport: Error while dialing dial tcp: operation was canceled"; Reconnecting to {localhost:2379 0  <nil>}
WARNING: 2018/05/17 12:45:21 grpc: addrConn.transportMonitor exits due to: grpc: the connection is closing
21.193589 I | raft: 7339c4e5e833c029 [term: 8] received a MsgVote message with higher term from 729934363faa4a24 [term: 9]
21.193626 I | raft: 7339c4e5e833c029 became follower at term 9
21.193651 I | raft: 7339c4e5e833c029 [logterm: 8, index: 9, vote: 0] cast MsgVote for 729934363faa4a24 [logterm: 8, index: 9] at term 9
21.193675 I | raft: raft.node: 7339c4e5e833c029 lost leader 7339c4e5e833c029 at term 9
21.194424 I | raft: raft.node: 7339c4e5e833c029 elected leader 729934363faa4a24 at term 9
21.292898 I | etcdserver: 7339c4e5e833c029 finished leadership transfer from 7339c4e5e833c029 to 729934363faa4a24 (took 100.436391ms)
21.292975 I | rafthttp: stopping peer 729934363faa4a24...
21.293206 I | rafthttp: closed the TCP streaming connection with peer 729934363faa4a24 (stream MsgApp v2 writer)
21.293225 I | rafthttp: stopped streaming with peer 729934363faa4a24 (writer)
21.293437 I | rafthttp: closed the TCP streaming connection with peer 729934363faa4a24 (stream Message writer)
21.293459 I | rafthttp: stopped streaming with peer 729934363faa4a24 (writer)
21.293514 I | rafthttp: stopped HTTP pipelining with peer 729934363faa4a24
21.293590 W | rafthttp: lost the TCP streaming connection with peer 729934363faa4a24 (stream MsgApp v2 reader)
21.293610 I | rafthttp: stopped streaming with peer 729934363faa4a24 (stream MsgApp v2 reader)
21.293680 W | rafthttp: lost the TCP streaming connection with peer 729934363faa4a24 (stream Message reader)
21.293700 I | rafthttp: stopped streaming with peer 729934363faa4a24 (stream Message reader)
21.293711 I | rafthttp: stopped peer 729934363faa4a24
21.293720 I | rafthttp: stopping peer b548c2511513015...
21.293987 I | rafthttp: closed the TCP streaming connection with peer b548c2511513015 (stream MsgApp v2 writer)
21.294063 I | rafthttp: stopped streaming with peer b548c2511513015 (writer)
21.294467 I | rafthttp: closed the TCP streaming connection with peer b548c2511513015 (stream Message writer)
21.294561 I | rafthttp: stopped streaming with peer b548c2511513015 (writer)
21.294742 I | rafthttp: stopped HTTP pipelining with peer b548c2511513015
21.294867 W | rafthttp: lost the TCP streaming connection with peer b548c2511513015 (stream MsgApp v2 reader)
21.294892 I | rafthttp: stopped streaming with peer b548c2511513015 (stream MsgApp v2 reader)
21.294990 W | rafthttp: lost the TCP streaming connection with peer b548c2511513015 (stream Message reader)
21.295004 E | rafthttp: failed to read b548c2511513015 on stream Message (context canceled)
21.295013 I | rafthttp: peer b548c2511513015 became inactive
21.295024 I | rafthttp: stopped streaming with peer b548c2511513015 (stream Message reader)
21.295035 I | rafthttp: stopped peer b548c2511513015

Шаг 4: перезапуск сервера etcd с той же конфигурацией

Перезапустите сервер etcd с прежней конфигурацией, но с новым двоичным файлом etcd.

-etcd-old --name s1 \
+etcd-new --name s1 \
  --data-dir /tmp/etcd/s1 \
  --listen-client-urls http://localhost:2379 \
  --advertise-client-urls http://localhost:2379 \
  --listen-peer-urls http://localhost:2380 \
  --initial-advertise-peer-urls http://localhost:2380 \
  --initial-cluster s1=http://localhost:2380,s2=http://localhost:22380,s3=http://localhost:32380 \
  --initial-cluster-token tkn \
+ --initial-cluster-state new \
+ --logger zap \
+ --log-outputs stderr

Новый etcd v3.4 опубликует свои сведения в кластере. На этом этапе кластер всё ещё работает по протоколу v3.3 — наименьшей общей версии.

{"level":"info","ts":1526586617.1647713,"caller":"membership/cluster.go:485","msg":"set initial cluster version","cluster-id":"7dee9ba76d59ed53","local-member-id":"7339c4e5e833c029","cluster-version":"3.0"}

{"level":"info","ts":1526586617.1648536,"caller":"api/capability.go:76","msg":"enabled capabilities for version","cluster-version":"3.0"}

{"level":"info","ts":1526586617.1649303,"caller":"membership/cluster.go:473","msg":"updated cluster version","cluster-id":"7dee9ba76d59ed53","local-member-id":"7339c4e5e833c029","from":"3.0","from":"3.3"}

{"level":"info","ts":1526586617.1649797,"caller":"api/capability.go:76","msg":"enabled capabilities for version","cluster-version":"3.3"}

{"level":"info","ts":1526586617.2107732,"caller":"etcdserver/server.go:1770","msg":"published local member to cluster through raft","local-member-id":"7339c4e5e833c029","local-member-attributes":"{Name:s1 ClientURLs:[http://localhost:2379]}","request-path":"/0/members/7339c4e5e833c029/attributes","cluster-id":"7dee9ba76d59ed53","publish-timeout":7}

Убедитесь, что сначала каждый участник, а затем весь кластер становятся исправными с новым двоичным файлом etcd v3.4:

etcdctl endpoint health --endpoints=localhost:2379,localhost:22379,localhost:32379
<<COMMENT
localhost:32379 is healthy: successfully committed proposal: took = 2.337471ms
localhost:22379 is healthy: successfully committed proposal: took = 1.130717ms
localhost:2379 is healthy: successfully committed proposal: took = 2.124843ms
COMMENT

До обновления всего кластера необновлённые участники будут записывать в журнал подобные предупреждения.

Это ожидаемо и прекратится после обновления всех участников кластера etcd до v3.4:

:41.942121 W | etcdserver: member 7339c4e5e833c029 has a higher version 3.4.0
:45.945154 W | etcdserver: the local etcd version 3.3.5 is not up-to-date

Шаг 5: повторение шага 3 и шага 4 для остальных участников

После обновления всех участников кластер сообщит об успешном переходе на 3.4:

Участник 1:

{"level":"info","ts":1526586949.0920913,"caller":"api/capability.go:76","msg":"enabled capabilities for version","cluster-version":"3.4"} {"level":"info","ts":1526586949.0921566,"caller":"etcdserver/server.go:2272","msg":"cluster version is updated","cluster-version":"3.4"}

Участник 2:

{"level":"info","ts":1526586949.092117,"caller":"membership/cluster.go:473","msg":"updated cluster version","cluster-id":"7dee9ba76d59ed53","local-member-id":"729934363faa4a24","from":"3.3","from":"3.4"} {"level":"info","ts":1526586949.0923078,"caller":"api/capability.go:76","msg":"enabled capabilities for version","cluster-version":"3.4"}

Участник 3:

{"level":"info","ts":1526586949.0921423,"caller":"membership/cluster.go:473","msg":"updated cluster version","cluster-id":"7dee9ba76d59ed53","local-member-id":"b548c2511513015","from":"3.3","from":"3.4"} {"level":"info","ts":1526586949.0922918,"caller":"api/capability.go:76","msg":"enabled capabilities for version","cluster-version":"3.4"}

endpoint health --endpoints=localhost:2379,localhost:22379,localhost:32379
<<COMMENT
localhost:2379 is healthy: successfully committed proposal: took = 492.834µs
localhost:22379 is healthy: successfully committed proposal: took = 1.015025ms
localhost:32379 is healthy: successfully committed proposal: took = 1.853077ms
COMMENT

curl http://localhost:2379/version
<<COMMENT
{"etcdserver":"3.4.0","etcdcluster":"3.4.0"}
COMMENT

curl http://localhost:22379/version
<<COMMENT
{"etcdserver":"3.4.0","etcdcluster":"3.4.0"}
COMMENT

curl http://localhost:32379/version
<<COMMENT
{"etcdserver":"3.4.0","etcdcluster":"3.4.0"}
COMMENT

5 - Обновление etcd с v3.6 до v3.7

Процессы, контрольные списки и примечания по обновлению etcd с v3.6 до v3.7

В общем случае переход с etcd v3.6 на v3.7 можно выполнить как скользящее обновление без простоя:

  • поочерёдно останавливать процессы etcd v3.6 и заменять их процессами etcd v3.7
  • после запуска всех процессов v3.7 кластеру становятся доступны новые возможности v3.7

До начала обновления прочитайте оставшуюся часть руководства и подготовьтесь.

Контрольные списки обновления

Обновление 3.6

Важно

Перед обновлением до 3.7 убедитесь, что все участники 3.6 обновлены до 3.6.11 или более поздней версии. Предыдущие корректирующие выпуски 3.6 могут быть несовместимы со скользящим обновлением до 3.7.

Хранилище V2

Хранилище v2 полностью удалено в v3.7. HTTP API v2 (--enable-v2), эмуляция v2 поверх v3 (--experimental-enable-v2v3), служба обнаружения v2, пакет client/v2 и загрузка файлов снимков v2 больше не существуют. Ссылки на нарушающие совместимость изменения приведены в CHANGELOG-3.7 .

При обновлении кластера 3.6 эти флаги уже отсутствуют, и никаких действий не требуется. Если переход выполняется со старого выпуска с пользовательскими данными v2, до обновления следуйте руководству по миграции v2 .

Рефакторинг Go

v3.7 содержит значительный внутренний рефакторинг, который не влияет на обычное обновление, но его следует учитывать при обновлении пользовательских интеграций:

  • Переход с gogo/protobuf на стандартный google.golang.org/protobuf (отслеживается в #14533 ).
  • Переход с устаревших библиотек журналирования и тегов go-grpc-middleware v1 на перехватчики v2 (#20420 ).
  • Перехватчики gRPC OpenTelemetry обновлены до otelgrpc v0.61.0: устаревшие UnaryServerInterceptor и StreamServerInterceptor заменены на NewServerHandler (#20017 ).

Если etcd встраивается как библиотека, приложение собирается с API clientv3 или зависит от внутренних пакетов, перед обновлением изучите CHANGELOG .

Удалённые флаги

В v3.7 удалены все устаревшие флаги --experimental-* (#19959 ). В v3.6 каждый из них был заменён либо одноимённым неэкспериментальным флагом, либо записью --feature-gates. Если какие-либо из этих флагов всё ещё заданы, замените их эквивалентами v3.6 до скользящего обновления до v3.7, иначе процесс v3.7 не запустится.

-etcd --experimental-bootstrap-defrag-threshold-megabytes
-etcd --experimental-compact-hash-check-enabled
-etcd --experimental-compact-hash-check-time
-etcd --experimental-compaction-batch-limit
-etcd --experimental-compaction-sleep-interval
-etcd --experimental-corrupt-check-time
-etcd --experimental-distributed-tracing-address
-etcd --experimental-distributed-tracing-instance-id
-etcd --experimental-distributed-tracing-sampling-rate
-etcd --experimental-distributed-tracing-service-name
-etcd --experimental-downgrade-check-time
-etcd --experimental-enable-distributed-tracing
-etcd --experimental-enable-lease-checkpoint
-etcd --experimental-enable-lease-checkpoint-persist
-etcd --experimental-initial-corrupt-check
-etcd --experimental-memory-mlock
-etcd --experimental-peer-skip-client-san-verification
-etcd --experimental-snapshot-catchup-entries
-etcd --experimental-stop-grpc-service-on-defrag
-etcd --experimental-txn-mode-write-with-shared-buffer
-etcd --experimental-warning-apply-duration
-etcd --experimental-warning-unary-request-duration
-etcd --experimental-watch-progress-notify-interval

Соответствие каждого удалённого флага его неэкспериментальному эквиваленту или записи --feature-gates приведено в руководстве по обновлению с v3.5 до v3.6 .

Добавленные флаги

Нет.

Флаги с новыми значениями по умолчанию

Нет.

Контрольные списки обновления сервера

Требования к обновлению

Для обновления существующего развёртывания etcd до v3.7 работающий кластер должен иметь версию v3.6.11 или более позднюю. Если он использует более старую дополнительную версию, сначала обновитесь до v3.6 ; etcd поддерживает обновление только на одну дополнительную версию за раз.

Кроме того, для плавного скользящего обновления работающий кластер должен быть исправен. Перед продолжением проверьте его работоспособность командой etcdctl endpoint health.

Подготовка

Перед обновлением etcd обязательно протестируйте службы, зависящие от etcd, в промежуточном окружении, прежде чем развёртывать обновление в рабочем окружении.

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

Смешанные версии

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

Откат

Перед обновлением кластера etcd создайте и загрузите резервную копию снимка . При необходимости этот снимок можно использовать для восстановления состояния кластера до обновления. Если во время обновления возникнут проблемы, пользователям следует сначала определить и устранить их первопричину. Пока кластер остаётся в состоянии смешанных версий и хотя бы один участник работает на v3.6, можно либо заменить двоичный файл или образ старой версией v3.6, либо непосредственно восстановить кластер из снимка. В таком смешанном состоянии кластер продолжает работать как кластер v3.6, что позволяет откатиться без формальной процедуры понижения версии.

Однако после обновления всех участников до v3.7 кластер считается полностью обновлённым, и откат заменой двоичных файлов больше невозможен. В этом случае остаётся только восстановиться из снимка, сделанного перед обновлением, либо при неудачном обновлении следовать официальному руководству по понижению версии .

Процедура обновления

В этом примере показано обновление работающего на локальной машине кластера etcd v3.6 из 3 участников. Приведённый ниже вывод получен при реальном запуске etcd v3.6.12 и etcd v3.7.0-rc.0 на одном узле с тремя портами обратной петли.

Шаг 1: проверка требований к обновлению

Кластер исправен и использует v3.6.11 или более позднюю версию?

etcdctl --endpoints=localhost:2379,localhost:22379,localhost:32379 endpoint health
<<COMMENT
localhost:2379 is healthy: successfully committed proposal: took = 7.681459ms
localhost:22379 is healthy: successfully committed proposal: took = 7.691750ms
localhost:32379 is healthy: successfully committed proposal: took = 7.698000ms
COMMENT

curl http://localhost:2379/version
<<COMMENT
{"etcdserver":"3.6.12","etcdcluster":"3.6.0","storage":"3.6.0"}
COMMENT

Шаг 2: загрузка резервной копии снимка с лидера

Загрузите резервную копию снимка , чтобы обеспечить путь понижения версии в случае возникновения проблем.

Лидер etcd гарантированно содержит последние данные приложения, поэтому снимок следует получать с лидера:

for p in 2379 22379 32379; do
  echo -n "localhost:$p leader="
  curl -sL http://localhost:$p/metrics | grep "^etcd_server_is_leader " | awk '{print $2}'
done
<<COMMENT
localhost:2379 leader=1
localhost:22379 leader=0
localhost:32379 leader=0
COMMENT

etcdctl --endpoints=localhost:2379 snapshot save backup.db
<<COMMENT
{"level":"info","ts":"2026-06-02T07:01:41.863225+0300","caller":"snapshot/v3_snapshot.go:83","msg":"created temporary db file","path":"backup.db.part"}
{"level":"info","ts":"2026-06-02T07:01:41.866451+0300","logger":"client","caller":"v3@v3.6.12/maintenance.go:236","msg":"opened snapshot stream; downloading"}
{"level":"info","ts":"2026-06-02T07:01:41.874080+0300","caller":"snapshot/v3_snapshot.go:96","msg":"fetching snapshot","endpoint":"localhost:2379"}
{"level":"info","ts":"2026-06-02T07:01:41.877203+0300","caller":"snapshot/v3_snapshot.go:111","msg":"fetched snapshot","endpoint":"localhost:2379","size":"98 kB","took":"13.822583ms","etcd-version":"3.6.0"}
{"level":"info","ts":"2026-06-02T07:01:41.877303+0300","caller":"snapshot/v3_snapshot.go:121","msg":"saved","path":"backup.db"}
Snapshot saved at backup.db
Server version 3.6.0
COMMENT

Шаг 3: остановка одного существующего сервера etcd

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

{"level":"info","ts":"2026-06-02T07:01:54.949299+0300","caller":"etcdserver/server.go:1274","msg":"leadership transfer finished","local-member-id":"7339c4e5e833c029","old-leader-member-id":"7339c4e5e833c029","new-leader-member-id":"b548c2511513015","took":"101.052625ms"}
{"level":"info","ts":"2026-06-02T07:01:54.949369+0300","caller":"etcdserver/server.go:2349","msg":"server has stopped; stopping cluster version's monitor"}
{"level":"info","ts":"2026-06-02T07:01:55.503219+0300","caller":"embed/etcd.go:626","msg":"stopped serving peer traffic","address":"127.0.0.1:2380"}

Шаг 4: перезапуск сервера etcd с той же конфигурацией

Перезапустите сервер etcd с прежней конфигурацией, но с новым двоичным файлом etcd.

-etcd-old --name ${name} \
+etcd-new --name ${name} \
  --data-dir /path/to/${name}.etcd \
  --listen-client-urls http://localhost:2379 \
  --advertise-client-urls http://localhost:2379 \
  --listen-peer-urls http://localhost:2380 \
  --initial-advertise-peer-urls http://localhost:2380 \
  --initial-cluster s1=http://localhost:2380,s2=http://localhost:22380,s3=http://localhost:32380 \
  --initial-cluster-token tkn \
  --initial-cluster-state new

Новый etcd v3.7 опубликует свои сведения в кластере. На этом этапе кластер всё ещё работает по протоколу v3.6 — наименьшей общей версии.

{"level":"info","ts":"2026-06-02T07:01:58.920780+0300","caller":"membership/cluster.go:296","msg":"set cluster version from store","cluster-version":"3.6"}

{"level":"info","ts":"2026-06-02T07:01:58.979186+0300","caller":"etcdserver/server.go:1828","msg":"published local member to cluster through raft","local-member-id":"7339c4e5e833c029","local-member-attributes":"{Name:s1 ClientURLs:[http://localhost:2379]}","cluster-id":"7dee9ba76d59ed53","publish-timeout":"7s"}

Убедитесь, что сначала каждый участник, а затем весь кластер становятся исправными с новым двоичным файлом etcd v3.7:

etcdctl --endpoints=localhost:2379,localhost:22379,localhost:32379 endpoint status -w table
<<COMMENT
+-----------------+------------------+------------+-----------------+---------+--------+-----------+
|    ENDPOINT     |        ID        |  VERSION   | STORAGE VERSION | DB SIZE | LEADER | RAFT TERM |
+-----------------+------------------+------------+-----------------+---------+--------+-----------+
|  localhost:2379 | 7339c4e5e833c029 | 3.7.0-rc.0 |           3.6.0 |   98 kB |  false |         3 |
| localhost:22379 | 729934363faa4a24 |     3.6.12 |           3.6.0 |   98 kB |  false |         3 |
| localhost:32379 |  b548c2511513015 |     3.6.12 |           3.6.0 |   98 kB |   true |         3 |
+-----------------+------------------+------------+-----------------+---------+--------+-----------+
COMMENT

До обновления всего кластера необновлённые и уже обновлённый участники будут записывать сообщения о состоянии смешанных версий. Это ожидаемо и прекратится после обновления всех участников кластера etcd до v3.7.

Шаг 5: повторение шага 3 и шага 4 для остальных участников

После обновления всех участников кластер сообщит об успешном переходе на v3.7:

{"level":"info","ts":"2026-06-02T07:02:36.054783+0300","caller":"etcdserver/server.go:2311","msg":"updating cluster version using v3 API","from":"3.6","to":"3.7"}

{"level":"info","ts":"2026-06-02T07:02:36.059345+0300","caller":"membership/cluster.go:593","msg":"updated cluster version","cluster-id":"7dee9ba76d59ed53","local-member-id":"7339c4e5e833c029","from":"3.6","to":"3.7"}

{"level":"info","ts":"2026-06-02T07:02:36.059409+0300","caller":"etcdserver/server.go:2326","msg":"cluster version is updated","cluster-version":"3.7"}

etcdctl --endpoints=localhost:2379,localhost:22379,localhost:32379 endpoint health
<<COMMENT
localhost:2379 is healthy: successfully committed proposal: took = 550.833µs
localhost:32379 is healthy: successfully committed proposal: took = 733.458µs
localhost:22379 is healthy: successfully committed proposal: took = 714.416µs
COMMENT

curl http://localhost:2379/version
<<COMMENT
{"etcdserver":"3.7.0-rc.0","etcdcluster":"3.7.0","storage":"3.7.0"}
COMMENT

curl http://localhost:22379/version
<<COMMENT
{"etcdserver":"3.7.0-rc.0","etcdcluster":"3.7.0","storage":"3.7.0"}
COMMENT

curl http://localhost:32379/version
<<COMMENT
{"etcdserver":"3.7.0-rc.0","etcdcluster":"3.7.0","storage":"3.7.0"}
COMMENT

6 - Обновление etcd с 3.2 до 3.3

Процессы, контрольные списки и примечания по обновлению etcd с 3.2 до 3.3

В общем случае переход с etcd 3.2 на 3.3 можно выполнить как скользящее обновление без простоя:

  • поочерёдно останавливать процессы etcd v3.2 и заменять их процессами etcd v3.3
  • после запуска всех процессов v3.3 кластеру становятся доступны новые возможности v3.3

До начала обновления прочитайте оставшуюся часть руководства и подготовьтесь.

Контрольные списки обновления

Предупреждение

При миграции с v2 без данных v3 сервер etcd v3.2+ аварийно завершается, если etcd восстанавливается из существующих снимков, но файл v3 ETCD_DATA_DIR/member/snap/db отсутствует. Это происходит, когда сервер был перенесён с v2 и ранее не содержал данных v3. Такое поведение также предотвращает случайную потерю данных v3, например если файл db перемещён. etcd требует, чтобы после миграции на v3 работа продолжалась только при наличии данных v3. Не обновляйтесь до более новых версий v3, пока сервер v3.0 не содержит данные v3.

Предупреждение

Если включена аутентификация и используются аренды с малым ttl, высока вероятность столкнуться с проблемой , приводящей к несогласованности данных. Настоятельно рекомендуется сначала обновиться до 3.2.31+ для её устранения, а затем до 3.3. Кроме того, если во время обновления пользователь без разрешения отправит запрос LeaseRevoke узлу 3.3, данные всё ещё могут быть повреждены. Перед обновлением лучше убедиться, что в окружении нет таких аномальных вызовов; подробнее см. #11691 .

Основные нарушающие совместимость изменения в 3.3.

Изменение типа значения флага etcd --auto-compaction-retention на string

Флаг --auto-compaction-retention изменён так, чтобы принимать строковые значения с более высокой точностью . Поскольку теперь --auto-compaction-retention принимает строки, тип поля auto-compaction-retention в файле конфигурации YAML etcd необходимо изменить на string. Ранее --config-file etcd.config.yaml мог содержать auto-compaction-retention: 24, теперь требуется auto-compaction-retention: "24" или auto-compaction-retention: "24h". При конфигурации --auto-compaction-mode periodic --auto-compaction-retention "24h" значение длительности флага --auto-compaction-retention должно быть допустимо для функции Go time.ParseDuration .

# etcd.config.yaml
+auto-compaction-mode: periodic
-auto-compaction-retention: 24
+auto-compaction-retention: "24"
+# Or
+auto-compaction-retention: "24h"

Изменение etcdserver.EtcdServer.ServerConfig на *etcdserver.EtcdServer.ServerConfig

В etcdserver.EtcdServer тип поля участника изменён с *etcdserver.ServerConfig на etcdserver.ServerConfig. Кроме того, etcdserver.NewServer теперь принимает etcdserver.ServerConfig вместо *etcdserver.ServerConfig.

До и после (например, k8s.io/kubernetes/test/e2e_node/services/etcd.go )

import "github.com/coreos/etcd/etcdserver"

type EtcdServer struct {
	*etcdserver.EtcdServer
-	config *etcdserver.ServerConfig
+	config etcdserver.ServerConfig
}

func NewEtcd(dataDir string) *EtcdServer {
-	config := &etcdserver.ServerConfig{
+	config := etcdserver.ServerConfig{
		DataDir: dataDir,
        ...
	}
	return &EtcdServer{config: config}
}

func (e *EtcdServer) Start() error {
	var err error
	e.EtcdServer, err = etcdserver.NewServer(e.config)
    ...

Добавление структуры embed.Config.LogOutput

Предупреждение

Обратите внимание: в v3.4 поле переименовано в embed.Config.LogOutputs с типом []string. Подробнее см. руководство по обновлению до v3.4 .

В embed.Config добавлено поле LogOutput:

package embed

type Config struct {
 	Debug bool `json:"debug"`
 	LogPkgLevels string `json:"log-package-levels"`
+	LogOutput string `json:"log-output"`
 	...

Ранее предупреждения сервера gRPC записывались в журнал etcdserver.

WARNING: 2017/11/02 11:35:51 grpc: addrConn.resetTransport failed to create client transport: connection error: desc = "transport: Error while dialing dial tcp: operation was canceled"; Reconnecting to {localhost:2379 <nil>}
WARNING: 2017/11/02 11:35:51 grpc: addrConn.resetTransport failed to create client transport: connection error: desc = "transport: Error while dialing dial tcp: operation was canceled"; Reconnecting to {localhost:2379 <nil>}

Начиная с v3.3 журналы сервера gRPC по умолчанию отключены.

Предупреждение

Обратите внимание: метод embed.Config.SetupLogging объявлен устаревшим в v3.4. Подробнее см. руководство по обновлению до v3.4 .

import "github.com/coreos/etcd/embed"

cfg := &embed.Config{Debug: false}
cfg.SetupLogging()

Чтобы включить журналы сервера gRPC, задайте полю embed.Config.Debug значение true.

Изменение ответа конечной точки /health

Ранее [endpoint]:[client-port]/health возвращала вручную сериализованное значение JSON. В 3.3 определена структура etcdhttp.Health .

Обратите внимание: в v3.3.0-rc.0, v3.3.0-rc.1 и v3.3.0-rc.2 структура etcdhttp.Health содержит поля "health" и "errors" логического типа. Для обратной совместимости тип поля "health" возвращён к string, а поле "errors" удалено. Дополнительные сведения о работоспособности будут предоставляться отдельными API.

$ curl http://localhost:2379/health
{"health":"true"}

Изменение конечных точек HTTP шлюза gRPC (/v3alpha заменена на /v3beta)

До

curl -L http://localhost:2379/v3alpha/kv/put \
  -X POST -d '{"key": "Zm9v", "value": "YmFy"}'

После

curl -L http://localhost:2379/v3beta/kv/put \
  -X POST -d '{"key": "Zm9v", "value": "YmFy"}'

Запросы к конечным точкам /v3alpha перенаправляются на /v3beta, а /v3alpha будет удалена в выпуске 3.4.

Изменение ограничений максимального размера запроса

В 3.3 можно настраивать ограничения размера запросов как на стороне сервера, так и на стороне клиента. В предыдущих версиях (v3.2.10, v3.2.11) размер клиентского ответа был ограничен 4 MiB.

Серверное ограничение запросов настраивается флагом --max-request-bytes:

# limits request size to 1.5 KiB
etcd --max-request-bytes 1536

# client writes exceeding 1.5 KiB will be rejected
etcdctl put foo [LARGE VALUE...]
# etcdserver: request is too large

Либо полем embed.Config.MaxRequestBytes:

import "github.com/coreos/etcd/embed"
import "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes"

// limit requests to 5 MiB
cfg := embed.NewConfig()
cfg.MaxRequestBytes = 5 * 1024 * 1024

// client writes exceeding 5 MiB will be rejected
_, err := cli.Put(ctx, "foo", [LARGE VALUE...])
err == rpctypes.ErrRequestTooLarge

Если значение не указано, серверное ограничение по умолчанию равно 1.5 MiB.

Клиентские ограничения запросов необходимо настраивать с учётом серверных.

# limits request size to 1 MiB
etcd --max-request-bytes 1048576
import "github.com/coreos/etcd/clientv3"

cli, _ := clientv3.New(clientv3.Config{
    Endpoints: []string{"127.0.0.1:2379"},
    MaxCallSendMsgSize: 2 * 1024 * 1024,
    MaxCallRecvMsgSize: 3 * 1024 * 1024,
})


// client writes exceeding "--max-request-bytes" will be rejected from etcd server
_, err := cli.Put(ctx, "foo", strings.Repeat("a", 1*1024*1024+5))
err == rpctypes.ErrRequestTooLarge


// client writes exceeding "MaxCallSendMsgSize" will be rejected from client-side
_, err = cli.Put(ctx, "foo", strings.Repeat("a", 5*1024*1024))
err.Error() == "rpc error: code = ResourceExhausted desc = grpc: trying to send message larger than max (5242890 vs. 2097152)"


// some writes under limits
for i := range []int{0,1,2,3,4} {
    _, err = cli.Put(ctx, fmt.Sprintf("foo%d", i), strings.Repeat("a", 1*1024*1024-500))
    if err != nil {
        panic(err)
    }
}
// client reads exceeding "MaxCallRecvMsgSize" will be rejected from client-side
_, err = cli.Get(ctx, "foo", clientv3.WithPrefix())
err.Error() == "rpc error: code = ResourceExhausted desc = grpc: received message larger than max (5240509 vs. 3145728)"

Если значения не указаны, клиентское ограничение отправки по умолчанию равно 2 MiB (1.5 MiB плюс служебные байты gRPC), а ограничение получения — math.MaxInt32. Подробнее см. документацию clientv3 .

Изменение сигнатур функций низкоуровневой оболочки клиента gRPC

В 3.3 изменены сигнатуры функций оболочки клиента gRPC clientv3. Изменение необходимо для поддержки пользовательского grpc.CallOption для ограничений размера сообщений .

До и после

-func NewKVFromKVClient(remote pb.KVClient) KV {
+func NewKVFromKVClient(remote pb.KVClient, c *Client) KV {

-func NewClusterFromClusterClient(remote pb.ClusterClient) Cluster {
+func NewClusterFromClusterClient(remote pb.ClusterClient, c *Client) Cluster {

-func NewLeaseFromLeaseClient(remote pb.LeaseClient, keepAliveTimeout time.Duration) Lease {
+func NewLeaseFromLeaseClient(remote pb.LeaseClient, c *Client, keepAliveTimeout time.Duration) Lease {

-func NewMaintenanceFromMaintenanceClient(remote pb.MaintenanceClient) Maintenance {
+func NewMaintenanceFromMaintenanceClient(remote pb.MaintenanceClient, c *Client) Maintenance {

-func NewWatchFromWatchClient(wc pb.WatchClient) Watcher {
+func NewWatchFromWatchClient(wc pb.WatchClient, c *Client) Watcher {

Изменение типа ошибки API Snapshot в clientv3

Ранее API Snapshot clientv3 возвращал необработанную ошибку типа [grpc/*status.statusError]. В v3.3 такие ошибки преобразуются в соответствующие общедоступные типы для согласованности с другими API.

До

import "context"

// reading snapshot with canceled context should error out
ctx, cancel := context.WithCancel(context.Background())
rc, _ := cli.Snapshot(ctx)
cancel()
_, err := io.Copy(f, rc)
err.Error() == "rpc error: code = Canceled desc = context canceled"

// reading snapshot with deadline exceeded should error out
ctx, cancel = context.WithTimeout(context.Background(), time.Second)
defer cancel()
rc, _ = cli.Snapshot(ctx)
time.Sleep(2 * time.Second)
_, err = io.Copy(f, rc)
err.Error() == "rpc error: code = DeadlineExceeded desc = context deadline exceeded"

После

import "context"

// reading snapshot with canceled context should error out
ctx, cancel := context.WithCancel(context.Background())
rc, _ := cli.Snapshot(ctx)
cancel()
_, err := io.Copy(f, rc)
err == context.Canceled

// reading snapshot with deadline exceeded should error out
ctx, cancel = context.WithTimeout(context.Background(), time.Second)
defer cancel()
rc, _ = cli.Snapshot(ctx)
time.Sleep(2 * time.Second)
_, err = io.Copy(f, rc)
err == context.DeadlineExceeded

Изменение вывода команды etcdctl lease timetolive

Ранее команда lease timetolive LEASE_ID для истёкшей аренды выводила -1s как оставшееся время. В 3.3 сообщения стали понятнее.

До

lease 2d8257079fa1bc0c granted with TTL(0s), remaining(-1s)

После

lease 2d8257079fa1bc0c already expired

Изменение импортов golang.org/x/net/context

В clientv3 пакет golang.org/x/net/context объявлен устаревшим. Если проект включает golang.org/x/net/context в другой код, например сгенерированный код Protocol Buffer etcd, и импортирует github.com/coreos/etcd/clientv3, для компиляции требуется Go 1.9+.

До

import "golang.org/x/net/context"
cli.Put(context.Background(), "f", "v")

После

import "context"
cli.Put(context.Background(), "f", "v")

Изменение зависимости gRPC

Теперь 3.3 требует grpc/grpc-go v1.7.5.

Устаревший grpclog.Logger

grpclog.Logger объявлен устаревшим в пользу grpclog.LoggerV2 . Теперь clientv3.Logger — это grpclog.LoggerV2.

До

import "github.com/coreos/etcd/clientv3"
clientv3.SetLogger(log.New(os.Stderr, "grpc: ", 0))

После

import "github.com/coreos/etcd/clientv3"
import "google.golang.org/grpc/grpclog"
clientv3.SetLogger(grpclog.NewLoggerV2(os.Stderr, os.Stderr, os.Stderr))

// log.New above cannot be used (not implement grpclog.LoggerV2 interface)
Устаревший grpc.ErrClientConnTimeout

Ранее при истечении тайм-аута клиентского подключения возвращалась ошибка grpc.ErrClientConnTimeout. Вместо неё 3.3 возвращает context.DeadlineExceeded (см. #8504 ).

До

// expect dial time-out on ipv4 blackhole
_, err := clientv3.New(clientv3.Config{
    Endpoints:   []string{"http://254.0.0.1:12345"},
    DialTimeout: 2 * time.Second
})
if err == grpc.ErrClientConnTimeout {
	// handle errors
}

После

_, err := clientv3.New(clientv3.Config{
    Endpoints:   []string{"http://254.0.0.1:12345"},
    DialTimeout: 2 * time.Second
})
if err == context.DeadlineExceeded {
	// handle errors
}

Изменение официального реестра контейнеров

Теперь etcd использует gcr.io/etcd-development/etcd как основной реестр контейнеров, а quay.io/coreos/etcd — как дополнительный.

До

docker pull quay.io/coreos/etcd:v3.2.5

После

docker pull gcr.io/etcd-development/etcd:v3.3.0

Обновления до >= v3.3.14

В v3.3.14 пришлось включить некоторые возможности 3.4, стараясь свести к минимуму различия реализаций клиентского балансировщика. Выпуск исправляет проблему “kube-apiserver 1.13.x refuses to work when first etcd-server is not available” (kubernetes#72102) .

grpc.ErrClientConnClosing объявлена устаревшей в gRPC >= 1.10 .

import (
+	"go.etcd.io/etcd/clientv3"

	"google.golang.org/grpc"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
)

_, err := kvc.Get(ctx, "a")
-if err == grpc.ErrClientConnClosing {
+if clientv3.IsConnCanceled(err) {

// or
+s, ok := status.FromError(err)
+if ok {
+  if s.Code() == codes.Canceled

Новый клиентский балансировщик использует асинхронный разрешитель для передачи конечных точек функции подключения gRPC. Поэтому v3.3.14 или более поздней версии требуется параметр подключения grpc.WithBlock, чтобы дождаться установления нижележащего соединения.

import (
	"time"
	"go.etcd.io/etcd/clientv3"
+	"google.golang.org/grpc"
)

+// "grpc.WithBlock()" to block until the underlying connection is up
ccfg := clientv3.Config{
  Endpoints:            []string{"localhost:2379"},
  DialTimeout:          time.Second,
+ DialOptions:          []grpc.DialOption{grpc.WithBlock()},
  DialKeepAliveTime:    time.Second,
  DialKeepAliveTimeout: 500 * time.Millisecond,
}

Полный список изменений приведён в CHANGELOG .

Контрольные списки обновления сервера

Требования к обновлению

Для обновления существующего развёртывания etcd до 3.3 работающий кластер должен иметь версию 3.2 или более позднюю. Если версия старше 3.2, перед переходом на 3.3 обновитесь до 3.2 .

Кроме того, для плавного скользящего обновления работающий кластер должен быть исправен. Перед продолжением проверьте его работоспособность командой etcdctl endpoint health.

Подготовка

Перед обновлением etcd обязательно протестируйте зависящие от него службы в промежуточном окружении, прежде чем развёртывать обновление в рабочем окружении.

До начала создайте резервную копию данных etcd . Если при обновлении возникнет проблема, эту копию можно использовать для понижения версии до существующей версии etcd. Обратите внимание: команда snapshot сохраняет только данные v3. О данных v2 см. раздел резервное копирование хранилища v2 .

Смешанные версии

Во время обновления кластер etcd поддерживает участников разных версий и работает по протоколу наименьшей общей версии. Кластер считается обновлённым только после обновления всех участников до 3.3. Участники etcd согласуют между собой общую версию кластера, которая определяет сообщаемую версию и поддерживаемые возможности.

Ограничения

Примечание: это ограничение не относится к кластеру, содержащему только данные v3 и не содержащему данные v2.

Если кластер обслуживает набор данных v2 объёмом более 50MB, каждому только что обновлённому участнику может потребоваться до двух минут, чтобы догнать существующий кластер. Для оценки общего объёма данных проверьте размер недавнего снимка. Иными словами, безопаснее всего ждать 2 минуты между обновлениями участников.

При значительно большем общем объёме данных, 100MB или более, этот однократный процесс может занять ещё больше времени. Администраторы столь крупных кластеров etcd могут перед обновлением обратиться к команде etcd за рекомендациями по процедуре.

Понижение версии

После обновления всех участников до v3.3 кластер также переходит на v3.3, и понижение версии из этого завершённого состояния невозможно. Однако пока хотя бы один участник остаётся на v3.2, кластер и его операции имеют версию “v3.2”, а из смешанного состояния можно вернуться к использованию двоичного файла etcd v3.2 на всех участниках.

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

Процедура обновления

В этом примере показано обновление работающего на локальной машине кластера etcd v3.2 из 3 участников.

1. Проверка требований к обновлению

Кластер исправен и использует v3.2.x?

$ ETCDCTL_API=3 etcdctl endpoint health --endpoints=localhost:2379,localhost:22379,localhost:32379
localhost:2379 is healthy: successfully committed proposal: took = 6.600684ms
localhost:22379 is healthy: successfully committed proposal: took = 8.540064ms
localhost:32379 is healthy: successfully committed proposal: took = 8.763432ms

$ curl http://localhost:2379/version
{"etcdserver":"3.2.7","etcdcluster":"3.2.0"}

2. Остановка существующего процесса etcd

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

14:13:31.491746 I | raft: c89feb932daef420 [term 3] received MsgTimeoutNow from 6d4f535bae3ab960 and starts an election to get leadership.
14:13:31.491769 I | raft: c89feb932daef420 became candidate at term 4
14:13:31.491788 I | raft: c89feb932daef420 received MsgVoteResp from c89feb932daef420 at term 4
14:13:31.491797 I | raft: c89feb932daef420 [logterm: 3, index: 9] sent MsgVote request to 6d4f535bae3ab960 at term 4
14:13:31.491805 I | raft: c89feb932daef420 [logterm: 3, index: 9] sent MsgVote request to 9eda174c7df8a033 at term 4
14:13:31.491815 I | raft: raft.node: c89feb932daef420 lost leader 6d4f535bae3ab960 at term 4
14:13:31.524084 I | raft: c89feb932daef420 received MsgVoteResp from 6d4f535bae3ab960 at term 4
14:13:31.524108 I | raft: c89feb932daef420 [quorum:2] has received 2 MsgVoteResp votes and 0 vote rejections
14:13:31.524123 I | raft: c89feb932daef420 became leader at term 4
14:13:31.524136 I | raft: raft.node: c89feb932daef420 elected leader c89feb932daef420 at term 4
14:13:31.592650 W | rafthttp: lost the TCP streaming connection with peer 6d4f535bae3ab960 (stream MsgApp v2 reader)
14:13:31.592825 W | rafthttp: lost the TCP streaming connection with peer 6d4f535bae3ab960 (stream Message reader)
14:13:31.693275 E | rafthttp: failed to dial 6d4f535bae3ab960 on stream Message (dial tcp [::1]:2380: getsockopt: connection refused)
14:13:31.693289 I | rafthttp: peer 6d4f535bae3ab960 became inactive
14:13:31.936678 W | rafthttp: lost the TCP streaming connection with peer 6d4f535bae3ab960 (stream Message writer)

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

$ etcdctl snapshot save backup.db

3. Установка двоичного файла etcd v3.3 и запуск нового процесса etcd

Новый etcd v3.3 опубликует свои сведения в кластере:

14:14:25.363225 I | etcdserver: published {Name:s1 ClientURLs:[http://localhost:2379]} to cluster a9ededbffcb1b1f1

Убедитесь, что сначала каждый участник, а затем весь кластер становятся исправными с новым двоичным файлом etcd v3.3:

$ ETCDCTL_API=3 /etcdctl endpoint health --endpoints=localhost:2379,localhost:22379,localhost:32379
localhost:22379 is healthy: successfully committed proposal: took = 5.540129ms
localhost:32379 is healthy: successfully committed proposal: took = 7.321771ms
localhost:2379 is healthy: successfully committed proposal: took = 10.629901ms

До обновления всего кластера обновлённые участники будут записывать в журнал подобные предупреждения. Это ожидаемо и прекратится после обновления всех участников кластера etcd до v3.3:

14:15:17.071804 W | etcdserver: member c89feb932daef420 has a higher version 3.3.0
14:15:21.073110 W | etcdserver: the local etcd version 3.2.7 is not up-to-date
14:15:21.073142 W | etcdserver: member 6d4f535bae3ab960 has a higher version 3.3.0
14:15:21.073157 W | etcdserver: the local etcd version 3.2.7 is not up-to-date
14:15:21.073164 W | etcdserver: member c89feb932daef420 has a higher version 3.3.0

4. Повторение шагов 2–3 для остальных участников

5. Завершение

После обновления всех участников кластер сообщит об успешном переходе на 3.3:

14:15:54.536901 N | etcdserver/membership: updated the cluster version from 3.2 to 3.3
14:15:54.537035 I | etcdserver/api: enabled capabilities for version 3.3
$ ETCDCTL_API=3 /etcdctl endpoint health --endpoints=localhost:2379,localhost:22379,localhost:32379
localhost:2379 is healthy: successfully committed proposal: took = 2.312897ms
localhost:22379 is healthy: successfully committed proposal: took = 2.553476ms
localhost:32379 is healthy: successfully committed proposal: took = 2.517902ms

7 - Обновление etcd от 3.1 до 3.2

Процессы, списки действий и примечания по обновлению etcd с 3.1 до 3.2

В общем случае, обновление от etcd 3.1 до 3.2 может быть обновлением с нулевым временем простоя:

  • по одному, останавливайте процессы etcd v3.1 и заменяйте их процессами etcd v3.2
  • после запуска всех процессов v3.2, новые функции в v3.2 становятся доступны для кластера

Перед обновлением внимательно прочитайте оставшуюся часть этого руководства для подготовки.

Обновление списков проверки

Предупреждение

При миграции с v2 без данных v3 сервер etcd v3.2+ аварийно завершается при восстановлении из снимка без файла v3 ETCD_DATA_DIR/member/snap/db. Это происходит после миграции с v2 без прежних данных v3 и предотвращает случайную потерю v3, например при перемещении db. После миграции на v3 etcd требует данные v3. Не обновляйтесь до более новых версий v3, пока сервер v3.0 не содержит данные v3.

Изменения, требующие пересборки, в 3.2.

Изменено стандартное значение snapshot-count

Большее значение --snapshot-count удерживает до снимка больше записей Raft в памяти, вызывая периодически повышенное потребление памяти . Лидер дольше хранит последние записи, и медленный последователь получает больше времени догнать его до снимка. --snapshot-count — компромисс между памятью и доступностью медленных последователей.

Начиная с v3.2 значение --snapshot-count по умолчанию изменено с 10,000 на 100,000 .

Изменена зависимость gRPC (>=3.2.10)

Выпуск 3.2.10 или более поздний теперь требует grpc/grpc-go v1.7.5 (<=3.2.9 требует v1.2.1).

Устаревшая grpclog.Logger

grpclog.Logger был устаревшим в пользу grpclog.LoggerV2 . clientv3.Logger теперь grpclog.LoggerV2.

Перед

import "github.com/coreos/etcd/clientv3"
clientv3.SetLogger(log.New(os.Stderr, "grpc: ", 0))

После

import "github.com/coreos/etcd/clientv3"
import "google.golang.org/grpc/grpclog"
clientv3.SetLogger(grpclog.NewLoggerV2(os.Stderr, os.Stderr, os.Stderr))

// log.New above cannot be used (not implement grpclog.LoggerV2 interface)
Устаревшая grpc.ErrClientConnTimeout

Ранее, grpc.ErrClientConnTimeout ошибка возвращалась при таймаутах на подключении клиента. 3.2 теперь возвращает context.DeadlineExceeded (см. #8504 ).

Перед

// expect dial time-out on ipv4 blackhole
_, err := clientv3.New(clientv3.Config{
    Endpoints:   []string{"http://254.0.0.1:12345"},
    DialTimeout: 2 * time.Second
})
if err == grpc.ErrClientConnTimeout {
	// handle errors
}

После

_, err := clientv3.New(clientv3.Config{
    Endpoints:   []string{"http://254.0.0.1:12345"},
    DialTimeout: 2 * time.Second
})
if err == context.DeadlineExceeded {
	// handle errors
}

Изменены максимальные ограничения размера запроса (>=3.2.10)

Версии 3.2.10 и 3.2.11 позволяют настраивать ограничение размера запроса на сервере. >=3.2.12 позволяет задавать его и на сервере, и на клиенте. В предыдущих версиях (v3.2.10, v3.2.11) ответ клиенту был ограничен 4 MiB.

Серверные ограничения на запросы можно настроить с помощью флага --max-request-bytes:

# limits request size to 1.5 KiB
etcd --max-request-bytes 1536

# client writes exceeding 1.5 KiB will be rejected
etcdctl put foo [LARGE VALUE...]
# etcdserver: request is too large

Или настройте поле embed.Config.MaxRequestBytes:

import "github.com/coreos/etcd/embed"
import "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes"

// limit requests to 5 MiB
cfg := embed.NewConfig()
cfg.MaxRequestBytes = 5 * 1024 * 1024

// client writes exceeding 5 MiB will be rejected
_, err := cli.Put(ctx, "foo", [LARGE VALUE...])
err == rpctypes.ErrRequestTooLarge

Если значение не задано, серверное ограничение по умолчанию равно 1.5 MiB.

Клиентские ограничения на запросы должны быть настроены в соответствии с серверными ограничениями.

# limits request size to 1 MiB
etcd --max-request-bytes 1048576
import "github.com/coreos/etcd/clientv3"

cli, _ := clientv3.New(clientv3.Config{
    Endpoints: []string{"127.0.0.1:2379"},
    MaxCallSendMsgSize: 2 * 1024 * 1024,
    MaxCallRecvMsgSize: 3 * 1024 * 1024,
})


// client writes exceeding "--max-request-bytes" will be rejected from etcd server
_, err := cli.Put(ctx, "foo", strings.Repeat("a", 1*1024*1024+5))
err == rpctypes.ErrRequestTooLarge


// client writes exceeding "MaxCallSendMsgSize" will be rejected from client-side
_, err = cli.Put(ctx, "foo", strings.Repeat("a", 5*1024*1024))
err.Error() == "rpc error: code = ResourceExhausted desc = grpc: trying to send message larger than max (5242890 vs. 2097152)"


// some writes under limits
for i := range []int{0,1,2,3,4} {
    _, err = cli.Put(ctx, fmt.Sprintf("foo%d", i), strings.Repeat("a", 1*1024*1024-500))
    if err != nil {
        panic(err)
    }
}
// client reads exceeding "MaxCallRecvMsgSize" will be rejected from client-side
_, err = cli.Get(ctx, "foo", clientv3.WithPrefix())
err.Error() == "rpc error: code = ResourceExhausted desc = grpc: received message larger than max (5240509 vs. 3145728)"

Если значения не заданы, клиентское ограничение отправки по умолчанию равно 2 MiB (1.5 MiB + накладные байты gRPC), а получения — math.MaxInt32. Подробнее см. godoc clientv3 .

Изменены.raw оболочки клиентов gRPC

3.2.12 или более поздняя версия изменяет сигнатуры функций оболочки gRPC клиентского clientv3. Этот изменения были необходимы для поддержки пользовательских ограничений размера сообщений grpc.CallOption.

До и после

-func NewKVFromKVClient(remote pb.KVClient) KV {
+func NewKVFromKVClient(remote pb.KVClient, c *Client) KV {

-func NewClusterFromClusterClient(remote pb.ClusterClient) Cluster {
+func NewClusterFromClusterClient(remote pb.ClusterClient, c *Client) Cluster {

-func NewLeaseFromLeaseClient(remote pb.LeaseClient, keepAliveTimeout time.Duration) Lease {
+func NewLeaseFromLeaseClient(remote pb.LeaseClient, c *Client, keepAliveTimeout time.Duration) Lease {

-func NewMaintenanceFromMaintenanceClient(remote pb.MaintenanceClient) Maintenance {
+func NewMaintenanceFromMaintenanceClient(remote pb.MaintenanceClient, c *Client) Maintenance {

-func NewWatchFromWatchClient(wc pb.WatchClient) Watcher {
+func NewWatchFromWatchClient(wc pb.WatchClient, c *Client) Watcher {

Изменена clientv3.Lease.TimeToLive API

Прежде, clientv3.Lease.TimeToLive API возвращал lease.ErrLeaseNotFound при несуществующем идентификаторе арены. 3.2 вместо этого возвращает TTL=-1 в ответе и не выдает ошибку (см. #7305 ).

Перед

// when leaseID does not exist
resp, err := TimeToLive(ctx, leaseID)
resp == nil
err == lease.ErrLeaseNotFound

После

// when leaseID does not exist
resp, err := TimeToLive(ctx, leaseID)
resp.TTL == -1
err == nil

Перемещен clientv3.NewFromConfigFile в clientv3.yaml.NewConfig

clientv3.NewFromConfigFile перенесен в yaml.NewConfig.

Перед

import "github.com/coreos/etcd/clientv3"
clientv3.NewFromConfigFile

После

import clientv3yaml "github.com/coreos/etcd/clientv3/yaml"
clientv3yaml.NewConfig

Изменение в --listen-peer-urls и --listen-client-urls

3.2 теперь отвергает доменные имена для --listen-peer-urls и --listen-client-urls (3.1 только выводит предупреждения), так как доменное имя недопустимо для привязки к сетевому интерфейсу. Убедитесь, что эти URL правильно форматированы как scheme://IP:port.

См. issue #6336 для более подробной информации.

Проверки для обновления сервера

Требования к обновлению

Для обновления существующего развёртывания etcd до 3.2 кластер должен быть версии 3.1 или выше. Если это раньше 3.1, рекомендуется обновить до 3.1 перед обновлением до 3.2.

Также, для обеспечения плавного обновления кластер должен быть здоровым. Проверьте состояние кластера с помощью команды etcdctl endpoint health перед продолжением.

Подготовка

Перед обновлением etcd всегда протестируйте сервисы, зависящие от etcd, в стендовой среде перед развертыванием обновления в производственную среду.

Перед началом сделайте резервную копию данных etcd . Если что-то пойдет не так с обновлением, можно использовать эту резервную копию для понижения версии обратно к существующей версии etcd. Пожалуйста, примечание: команда snapshot выполняет только резервное копирование v3 данных. Для v2 данных см. резервное копирование v2 хранилища данных .

Смешанные версии

При обновлении кластер etcd поддерживает смешанные версии участников etcd и работает с протоколом самой низкой общей версии. Кластер считается обновленным только после того, как все его участники будут обновлены до версии 3.2. Внутри кластерные участники переговариваются между собой, чтобы определить общую версию кластера, которая контролирует отчетываемую версию и поддерживаемые функции.

Ограничения

Примечание: если кластер содержит только данные версии 3 и нет данных версии 2, то он не подлежит этому ограничению.

Если кластер обслуживает набор данных версии v2 размером более 50MB, каждый новый обновленный участник может потребовать до двух минут для того, чтобы синхронизироваться с существующим кластером. Проверьте размер последнего снимка, чтобы оценить общий размер данных. Иными словами, наиболее безопасно ждать 2 минут между обновлением каждого участника.

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

Понижение версии

Если все участники были обновлены до v3.2, кластер будет обновлен до v3.2, и понижение версии из этого завершенного состояния невозможно. Если хотя бы один участник остается v3.1, кластер и его операции остаются “v3.1”, и из этого смешанного состояния кластера возможно вернуться к использованию etcd-бинарного файла версии v3.1 на всех участниках.

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

Процедура обновления

Этот пример показывает, как обновить кластер etcd, работающий локально, состоящий из участника 3-члена v3.1.

1. Проверьте требования к обновлению

Я здоров и работает ли кластер v3.1.x?

$ ETCDCTL_API=3 etcdctl endpoint health --endpoints=localhost:2379,localhost:22379,localhost:32379
localhost:2379 is healthy: successfully committed proposal: took = 6.600684ms
localhost:22379 is healthy: successfully committed proposal: took = 8.540064ms
localhost:32379 is healthy: successfully committed proposal: took = 8.763432ms

$ curl http://localhost:2379/version
{"etcdserver":"3.1.7","etcdcluster":"3.1.0"}

2. Остановите существующий процесс etcd

Когда процесс etcd останавливается, ожидаемые ошибки будут записаны другими участниками кластера. Это нормально, так как соединение участника было (временно) прервано:

2017-04-27 14:13:31.491746 I | raft: c89feb932daef420 [term 3] received MsgTimeoutNow from 6d4f535bae3ab960 and starts an election to get leadership.
2017-04-27 14:13:31.491769 I | raft: c89feb932daef420 became candidate at term 4
2017-04-27 14:13:31.491788 I | raft: c89feb932daef420 received MsgVoteResp from c89feb932daef420 at term 4
2017-04-27 14:13:31.491797 I | raft: c89feb932daef420 [logterm: 3, index: 9] sent MsgVote request to 6d4f535bae3ab960 at term 4
2017-04-27 14:13:31.491805 I | raft: c89feb932daef420 [logterm: 3, index: 9] sent MsgVote request to 9eda174c7df8a033 at term 4
2017-04-27 14:13:31.491815 I | raft: raft.node: c89feb932daef420 lost leader 6d4f535bae3ab960 at term 4
2017-04-27 14:13:31.524084 I | raft: c89feb932daef420 received MsgVoteResp from 6d4f535bae3ab960 at term 4
2017-04-27 14:13:31.524108 I | raft: c89feb932daef420 [quorum:2] has received 2 MsgVoteResp votes and 0 vote rejections
2017-04-27 14:13:31.524123 I | raft: c89feb932daef420 became leader at term 4
2017-04-27 14:13:31.524136 I | raft: raft.node: c89feb932daef420 elected leader c89feb932daef420 at term 4
2017-04-27 14:13:31.592650 W | rafthttp: lost the TCP streaming connection with peer 6d4f535bae3ab960 (stream MsgApp v2 reader)
2017-04-27 14:13:31.592825 W | rafthttp: lost the TCP streaming connection with peer 6d4f535bae3ab960 (stream Message reader)
2017-04-27 14:13:31.693275 E | rafthttp: failed to dial 6d4f535bae3ab960 on stream Message (dial tcp [::1]:2380: getsockopt: connection refused)
2017-04-27 14:13:31.693289 I | rafthttp: peer 6d4f535bae3ab960 became inactive
2017-04-27 14:13:31.936678 W | rafthttp: lost the TCP streaming connection with peer 6d4f535bae3ab960 (stream Message writer)

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

$ etcdctl snapshot save backup.db

3. Замените встраиваемую версию etcd v3.2 и запустите новый процесс etcd

The новое v3.2 etcd будет публиковать свои данные в кластер:

2017-04-27 14:14:25.363225 I | etcdserver: published {Name:s1 ClientURLs:[http://localhost:2379]} to cluster a9ededbffcb1b1f1

Убедитесь, что с новым двоичным файлом etcd v3.2 каждый участник, а затем весь кластер становятся исправными:

$ ETCDCTL_API=3 /etcdctl endpoint health --endpoints=localhost:2379,localhost:22379,localhost:32379
localhost:22379 is healthy: successfully committed proposal: took = 5.540129ms
localhost:32379 is healthy: successfully committed proposal: took = 7.321771ms
localhost:2379 is healthy: successfully committed proposal: took = 10.629901ms

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

2017-04-27 14:15:17.071804 W | etcdserver: member c89feb932daef420 has a higher version 3.2.0
2017-04-27 14:15:21.073110 W | etcdserver: the local etcd version 3.1.7 is not up-to-date
2017-04-27 14:15:21.073142 W | etcdserver: member 6d4f535bae3ab960 has a higher version 3.2.0
2017-04-27 14:15:21.073157 W | etcdserver: the local etcd version 3.1.7 is not up-to-date
2017-04-27 14:15:21.073164 W | etcdserver: member c89feb932daef420 has a higher version 3.2.0

4. Повторите шаг 2 до шага 3 для всех других участников

5. Завершить

Когда все участники будут обновлены, кластер будет сообщать о успешном переходе к 3.2:

2017-04-27 14:15:54.536901 N | etcdserver/membership: updated the cluster version from 3.1 to 3.2
2017-04-27 14:15:54.537035 I | etcdserver/api: enabled capabilities for version 3.2
$ ETCDCTL_API=3 /etcdctl endpoint health --endpoints=localhost:2379,localhost:22379,localhost:32379
localhost:2379 is healthy: successfully committed proposal: took = 2.312897ms
localhost:22379 is healthy: successfully committed proposal: took = 2.553476ms
localhost:32379 is healthy: successfully committed proposal: took = 2.517902ms

8 - Обновление etcd с 3.0 до 3.1

Процесс, контрольные списки и примечания по обновлению etcd с 3.0 до 3.1

В общем случае обновление etcd с 3.0 до 3.1 можно выполнить поэтапно без простоя:

  • по очереди останавливать процессы etcd v3.0 и заменять их процессами etcd v3.1;
  • после запуска всех процессов v3.1 кластеру станут доступны новые возможности v3.1.

Перед началом обновления прочитайте остальную часть руководства и подготовьтесь.

Контрольные списки обновления

Предупреждение

При миграции с v2 без данных v3 сервер etcd v3.2+ аварийно завершается при восстановлении из существующих снимков, если отсутствует файл v3 ETCD_DATA_DIR/member/snap/db. Это происходит, когда сервер мигрировал с v2 и ранее не содержал данных v3. Такое поведение также предотвращает случайную потерю данных v3, например при перемещении файла db. После миграции на v3 etcd может работать только с данными v3. Не обновляйтесь до более новых версий v3, пока сервер v3.0 не содержит данных v3.

Мониторинг

Следующие метрики v3.0.x устарели в пользу go-grpc-prometheus :

  • etcd_grpc_requests_total
  • etcd_grpc_requests_failed_total
  • etcd_grpc_active_streams
  • etcd_grpc_unary_requests_duration_seconds

Требования к обновлению

Для обновления существующего развёртывания etcd до 3.1 работающий кластер должен иметь версию 3.0 или новее. Версию ниже 3.0 сначала обновите до 3.0 , а затем до 3.1.

Для плавного поэтапного обновления работающий кластер также должен быть исправен. Перед продолжением проверьте его командой etcdctl endpoint health.

Подготовка

Перед обновлением etcd обязательно протестируйте зависящие от него службы в промежуточной среде до развёртывания обновления в производственной.

До начала создайте резервную копию данных etcd . Если обновление завершится неудачно, копия позволит вернуться к предыдущей версии . Обратите внимание: команда snapshot копирует только данные v3. Для данных v2 см. резервное копирование хранилища v2 .

Смешанные версии

Во время обновления кластер etcd поддерживает участников разных версий и работает по протоколу наименьшей общей версии. Кластер считается обновлённым только после обновления всех участников до 3.1. Участники etcd согласуют общую версию кластера, которая определяет сообщаемую версию и поддерживаемые возможности.

Ограничения

Примечание: ограничение не относится к кластеру, содержащему только данные v3 без данных v2.

Если кластер обслуживает набор данных v2 больше 50MB, новому обновлённому участнику может потребоваться до двух минут, чтобы догнать кластер. Оцените объём по размеру последнего снимка. Безопаснее всего ждать 2 минуты между обновлениями участников.

При значительно большем объёме, 100MB или более, этот однократный процесс может занять ещё больше времени. Администраторы настолько крупных кластеров etcd могут до обновления обратиться к команде etcd за рекомендациями.

Понижение версии

После обновления всех участников до v3.1 кластер становится кластером v3.1, и понизить версию из этого завершённого состояния невозможно. Пока хотя бы один участник остаётся на v3.0, кластер и его операции сохраняют версию “v3.0”, и из такого смешанного состояния можно вернуть двоичный файл etcd v3.0 на всех участниках.

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

Процедура обновления

В примере показано обновление локального кластера etcd v3.0 из 3 участников.

1. Проверьте требования к обновлению

Кластер исправен и работает под управлением v3.0.x?

$ ETCDCTL_API=3 etcdctl endpoint health --endpoints=localhost:2379,localhost:22379,localhost:32379
localhost:2379 is healthy: successfully committed proposal: took = 6.600684ms
localhost:22379 is healthy: successfully committed proposal: took = 8.540064ms
localhost:32379 is healthy: successfully committed proposal: took = 8.763432ms

$ curl http://localhost:2379/version
{"etcdserver":"3.0.16","etcdcluster":"3.0.0"}

2. Остановите существующий процесс etcd

При остановке каждого процесса etcd другие участники записывают ожидаемые ошибки. Это нормально, поскольку соединение с участником временно разорвано:

2017-01-17 09:34:18.352662 I | raft: raft.node: 1640829d9eea5cfb elected leader 1640829d9eea5cfb at term 5
2017-01-17 09:34:18.359630 W | etcdserver: failed to reach the peerURL(http://localhost:2380) of member fd32987dcd0511e0 (Get http://localhost:2380/version: dial tcp 127.0.0.1:2380: getsockopt: connection refused)
2017-01-17 09:34:18.359679 W | etcdserver: cannot get the version of member fd32987dcd0511e0 (Get http://localhost:2380/version: dial tcp 127.0.0.1:2380: getsockopt: connection refused)
2017-01-17 09:34:18.548116 W | rafthttp: lost the TCP streaming connection with peer fd32987dcd0511e0 (stream Message writer)
2017-01-17 09:34:19.147816 W | rafthttp: lost the TCP streaming connection with peer fd32987dcd0511e0 (stream MsgApp v2 writer)
2017-01-17 09:34:34.364907 W | etcdserver: failed to reach the peerURL(http://localhost:2380) of member fd32987dcd0511e0 (Get http://localhost:2380/version: dial tcp 127.0.0.1:2380: getsockopt: connection refused)

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

$ etcdctl snapshot save backup.db

3. Установите двоичный файл etcd v3.1 и запустите новый процесс etcd

Новый etcd v3.1 опубликует свои сведения в кластере:

2017-01-17 09:36:00.996590 I | etcdserver: published {Name:my-etcd-1 ClientURLs:[http://localhost:2379]} to cluster 46bc3ce73049e678

Убедитесь, что с новым двоичным файлом etcd v3.1 каждый участник, а затем весь кластер становятся исправными:

$ ETCDCTL_API=3 /etcdctl endpoint health --endpoints=localhost:2379,localhost:22379,localhost:32379
localhost:22379 is healthy: successfully committed proposal: took = 5.540129ms
localhost:32379 is healthy: successfully committed proposal: took = 7.321671ms
localhost:2379 is healthy: successfully committed proposal: took = 10.629901ms

До обновления всего кластера обновлённые участники будут записывать следующие предупреждения. Это ожидаемо и прекратится после обновления всех участников до v3.1:

2017-01-17 09:36:38.406268 W | etcdserver: the local etcd version 3.0.16 is not up-to-date
2017-01-17 09:36:38.406295 W | etcdserver: member fd32987dcd0511e0 has a higher version 3.1.0
2017-01-17 09:36:42.407695 W | etcdserver: the local etcd version 3.0.16 is not up-to-date
2017-01-17 09:36:42.407730 W | etcdserver: member fd32987dcd0511e0 has a higher version 3.1.0

4. Повторите шаги 2–3 для остальных участников

5. Завершите обновление

После обновления всех участников кластер сообщит об успешном переходе на 3.1:

2017-01-17 09:37:03.100015 I | etcdserver: updating the cluster version from 3.0 to 3.1
2017-01-17 09:37:03.104263 N | etcdserver/membership: updated the cluster version from 3.0 to 3.1
2017-01-17 09:37:03.104374 I | etcdserver/api: enabled capabilities for version 3.1
$ ETCDCTL_API=3 /etcdctl endpoint health --endpoints=localhost:2379,localhost:22379,localhost:32379
localhost:2379 is healthy: successfully committed proposal: took = 2.312897ms
localhost:22379 is healthy: successfully committed proposal: took = 2.553476ms
localhost:32379 is healthy: successfully committed proposal: took = 2.516902ms

9 - Обновление etcd с 2.3 до 3.0

Процесс, контрольные списки и примечания по обновлению etcd с 2.3 до 3.0

В общем случае обновление etcd с 2.3 до 3.0 можно выполнить поэтапно без простоя:

  • по очереди останавливать процессы etcd v2.3 и заменять их процессами etcd v3.0;
  • после запуска всех процессов v3.0 кластеру станут доступны новые возможности v3.0.

Перед началом обновления прочитайте остальную часть руководства и подготовьтесь.

Контрольные списки обновления

Предупреждение

При миграции с v2 без данных v3 сервер etcd v3.2+ аварийно завершается при восстановлении из существующих снимков, если отсутствует файл v3 ETCD_DATA_DIR/member/snap/db. Это происходит, когда сервер мигрировал с v2 и ранее не содержал данных v3. Такое поведение также предотвращает случайную потерю данных v3, например при перемещении файла db. После миграции на v3 etcd может работать только с данными v3. Не обновляйтесь до более новых версий v3, пока сервер v3.0 не содержит данных v3.

Требования к обновлению

Для обновления существующего развёртывания etcd до 3.0 работающий кластер должен иметь версию 2.3 или новее. Версию ниже 2.3 сначала обновите до 2.3 , а затем до 3.0.

Для плавного поэтапного обновления работающий кластер также должен быть исправен. Перед продолжением проверьте его командой etcdctl cluster-health.

Подготовка

Перед обновлением etcd обязательно протестируйте зависящие от него службы в промежуточной среде до развёртывания обновления в производственной.

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

Смешанные версии

Во время обновления кластер etcd поддерживает участников разных версий и работает по протоколу наименьшей общей версии. Кластер считается обновлённым только после обновления всех участников до 3.0. Участники etcd согласуют общую версию кластера, которая определяет сообщаемую версию и поддерживаемые возможности.

Ограничения

Если общий объём данных превышает 50MB, новому обновлённому участнику может потребоваться до 2 минут, чтобы догнать кластер. Оцените объём по размеру последнего снимка. Безопаснее всего ждать 2 минуты между обновлениями участников.

При значительно большем объёме, 100MB или более, этот однократный процесс может занять ещё больше времени. Администраторы настолько крупных кластеров etcd могут до обновления обратиться к команде etcd за рекомендациями.

Понижение версии

После обновления всех участников до v3.0 кластер становится кластером v3.0, и понизить версию из этого завершённого состояния невозможно. Пока хотя бы один участник остаётся на v2.3, кластер и его операции сохраняют версию «v2.3», и из такого смешанного состояния можно вернуть двоичный файл etcd v2.3 на всех участниках.

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

Процедура обновления

В примере подробно показано обновление локального кластера etcd v2.3 из трёх участников.

1. Проверьте требования к обновлению

Кластер исправен и работает под управлением v.2.3.x?

$ etcdctl cluster-health
member 6e3bd23ae5f1eae0 is healthy: got healthy result from http://localhost:22379
member 924e2e83e93f2560 is healthy: got healthy result from http://localhost:32379
member 8211f1d0f64f3269 is healthy: got healthy result from http://localhost:12379
cluster is healthy

$ curl http://localhost:2379/version
{"etcdserver":"2.3.x","etcdcluster":"2.3.8"}

2. Остановите существующий процесс etcd

При остановке каждого процесса etcd другие участники записывают ожидаемые ошибки. Это нормально, поскольку соединение с участником временно разорвано:

2016-06-27 15:21:48.624124 E | rafthttp: failed to dial 8211f1d0f64f3269 on stream Message (dial tcp 127.0.0.1:12380: getsockopt: connection refused)
2016-06-27 15:21:48.624175 I | rafthttp: the connection with 8211f1d0f64f3269 became inactive

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

$ etcdctl backup \
      --data-dir /var/lib/etcd \
      --backup-dir /tmp/etcd_backup

3. Установите двоичный файл etcd v3.0 и запустите новый процесс etcd

Новый etcd v3.0 опубликует свои сведения в кластере:

09:58:25.938673 I | etcdserver: published {Name:infra1 ClientURLs:[http://localhost:12379]} to cluster 524400597fb1d5f6

Убедитесь, что с новым двоичным файлом etcd v3.0 каждый участник, а затем весь кластер становятся исправными:

$ etcdctl cluster-health
member 6e3bd23ae5f1eae0 is healthy: got healthy result from http://localhost:22379
member 924e2e83e93f2560 is healthy: got healthy result from http://localhost:32379
member 8211f1d0f64f3269 is healthy: got healthy result from http://localhost:12379
cluster is healthy

До обновления всего кластера обновлённые участники будут записывать следующие предупреждения. Это ожидаемо и прекратится после обновления всех участников до v3.0:

2016-06-27 15:22:05.679644 W | etcdserver: the local etcd version 2.3.7 is not up-to-date
2016-06-27 15:22:05.679660 W | etcdserver: member 8211f1d0f64f3269 has a higher version 3.0.0

4. Повторите шаги 2–3 для остальных участников

5. Завершите обновление

После обновления всех участников кластер сообщит об успешном переходе на 3.0:

2016-06-27 15:22:19.873751 N | membership: updated the cluster version from 2.3 to 3.0
2016-06-27 15:22:19.914574 I | api: enabled capabilities for version 3.0.0
$ ETCDCTL_API=3 etcdctl endpoint health
127.0.0.1:12379 is healthy: successfully committed proposal: took = 18.440155ms
127.0.0.1:32379 is healthy: successfully committed proposal: took = 13.651368ms
127.0.0.1:22379 is healthy: successfully committed proposal: took = 18.513301ms

Дополнительные соображения

  • Переменные окружения etcdctl были обновлены. Если ETCDCTL_API=2 etcdctl cluster-health работает, но ETCDCTL_API=3 etcdctl endpoints health отвечает Error: grpc: timed out when dialing, убедитесь, что используются новые имена переменных .

Известные проблемы

  • etcd < v3.1 работает неправильно при сборке с Go > v1.7. Дополнительные сведения см. в задаче 6951 .
  • Если в журнале сервера etcd появляется ошибка transport: http2Client.notifyError got notified that the client transport was broken unexpected EOF., убедитесь, что используется готовый выпуск etcd либо сборка с (etcd v3.1+ & go v1.7+) или (etcd <v3.1 & go v1.6.x).
  • Добавление узла v3 в кластер v2.3 во время обновления не поддерживается и может вызвать аварийное завершение. Дополнительные сведения см. в задаче 7249 . Смешанные версии участников разрешены только во время миграции на v3. Завершите обновление до любых изменений состава кластера.