diff --git a/Documentation/op-guide/runtime-configuration.md b/Documentation/op-guide/runtime-configuration.md index 675945810..a5f27aa05 100644 --- a/Documentation/op-guide/runtime-configuration.md +++ b/Documentation/op-guide/runtime-configuration.md @@ -132,8 +132,6 @@ and to reduce cluster downtime when the new member is added, it is recommended t as a learner until it catches up. This can be described as a three step process: * Add the new member as learner via [gRPC members API][member-api-grpc] or the `etcdctl member add --learner` command. - Note that v2 [HTTP member API][member-api] does not support this feature. (If user wants to use HTTP, - etcd provides a JSON [gRPC gateway][grpc-gateway], which serves a RESTful proxy that translates HTTP/JSON requests into gRPC messages.) * Start the new member with the new cluster configuration, including a list of the updated members (existing members + the new member). This step is exactly the same as before. @@ -244,5 +242,4 @@ It is enabled by default. [member migration]: ../v2/admin_guide.md#member-migration [remove member]: #remove-a-member [runtime-reconf]: runtime-reconf-design.md -[grpc-gateway]: https://github.com/grpc-ecosystem/grpc-gateway [error cases when promoting a member]: #error-cases-when-promoting-a-learner-member diff --git a/etcdserver/server.go b/etcdserver/server.go index 0139f5908..115ef8a90 100644 --- a/etcdserver/server.go +++ b/etcdserver/server.go @@ -1635,6 +1635,9 @@ func (s *EtcdServer) RemoveMember(ctx context.Context, id uint64) ([]*membership // PromoteMember promotes a learner node to a voting node. func (s *EtcdServer) PromoteMember(ctx context.Context, id uint64) ([]*membership.Member, error) { + // only raft leader has information on whether the to-be-promoted learner node is ready. If promoteMember call + // fails with ErrNotLeader, forward the request to leader node via HTTP. If promoteMember call fails with error + // other than ErrNotLeader, return the error. resp, err := s.promoteMember(ctx, id) if err != ErrNotLeader { return resp, err @@ -1666,6 +1669,12 @@ func (s *EtcdServer) PromoteMember(ctx context.Context, id uint64) ([]*membershi return nil, ErrCanceled } +// promoteMember checks whether the to-be-promoted learner node is ready before sending the promote +// request to raft. +// The function returns ErrNotLeader if the local node is not raft leader (therefore does not have +// enough information to determine if the learner node is ready), returns ErrLearnerNotReady if the +// local node is leader (therefore has enough information) but decided the learner node is not ready +// to be promoted. func (s *EtcdServer) promoteMember(ctx context.Context, id uint64) ([]*membership.Member, error) { if err := s.checkMembershipOperationPermission(ctx); err != nil { return nil, err