浅谈云原生技术组件—etcd

技术官网:https://etcd.io/

GitHub:https://github.com/etcd-io/etcd

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 424 18:45 .
drwxr-xr-x 14 root   root      4096 515 14:20 ..
drwxr-xr-x  3 528287 89939     4096 424 18:45 Documentation
-rwxr-xr-x  1 528287 89939 23564288 424 18:45 etcd
-rwxr-xr-x  1 528287 89939 17960960 424 18:45 etcdctl
-rwxr-xr-x  1 528287 89939 16039936 424 18:45 etcdutl
-rw-r--r--  1 528287 89939    42066 424 18:45 README-etcdctl.md
-rw-r--r--  1 528287 89939     7359 424 18:45 README-etcdutl.md
-rw-r--r--  1 528287 89939     9394 424 18:45 README.md
-rw-r--r--  1 528287 89939     7896 424 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

https://github.com/etcd-io/etcd

https://etcd.io/docs/v3.5/integrations/

更多推荐