当前位置:   article > 正文

云原生|kubernetes|etcd集群详细介绍+安装部署+调优_etcd集群只读

etcd集群只读

前言

etcd集群作为kubernetes集群的大脑,重要性不言而喻,但我好像没有对etcd集群做过一个全方面的总结,部署手法也只是单调的使用ansible快速部署,很多细节并没有说清楚,并且对于etcd集群部署后的性能调优也没有过多的提及。因此,本文将对etcd集群的由来,etcd集群的特点,etcd集群的部署手法,etcd应该注意的调优方案这些做一个全面的总结。

一,etcd集群的由来,特点,地位

etcd集群的由来:

名称 “etcd” 源自两个想法,即 unix “/etc” 文件夹 和 “d” 分布式系统。“/etc” 文件夹是用于存储单个系统的配置数据的位置,而 etcd 用于存储大规模分布式的配置信息。因此,分配了 “d” 的 “/etc” 就是 “etcd”。

etcd 被设计为大型分布式系统的通用基板。这些大型系统需要避免脑裂问题,并且愿意牺牲可用性来实现此目的。 etcd 以一致且容错的方式存储元数据。 etcd 集群旨在提供具有稳定性、可靠性、可伸缩性和性能的键值存储,也因此etcd通常也可以被称之为非关系型键值对数据库

分布式系统将 etcd 用作配置管理、服务发现和协调分布式工作的一致键值存储组件。许多组织在生产系统上使用 etcd,例如容器调度程序、服务发现服务和分布式数据存储。使用 etcd 的常见分布式模式包括领导者选举、分布式锁和监视机器活动状态等。

etcd集群在kubernetes集群内的地位:

etcd是 Kubernetes的关键组件,因为它存储了集群的整个状态:集群的配置,规格以及运行中的工作负载的状态。在Kubernetes世界中,etcd用作服务发现的后端,并存储集群的状态及其配置。

由于etcd如此的重要,因此,通常Etcd被部署为一个集群,几个节点的通信由Raft算法处理。在生产环境中,集群包含奇数个节点,并且至少需要三个。(多啰嗦几句,集群可以保证服务的高可用,当然,kubernetes集群可以只使用一个单实例的etcd,但,这么重要的组件如果某天突然坏了,是那种无法恢复的损坏,kubernetes集群是不是就彻底报废了?为了避免这么尴尬的情况出现,我们需要一个分布式集群来降低集群挂掉的概率,当然,集群的好处之一是一个节点彻底无法恢复了可以快速的扩展集群,克隆复制出一个新节点从而顶替损坏的节点。)

etcd集群的基本特点

  • 简单性:使用标准HTTP工具(如curl)读取和写入值,其实呢,也就是我们常说的对外接口
  • 观测性:可持续watch key的变化,做出相应的响应,
  • 高可用:分布式集群,解决单点故障
  • 完全复制:每个节点都是一份完整的的存档
  • 安全:带有客户端验证的TLS
  • 一致性:每次读取都会返回垮多主机的最新写入,这里的一致性主要指的是数据的强一致性。

为什么kubernetes选择的是etcd而不是zookeeper?

ZooKeeper 是一款与 etcd 十分类似的键值对存储数据库,都是分布式系统协调和元数据存储。但是, etcd 踩在前人的肩膀上,其参考了 ZooKeeper 的设计和实现经验。从 Zookeeper 汲取的经验教训无疑为 etcd 的设计提供了支撑,从而帮助其支持 Kubernetes 等大型系统。对 Zookeeper 进行的 etcd 改进包括:

  • 动态重新配置集群成员
  • 高负载下稳定的读写
  • 多版本并发控制数据模型
  • 可靠的键值监控
  • 用于分布式共享锁的 API

etcd是go语言编写的,天然契合kubernetes集群(亲儿子嘛),并且etcd 开箱即用地支持多种语言和框架。Zookeeper 拥有自己的自定义Jute RPC 协议,该协议对于 Zookeeper 而言是完全唯一的,并限制了其受支持的语言绑定,而 etcd 的客户端协议则是基于 gRPC 构建的,gRP 是一种流行的 RPC 框架,具有 go,C ++,Java 等语言支持。同样,gRPC 可以通过 HTTP 序列化为 JSON,因此即使是通用命令行实用程序(例如curl)也可以与之通信。由于系统可以从多种选择中进行选择,因此它们是基于具有本机工具的 etcd 构建的,而不是基于一组固定的技术围绕 etcd 构建的。

在综合考虑功能,支持和稳定性时,etcd 相比于 Zookeeper,更加适合用作一致性的键值存储的组件。总结一句话,etcd的功能和性能以及对其它语言的支持友好度方面etcd是有明显优势的。

etcd集群节点数量的相关说明

etcd 是基于 raft算法的分布式键值数据库,生来就为集群化而设计的,由于Raft算法在做决策时需要超半数节点的投票,所以etcd集群一般推荐奇数节点,如3、5或者7个节点构成一个集群。

etcd官方推荐3、5、7个节点,虽然raft算法也是半数以上投票才能有 leader,但奇数只是推荐,其实偶数也是可以的。如 2、4、8个节点。下面分情况说明:

  • 1 个节点:就是单实例,没有集群概念,不做讨论
  • 2 个节点:是集群,但没人会这么配,这里说点废话:双节点的etcd能启动,启动时也能有主,可以正常提供服务,但是一台挂掉之后,就选不出主了,因为他只能拿到1票,剩下的那台也无法提供服务,也就是双节点无容错能力,不要使用。
  • 3 节点:标准的3 节点etcd 集群只能容忍1台机器宕机,挂掉 1 台此时等于2个节点的情况,如果再挂 1 台,就和 2节点的情形一致了,一直选,一直增加任期,但就是选不出来,服务也就不可用了
  • 4 节点:最大容忍1 台 服务器宕机
  • 5 节点:最大容忍 2 台 服务器宕机
  • 6 节点:最大容忍 2 台 服务器宕机
  • 7和8个节点,最大容忍3台 服务器宕机

以此类推,9和10个节点,最大容忍4台 服务器宕机,总结以上可以得出结论:偶数节点虽然多了一台机器,但是容错能力是一样的,也就是说,你可以设置偶数节点,但没增加什么能力,还浪费了一台机器。同时etcd 是通过复制数据给所有节点来达到一致性,因此偶数的多一台机器增加不了性能,反而会拉低写入速度。

etcd集群节点数越多越好吗?

那可能有同学会说,我搞个几十上百台服务器做etcd集群,那集群的整体性能不是屌炸了,etcd集群永不会停止嘛。有这个想法那就大错特错了,etcd 集群是一个 Raft Group,没有 shared。所以它的极限有两部分,一是单机的容量限制,内存和磁盘;二是网络开销,每次 Raft 操作需要所有节点参与,每一次写操作需要集群中大多数节点将日志落盘成功后,Leader 节点才能修改内部状态机,并将结果返回给客户端。因此节点越多性能越低,并且出错的概率会直线上升,并且是呈现线性的性能下降,所以扩展很多 etcd 节点是没有意义的,其次,如果etcd集群超过7个达到十几个几十个,那么,对运维来说也是一个不小的压力了,并且集群的配置什么的也会更加的复杂,而不是简单易用了。因此,etcd集群的数量一般是 3、5、7, 3 个是最低标准,7个也就是最高了。

二,

kubernetes集群和etcd集群的结合方式

由于kubernetes官方是强烈推荐etcd作为集群的服务状态存储管理工具的,因此,kubernetes和etcd是可以深度绑定融合的,etcd实例可以作为Pod部署在master节点上,也就是常说的etcd堆叠式集群。还一种是kubernetes和etcd为了增加安全性和弹性,而采用解耦形式的扩展etcd集群,也就是kubernetes集群使用外部的etcd集群。通常的两者结合方式就这么两种。它们的通常的架构图如下:

                                                         堆叠式etcd集群架构图

                                                  扩展式etcd集群架构图 

 部署方式:

etcd堆叠式集群通常指的是kubeadm方式部署的多masterkubernetes集群,如上图所示,多套kubernetes组件组成kubernetes集群,其中就包含了etcd。

扩展式外部集群通常指的是独立于kubernetes集群部署的二进制方式部署的etcd集群。而二进制方式部署又可以使用自动化的工具ansible部署或者手工搭建etcd集群。那么,下面就来一次手工搭建etcd集群吧。

二进制手工搭建etcd集群

etcd集群用三台centos7搭建完成。
etcd-1:192.168.217.19
etcd-2:192.168.217.20
etcd-3:192.168.217.21

一、创建CA证书和密钥,下面步骤是在k8s-master1上操作的。
1、所有机器上创建相关目录

  1. mkdir -p /opt/etcd/{bin,ssl,cfg}
  2. echo 'export PATH=$PATH:/opt/etcd/bin' >> /etc/profile
  3. source /etc/profile

2、下载cfssl

  1. curl -L https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -o /usr/local/bin/cfssl
  2. curl -L https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -o /usr/local/bin/cfssljson
  3. curl -L https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -o /usr/local/bin/cfssl-certinfo
  4. chmod +x /usr/local/bin/cfssl /usr/local/bin/cfssljson /usr/local/bin/cfssl-certinfo

3、创建证书签发机构CA,先创建一个证书制作的文件夹。

  1. mkdir -p /data/ssl
  2. cd /data/ssl
  3. cat > ca-config.json <<EOF
  4. {
  5. "signing": {
  6. "default": {
  7. "expiry": "87600h"
  8. },
  9. "profiles": {
  10. "kubernetes": {
  11. "usages": [
  12. "signing",
  13. "key encipherment",
  14. "server auth",
  15. "client auth"
  16. ],
  17. "expiry": "87600h"
  18. }
  19. }
  20. }
  21. }
  22. EOF
  23. ca-config.json:可以定义多个 profiles,分别指定不同的过期时间、使用场景等参数;后续在签名证书时使用某个 profile;
  24. signing:表示该证书可用于签名其它证书;生成的 ca.pem 证书中 CA=TRUE
  25. server auth:表示 client 可以用该 CA 对 server 提供的证书进行验证;
  26. client auth:表示 server 可以用该 CA 对 client 提供的证书进行验证;

4、创建CA证书签名请求

  1. cat > ca-csr.json <<EOF
  2. {
  3. "CN": "kubernetes",
  4. "key": {
  5. "algo": "rsa",
  6. "size": 2048
  7. },
  8. "names": [
  9. {
  10. "C": "CN",
  11. "L": "beijing",
  12. "ST": "beijing",
  13. "O": "k8s",
  14. "OU": "System"
  15. }
  16. ]
  17. }
  18. EOF
  19. CN:Common Name,kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name),浏览器使用该字段验证网站是否合法;
  20. O:Organization,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group);
  21. kube-apiserver 将提取的 User、Group 作为 RBAC 授权的用户标识;

6、生成 CA 证书和私钥:

  1. cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
  2. [root@master1 ssl]# ls
  3. ca-config.json ca.csr ca-csr.json ca-key.pem ca.pem
  4. 拷贝etcd证书到相关文件夹
  5. cp *.pem /opt/etcd/ssl/

7、创建 etcd 证书签名请求,在存放etcd证书的文件夹内制作

  1. cd /opt/etcd/ssl/
  2. cat > etcd-csr.json <<EOF
  3. {
  4. "CN": "etcd",
  5. "hosts": [
  6. "192.168.217.19",
  7. "192.168.217.20",
  8. "192.168.217.21"
  9. ],
  10. "key": {
  11. "algo": "rsa",
  12. "size": 2048
  13. },
  14. "names": [
  15. {
  16. "C": "CN",
  17. "L": "beijing",
  18. "ST": "wuhan",
  19. "O": "k8s",
  20. "OU": "System"
  21. }
  22. ]
  23. }
  24. EOF

8、生成etcd证书和对应的私钥

  1. cfssl gencert -ca=/opt/etcd/ssl/ca.pem \
  2. -ca-key=/opt/etcd/ssl/ca-key.pem \
  3. -config=/opt/etcd/ssl/ca-config.json \
  4. -profile=kubernetes etcd-csr.json \
  5. | cfssljson -bare etcd
  6. cp *.pem /opt/etcd/ssl/

注意:证书3个etcd都要放哦。

ETCD使用证书的组件如下:
etcd:使用 ca.pem、etcd-key.pem、etcd.pem;

二、部署etcd集群
1、下载etcd安装包

  1. wget https://github.com/etcd-io/etcd/releases/download/v3.3.10/etcd-v3.3.10-linux-amd64.tar.gz
  2. tar zxf etcd-v3.3.10-linux-amd64.tar.gz
  3. cp etcd-v3.3.10-linux-amd64/etcd* /opt/etcd/bin/

2、创建etcd的工作目录,也就是数据存放目录

mkdir /opt/etcd/data

3、创建etcd启动脚本文件(修改对应etcd主机名称和ip,比如,在192.168.217.19上,IP都是19,name是etcd-1,那么,在20服务器上,这里的IP就都是20,name是etcd-2)

  1. cat > /etc/systemd/system/etcd.service << EOF
  2. [Unit]
  3. Description=Etcd Server
  4. After=network.target
  5. After=network-online.target
  6. Wants=network-online.target
  7. Documentation=https://github.com/coreos
  8. [Service]
  9. Type=notify
  10. WorkingDirectory=/opt/kubernetes/etcd/
  11. ExecStart=/opt/kubernetes/bin/etcd \
  12. --name etcd-1 \
  13. --cert-file=/opt/etcd/ssl/etcd.pem \
  14. --key-file=/opt/etcd/ssl/etcd-key.pem \
  15. --peer-cert-file=/opt/etcd/ssl/etcd.pem \
  16. --peer-key-file=/opt/etcd/ssl/etcd-key.pem \
  17. --trusted-ca-file=/opt/etcd/ssl/ca.pem \
  18. --peer-trusted-ca-file=/opt/etcd/ssl/etcd/ca.pem \
  19. --initial-advertise-peer-urls https://192.168.217.19:2380 \
  20. --listen-peer-urls https://192.168.217.19:2380 \
  21. --listen-client-urls https://192.168.217.19:2379,http://127.0.0.1:2379 \
  22. --advertise-client-urls https://192.168.217.19:2379 \
  23. --initial-cluster-token etcd-cluster-0 \
  24. --initial-cluster etcd1=https://192.168.217.19:2380,etcd2=https://192.168.217.20:2380,etcd3=https://192.168.217.21:2380 \
  25. --initial-cluster-state new \
  26. --data-dir=/opt/kubernetes/etcd
  27. Restart=on-failure
  28. RestartSec=5
  29. LimitNOFILE=65536
  30. [Install]
  31. WantedBy=multi-user.target
  32. EOF
  33. 为了保证通信安全,需要指定 etcd 的公私钥(cert-file和key-file)、Peers 通信的公私钥和 CA 证书(peer-cert-file、peer-key-file、peer-trusted-ca-file)、客户端的CA证书(trusted-ca-file);
  34. 创建etcd.pem 证书时使用的 etcd-csr.json 文件的 hosts 字段包含所有 etcd 节点的IP,否则证书校验会出错;
  35. –initial-cluster-state 值为 new 时,–name 的参数值必须位于 –initial-cluster 列表中.

4、启动etcd服务并且设置开机自启动

  1. systemctl daemon-reload
  2. systemctl start etcd.service
  3. systemctl status etcd.service
  4. systemctl enable etcd.service

最先启动的 etcd 进程会卡住一段时间,等待其它节点上的 etcd 进程加入集群,为正常现象。

5、验证etcd集群状态,以及查看leader,在任何一个etcd节点执行

  1. [root@k8s-master1 etcd]# etcdctl --ca-file=/opt/etcd/ssl/ca.pem --cert-file=/opt/etcd/ssl/etcd.pem --key-file=/opt/etcd/ssl/etcd-key.pem cluster-health
  2. member 8b7aa04311a7389f is healthy: got healthy result from https://192.168.217.19:2379
  3. member 9b7dcd0eef5c1758 is healthy: got healthy result from https://192.168.217.20:2379
  4. member f617b05c8dbf5231 is healthy: got healthy result from https://192.168.217.21:2379
  5. cluster is healthy
  6. [root@k8s-master1 etcd]# etcdctl --ca-file=/opt/etcd/ssl/etcd/ca.pem --cert-file=/opt/etcd/ssl/etcd.pem --key-file=/opt/etcd/ssl/etcd-key.pem member list
  7. 8b7aa04311a7389f: name=etcd-2 peerURLs=https://192.168.217.20:2380 clientURLs=https://192.168.217.19:2379 isLeader=false
  8. 9b7dcd0eef5c1758: name=etcd-3 peerURLs=https://192.168.217.21:2380 clientURLs=https://192.168.217.20:2379 isLeader=true
  9. f617b05c8dbf5231: name=etcd-1 peerURLs=https://192.168.217.19:2380 clientURLs=https://192.168.217.21:2379 isLeader=false

附1  etcdctl的 常用子命令:

  • version: 查看版本
  • member list: 查看节点状态,learner 情况
  • endpoint status: 节点状态,leader 情况
  • endpoint health: 健康状态与耗时
  • alarm list: 查看警告,如存储满时会切换为只读,产生 alarm
  • alarm disarm:清除所有警告
  • set app demo: 写入
  • get app: 获取
  • update app demo1:更新
  • rm app: 删除
  • mkdir demo 创建文件夹
  • rmdir dir 删除文件夹
  • backup 备份
  • compaction: 压缩
  • defrag:整理碎片
  • watch key 监测 key 变化
  • get / –prefix –keys-only: 查看所有 key




etcd集群调优:

ETCD作为kubernetes集群后端存储的分布式键值数据库,保存整个集群的状态信息,因此,对于etcd的备份和优化显得至关重要。etcd 使用 Raft 一致性算法来在成员之间复制请求并达成一致。一致性性能,特别是提交延迟,受限于两个物理约束:网络 IO 延迟和磁盘 IO 延迟,因此,调优也主要是针对这两个方面。

通常的etcd的参数设置可以在两个地方修改,一个是etcd的启动脚本,一个是etcd的配置文件,建议所有的参数都放置到etcd的配置文件内。

一个包含所有的参数的etcd配置文件是这样的;

  1. [root@etcd1 etcd]# cat /etc/etcd/etcd.conf
  2. #[Member]
  3. #ETCD_CORS=""
  4. ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
  5. #ETCD_WAL_DIR=""
  6. #ETCD_LISTEN_PEER_URLS="http://localhost:2380"
  7. ETCD_LISTEN_CLIENT_URLS="http://localhost:2379"
  8. #ETCD_MAX_SNAPSHOTS="5"
  9. #ETCD_MAX_WALS="5"
  10. ETCD_NAME="default"
  11. #ETCD_SNAPSHOT_COUNT="100000"
  12. #ETCD_HEARTBEAT_INTERVAL="100"
  13. #ETCD_ELECTION_TIMEOUT="1000"
  14. #ETCD_QUOTA_BACKEND_BYTES="0"
  15. #ETCD_MAX_REQUEST_BYTES="1572864"
  16. #ETCD_GRPC_KEEPALIVE_MIN_TIME="5s"
  17. #ETCD_GRPC_KEEPALIVE_INTERVAL="2h0m0s"
  18. #ETCD_GRPC_KEEPALIVE_TIMEOUT="20s"
  19. #
  20. #[Clustering]
  21. #ETCD_INITIAL_ADVERTISE_PEER_URLS="http://localhost:2380"
  22. ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379"
  23. #ETCD_DISCOVERY=""
  24. #ETCD_DISCOVERY_FALLBACK="proxy"
  25. #ETCD_DISCOVERY_PROXY=""
  26. #ETCD_DISCOVERY_SRV=""
  27. #ETCD_INITIAL_CLUSTER="default=http://localhost:2380"
  28. #ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
  29. #ETCD_INITIAL_CLUSTER_STATE="new"
  30. #ETCD_STRICT_RECONFIG_CHECK="true"
  31. #ETCD_ENABLE_V2="true"
  32. #
  33. #[Proxy]
  34. #ETCD_PROXY="off"
  35. #ETCD_PROXY_FAILURE_WAIT="5000"
  36. #ETCD_PROXY_REFRESH_INTERVAL="30000"
  37. #ETCD_PROXY_DIAL_TIMEOUT="1000"
  38. #ETCD_PROXY_WRITE_TIMEOUT="5000"
  39. #ETCD_PROXY_READ_TIMEOUT="0"
  40. #
  41. #[Security]
  42. #ETCD_CERT_FILE=""
  43. #ETCD_KEY_FILE=""
  44. #ETCD_CLIENT_CERT_AUTH="false"
  45. #ETCD_TRUSTED_CA_FILE=""
  46. #ETCD_AUTO_TLS="false"
  47. #ETCD_PEER_CERT_FILE=""
  48. #ETCD_PEER_KEY_FILE=""
  49. #ETCD_PEER_CLIENT_CERT_AUTH="false"
  50. #ETCD_PEER_TRUSTED_CA_FILE=""
  51. #ETCD_PEER_AUTO_TLS="false"
  52. #
  53. #[Logging]
  54. #ETCD_DEBUG="false"
  55. #ETCD_LOG_PACKAGE_LEVELS=""
  56. #ETCD_LOG_OUTPUT="default"
  57. #
  58. #[Unsafe]
  59. #ETCD_FORCE_NEW_CLUSTER="false"
  60. #
  61. #[Version]
  62. #ETCD_VERSION="false"
  63. #ETCD_AUTO_COMPACTION_RETENTION="0"
  64. #
  65. #[Profiling]
  66. #ETCD_ENABLE_PPROF="false"
  67. #ETCD_METRICS="basic"
  68. #
  69. #[Auth]
  70. #ETCD_AUTH_TOKEN="simple"

磁盘IO

  • –quota-backend-bytes: DB 数据大小,比如 10G,50G。
  • –auto-compaction-retention: 自动压缩,默认为 0 不开启,k8s中 apiserver会开启这个压缩,5 分钟一次。如果你的 etcd 还被其他人使用,这里也可以设置下时间
  • --auto-compaction-mode=periodic 周期性压缩

Etcd 的存储配额可保证集群操作的可靠性。如果没有存储配额,那么 Etcd 的性能就会因为存储空间的持续增长而严重下降,甚至有耗完集群磁盘空间导致不可预测集群行为的风险。一旦其中一个节点的后台数据库的存储空间超出了存储配额,Etcd 就会触发集群范围的告警,并将集群置于接受读 key 和删除 key 的维护模式。只有在释放足够的空间和消除后端数据库的碎片之后,清除存储配额告警,集群才能恢复正常操作。

启动 etcd 时。–quota-backend-bytes 默认为 2G,2G 一般情况下是不够用的

可以通过 etcdctl endpoint status 命令来查看当前的存储使用量,例如:

DB SIZE就是现在的etcd使用的存储空间大小,目前为2.6MB,三个节点都一样大小,如果不一样,那才是真的有问题了。

  1. [root@master1 ssl]# etcd_search endpoint status -w table
  2. +-----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
  3. | ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
  4. +-----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
  5. | https://192.168.217.19:2379 | 97c1c1003e0d4bf | 3.4.9 | 2.6 MB | false | false | 194 | 388655 | 388655 | |
  6. | https://192.168.217.21:2379 | f5b8cb45a0dcf520 | 3.4.9 | 2.6 MB | true | false | 194 | 388655 | 388655 | |
  7. | https://192.168.217.20:2379 | ef2fee107aafca91 | 3.4.9 | 2.6 MB | false | false | 194 | 388655 | 388655 | |
  8. +-----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+

在 3.4 版本中,etcd 的存储容量得到了提高,你可以设置 100G 的存储空间,当然并不是越大越好,key 存储过多性能也会变差,根据集群规模适当调整。

OK了,那么现在这些参数在哪里设置呢?在etcd的启动脚本内设置或者在etcd的配置文件内设置。例如:

在启动脚本内,相关配置是这些:

  1. --max-request-bytes=$((10*1024*1024)) \ #请求的最大字节数,默认一个key为1.5M,官方推荐最大为10M
  2. --quota-backend-bytes=$((8*1024*1024*1024)) #磁盘配额,也就是etcd的使用空间限制,这里是8G
  3. --auto-compaction-retention=1 \ #首次压缩周期为1小时,后续压缩周期为当前值的10%,也就是每隔6分钟压缩一次
  4. --auto-compaction-mode=periodic \ #周期性压缩

重启etcd服务后,可以在etcd服务状态内直接看到压缩日志,确实是5分钟一压缩:

  1. [root@master1 ~]# systemctl status etcd -l
  2. ● etcd.service - Etcd Server
  3. Loaded: loaded (/usr/lib/systemd/system/etcd.service; enabled; vendor preset: disabled)
  4. Active: active (running) since Mon 2022-10-31 11:19:49 CST; 2h 23min ago
  5. Main PID: 1020 (etcd)
  6. Memory: 443.5M
  7. CGroup: /system.slice/etcd.service
  8. └─1020 /opt/etcd/bin/etcd --cert-file=/opt/etcd/ssl/server.pem --key-file=/opt/etcd/ssl/server-key.pem --peer-cert-file=/opt/etcd/ssl/server.pem --peer-key-file=/opt/etcd/ssl/server-key.pem --trusted-ca-file=/opt/etcd/ssl/ca.pem --peer-trusted-ca-file=/opt/etcd/ssl/ca.pem
  9. Oct 31 13:19:53 master1 etcd[1020]: store.index: compact 303965
  10. Oct 31 13:19:53 master1 etcd[1020]: finished scheduled compaction at 303965 (took 1.390764ms)
  11. Oct 31 13:24:53 master1 etcd[1020]: store.index: compact 304473
  12. Oct 31 13:24:53 master1 etcd[1020]: finished scheduled compaction at 304473 (took 1.833708ms)
  13. Oct 31 13:29:53 master1 etcd[1020]: store.index: compact 304980
  14. Oct 31 13:29:53 master1 etcd[1020]: finished scheduled compaction at 304980 (took 1.51143ms)
  15. Oct 31 13:34:53 master1 etcd[1020]: store.index: compact 305488
  16. Oct 31 13:34:53 master1 etcd[1020]: finished scheduled compaction at 305488 (took 1.188379ms)
  17. Oct 31 13:39:53 master1 etcd[1020]: store.index: compact 305995
  18. Oct 31 13:39:53 master1 etcd[1020]: finished scheduled compaction at 305995 (took 1.205064ms)

 

在配置文件内,相关配置是这两个:

  1. #ETCD_QUOTA_BACKEND_BYTES=$((8*1024*1024*1024)) #默认数值是0,表示2G磁盘配额
  2. #ETCD_MAX_REQUEST_BYTES=$((10*1024*1024)) #服务器将接受的最大客户端请求大小(以字节为单位),这里设置的是10M

 

以上是软件层面的关于etcd读写方面的优化,其实也就这么两个地方,那么,硬件层面自然是需要使用好的硬盘了,因为etcd对于磁盘写入延迟非常敏感,所以对于负载较重的集群,etcd一定要使用local SSD或者高性能云盘。可以使用fio测量磁盘实际顺序 IOPS,测试命令如下:

  1. [root@master1 ~]# fio -filename=/dev/sda1 -ioengine=sync -direct=1 -rw=write -bs=8k -size=10G -numjobs=8 -runtime=100 -allow_mounted_write=1 -group_reporting -name=fio_test
  2. fio_test: (g=0): rw=write, bs=(R) 8192B-8192B, (W) 8192B-8192B, (T) 8192B-8192B, ioengine=sync, iodepth=1
  3. ...
  4. fio-3.7
  5. Starting 8 processes
  6. Jobs: 8 (f=8): [W(8)][100.0%][r=0KiB/s,w=47.2MiB/s][r=0,w=6037 IOPS][eta 00m:00s]
  7. fio_test: (groupid=0, jobs=8): err= 0: pid=22064: Mon Oct 31 14:36:39 2022
  8. write: IOPS=6011, BW=46.0MiB/s (49.2MB/s)(4697MiB/100006msec)
  9. clat (usec): min=200, max=86655, avg=1326.13, stdev=2106.37
  10. lat (usec): min=201, max=86655, avg=1326.74, stdev=2106.40
  11. clat percentiles (usec):
  12. | 1.00th=[ 537], 5.00th=[ 742], 10.00th=[ 791], 20.00th=[ 840],
  13. | 30.00th=[ 873], 40.00th=[ 898], 50.00th=[ 922], 60.00th=[ 963],
  14. | 70.00th=[ 1004], 80.00th=[ 1139], 90.00th=[ 1893], 95.00th=[ 2114],
  15. | 99.00th=[12780], 99.50th=[13960], 99.90th=[24249], 99.95th=[37487],
  16. | 99.99th=[52691]
  17. bw ( KiB/s): min= 464, max= 8848, per=12.50%, avg=6011.00, stdev=2497.40, samples=1598
  18. iops : min= 58, max= 1106, avg=751.33, stdev=312.23, samples=1598
  19. lat (usec) : 250=0.01%, 500=0.66%, 750=4.71%, 1000=63.48%
  20. lat (msec) : 2=24.27%, 4=4.65%, 10=0.38%, 20=1.62%, 50=0.21%
  21. lat (msec) : 100=0.01%
  22. cpu : usr=0.65%, sys=3.28%, ctx=603442, majf=0, minf=79
  23. IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
  24. submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
  25. complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
  26. issued rwts: total=0,601235,0,0 short=0,0,0,0 dropped=0,0,0,0
  27. latency : target=0, window=0, percentile=100.00%, depth=1
  28. Run status group 0 (all jobs):
  29. WRITE: bw=46.0MiB/s (49.2MB/s), 46.0MiB/s-46.0MiB/s (49.2MB/s-49.2MB/s), io=4697MiB (4925MB), run=100006-100006msec
  30. Disk stats (read/write):
  31. sda: ios=0/598863, merge=0/2942, ticks=0/756213, in_queue=756214, util=99.46%

由于etcd必须将数据持久保存到磁盘日志文件中,因此来自其他进程的磁盘活动可能会导致增加写入时间,结果导致etcd请求超时和临时leader丢失。因此可以给etcd进程更高的磁盘优先级,使etcd服务可以稳定地与这些进程一起运行,一般使用命令ionice命令:

先查询出etcd的pid,然后调整io优先级为best-effort的最高优先等级。

  1. [root@master3 ~]# pgrep etcd
  2. 15963
  3. [root@master3 ~]# ionice -c 2 -n 0 -p 15963
  4. [root@master3 ~]# ionice -p `pgrep etcd`
  5. best-effort: prio 0

附2 IO调度策略:

ionice将磁盘IO调度分为三类:

ilde:空闲磁盘调度,该调度策略是在当前系统没有其他进程需要进行磁盘IO时,才能进行磁盘;因此该策略对当前系统的影响基本为0;当然,该调度策略不能带有任何优先级参数;目前,普通用户是可以使用该调度策略(自从内核2.6.25开始)。

Best effort:是缺省的磁盘IO调度策略;(1)该调度策略可以指定优先级参数(范围是0~7,数值越小,优先级越高);(2)针对处于同一优先级的程序将采round-robin方式;(3)对于best effort调度策略,8个优先级等级可以说明在给定的一个调度窗口中时间片的大小。(4)目前,普调用户(非root用户)是可以使用该调度策略。(5)在内核2.6.26之前,没有设置IO优先级的进程会使用“none”作为调度策略,但是这种策略使得进程看起来像是采用了best effort调度策略,因为其优先级是通过关于cpu nice有关的公式计算得到的:io_priority = (cpu_nice + 20) / 5。(6)在内核2.6.26之后,如果当前系统使用的是CFQ调度器,那么如果进程没有设置IO优先级级别,将采用与内核2.6.26之前版本同样的方式,推到出io优先级级别。

Real time:实时调度策略,如果设置了该磁盘IO调度策略,则立即访问磁盘,不管系统中其他进程是否有IO。因此使用实时调度策略,需要注意的是,该访问策略可能会使得其他进程处于等待状态。

ionice的参数说明:

-c class :class表示调度策略,其中0 for none, 1 for real time, 2 for best-effort, 3 for idle。

-n classdata:classdata表示IO优先级级别,对于best effort和real time,classdata可以设置为0~7,0是最高优先级,7是最低优先级。

-p pid:指定要查看或设置的进程号或者线程号,如果没有指定pid参数,ionice will run the listed program with the given parameters。

-t :忽视设置优先级时产生的错误。

 

 

网络层面的调优:

etcd 的一致性协议依赖两个时间参数。

  • –heartbeat-interval:心跳间隔,即 leader 通知member 并保证自己 leader 地位的心跳,默认是 100ms(单位毫秒),这个应该设置为节点间的 RTT 时间。
  • –election-timeout:选举超时时间,即 member 多久没有收到 leader 的回应,就开始自己竞选 leader,默认超时时间为 1s(单位毫秒)

如果心跳间隔太短,则 etcd 将发送不必要的消息,从而增加 CPU 和网络资源的使用。另一方面,心跳间隔过长会导致选举超时。较高的选举超时时间需要更长的时间来检测领导者失败。测量往返时间(RTT)的最简单方法是使用PING,例如我的etcd集群ping值在500毫秒左右,那么,–heartbeat-interval应该是500,而不是默认的100,–election-timeout的值应该为心跳的5倍,因此是2500比较好。

  1. [root@master1 ~]# ping 192.168.217.20
  2. PING 192.168.217.20 (192.168.217.20) 56(84) bytes of data.
  3. 64 bytes from 192.168.217.20: icmp_seq=1 ttl=64 time=0.488 ms
  4. 64 bytes from 192.168.217.20: icmp_seq=2 ttl=64 time=0.416 ms
  5. 64 bytes from 192.168.217.20: icmp_seq=3 ttl=64 time=0.459 ms

因此,启动脚本文件应该是这样的:

cat  /usr/lib/systemd/system/etcd.service

  1. [Unit]
  2. Description=Etcd Server
  3. After=network.target
  4. After=network-online.target
  5. Wants=network-online.target
  6. [Service]
  7. Type=notify
  8. EnvironmentFile=/opt/etcd/cfg/etcd.conf
  9. ExecStart=/opt/etcd/bin/etcd \
  10. --cert-file=/opt/etcd/ssl/server.pem \
  11. --key-file=/opt/etcd/ssl/server-key.pem \
  12. --peer-cert-file=/opt/etcd/ssl/server.pem \
  13. --peer-key-file=/opt/etcd/ssl/server-key.pem \
  14. --trusted-ca-file=/opt/etcd/ssl/ca.pem \
  15. --peer-trusted-ca-file=/opt/etcd/ssl/ca.pem
  16. --wal-dir=/var/lib/etcd \ #快照日志路径
  17. --snapshot-count=50000 \ #最大快照次数,指定有多少事务被提交时,触发截取快照保存到磁盘,释放wal日志,默认值100000
  18. --auto-compaction-retention=1 \ #首次压缩周期为1小时,后续压缩周期为当前值的10%,也就是每隔6分钟压缩一次
  19. --auto-compaction-mode=periodic \ #周期性压缩
  20. --max-request-bytes=$((10*1024*1024)) \ #请求的最大字节数,默认一个key为1.5M,官方推荐最大为10M
  21. --quota-backend-bytes=$((8*1024*1024*1024)) \
  22. --heartbeat-interval="500" \ #心跳检测500毫秒
  23. --election-timeout="1000" #选举超时1000毫秒,也就是1秒
  24. Restart=on-failure
  25. LimitNOFILE=65536
  26. [Install]
  27. WantedBy=multi-user.target

 

总结:以上为etcd集群需要调优的参数,大体是7个参数,调整方向为磁盘io和网络负载。

未完待续

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/195587
推荐阅读
相关标签
  

闽ICP备14008679号