Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Member Add Failure #11554

Closed
daniel-keeney opened this issue Jan 22, 2020 · 18 comments · Fixed by #11638
Closed

Member Add Failure #11554

daniel-keeney opened this issue Jan 22, 2020 · 18 comments · Fixed by #11638
Labels

Comments

@daniel-keeney
Copy link

daniel-keeney commented Jan 22, 2020

We are trying to set up a 3-node cluster of etcd. The first two nodes start up fine, but the third one experiences trouble approximately 80% of the time. The steps that the nodes take to join the cluster are to:

  1. join the cluster via etcdctl member add ...
  2. start up the etcd server with the relevant initial cluster data from step 1

This is failing at step 1, and so the etcd server ends up not running on the third node.

Version: 3.3.17

Script:
ETCDCTL_API=3 etcdctl member add <memberName> --peer-urls "https://master-2.internal:2380"

(master-2.internal is itself)

Expected Output:

Member ec15b94869b0fca7 added to cluster 6d938e3be5102340

ETCD_NAME="memberName"
ETCD_INITIAL_CLUSTER="2846f720-4ec2-4794-af5e-2261f3d047ea=https://master-0.internal:2380,7b915602-0b4b-473c-8d92-1afdc1d03c58=https://master-1.internal:2380,2e51e8ec-8c1d-493a-9b2a-a8bb07f9f630=https://master-2.internal:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://master-2.internal:2380"
ETCD_INITIAL_CLUSTER_STATE="existing"

Actual Output:

Member db14cc7363e1acfb added to cluster 6d938e3be5102340
{"level":"warn","ts":"2020-01-22T19:16:35.617Z","caller":"clientv3/retry_interceptor.go:61","msg":"retrying of unary invoker failed","target":"endpoint://client-ef3acb95-0e80-4a52-97ba-b3c2ff99f703/master-0.internal:2379","attempt":0,"error":"rpc error: code = DeadlineExceeded desc = context deadline exceeded"}
Error: context deadline exceeded

Output of etcdctl endpoint health:

{"level":"warn","ts":"2020-01-22T19:19:53.005Z","caller":"clientv3/retry_interceptor.go:61","msg":"retrying of unary invoker failed","target":"endpoint://client-e6eec11d-f769-41e4-8c4d-b5d262987894/master-2.internal:2379","attempt":0,"error":"rpc error: code = DeadlineExceeded desc = latest connection error: connection error: desc = \"transport: Error while dialing dial tcp 10.0.10.4:2379: connect: connection refused\""}
https://master-1.internal:2379 is healthy: successfully committed proposal: took = 17.114338ms
https://master-0.internal:2379 is healthy: successfully committed proposal: took = 17.410487ms
https://master-2.internal:2379 is unhealthy: failed to commit proposal: context deadline exceeded
Error: unhealthy cluster

We are able to dig the relevant host names from all 3 nodes (master-0|1|2.internal), and we tried adding the --command-timeout=30s flag to etcdctl member add which did not help. We are able to manually remove the member and retry, which works about 20% of the time. How can we go about diagnosing this problem further?

EDIT: Markdown formatting

@daniel-keeney
Copy link
Author

daniel-keeney commented Jan 23, 2020

To reproduce this, it will help to run 3 instances of etcd inside a single etcd docker container. You might want to use 3 separate terminal windows to make this easy to follow. Steps to reproduce:

Window 1

docker run \
  --name=experiment \
  -it \
  gcr.io/etcd-development/etcd:v3.3.12 \
  sh
/usr/local/bin/etcd \
  --name "node-0" \
  --data-dir /etcd-data1 \
  --listen-client-urls http://0.0.0.0:12379 \
  --advertise-client-urls http://0.0.0.0:12380 \
  --listen-peer-urls http://0.0.0.0:12380 \
  --initial-advertise-peer-urls http://0.0.0.0:12380 \
  --initial-cluster node-0=http://0.0.0.0:12380 \
  --initial-cluster-state new

Window 2

  1. docker exec -it $(docker ps -f name=experiment -q) sh
  2. export ETCDCTL_API=3
  3. MEMBER_ADD_OUTPUT="$(etcdctl --endpoints "http://0.0.0.0:12379,http://0.0.0.0:22379,http://0.0.0.0:32379" member add node-1 --peer-urls "http://0.0.0.0:22380")"
  4. echo "MEMBER_ADD_OUTPUT = $MEMBER_ADD_OUTPUT"
  5. CLUSTER="$(echo "${MEMBER_ADD_OUTPUT}" | grep "ETCD_INITIAL_CLUSTER=" | cut -d'=' -f2- | tr -d '"')"
  6. echo "CLUSTER = $CLUSTER"
/usr/local/bin/etcd \
  --name="node-1" \
  --data-dir="/etcd-data2" \
  --listen-peer-urls="http://0.0.0.0:22380" \
  --initial-advertise-peer-urls="http://0.0.0.0:22380" \
  --listen-client-urls="http://0.0.0.0:22379" \
  --advertise-client-urls="http://0.0.0.0:22380" \
  --initial-cluster="${CLUSTER}" \
  --initial-cluster-state="existing"

Window 3

  1. docker exec -it $(docker ps -f name=experiment -q) sh
  2. export ETCDCTL_API=3
  3. etcdctl --endpoints "http://0.0.0.0:12379,http://0.0.0.0:22379,http://0.0.0.0:32379" member add node-2 --peer-urls "http://0.0.0.0:32380"
  4. etcdctl --endpoints "http://0.0.0.0:12379,http://0.0.0.0:22379,http://0.0.0.0:32379" member remove $(etcdctl --endpoints "http://0.0.0.0:12379,http://0.0.0.0:22379,http://0.0.0.0:32379" member list | grep unstarted | cut -d',' -f1)

Repeat the last two steps in Window 3 repeatedly to see how consistently it passes or fails. Then you can start over and change the version of the docker image you run with in step 1 of Window 1. Our results:

v3.3.12
passed 10x

v3.3.13
passed 10x

v3.3.14
failed 2x
passed 2x
failed 2x
passed 1x
failed 3x

v3.3.15
failed 2x
passed 2x
failed 2x
passed 1x
failed 3x

v3.3.17
passed 2x
failed 1x
passed 3x
failed 3x
passed 1x

@daniel-keeney
Copy link
Author

To summarize, it looks like this was a regression introduced in v3.3.14

@YoyinZyc
Copy link
Contributor

It looks like similar to #11186. It should have been fixed in 3.3.17 with PR #11194. @jingyih could you please have a look?

@jingyih
Copy link
Contributor

jingyih commented Jan 27, 2020

etcdctl --endpoints "http://0.0.0.0:12379,http://0.0.0.0:22379,http://0.0.0.0:32379" member add node-2 --peer-urls "http://0.0.0.0:32380"

@daniel-keeney
When you run this command, is endpoint http://0.0.0.0:32379 available? Or is it the endpoint that is going to be served by the 3rd member?

@jfmyers9
Copy link

We are running this command from the third node that is being added. The process looks like:

  • Have a running closer of N nodes on N machines.
  • Spin up a new machine
  • Run etcdctl member add from the new machine
  • Extract the cluster information from the output of etcdctl member add
  • Start up the new ETCD process on the new machine.

Therefore there will be nothing listening on any interfaces at the time of running etcdctl member add.

@jfmyers9
Copy link

If it helps, I grabbed a goroutine dump of the etcdctl process when it fails to fetch the cluster information. I've attached it the full contents but it appears to be hanging on this line in the member add command.

goroutines.txt

@swalner-pivotal
Copy link

@jingyih (answering for @daniel-keeney since he's out): http://0.0.0.:32379 is the endpoint that is going to be served by the 3rd member.

@jingyih
Copy link
Contributor

jingyih commented Jan 30, 2020

@swalner-pivotal Thanks! Given that http://0.0.0.:32379 is not yet available at the time of command execution. Could you remove it from the "--endpoints" flag and see if it helps?

@swalner-pivotal
Copy link

Hi @jingyih, we also tried that, but it's important to note that this exact configuration works when run with 3.3.12 (and 3.3.13).
We are using a work-around of combining etcdctl 3.3.12 with etcd server 3.3.17, and (for our limited purposes) this seems to work well.

@jingyih
Copy link
Contributor

jingyih commented Jan 31, 2020

In 3.3.14, the etcd client balancer was rewritten to fix a major bug. It is a breaking change [1]. That might explain the different behavior you observed.

[1] https://github.com/etcd-io/etcd/blob/master/CHANGELOG-3.3.md#v3314-2019-08-16

@daniel-keeney
Copy link
Author

daniel-keeney commented Jan 31, 2020

@jingyih Thanks for your responsiveness! We took your advice and tried replacing Window 3's step 3, which was originally:
etcdctl --endpoints "http://0.0.0.0:12379,http://0.0.0.0:22379,http://0.0.0.0:32379" member add node-2 --peer-urls "http://0.0.0.0:32380"
with this:
etcdctl --endpoints "http://0.0.0.0:12379,http://0.0.0.0:22379" member add node-2 --peer-urls "http://0.0.0.0:32380"
(note that http://0.0.0.0:32379 is missing from the endpoints), and we still had a failure rate higher than 50% in version 3.3.17. Thanks for the pointer about the changelog, you may be right that the load balancer rewrite is the source of the problem.

Please advise us if there is something else we should try, we appreciate your help.

@jingyih
Copy link
Contributor

jingyih commented Feb 3, 2020

Could you paste the error message of the following command you tried?

etcdctl --endpoints "http://0.0.0.0:12379,http://0.0.0.0:22379" member add node-2 --peer-urls "http://0.0.0.0:32380"

@daniel-keeney
Copy link
Author

Sorry for leaving out that detail. It was the same as in the initial report:

Member db14cc7363e1acfb added to cluster 6d938e3be5102340
{"level":"warn","ts":"2020-01-22T19:16:35.617Z","caller":"clientv3/retry_interceptor.go:61","msg":"retrying of unary invoker failed","target":"endpoint://client-ef3acb95-0e80-4a52-97ba-b3c2ff99f703/master-0.internal:2379","attempt":0,"error":"rpc error: code = DeadlineExceeded desc = context deadline exceeded"}
Error: context deadline exceeded

@jingyih
Copy link
Contributor

jingyih commented Feb 4, 2020

But "endpoint://client-ef3acb95-0e80-4a52-97ba-b3c2ff99f703/master-0.internal:2379", which is part of the error message, is not included in the command flag --endpoints? I am asking because I cannot reproduce this issue. Could you reproduce this issue using the following command?

etcdctl --endpoints "http://0.0.0.0:12379,http://0.0.0.0:22379" member add node-2 --peer-urls "http://0.0.0.0:32380"

@daniel-keeney
Copy link
Author

daniel-keeney commented Feb 4, 2020

Sorry about that, I was trying to indicate that it was the same "DeadlineExceeded" error as before. Here is the combined shell prompt, command, and output:

/ # etcdctl --endpoints "http://0.0.0.0:12379,http://0.0.0.0:22379" member add node-2 --peer-urls "http://0.0.0.0:
32380"
Member ced8f1ec7181d330 added to cluster 3cc7a70a26c80530
{"level":"warn","ts":"2020-02-04T20:12:56.757Z","caller":"clientv3/retry_interceptor.go:61","msg":"retrying of unary invoker failed","target":"endpoint://client-338a57d6-68c2-4933-b74d-bfc48410cc20/0.0.0.0:12379","attempt":0,"error":"rpc error: code = DeadlineExceeded desc = context deadline exceeded"}
Error: <nil>

If you are not able to reproduce it on the first try, then run:

etcdctl --endpoints "http://0.0.0.0:12379,http://0.0.0.0:22379" member remove $(etcdctl --endpoints "http://0.0.0.0:12379,http://0.0.0.0:22379" member list | grep unstarted | cut -d',' -f1)

to reset the cluster back to 2 members and try member add again, it will fail around 50% or more of the time.

@jingyih
Copy link
Contributor

jingyih commented Feb 5, 2020

Thanks @daniel-keeney, I was able to reproduce this. I will take a closer look.

@daniel-keeney
Copy link
Author

Great, thank you!

@eselvam
Copy link

eselvam commented Jul 15, 2020

{"level":"warn","ts":"2020-07-15T05:45:40.089+0100","caller":"clientv3/retry_interceptor.go:61","msg":"retrying of unary invoker failed","target":"passthrough:///https://ipmasked:2379","attempt":0,"error":"rpc error: code = DeadlineExceeded desc = context deadline exceeded"}

It is happening when we add stacked kubernetes masters based on instruction at kubernetes.io. It is a second master node.

The etcdctl member status and list are showing correctly with node 1 as master and node 2 as false however when we down the master 1, the entire cluster is going done.

Kubernetes version 1.18.5 and etcd version: 3.4.3

+------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| master1:2379 | 16cf629ee72c2590 | 3.4.3 | 3.2 MB | false | false | 6 | 3637096 | 3637096 | |
| master2:2379 | 448a38484560a13c | 3.4.3 | 3.2 MB | true | false | 6 | 3637096 | 3637096 | |
+------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging a pull request may close this issue.

6 participants