etcd 网关模式
-
- 构建 etcd 集群的门户
-
- etcd 网关是一个简单的TCP 代理
什么时候使用 etcd 网关模式
- 必须知道所要访问的 etcd 集群实例的地址
- 多个应用程序访问相同的 etcd 集群
- 需要知道 etcd 集群的广播的客户端端点地址
- 对于客户端应用程序来说,不会感知到集群实例的变化
对性能提升的作用
- 没有作用
在集群上运行管理系统
- 类似 Kubernetes 的高级集群管理系统本身支持服务发现
- 应用程序可以使用系统默认的 DNS 名称或虚拟 IP 地址访问 etcd 集群
etcd 网关模式实践
实战1
etcd gateway start --endpoints=http://192.168.10.7:2379,http://192.168.10.8:2379,http://192.168.10.9:2379
#响应结果如下所示:
{"level":"info","ts":1607794339.7171252,"caller":"tcpproxy/userspace.go:90","msg":"ready to proxy client requests","endpoints":["192.168.10.7:2379","192.168.10.8:2379","192.168.10.9:2379"]}
- –-endpoints是以逗号分隔的,
- 默认值为127.0.0.1:2379
- –endpoints=https://127.0.0.1:2379 不能使用,因为不能确定使用TLS.
- –listen-addr 绑定的接口和端口,用于接受客户端请求,默认配置为 127.0.0.1:23790
- –retry-delay 重试连接到失败的端点延迟时间。默认为1m0s。需要注意的是,值的后面标注单位,类似123的设置不合法,命令行会出现参数不合法
- –insecure-discovery 接受不安全或容易受到中间人攻击的 SRV 记录。默认为 false
- –trusted-ca-file 是 etcd 集群的客户端 TLS CA 文件的路径,用于认证端点
gRPC-Gateway:为非 gRPC 的客户端提供 HTTP 接口
- etcd v3 使用 gRPC 作为消息传输协议,客户端通过 gRPC 框架与 etcd 集群通讯
- 不支持 gRPC 的客户端语言,etcd 提供 JSON 的 gRPC-Gateway,通过 gRPC-Gateway 提供 RESTful 代理,转换 HTTP/JSON 请求为 gRPC 的 Protocol Buffer 格式的消息
- 必须在 JSON 对象中,使用 base64 编码对内容进行处理
etcd 版本与 gRPC-Gateway 接口对应的关
-
etcd v3.2 及之前的版本只能使用 [CLIENT-URL]/v3alpha/* 接口;
-
etcd v3.3 使用 CLIENT-URL/v3alpha/*;
-
etcd v3.4 使用 CLIENT-URL/v3beta/,且废弃了[CLIENT-URL]/v3alpha/;
-
etcd v3.5 只使用 CLIENT-URL/v3beta/
键值对读写操作
- put
$ curl -L http://localhost:2379/v3/kv/put \
-X POST -d '{"key": "Zm9v", "value": "YmFy"}'
# 输出结果如下:
{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"16","raft_term":"9"}}
- range
curl -L http://localhost:2379/v3/kv/range \
-X POST -d '{"key": "Zm9v"}'
- 获取范围Zm9v-Zm9w
curl -L http://localhost:2379/v3/kv/range \
-X POST -d '{"key": "Zm9v", "range_end": "Zm9w"}'
# 输出结果如下:
{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"16","raft_term":"9"},"kvs":[{"key":"Zm9v","create_revision":"13","mod_revision":"16","version":"4","value":"YmFy"}],"count":"1"}
- watch 键值
- watch
curl -N http://localhost:2379/v3/watch \
-X POST -d '{"create_request": {"key":"Zm9v"} }' &
# 输出结果如下:
{"result":{"header":{"cluster_id":"12585971608760269493","member_id":"13847567121247652255","revision":"1","raft_term":"2"},"created":true}}
- 修改
curl -L http://localhost:2379/v3/kv/put \
-X POST -d '{"key": "Zm9v", "value": "YmFy"}' >/dev/null 2>&1
- watch 结果
{"result":{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"77","raft_term":"2"},"events":[{"kv":{"key":"Zm9v","create_revision":"75","mod_revision":"77","version":"3","value":"YmFy"}}]}}
{"result":{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"77","raft_term":"2"},"events":[{"kv":{"key":"Zm9v","create_revision":"75","mod_revision":"77","version":"3","value":"YmFy"}}]}}
{"result":{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"77","raft_term":"2"},"events":[{"kv":{"key":"Zm9v","create_revision":"75","mod_revision":"77","version":"3","value":"YmFy"}}]}}
etcd 事务的实现
gRPC-Gateway 中提供了 API接口,通过 /v3/kv/txn 接口发起一个事务
# 查询键值对的版本
$ curl -L http://localhost:2379/v3/kv/range -X POST -d '{"key": "Zm9v"}'
#响应结果
{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"20","raft_term":"9"},"kvs":[{"key":"Zm9v","create_revision":"13","mod_revision":"20","version":"8","value":"YmFy"}],"count":"1"}
# 事务,对比指定键值对的创建版本
$ curl -L http://localhost:2379/v3/kv/txn \
-X POST \
-d '{"compare":[{"target":"CREATE","key":"Zm9v","createRevision":"13"}],"success":[{"requestPut":{"key":"Zm9v","value":"YmFy"}}]}'
#响应结果
{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"20","raft_term":"9"},"succeeded":true,"responses":[{"response_put":{"header":{"revision":"20"}}}]}
- compare 是断言列表,拥有多个联合的条件,这里的条件是当 createRevision 的值为 13 时(我们在上面请求查询到该键值的创建版本为 13),表示符合条件,因此事务可以成功执行
对比指定键值对版本的事务
# 事务,对比指定键值对的版本
$ curl -L http://localhost:2379/v3/kv/txn \
-X POST \
-d '{"compare":[{"version":"8","result":"EQUAL","target":"VERSION","key":"Zm9v"}],"success":[{"requestRange":{"key":"Zm9v"}}]}'
#响应结果
{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"6","raft_term":"3"},"succeeded":true,"responses":[{"response_range":{"header":{"revision":"6"},"kvs":[{"key":"Zm9v","create_revision":"2","mod_revision":"6","version":"4","value":"YmF6"}],"count":"1"}}]}
- compare 中 target 的枚举值为 VERSION。通过比较,发现键 Zm9v 对应的 version 确实是 8,因此执行查询结果,返回 Zm9v 对应的正确值 YmF6
HTTP 请求的安全认证
- 通过 /v3/auth 接口设置认证
- 创建用户-》创建角色-》收于用户权限-》开始认证
- 创建 root 用户
$ curl -L http://localhost:2379/v3/auth/user/add \
-X POST -d '{"name": "allen", "password": "123456"}'
#响应结果
{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"20","raft_term":"9"}}
# 创建 root 角色
curl -L http://localhost:2379/v3/auth/role/add \
-X POST -d '{"name": "allen"}'
#响应结果 {"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"20","raft_term":"9"}}
# 为 root 用户授予角色
curl -L http://localhost:2379/v3/auth/user/grant \
-X POST -d '{"user": "allen", "role": "root"}'
#响应结果{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"20","raft_term":"9"}}
# 开启权限
$ curl -L http://localhost:2379/v3/auth/enable -X POST -d '{}'
#响应结果 {"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"20","raft_term":"9"}}
身份验证
- 流程
- 身份验证- 获取令牌 - 在头部设置令牌进行访问。
curl -L http://localhost:2379/v3/kv/put \
-H 'Authorization : AhezcBBebwcEQqzI.97' \
-X POST -d '{"key": "Zm9v", "value": "YmFy"}'
- 使用身份凭证获取key
```
$ curl -L http://localhost:2379/v3/kv/put \
-H ‘Authorization : DhRvXkWhOkINVQXI.57’
-X POST -d ‘{“key”: “Zm9v”, “value”: “YmFy”}’
#响应结果 {“header”:{“cluster_id”:“14841639068965178418”,“member_id”:“10276657743932975437”,“revision”:“21”,“raft_term”:“9”}}
```