浅谈云原生技术组件—etcd
技术官网: https://etcd.io/
1 什么是etcd?
etcd是一种强一致性的分布式键值存储组件,使用Raft算法,利用Go语言编写,它提供了一种可靠的方式来存储需要由分布式系统或机器集群访问的数据。它在网络分区期间优雅地处理领导者选举,并且可以容忍机器故障,即使在领导者节点中也是如此。
特点:
- 操作简单整洁,使用HTTP协议和JSON文件格式进行存取键值对
- 键值对存储,类似于Zookeeper
- 更够根据值的变化快速相应
- 可以利用TLS增强安全性
2 动手运行etcd
2.1 安装要求
支持平台:https://etcd.io/docs/v3.5/op-guide/hardware/
硬件要求:https://etcd.io/docs/v3.5/op-guide/supported-platform/
本次实验将使用Ubuntu虚拟机,64bit、4GB内存、4核CPU
2.2 下载并测试
下载页面:https://github.com/etcd-io/etcd/releases/
我们选择的版本是v3.5.4,下面演示下:
root@ymx-ubuntu:/usr/local# wget https://github.com/etcd-io/etcd/releases/download/v3.5.4/etcd-v3.5.4-linux-amd64.tar.gz
......
2022-05-15 14:20:34 (1.45 MB/s) - 已保存 “etcd-v3.5.4-linux-amd64.tar.gz” [19432359/19432359])
root@ymx-ubuntu:/usr/local# ls
etcd-v3.5.4-linux-amd64.tar.gz ......
root@ymx-ubuntu:/usr/local# tar -zxvf etcd-v3.5.4-linux-amd64.tar.gz
......
root@ymx-ubuntu:/usr/local# cd etcd-v3.5.4-linux-amd64/
root@ymx-ubuntu:/usr/local/etcd-v3.5.4-linux-amd64# ls -al
总用量 56300
drwxr-xr-x 3 528287 89939 4096 4月 24 18:45 .
drwxr-xr-x 14 root root 4096 5月 15 14:20 ..
drwxr-xr-x 3 528287 89939 4096 4月 24 18:45 Documentation
-rwxr-xr-x 1 528287 89939 23564288 4月 24 18:45 etcd
-rwxr-xr-x 1 528287 89939 17960960 4月 24 18:45 etcdctl
-rwxr-xr-x 1 528287 89939 16039936 4月 24 18:45 etcdutl
-rw-r--r-- 1 528287 89939 42066 4月 24 18:45 README-etcdctl.md
-rw-r--r-- 1 528287 89939 7359 4月 24 18:45 README-etcdutl.md
-rw-r--r-- 1 528287 89939 9394 4月 24 18:45 README.md
-rw-r--r-- 1 528287 89939 7896 4月 24 18:45 READMEv2-etcdctl.md
root@ymx-ubuntu:/usr/local/etcd-v3.5.4-linux-amd64# ./etcd -version
etcd Version: 3.5.4
Git SHA: 0xxxxxx
Go Version: go1.16.15
Go OS/Arch: linux/amd64
etcd
:etcd服务etcdctl
:etcd的命令行客户端etcdutl
:etcd的命令行管理工具
2.3 运行并初步使用etcd
2.3.1 设置环境变量
root@ymx-ubuntu:/usr/local/etcd-v3.5.4-linux-amd64# vim /etc/profile
#### 在文件末尾加入以下内容
export ETCD_HOME=/usr/local/etcd-v3.5.4-linux-amd64
export PATH=$PATH:$ETCD_HOME
2.3.1 启动etcd(单节点)
TOKEN=my_etcd
CLUSTER_STATE=new
NAME_1=my_etcd_name
HOST_1=127.0.0.1
CLUSTER=${NAME_1}=http://${HOST_1}:2380
THIS_NAME=${NAME_1}
THIS_IP=${HOST_1}
etcd --data-dir=data.etcd --name ${THIS_NAME} \
--initial-advertise-peer-urls http://${THIS_IP}:2380 --listen-peer-urls http://${THIS_IP}:2380 \
--advertise-client-urls http://${THIS_IP}:2379 --listen-client-urls http://${THIS_IP}:2379 \
--initial-cluster ${CLUSTER} \
--initial-cluster-state ${CLUSTER_STATE} --initial-cluster-token ${TOKEN}
2.3.2 使用 etcdctl 连接到 etcd
etcdctl --endpoints=127.0.0.1:2379 member list
演示:
root@ymx-ubuntu:/usr/local/etcd-v3.5.4-linux-amd64# ./etcdctl --endpoints=127.0.0.1:2379 member list
xxxxxxxx, started, my_etcd_name, http://127.0.0.1:2380, http://127.0.0.1:2379, false
2.3.3 使用etcd的Hello World
ENDPOINTS=127.0.0.1:2379
etcdctl --endpoints=$ENDPOINTS put foo "Hello World!"
etcdctl --endpoints=$ENDPOINTS get foo
etcdctl --endpoints=$ENDPOINTS --write-out="json" get foo
演示:
root@ymx-ubuntu:/usr/local/etcd-v3.5.4-linux-amd64# ./etcdctl --endpoints=$ENDPOINTS put foo "Hello World!"
OK
root@ymx-ubuntu:/usr/local/etcd-v3.5.4-linux-amd64# ./etcdctl --endpoints=$ENDPOINTS get foo
foo
Hello World!
root@ymx-ubuntu:/usr/local/etcd-v3.5.4-linux-amd64# ./etcdctl --endpoints=$ENDPOINTS --write-out="json" get foo
{"header":{"cluster_id":87772999870000089,"member_id":10756500090258089453,"revision":3,"raft_term":2},"kvs":[{"key":"Zm9v","create_revision":2,"mod_revision":3,"version":2,"value":"SGV00000ybGQh"}],"count":1}
2.3.4 将etcd数据进行持久化
ENDPOINTS=127.0.0.1:2379
etcdctl --endpoints=$ENDPOINTS snapshot save my.db
etcdctl --write-out=table --endpoints=$ENDPOINTS snapshot status my.db
演示:
root@ymx-ubuntu:/usr/local/etcd-v3.5.4-linux-amd64# ./etcdctl --endpoints=$ENDPOINTS snapshot save my.db
......
Snapshot saved at my.db
root@ymx-ubuntu:/usr/local/etcd-v3.5.4-linux-amd64# ./etcdctl --write-out=table --endpoints=$ENDPOINTS snapshot status my.db
Deprecated: Use `etcdutl snapshot status` instead.
+----------+----------+------------+------------+
| HASH | REVISION | TOTAL KEYS | TOTAL SIZE |
+----------+----------+------------+------------+
| ebfb411d | 3 | 8 | 20 kB |
+----------+----------+------------+------------+
3 使用客户端连接etcd
etcd支持以下客户端:
- Go
- Java
- Scala
- Perl
- Python
- Node
- Ruby
- C
- C++
- ......
因为作者本人目前只能够熟练的使用Java和Go,因此只那这两个做演示哈~
3.1 使用Go操作etcd
3.1.1 Go官方推荐的etcd连接工具(3.x版本以上)
https://github.com/etcd-io/etcd/tree/main/client/v3
下载:go get go.etcd.io/etcd/client/v3
3.1.2 代码
func main() {
cli, err := clientv3.New(clientv3.Config{
Endpoints: []string{"127.0.0.1:2379"},
DialTimeout: 5 * time.Second,
})
if err != nil {
panic(err)
}
resp, err := cli.Put(context.TODO(), "sample_key", "sample_value")
fmt.Println(resp)
response, err := cli.Get(context.TODO(), "sample_key")
fmt.Println(response)
defer cli.Close()
}
3.2 使用Java连接etcd
3.2.1 使用jetcd进行连接
https://github.com/etcd-io/jetcd
maven依赖:
<dependency>
<groupId>io.etcd</groupId>
<artifactId>jetcd-core</artifactId>
<version>0.5.0</version>
</dependency>
3.2.2 代码
@Test
void TestEtcd() throws Exception {
//集群模式下可以使用逗号分隔
Client client = Client.builder().endpoints("http://127.0.0.1:2379").build();
KV kvClient = client.getKVClient();
ByteSequence key = ByteSequence.from("test_key".getBytes());
ByteSequence value = ByteSequence.from("test_value".getBytes());
// put值
kvClient.put(key, value).get();
// get值
CompletableFuture<GetResponse> getFuture = kvClient.get(key);
GetResponse response = getFuture.get();
System.out.println(response);
// 删除值
kvClient.delete(key).get();
}
4 小总结下
etcd作为Kubernetes集群默认的服务配置中心,可以说是最贴近云原生的,相比Zookeeper,虽说有几分相似,但是他们所使用的分布式一致性算法颇有些不同,etcd使用Raft协议, Zookeeper使用ZAB协议,而且etcd支持使用http和https进行访问,使用上更加方便。
参考:
https://github.com/etcd-io/jetcd
https://github.com/etcd-io/etcd/tree/main/client/v3