etcd 的容器的状态应为UpUp之后显示的持续时间是容器运行的时间。

输出示例:

  1. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  2. 605a124503b9 rancher/coreos-etcd:v3.2.18 "/usr/local/bin/et..." 2 hours ago Up 2 hours etcd

etcd 容器日志

容器的日志记录可以包含有关可能出现的问题的信息。

  1. docker logs etcd

etcd 监听的地址取决于运行 etcd 的主机的地址配置。如果为运行 etcd 的主机配置了内部地址,则需要显式指定etcdctl的端点。如果有任何命令响应Error: context deadline exceeded,则代表 etcd 实例不正常(仲裁丢失或该实例未正确加入集群)

输出应包含所有具有 etcd 角色的节点,并且所有节点上的输出应相同。

命令:

  1. docker exec etcd etcdctl member list

当使用低于 3.3.x 的 etcd 版本(Kubernetes 1.13.x 及更低版本)并且添加节点时指定了--internal-address 时的命令:

  1. docker exec etcd sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT member list"

输出示例:

  1. xxx, started, etcd-xxx, https://IP:2380, https://IP:2379,https://IP:4001
  2. xxx, started, etcd-xxx, https://IP:2380, https://IP:2379,https://IP:4001
  3. xxx, started, etcd-xxx, https://IP:2380, https://IP:2379,https://IP:4001

检查端点状态

RAFT TERM的值应相等,RAFT INDEX的距离不应太远。

命令:

  1. docker exec -e ETCDCTL_ENDPOINTS=$(docker exec etcd /bin/sh -c "etcdctl member list | cut -d, -f5 | sed -e 's/ //g' | paste -sd ','") etcd etcdctl endpoint status --write-out table

当使用低于 3.3.x 的 etcd 版本(Kubernetes 1.13.x 及更低版本)并且添加节点时指定了--internal-address 时的命令:

  1. docker exec etcd etcdctl endpoint status --endpoints=$(docker exec etcd /bin/sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT member list | cut -d, -f5 | sed -e 's/ //g' | paste -sd ','") --write-out table

输出示例:

  1. +-----------------+------------------+---------+---------+-----------+-----------+------------+
  2. | ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
  3. +-----------------+------------------+---------+---------+-----------+-----------+------------+
  4. | https://IP:2379 | 333ef673fc4add56 | 3.2.18 | 24 MB | false | 72 | 66887 |
  5. | https://IP:2379 | 5feed52d940ce4cf | 3.2.18 | 24 MB | true | 72 | 66887 |
  6. | https://IP:2379 | db6b3bdb559a848d | 3.2.18 | 25 MB | false | 72 | 66887 |

检查端点健康

命令:

  1. docker exec -e ETCDCTL_ENDPOINTS=$(docker exec etcd /bin/sh -c "etcdctl member list | cut -d, -f5 | sed -e 's/ //g' | paste -sd ','") etcd etcdctl endpoint health

当使用低于 3.3.x 的 etcd 版本(Kubernetes 1.13.x 及更低版本)并且添加节点时指定了--internal-address 时的命令:

  1. docker exec etcd etcdctl endpoint health --endpoints=$(docker exec etcd /bin/sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT member list | cut -d, -f5 | sed -e 's/ //g' | paste -sd ','")

输出示例:

  1. https://IP:2379 is healthy: successfully committed proposal: took = 2.113189ms
  2. https://IP:2379 is healthy: successfully committed proposal: took = 2.649963ms
  3. https://IP:2379 is healthy: successfully committed proposal: took = 2.451201ms

命令:

  1. for endpoint in $(docker exec etcd /bin/sh -c "etcdctl member list | cut -d, -f5"); do
  2. echo "Validating connection to ${endpoint}/health"
  3. done

当使用低于 3.3.x 的 etcd 版本(Kubernetes 1.13.x 及更低版本)并且添加节点时指定了--internal-address 时的命令:

  1. for endpoint in $(docker exec etcd /bin/sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT member list | cut -d, -f5"); do
  2. echo "Validating connection to ${endpoint}/health";
  3. docker run --net=host -v $(docker inspect kubelet --format '{{ range .Mounts }}{{ if eq .Destination "/etc/kubernetes" }}{{ .Source }}{{ end }}{{ end }}')/ssl:/etc/kubernetes/ssl:ro appropriate/curl -s -w "\n" --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) "${endpoint}/health"
  4. done

检查端口 TCP / 2380 的连接

命令:

  1. for endpoint in $(docker exec etcd /bin/sh -c "etcdctl member list | cut -d, -f4"); do
  2. echo "Validating connection to ${endpoint}/version";
  3. docker run --net=host -v $(docker inspect kubelet --format '{{ range .Mounts }}{{ if eq .Destination "/etc/kubernetes" }}{{ .Source }}{{ end }}{{ end }}')/ssl:/etc/kubernetes/ssl:ro appropriate/curl --http1.1 -s -w "\n" --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) "${endpoint}/version"
  4. done

当使用低于 3.3.x 的 etcd 版本(Kubernetes 1.13.x 及更低版本)并且添加节点时指定了--internal-address 时的命令:

  1. for endpoint in $(docker exec etcd /bin/sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT member list | cut -d, -f4"); do
  2. echo "Validating connection to ${endpoint}/version";
  3. docker run --net=host -v $(docker inspect kubelet --format '{{ range .Mounts }}{{ if eq .Destination "/etc/kubernetes" }}{{ .Source }}{{ end }}{{ end }}')/ssl:/etc/kubernetes/ssl:ro appropriate/curl --http1.1 -s -w "\n" --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) "${endpoint}/version"
  4. done

输出示例:

  1. Validating connection to https://IP:2380/version
  2. {"etcdserver":"3.2.18","etcdcluster":"3.2.0"}
  3. Validating connection to https://IP:2380/version
  4. {"etcdserver":"3.2.18","etcdcluster":"3.2.0"}
  5. Validating connection to https://IP:2380/version
  6. {"etcdserver":"3.2.18","etcdcluster":"3.2.0"}

etcd 警报

例如,etcd 空间不足时,etcd 将触发警报。

命令:

  1. docker exec etcd etcdctl alarm list

当使用低于 3.3.x 的 etcd 版本(Kubernetes 1.13.x 及更低版本)并且添加节点时指定了--internal-address 时的命令:

  1. docker exec etcd sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT alarm list"

触发 NOSPACE 警报时的示例输出:

  1. memberID:x alarm:NOSPACE
  2. memberID:x alarm:NOSPACE
  3. memberID:x alarm:NOSPACE

相关错误消息是etcdserver: mvcc: database space exceededapplying raft message exceeded backend quota。警报NOSPACE将被触发。

解决方法:

压缩键空间

命令:

  1. rev=$(docker exec etcd etcdctl endpoint status --write-out json | egrep -o '"revision":[0-9]*' | egrep -o '[0-9]*')
  2. docker exec etcd etcdctl compact "$rev"

当使用低于 3.3.x 的 etcd 版本(Kubernetes 1.13.x 及更低版本)并且添加节点时指定了--internal-address 时的命令:

  1. docker exec etcd sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT compact \"$rev\""

输出示例:

  1. compacted revision xxx

命令:

  1. docker exec -e ETCDCTL_ENDPOINTS=$(docker exec etcd /bin/sh -c "etcdctl member list | cut -d, -f5 | sed -e 's/ //g' | paste -sd ','") etcd etcdctl defrag

当使用低于 3.3.x 的 etcd 版本(Kubernetes 1.13.x 及更低版本)并且添加节点时指定了--internal-address 时的命令:

输出示例:

  1. Finished defragmenting etcd member[https://IP:2379]
  2. Finished defragmenting etcd member[https://IP:2379]
  3. Finished defragmenting etcd member[https://IP:2379]

检查端点状态

命令:

  1. docker exec -e ETCDCTL_ENDPOINTS=$(docker exec etcd /bin/sh -c "etcdctl member list | cut -d, -f5 | sed -e 's/ //g' | paste -sd ','") etcd etcdctl endpoint status --write-out table

当使用低于 3.3.x 的 etcd 版本(Kubernetes 1.13.x 及更低版本)并且添加节点时指定了--internal-address 时的命令:

  1. +-----------------+------------------+---------+---------+-----------+-----------+------------+
  2. | ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
  3. +-----------------+------------------+---------+---------+-----------+-----------+------------+
  4. | https://IP:2379 | e973e4419737125 | 3.2.18 | 553 kB | false | 32 | 2449410 |
  5. | https://IP:2379 | 4a509c997b26c206 | 3.2.18 | 553 kB | false | 32 | 2449410 |
  6. | https://IP:2379 | b217e736575e9dd3 | 3.2.18 | 553 kB | true | 32 | 2449410 |
  7. +-----------------+------------------+---------+---------+-----------+-----------+------------+

解除告警

确认压缩和碎片整理后 DB 大小减小后,需要解除该告警,以便 etcd 允许再次写入。

命令:

  1. docker exec etcd etcdctl alarm list
  2. docker exec etcd etcdctl alarm disarm
  3. docker exec etcd etcdctl alarm list

当使用低于 3.3.x 的 etcd 版本(Kubernetes 1.13.x 及更低版本)并且添加节点时指定了--internal-address 时的命令:

  1. docker exec etcd sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT alarm list"
  2. docker exec etcd sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT alarm disarm"
  3. docker exec etcd sh -c "etcdctl --endpoints=\$ETCDCTL_ENDPOINT alarm list"

输出示例:

  1. docker exec etcd etcdctl alarm list
  2. memberID:x alarm:NOSPACE
  3. memberID:x alarm:NOSPACE
  4. memberID:x alarm:NOSPACE
  5. docker exec etcd etcdctl alarm disarm
  6. docker exec etcd etcdctl alarm list

日志级别

可以通过 API 动态更改 etcd 的日志级别。您可以使用以下命令配置调试日志记录。

命令:

  1. docker run --net=host -v $(docker inspect kubelet --format '{{ range .Mounts }}{{ if eq .Destination "/etc/kubernetes" }}{{ .Source }}{{ end }}{{ end }}')/ssl:/etc/kubernetes/ssl:ro appropriate/curl -s -XPUT -d '{"Level":"DEBUG"}' --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) $(docker exec etcd printenv ETCDCTL_ENDPOINTS)/config/local/log

当使用低于 3.3.x 的 etcd 版本(Kubernetes 1.13.x 及更低版本)并且添加节点时指定了--internal-address 时的命令:

  1. docker run --net=host -v $(docker inspect kubelet --format '{{ range .Mounts }}{{ if eq .Destination "/etc/kubernetes" }}{{ .Source }}{{ end }}{{ end }}')/ssl:/etc/kubernetes/ssl:ro appropriate/curl -s -XPUT -d '{"Level":"DEBUG"}' --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) $(docker exec etcd printenv ETCDCTL_ENDPOINT)/config/local/log

要将日志级别重置回默认值(INFO),可以使用以下命令。

命令:

  1. docker run --net=host -v $(docker inspect kubelet --format '{{ range .Mounts }}{{ if eq .Destination "/etc/kubernetes" }}{{ .Source }}{{ end }}{{ end }}')/ssl:/etc/kubernetes/ssl:ro appropriate/curl -s -XPUT -d '{"Level":"INFO"}' --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) $(docker exec etcd printenv ETCDCTL_ENDPOINTS)/config/local/log

当使用低于 3.3.x 的 etcd 版本(Kubernetes 1.13.x 及更低版本)并且添加节点时指定了--internal-address 时的命令:

  1. docker run --net=host -v $(docker inspect kubelet --format '{{ range .Mounts }}{{ if eq .Destination "/etc/kubernetes" }}{{ .Source }}{{ end }}{{ end }}')/ssl:/etc/kubernetes/ssl:ro appropriate/curl -s -XPUT -d '{"Level":"INFO"}' --cacert $(docker exec etcd printenv ETCDCTL_CACERT) --cert $(docker exec etcd printenv ETCDCTL_CERT) --key $(docker exec etcd printenv ETCDCTL_KEY) $(docker exec etcd printenv ETCDCTL_ENDPOINT)/config/local/log

如果要调查 etcd 的内容,则可以观看事件流或直接查询 etcd,请参见以下示例。

命令:

  1. docker exec etcd etcdctl watch --prefix /registry

当使用低于 3.3.x 的 etcd 版本(Kubernetes 1.13.x 及更低版本)并且添加节点时指定了--internal-address 时的命令:

  1. docker exec etcd etcdctl --endpoints=\$ETCDCTL_ENDPOINT watch --prefix /registry

如果只想查看受影响的键(而不是二进制数据),则可以附加 | grep -a ^/registry 命令仅过滤键。

直接查询 etcd

命令:

  1. docker exec etcd etcdctl get /registry --prefix=true --keys-only

当使用低于 3.3.x 的 etcd 版本(Kubernetes 1.13.x 及更低版本)并且添加节点时指定了--internal-address 时的命令:

    您可以使用以下命令处理数据以获取每个键计数的摘要:

    更换不健康的 etcd 节点