ETCD入門實(shí)戰(zhàn):

一、什么是ETCD

etcd是CoreOS團(tuán)隊(duì)于2013年6月發(fā)起的開源項(xiàng)目,它的目標(biāo)是構(gòu)建一個(gè)高可用的分布式鍵值(key-value)數(shù)據(jù)庫。etcd內(nèi)部采用raft協(xié)議作為一致性算法,etcd基于Go語言實(shí)現(xiàn),號(hào)稱云原生分布式存儲(chǔ)的基石
官網(wǎng)地址:https://etcd.io/

/etc 是linux 操作系統(tǒng)的配置存儲(chǔ)目錄, d distributed分布式縮寫,簡單理解為分布式配置數(shù)據(jù)庫

CAP原理

也叫CAP原則,指的是在一個(gè)分布式系統(tǒng)中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分區(qū)容錯(cuò)性),最多只能同時(shí)三個(gè)特性中的兩個(gè),三者不可兼得。
CAP原理的提出主要是針對(duì)分布式場景,所以P是必須具備的。


CAP原理

分布式鍵值存儲(chǔ)系統(tǒng)對(duì)比

etcd zookeeper consul NewSQL
CAP CP CP CP CP
開發(fā)語言 go java go C/C++
線性讀 Y N N 有時(shí)候
多版本并發(fā)控制 Y N N 有時(shí)候
事務(wù) 數(shù)據(jù)內(nèi)容比較、讀或?qū)?/td> 版本檢查,寫 數(shù)據(jù)內(nèi)容比較、鎖、讀或?qū)?/td> SQL式事務(wù)
用戶權(quán)限 RBAC 訪問控制列表 訪問控制列表 每個(gè)數(shù)據(jù)庫的權(quán)限和每個(gè)表的授權(quán)
數(shù)據(jù)更新通知 歷史和當(dāng)前健范圍 當(dāng)前鍵和目錄 當(dāng)前鍵(支持前綴) 觸發(fā)器(有時(shí)候)
http/json api Y N Y 很少
最大數(shù)據(jù)庫大小 幾GB 幾百M(fèi)B到幾GB 幾百M(fèi)B以上 幾TB
最小線性讀時(shí)延 網(wǎng)絡(luò)RTT 不支持線性讀 網(wǎng)絡(luò)RTT+fsync 取決于系統(tǒng)和網(wǎng)絡(luò)時(shí)鐘

其實(shí)eureka專注于服務(wù)發(fā)現(xiàn),嚴(yán)格來說不算是分布式鍵值存儲(chǔ)系統(tǒng)

NewSQL 分布式關(guān)系型數(shù)據(jù)庫,主流有g(shù)oogle公司的Cloud Spanner,CockroachDB(與PostgreSQL兼容的開源分布式SQL數(shù)據(jù)庫,由熟悉Google Cloud Spanner的前谷歌員工開發(fā)),ClustrixDB(現(xiàn)歸MariaDB所有,這個(gè)橫向擴(kuò)展的集群關(guān)系HTAP(混合事務(wù)/分析處理)數(shù)據(jù)庫采用無共享架構(gòu)設(shè)計(jì)。ClustrixDB主要與MySQL和MariaDB兼容)

總的來說,每種系統(tǒng)都有其優(yōu)勢,etcd的優(yōu)勢在于配置信息共享和方便運(yùn)維,etcd設(shè)計(jì)理念是設(shè)計(jì)成大規(guī)模分布式系統(tǒng)的通用底座,因此在云原生領(lǐng)域得到廣泛使用;Zookeeper優(yōu)勢在于穩(wěn)定性在大數(shù)據(jù)領(lǐng)域應(yīng)用很廣;Consul的優(yōu)勢在于服務(wù)發(fā)現(xiàn)。

二、 實(shí)現(xiàn)原理

1.架構(gòu)圖

架構(gòu)圖

2.架構(gòu)解析

從 etcd 的架構(gòu)圖中我們可以看到,etcd 主要分為四個(gè)部分。

  • HTTP Server:用于處理用戶發(fā)送的 API 請(qǐng)求以及其集群節(jié)點(diǎn)之間數(shù)據(jù)通信。
  • Store:涉及KV存儲(chǔ),WAL文件(預(yù)寫式日志),Snapshot管理等,用于處理 etcd 支持的各類功能的事務(wù),包括數(shù)據(jù)索引、節(jié)點(diǎn)狀態(tài)變更、監(jiān)控與反饋、事件處理與執(zhí)行等,是 etcd 對(duì)用戶提供的大多數(shù) API 功能的具體實(shí)現(xiàn)。
  • Raft: etcd 的核心,是Raft 強(qiáng)一致性算法的具體實(shí)現(xiàn)。
  • 復(fù)制狀態(tài)機(jī):抽象模塊的模塊,狀態(tài)機(jī)的數(shù)據(jù)維護(hù)在內(nèi)存中,定期持久化到磁盤,每次寫請(qǐng)求會(huì)持久化到WAL文件,并根據(jù)寫請(qǐng)求的內(nèi)容修改狀態(tài)機(jī)數(shù)據(jù)

3.數(shù)據(jù)讀寫過程

  • 讀?。河捎诩核泄?jié)點(diǎn)數(shù)據(jù)都是強(qiáng)一致性的,讀取可以隨機(jī)讀取,leader和follow 都可以讀取
  • 寫入:如果請(qǐng)求發(fā)到follow會(huì)轉(zhuǎn)發(fā)給leader,由leader寫入,然后分發(fā)給follower

4.如何選舉

  • 集群開始的時(shí)候,所有節(jié)點(diǎn)的角色都是Follower
  • 當(dāng)節(jié)點(diǎn)在指定的時(shí)間沒有收到Leader 或者 Candidate的有效消息時(shí)會(huì)發(fā)起選舉投票,指定時(shí)間是選舉超時(shí)時(shí)間,是一個(gè)隨機(jī)的值(防止多節(jié)點(diǎn)同時(shí)發(fā)起選舉,Leader無法被選出),心跳時(shí)間比這個(gè)時(shí)間短
  • 投票過程:
    1. Follower 遞增Term
    2. 自身狀態(tài)變成Candidate
    3. 投票給自己
    4.向集群其它節(jié)點(diǎn)發(fā)起投票請(qǐng)求(Request Vote)
    當(dāng)超過集群一半節(jié)點(diǎn)都同意,狀態(tài)變成Leader,立即向集群所有其它節(jié)點(diǎn)發(fā)送心跳
    當(dāng)發(fā)現(xiàn)其它Leader 節(jié)點(diǎn)并且Term不小于自己的term ,狀態(tài)變成Follow,否則丟棄消息

數(shù)據(jù)通道

  • Stream類型通道: 主要用于傳輸數(shù)據(jù)量較小的信息,例如心跳、日志追加消息,節(jié)點(diǎn)之間維護(hù)長連接

  • Pipeline 類型通道: 主要用于處理數(shù)據(jù)量大的信息,比如snapshot,采用短連接,與心跳等消息區(qū)分處理,保證集群穩(wěn)定

三、 應(yīng)用場景

etcd的定位是通用的一致性key/value的存儲(chǔ),典型的應(yīng)用場景包括分布式數(shù)據(jù)庫、服務(wù)注冊與發(fā)現(xiàn)、負(fù)載均衡、分布式鎖、分布式隊(duì)列、消息發(fā)布與訂閱、分布式通知與協(xié)調(diào)、集群監(jiān)控與leader競選

四、 發(fā)展里程碑

etcd目前最新的是3.x版本,有3個(gè)重要里程碑版本,分別是etcd 0.4,etcd 2.0 和etcd 3.0; etcd 0.4是對(duì)外發(fā)布的第一個(gè)穩(wěn)定版本,etcd2.0與etcd3.0版本差別比較,具體如下:

  • v3版本采用gRPC+protobuf 取代 v2版本的Http+json的通訊方式,同時(shí)保留v2版本的方式,提高整體吞吐率,降低時(shí)延
  • v3采用磁盤數(shù)據(jù)庫代替v2 key-value內(nèi)存數(shù)據(jù)庫
  • v3引入多版本的鍵空間(MVCC),支持訪問歷史版本key
  • v3引入事務(wù)概念,etcd服務(wù)的多個(gè)請(qǐng)求合并成一個(gè)操作
  • v3摒棄v2的key-value的層級(jí)和目錄,采用扁平的二進(jìn)制鍵空間
  • v3更輕量級(jí)的基于租約(Lease)的key自動(dòng)過期機(jī)制,取代基于TTL的key過期機(jī)制
  • v3 watch機(jī)制重新設(shè)計(jì),采用基于http2的server push,對(duì)事件進(jìn)行多路復(fù)用優(yōu)化
    v2采用的是http長連接的事件驅(qū)動(dòng)機(jī)制

etcd v3 版本依然保留etcd v2的協(xié)議和api,同時(shí)提供一套v3的API,也就是說,兩個(gè)版本共享一套raft協(xié)議代碼的,在于api不同,存儲(chǔ)不同,數(shù)據(jù)相互隔離,采用v2版本API 只能用v2版本的API,v3版本只能用v3 版本的API

五、 常用操作

1. 安裝部署

1) 單機(jī)部署

可以使用二進(jìn)制或源碼下載安裝,但是需要自己寫配置文件,推薦使用yum安裝方式

hostnamectl set-hostname etcd-1
wget http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
rpm -ivh epel-release-latest-7.noarch.rpm
# yum 倉庫中的etcd版本為3.3.11,如果需要最新版本的etcd可以進(jìn)行二進(jìn)制安裝
yum -y install etcd #安裝
systemctl enable etcd 
systemctl start etcd #啟動(dòng)

默認(rèn)配置文件vim /etc/etcd/etcd.conf

ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_CLIENT_URLS="http://localhost:2379"  
#ETCD_LISTEN_CLIENT_URLS="http://localhost:2379,http://xx.xx.xx.xx:2379"  #如果需要其它機(jī)器訪問需要添加機(jī)器ip的url
ETCD_NAME="default"
ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379" 

2) 集群部署

集群部署分靜態(tài)配置和服務(wù)發(fā)現(xiàn),常用是靜態(tài)配置

靜態(tài)配置

1.三臺(tái)機(jī)器分別安裝etcd,ip分別為172.16.0.1;172.16.0.2;172.16.0.3;

  yum install etcd -y

2.修改vim /etc/etcd/etcd.conf

#[Member]
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_CLIENT_URLS="http://172.16.0.1:2379"  #對(duì)外提供服務(wù)地址
ETCD_LISTEN_PEER_URLS="http://172.16.0.1:2380" #監(jiān)聽的地址
ETCD_NAME="etcd1"     # 節(jié)點(diǎn)名稱

#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://172.16.0.1:2380"  #該節(jié)點(diǎn)同伴監(jiān)聽地址,這個(gè)值會(huì)告訴集群中其他節(jié)點(diǎn)
ETCD_ADVERTISE_CLIENT_URLS="http://172.16.0.1:2379" #對(duì)外公告的該節(jié)點(diǎn)客戶端監(jiān)聽地址,同步給集群其它節(jié)點(diǎn)

ETCD_INITIAL_CLUSTER="etcd1=http://172.16.0.1:2380,etcd2=http://172.16.0.2:2380,etcd3=http://172.16.0.3:2380"   # 集群中所有節(jié)點(diǎn)的信息

ETCD_INITIAL_CLUSTER_TOKEN="etcd-token" #每個(gè)集群唯一
ETCD_INITIAL_CLUSTER_STATE="new"  #新建集群值為 new;已經(jīng)存在的集群值為 existing

另外兩個(gè)機(jī)器配置記得替換IP 172.16.0.1 和etcd1 節(jié)點(diǎn)名稱
3.分別啟動(dòng)etcd服務(wù)

systemctl start etcd # 第一個(gè)節(jié)點(diǎn)啟動(dòng)會(huì)阻塞等待第二個(gè)節(jié)點(diǎn)啟動(dòng)

2. 訪問安全

etcd 默認(rèn)是沒有開啟訪問控制的,訪問安全包括用戶的認(rèn)證和授權(quán),傳輸安全是指使用SSL/TLS來加密信道,本身證書也可以來做認(rèn)證

1) 基于身份驗(yàn)證的訪問控制

采用基于角色訪問控制(RBAC)

etcdctl user add root #首開添加root賬戶,才能開始認(rèn)證
etcdctl auth enable #開啟認(rèn)證 ,默認(rèn)有root角色,擁有所有權(quán)限,授予root用戶
etcdctl role add test --user=root:pwd # 添加角色
etcdctl role grant-permission  --from-key test read "" --user=root:pwd #角色授予所有key讀權(quán)限(read,write,readwrite)
etcdctl user grant-role test test # 用戶test授予test角色

2) 基于證書的訪問控制開(支持雙向認(rèn)證)

#[Security]
ETCD_CERT_FILE="server.pem" #服務(wù)端證書
ETCD_KEY_FILE="server-key.pem" #
ETCD_CLIENT_CERT_AUTH="true" #是否開啟客戶端端證書認(rèn)證
ETCD_TRUSTED_CA_FILE="ca.pem" #客戶端服務(wù)器TLS授信的CA證書路徑,
ETCD_AUTO_TLS="true" # 客戶端TLS是否使用自動(dòng)生成的證書

ETCD_PEER_CERT_FILE="peer.pem" #節(jié)點(diǎn)通訊采用的客戶端證書
ETCD_PEER_KEY_FILE="peer-key.pem" 
ETCD_PEER_CLIENT_CERT_AUTH="true" #是否啟用peer客戶端證書認(rèn)證
ETCD_PEER_TRUSTED_CA_FILE="ca.pem" 服務(wù)端TLS授信的CA證書路徑
ETCD_PEER_AUTO_TLS="true" #是否使用自動(dòng)生成的證書

3、 常用命令

默認(rèn)安裝自帶etcdctl 命令行客戶端,分兩個(gè)版本ETCDCTL_API=2和ETCDCTL_API=3,兩個(gè)版本不一樣,操作的數(shù)據(jù)也不相容

以export ETCDCTL_API=3 為例

  • help 查看所有命令集
etcdctl help
  • put 命令
etcdctl put /test1 value1 #設(shè)置test1=value1
etcdctl put /test1 value2 # 存在直接覆蓋

etcdctl put /test1 value3 --lease=1234abc #綁定租賃id,租賃時(shí)間到期自動(dòng)刪除
etcdctl put /test1 value4 --ignore-lease # 使用當(dāng)前key的租賃
etcdctl put /test1 value5 --prev-kv #設(shè)置值,并返回上一個(gè)版本的值
  • get查看
etcdctl get /test1 #獲取key=/test1的值,返回key和value
etcdctl get ""  --from-key #返回比空字符串大的key的鍵值對(duì),該例返回所有數(shù)據(jù)
etcdctl get "dir" --prefix --keys-only  --limit=5 # 返回"dir" 前綴的鍵最多5個(gè)
etcdctl get /test1 /test4 #獲取[/test1,/test4) 范圍的鍵值對(duì),左閉右開,不包括/test4
etcdctl get /test1 --print-value-only #只返回值
etcdctl get /test1  --consistency='l'  #獲取key=/test1的鍵值對(duì),consistency  'l' 代表線性讀(執(zhí)行raft), 's' 代表串行化讀

etcdctl get /test1 -w json #查看key=/test1的版本數(shù)據(jù),返回?cái)?shù)據(jù)如下:
#cluster_id:請(qǐng)求的etcd集群ID。
#member_id:請(qǐng)求的etcd節(jié)點(diǎn)ID。
#revision:etcd服務(wù)端當(dāng)前全局?jǐn)?shù)據(jù)版本號(hào)。對(duì)任一key的put或delete操作都會(huì)使#revision自增1。revision=1是etcd的保留版本號(hào),因此用戶的key版本號(hào)將從2開始。
#raft_term:etcd當(dāng)前raft主節(jié)點(diǎn)任期號(hào)。
#create_revision:當(dāng)前key創(chuàng)建時(shí)全局?jǐn)?shù)據(jù)版本號(hào)revision的值。
#mod_revision:當(dāng)前key最后一次修改時(shí)全局?jǐn)?shù)據(jù)版本號(hào)revision的值。
#version:當(dāng)前key的數(shù)據(jù)版本號(hào)。key創(chuàng)建時(shí)version為1,對(duì)當(dāng)前key進(jìn)行put操作會(huì)使version自增1,將key刪除后,重新創(chuàng)建,version又會(huì)從1開始計(jì)數(shù)

  • del 命令
etcdctl del /test1 #刪除指定key
etcdctl del /test1 --prev-kv #返回刪除的鍵值對(duì)
etcdctl del /test --from-key # 刪除比/test大的所有key,也支持--prefix 按前綴刪除
  • watch命令
etcdctl watch foo -- echo watch event received #watch key=foo 輸出指定文字
etchctl watch foo --rev=2 #從2版本開始watch,返回中間所有修改的版本
etcdctl watch foo -- sh -c "env | grep ETCD_WATCH_" 
# PUT
# foo
# bar
# ETCD_WATCH_REVISION=11
# ETCD_WATCH_KEY="foo"
# ETCD_WATCH_EVENT_TYPE="PUT"
# ETCD_WATCH_VALUE="bar"
  • lease 命令(租約)
etcdctl lease grant 10 #創(chuàng)建一個(gè)10s的租約,返回租約的id,用于綁定key
etcdctl lease revoke 1234abc #刪除id=1234abc 的租約
etcdctl lease timetolive 1234abc #查看id=1234abc 的租約剩余時(shí)間
etcdctl lease timetolive --keys 1234abc #查看id=1234abc 的租約剩余時(shí)間,并顯示關(guān)聯(lián)的key
etcdctl lease keep-alive -- once 1234abc #一次續(xù)約id=1234abc 的租約,并退出,不加--once 命令掛起,到期自動(dòng)續(xù)約
etcdctl lease list #查看所有激活的租期

  • member 命令(集群成員管理)
etcdctl member add newMember --peer-urls=https://127.0.0.1:12345

Member ced000fda4d05edf added to cluster 8c4281cc65c7b112

ETCD_NAME="newMember"
ETCD_INITIAL_CLUSTER="newMember=https://127.0.0.1:12345,default=http://10.0.0.30:2380"
ETCD_INITIAL_CLUSTER_STATE="existing"

etcdctl member update 2be1eb8f84b7f63e --peer-urls=https://127.0.0.1:11112
etcdctl member remove 2be1eb8f84b7f63e
etcdctl member list #查看集群列表
  • endpoint 查看節(jié)點(diǎn)狀態(tài)
etcdctl endpoint status -w table #查看默認(rèn)節(jié)點(diǎn)狀態(tài),table格式輸出
etcdctl endpoint --cluster  status -w table # 查看集群狀態(tài)
etcdctl endpoint --cluster hashkv -w json #查看集群hashkv

六、 集群故障處理

1. 數(shù)據(jù)備份

etcdctl snapshot save  backup.db  #數(shù)據(jù)備份到當(dāng)前目錄下backup.db
etcdctl -w table snapshot save  backup.db 

2. 數(shù)據(jù)恢復(fù)

etcdctl --data-dir=/var/lib/etcd/backup.etcd snapshot restore backup.db #恢復(fù)數(shù)據(jù)到新目錄
#每個(gè)節(jié)點(diǎn)恢復(fù)數(shù)據(jù),然后修改配置指定新的數(shù)據(jù)目錄,最后重啟所有節(jié)點(diǎn)

注意數(shù)據(jù)目錄權(quán)限,權(quán)限不夠,提示不是很友好

3. 數(shù)據(jù)遷移

場景1 更換高性能盤

1.停掉etcd服務(wù)
2.高性能盤上創(chuàng)建新的數(shù)據(jù)目錄
3.copy舊數(shù)據(jù)文件到新數(shù)據(jù)目錄中
4.修改配置文件的數(shù)據(jù)目錄為新目錄,然后重啟服務(wù)

場景2 更換高性能物理機(jī)器,不停服切換

1.新的機(jī)器先安裝好etcd服務(wù)
2.先啟動(dòng)安裝好的一臺(tái)etcd,單獨(dú)起來,然后查看etcd的member的ID
3.到原有的三臺(tái)etcd集群上,將第二部步中起來的etcd添加到集群(添加節(jié)點(diǎn)需要用到etcd的member ID 和peer-urls地址)
4.將原來三臺(tái)的etcd的ETCD_INITIAL_CLUSTER地址添加進(jìn)來,將ETCD_INITIAL_CLUSTER_STATE的new改為existing,刪除數(shù)據(jù)目錄,重啟etcd
5.其它兩臺(tái)重復(fù)2-4步驟
6.確保新的三臺(tái)已加入集群且數(shù)據(jù)一致,然后把原有三臺(tái)剔除集群

運(yùn)行時(shí)的重配置都需要經(jīng)過兩個(gè)階段,1.先通知集群新的配置,采用member api 操作,2.啟動(dòng)新的節(jié)點(diǎn),指定正確的initial-cluster,initial-cluster-state設(shè)置為existing,新節(jié)點(diǎn)啟動(dòng)會(huì)校驗(yàn)initial-cluster與當(dāng)前集群的配置匹配

場景3 直接拿著etcd快照,進(jìn)行etcd集群恢復(fù)

1.獲取快照
2.先將新的三臺(tái)組成集群,啟動(dòng)起來
3.用etcd快照恢復(fù)到新目錄,在三臺(tái)機(jī)器上都執(zhí)行
4.分別修改目錄配置到新目錄,最后重啟etcd

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容