目錄
文章目錄
- 目錄
- 與 etcd 互動
- etcdctl 互動
- Put(創建/更新)
- Get(查詢)
- Del(洗掉)
- Watch(監控)
- Lock(分布式鎖)
- Transactions(事務)
- Compact(壓縮)
- Lease(租約)
- API 互動
- Authentication
- Put and get keys
- Watch keys
- Transactions
- Golang Client SDK 互動
與 etcd 互動
etcd v3 API 使用 gRPC 協議,etcd 專案包括了一個基于 gRPC 的 Golang Client SDK 和一個指令行工具 etcdctl,用于通過 gRPC 協議與 etcd Cluster 進行通信,對于不支持 gRPC 的編程語言,etcd 還提供了一個 JSON gRPC 網關, 該網關提供一個 RESTful Proxy,該 Proxy 將 HTTP/JSON 請求轉換為 gRPC 訊息,
- Swagger API Docs:https://github.com/etcd-io/etcd/blob/master/Documentation/dev-guide/apispec/swagger/rpc.swagger.json
注意,gRPC 網關不支持使用 TLS 通用名稱的身份驗證,
etcdctl 互動
Put(創建/更新)
通過 put 將 key 和 value 存盤到 etcd 集群中,每個存盤的 key 都通過 Raft 協議復制到所有 etcd 集群成員,以實作一致性和可靠性,
$ ./etcdctl put foo bar --user root --password=pass
OK
Get(查詢)
通過 get 可以從一個 etcd 集群中讀取 key 的值,
假設現在 etcd 集群已經存盤了以下資料:
foo = bar
foo1 = bar1
foo2 = bar2
foo3 = bar3
a = 123
b = 456
z = 789
- 讀取鍵為 foo 的命令:
$ ./etcdctl get foo --user root --password=pass
foo // key
bar // value
- 只讀取 key 對應的值呢:
$ ./etcdctl get foo --print-value-only --user root --password=pass
bar
- 讀取一系列 key,例如區間 [foo, foo3):
$ ./etcdctl get foo foo3 --print-value-only --user root --password=pass
bar
bar1
bar2
- 按前綴讀取:
$ ./etcdctl get --prefix foo --print-value-only --user root --password=pass
bar
bar1
bar2
bar3
- 限制結果數量:
$ ./etcdctl get --prefix foo --print-value-only --limit=2 --user root --password=pass
bar
bar1
- 讀取大于或等于指定鍵的位元組值的鍵:
$ ./etcdctl get --from-key b --user root --password=pass
b
456
c
789
foo
bar
foo1
bar1
foo2
bar2
foo3
bar3
用戶可能希望通過訪問早期版本的 key 來回滾到舊版本的配置,由于對 etcd 集群鍵值存盤區的每次修改都會增加一個 etcd 集群的全域修訂版本(revision),因此用戶可以通過提供舊的 etcd 修訂版(revision)來讀取被取代的鍵,
假設一個 etcd 集群已經有以下 key:
foo = bar # revision = 2
foo1 = bar1 # revision = 3
foo = bar_new # revision = 4
foo1 = bar1_new # revision = 5
以下是訪問以前版本 key 的示例:
# 訪問最新版本的 key
$ etcdctl get --prefix foo
foo
bar_new
foo1
bar1_new
# 訪問第 4 個版本的 key
$ etcdctl get --prefix foo --rev=4
foo
bar_new
foo1
bar1
# 訪問第 3 個版本的key
$ etcdctl get --prefix foo --rev=3
foo
bar
foo1
bar1
Del(洗掉)
通過 del 可以從一個 etcd 集群中洗掉一個 key 或一系列 key,
假設一個 etcd 集群已經有以下key:
foo = bar
foo1 = bar1
foo3 = bar3
zoo = val
zoo1 = val1
zoo2 = val2
a = 123
b = 456
z = 789
- 洗掉指定的 key:
$ etcdctl del foo
1
- 洗掉指定的鍵值對:
$ etcdctl del --prev-kv zoo
1
zoo
val
- 洗掉從 foo 到 foo9 的命令:
$ etcdctl del foo foo9
2
- 洗掉具有前綴的鍵的命令:
$ etcdctl del --prefix zoo
2
- 洗掉大于或等于鍵的位元組值的鍵的命令:
$ etcdctl del --from-key b
2
Watch(監控)
Watch 用于監測一個 key-value 的變化,一旦 key-value 發生更新,就會輸出最新的值并退出,
- 打開第一個終端,監聽 foo 的變化:
$ etcdctl watch foo
- 打開另外一個終端來對 foo 進行操作:
$ etcdctl put foo 123
OK
$ etcdctl put foo 456
OK
$ ./etcdctl del foo
1
- 第一個終端追蹤的結果如下:
$ etcdctl watch foo
PUT
foo
123
PUT
foo
456
DELETE
foo
除了以上基本操作,Watch 也可以像 get、del 操作那樣使用 prefix、rev、hex 等引數,
Lock(分布式鎖)
Distributed locks(分布式鎖),即:一個人操作的時候,另外一個人只能看,不能操作,
etcd 的 lock 指令對指定的 key 進行加鎖,注意,只有當正常退出且釋放鎖后,lock 命令的退出碼是 0,否則這個鎖會一直被占用直到過期(默認 60 秒),
- 在第一個終端輸入如下命令:
$ etcdctl lock mutex1 --user root --password=pass
mutex1/326963a02758b52d
- 在第二個終端輸入同樣的命令:
$ etcdctl lock mutex1 --user root --password=pass
在此可以發現第二個終端發生了阻塞,并未回傳類似 mutex1/326963a02758b52d 的輸出,此時,如果我們使用 Ctrl+C 結束了第一個終端的 lock,然后第二個終端的顯示如下:
mutex1/694d74f33b51c654
可見,這就是一個分布式鎖的實作,
Transactions(事務)
txn 支持從標準輸入中讀取多個請求,并將它們看做一個原子性的事務執行,事務是由條件串列,條件判斷成功時的執行串列(條件串列中全部條件為真表示成功)和條件判斷失敗時的執行串列(條件串列中有一個為假即為失敗)組成的,
$ ./etcdctl put user frank --user root --password=pass
OK
$ ./etcdctl txn -i --user root --password=pass
compares:
value("user") = "frank"
success requests (get, put, del):
put result ok
failure requests (get, put, del):
put result failed
SUCCESS
OK
$ ./etcdctl get result --user root --password=pass
result
ok
- 先使用
etcdctl put user frank設定 user 為 frank,然后etcdctl txn -i開啟事務(-i 表示互動模式), - 第 2 步輸入命令后回車,終端顯示出
compares:, - 輸入
value("user") = "frank",此命令是比較 user 的值與 frank 是否相等, - 第 4 步完成后輸入回車,終端會換行顯示,此時可以繼續輸入判斷條件(前面說過事務由條件串列組成),再次輸入回車表示判斷條件輸入完畢,
- 第 5 步連續輸入兩個回車后,終端顯示出
success requests (get, put, delete):,表示下面輸入判斷條件為真時要執行的命令, - 與輸入判斷條件相同,連續兩個回車表示成功時的執行串列輸入完成,
- 終端顯示
failure requests (get, put, delete):后輸入條件判斷失敗時的執行串列,
為了看起來簡潔,此實體中條件串列和執行串列只寫了一行命令,實際可以輸入多行,總結上面的事務,要做的事情就是 user 為 frank 時設定 result 為 ok,否則設定 result 為 failed,事務執行完成后查看 result 值為 ok,
Compact(壓縮)
etcd 會保存資料的修訂版本,以便用戶可以讀取舊版本的 key,但是為了避免累積無盡頭的版本歷史,就需要壓縮過去的修訂版本,壓縮后,etcd 會洗掉歷史版本并釋放資源,
$ etcdctl compact 5
compacted revision 5
$ etcdctl get --rev=4 foo
Error: etcdserver: mvcc: required revision has been compacted
Lease(租約)
key TTL(生存時間)是 etcd 的重要特性之一,即設定 key 的超時時間,與 Redis 不同,etcd 需要先創建 lease(租約),通過 put --lease= 設定,而 lease 又由 TTL 管理,以此來實作 key 超時設定的功能,
- 授予 Lease:
$ etcdctl lease grant 30
lease 694d6ee9ac06945d granted with TTL(30s)
$ etcdctl put --lease=694d6ee9ac06945d foo bar
OK
- 撤銷指定 Lease:
$ etcdctl lease revoke 694d6ee9ac06945d
lease 694d6ee9ac06945d revoked
$ etcdctl get foo
- 用戶可以通過重繪指定的 key TTL 來保持 Lease:
$ etcdctl lease grant 10
lease 32695410dcc0ca06 granted with TTL(10s)
某些時候,用戶可能希望了解 Lease 的資訊,以便可以續約或檢查 Lease 是否仍然存在或已過期,另外,用戶也可能希望了解到指定 Lease 所附的 keys,
假設我們完成了以下一系列操作:
$ etcdctl lease grant 200
lease 694d6ee9ac06946a granted with TTL(200s)
$ etcdctl put demo1 val1 --lease=694d6ee9ac06946a
OK
$ etcdctl put demo2 val2 --lease=694d6ee9ac06946a
OK
- 獲取指定 Lease 的資訊:
$ etcdctl lease timetolive 694d6ee9ac06946a
lease 694d6ee9ac06946a granted with TTL(200s), remaining(178s)
- 獲取指定 Lease 所附的 keys:
$ etcdctl lease timetolive --keys 694d6ee9ac06946a
lease 694d6ee9ac06946a granted with TTL(200s), remaining(129s), attached keys([demo1 demo2])
API 互動
Authentication
Set up authentication with the /v3/auth service.
# create root user
$ curl -L http://localhost:2379/v3/auth/user/add \
-X POST -d '{"name": "root", "password": "pass"}'
{
"header": {
"cluster_id": "14841639068965178418",
"member_id": "10276657743932975437",
"revision": "5",
"raft_term": "3"
}
}
# create root role
$ curl -L http://localhost:2379/v3/auth/role/add \
-X POST -d '{"name": "root"}'
{
"header": {
"cluster_id": "14841639068965178418",
"member_id": "10276657743932975437",
"revision": "5",
"raft_term": "3"
}
}
# grant root role
$ curl -L http://localhost:2379/v3/auth/user/grant \
-X POST -d '{"user": "root", "role": "root"}'
{
"header": {
"cluster_id": "14841639068965178418",
"member_id": "10276657743932975437",
"revision": "5",
"raft_term": "3"
}
}
# enable auth
$ curl -L http://localhost:2379/v3/auth/enable -X POST -d '{}'
{
"header": {
"cluster_id": "14841639068965178418",
"member_id": "10276657743932975437",
"revision": "5",
"raft_term": "3"
}
}
Authenticate with etcd for an authentication token using /v3/auth/authenticate.
# get the auth token for the root user
$ curl -L http://localhost:2379/v3/auth/authenticate \
-X POST -d '{"name": "root", "password": "pass"}'
{
"header": {
"cluster_id": "14841639068965178418",
"member_id": "10276657743932975437",
"revision": "5",
"raft_term": "3"
},
"token": "CAmBqFhXjZCCFRQV.15"
}
Set the Authorization header to the authentication token to fetch a key using authentication credentials.
$ curl -L http://localhost:2379/v3/kv/put \
-H 'Authorization: CAmBqFhXjZCCFRQV.15' \
-X POST -d '{"key": "Zm9v", "value": "YmFy"}'
{
"header": {
"cluster_id": "14841639068965178418",
"member_id": "10276657743932975437",
"revision": "7",
"raft_term": "3"
}
}
Put and get keys
Use the /v3/kv/range and /v3/kv/put services to read and write keys.
# Write
$ curl -L http://localhost:2379/v3/kv/put \
-H 'Authorization: CAmBqFhXjZCCFRQV.15' \
-X POST -d '{"key": "Zm9v", "value": "YmFy"}'
{
"header": {
"cluster_id": "14841639068965178418",
"member_id": "10276657743932975437",
"revision": "3",
"raft_term": "3"
}
}
# Read
$ curl -L http://localhost:2379/v3/kv/range \
-H 'Authorization: CAmBqFhXjZCCFRQV.15' \
-X POST -d '{"key": "Zm9v"}'
{
"header": {
"cluster_id": "14841639068965178418",
"member_id": "10276657743932975437",
"revision": "3",
"raft_term": "3"
},
"kvs": [
{
"key": "Zm9v",
"create_revision": "2",
"mod_revision": "3",
"version": "2",
"value": "YmFy"
}
],
"count": "1"
}
# get all keys prefixed with "foo"
$ curl -L http://localhost:2379/v3/kv/range \
-H 'Authorization: CAmBqFhXjZCCFRQV.15' \
-X POST -d '{"key": "Zm9v", "range_end": "Zm9w"}'
{
"header": {
"cluster_id": "14841639068965178418",
"member_id": "10276657743932975437",
"revision": "3",
"raft_term": "3"
},
"kvs": [
{
"key": "Zm9v",
"create_revision": "2",
"mod_revision": "3",
"version": "2",
"value": "YmFy"
}
],
"count": "1"
}
Watch keys
Use the /v3/watch service to watch keys.
- Watch 指定的 key:
$ curl -N http://localhost:2379/v3/watch \
-H 'Authorization: CAmBqFhXjZCCFRQV.15' \
-X POST -d '{"create_request": {"key":"Zm9v"} }' | jq .
{
"result": {
"header": {
"cluster_id": "14841639068965178418",
"member_id": "10276657743932975437",
"revision": "3",
"raft_term": "3"
},
"created": true
}
}
- 更新該 key:
$ curl -L http://localhost:2379/v3/kv/put \
-H 'Authorization: CAmBqFhXjZCCFRQV.15' \
-X POST -d '{"key": "Zm9v", "value": "YmFy"}' >/dev/null 2>&1
- Watch key 的變更會被跟蹤到:
{
"result": {
"header": {
"cluster_id": "14841639068965178418",
"member_id": "10276657743932975437",
"revision": "4",
"raft_term": "3"
},
"events": [
{
"kv": {
"key": "Zm9v",
"create_revision": "2",
"mod_revision": "4",
"version": "3",
"value": "YmFy"
}
}
]
}
}
Transactions
Issue a transaction with /v3/kv/txn.
# target CREATE
$ curl -L http://localhost:2379/v3/kv/txn \
-H 'Authorization: CAmBqFhXjZCCFRQV.15' \
-X POST \
-d '{"compare":[{"target":"CREATE","key":"Zm9v","createRevision":"2"}],"success":[{"requestPut":{"key":"Zm9v","value":"YmFy"}}]}'
{
"header": {
"cluster_id": "14841639068965178418",
"member_id": "10276657743932975437",
"revision": "5",
"raft_term": "3"
},
"succeeded": true,
"responses": [
{
"response_put": {
"header": {
"revision": "5"
}
}
}
]
}
# target VERSION
$ curl -L http://localhost:2379/v3/kv/txn \
-H 'Authorization: CAmBqFhXjZCCFRQV.15' \
-X POST \
-d '{"compare":[{"version":"4","result":"EQUAL","target":"VERSION","key":"Zm9v"}],"success":[{"requestRange":{"key":"Zm9v"}}]}'
{
"header": {
"cluster_id": "14841639068965178418",
"member_id": "10276657743932975437",
"revision": "5",
"raft_term": "3"
},
"succeeded": true,
"responses": [
{
"response_range": {
"header": {
"revision": "5"
},
"kvs": [
{
"key": "Zm9v",
"create_revision": "2",
"mod_revision": "5",
"version": "4",
"value": "YmFy"
}
],
"count": "1"
}
}
]
}
Golang Client SDK 互動
etcd 提供了一個 Golang Client SDK 用于撰寫 etcd 客戶端程式,下面簡單列舉一些例子,加強體感,
首先實體化一個 client 實體:
cli,err := clientv3.New(clientv3.Config{
Endpoints:[]string{"localhost:2379"},
DialTimeout: 5 * time.Second,
})
- Endpoints:etcd 的多個節點服務地址,因為筆者使用的單點部署,所以只傳 1 個服務入口,
- DialTimeout:創建 client 的首次連接超時,這里傳了 5 秒,如果 5 秒都沒有連接成功就會回傳 err;值得注意的是,一旦 client 創建成功,我們就不用再關心后續底層連接的狀態了,client 內部會進行重連,
k-v 存取:
kv := clientev3.NewKV(client)
// Put
putResp, err := kv.Put(context.TODO(), "/data-dir/example", "hello-world!")
// Get
getResp, err := kv.Get(context.TODO(), "/data-dir/example")
Lease:
lease := clientv3.NewLease(client)
// 創建一個租約,它有 10 秒的 TTL
grantResp, err := lease.Grant(context.TODO(), 10)
// 指定一個租約創建 k-v
kv.Put(context.TODO(), "/example/expireme", "lease-go", clientv3.WithLease(grantResp.ID))
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/158959.html
標籤:python
上一篇:VM ESXI安裝英偉達顯卡驅動
