Golang—etcd

949 阅读5分钟

通过docker部署etcd

单机部署etcd

docker run \
  -d \
  -p 2379:2379 \
  -p 2380:2380 \
  --mount type=bind,source=/tmp/etcd-data.tmp,destination=/etcd-data \
  --name etcd-quay-v3.5.0 \
  quay.io/coreos/etcd:v3.5.0 \
  /usr/local/bin/etcd \
  --name s1 \
  --data-dir /etcd-data \
  --listen-client-urls http://0.0.0.0:2379 \
  --advertise-client-urls http://0.0.0.0:2379 \
  --listen-peer-urls http://0.0.0.0:2380 \
  --initial-advertise-peer-urls http://0.0.0.0:2380 \
  --initial-cluster s1=http://0.0.0.0:2380 \
  --initial-cluster-token tkn \
  --initial-cluster-state new \
  --log-level info \
  --logger zap \
  --log-outputs stderr

关键参数解析

参数说明
--nameetcd节点名称
--initial-clusteretcd启动的时候,通过此配置找到其他节点的地址列表 格式:'节点名称:http://ip:2380' 案例:s1=http://0.0.0.0:2380
--initial-cluster-state初始化的时候,集群的状态 "new" 或者 "existing"两种状态,new代表新建的集群,existing表示加入已经存在的集群。
--listen-client-urls监听客户端请求的地址列表,格式:'http://localhost:2379', 多个用逗号分隔。
--advertise-client-urls如果--listen-client-urls配置了,多个监听客户端请求的地址,这个参数可以给出,建议客户端使用什么地址访问etcd。
--listen-peer-urls服务端节点之间通讯的监听地址,格式:'http://localhost:2380'
--initial-advertise-peer-urls建议服务端之间通讯使用的地址列表。

安装过程

Unable to find image 'quay.io/coreos/etcd:v3.5.0' locally
v3.5.0: Pulling from coreos/etcd
1813d21adc01: Pull complete
6e96907ab677: Pull complete
444ed0ea8673: Pull complete
0fd2df5633f0: Pull complete
8cc22b9456bb: Pull complete
7ac70aecd290: Pull complete
4b376c64dfe4: Pull complete
Digest: sha256:28759af54acd6924b2191dc1a1d096e2fa2e219717a21b9d8edf89717db3631b
Status: Downloaded newer image for quay.io/coreos/etcd:v3.5.0

容器外验证

MacBook-Pro rpc % docker exec 9f62717b21a8 /bin/sh -c "/usr/local/bin/etcd --version"
etcd Version: 3.5.0
Git SHA: 946a5a6f2
Go Version: go1.16.3
Go OS/Arch: linux/amd64

MacBook-Pro rpc % docker exec 9f62717b21a8 /bin/sh -c "/usr/local/bin/etcdctl version"
etcdctl version: 3.5.0
API version: 3.5

MacBook-Pro rpc % docker exec 9f62717b21a8 /bin/sh -c "/usr/local/bin/etcdctl endpoint health"
127.0.0.1:2379 is healthy: successfully committed proposal: took = 5.6964ms

MacBook-Pro rpc % docker exec 9f62717b21a8 /bin/sh -c "/usr/local/bin/etcdctl put foo bar"
OK

MacBook-Pro rpc % docker exec 9f62717b21a8 /bin/sh -c "/usr/local/bin/etcdctl get foo"
foo
bar

容器内验证

MacBook-Pro rpc % docker exec -it 66658ceef406 /bin/sh

# cd /usr/local/bin

# ls -al
total 56240
drwxr-xr-x 1 root root     4096 Jun 15 21:53 .
drwxr-xr-x 1 root root     4096 Jan 11  2021 ..
-rwxr-xr-x 1 root root     1050 Jan 27  2021 clean-install
-rwxr-xr-x 1 root root 23560192 Jun 15 21:52 etcd
-rwxr-xr-x 1 root root 17969152 Jun 15 21:52 etcdctl
-rwxr-xr-x 1 root root 16048128 Jun 15 21:52 etcdutl
lrwxrwxrwx 1 root root        4 Jan 27  2021 invoke-rc.d -> noop
-r-xr-xr-x 1 root root        0 Jan 27  2021 noop
lrwxrwxrwx 1 root root        4 Jan 27  2021 runlevel -> noop
lrwxrwxrwx 1 root root        4 Jan 27  2021 update-rc.d -> noop

# etcd --version
etcd Version: 3.5.0
Git SHA: 946a5a6f2
Go Version: go1.16.3
Go OS/Arch: linux/amd64

# etcdctl version
etcdctl version: 3.5.0
API version: 3.5

# etcdctl endpoint health
127.0.0.1:2379 is healthy: successfully committed proposal: took = 4.1765ms

# etcdctl get foo
foo
bar

集群模式

docker-compose.yaml文件

version: '2'
networks:
  etcdnet:

services:
  etcd1:
    image: quay.io/coreos/etcd:v3.5.0
    container_name: etcd1
    command: etcd -name etcd1 -advertise-client-urls http://0.0.0.0:2379 -listen-client-urls http://0.0.0.0:2379 -listen-peer-urls http://0.0.0.0:2380 -initial-cluster-token etcd-cluster -initial-cluster "etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380" -initial-cluster-state new
    ports:
      - 2379
      - 2380
    networks:
      - etcdnet

  etcd2:
    image: quay.io/coreos/etcd:v3.5.0
    container_name: etcd2
    command: etcd -name etcd2 -advertise-client-urls http://0.0.0.0:2379 -listen-client-urls http://0.0.0.0:2379 -listen-peer-urls http://0.0.0.0:2380 -initial-cluster-token etcd-cluster -initial-cluster "etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380" -initial-cluster-state new
    ports:
      - 2379
      - 2380
    networks:
      - etcdnet

  etcd3:
    image: quay.io/coreos/etcd:v3.5.0
    container_name: etcd3
    command: etcd -name etcd3 -advertise-client-urls http://0.0.0.0:2379 -listen-client-urls http://0.0.0.0:2379 -listen-peer-urls http://0.0.0.0:2380 -initial-cluster-token etcd-cluster -initial-cluster "etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380" -initial-cluster-state new
    ports:
      - 2379
      - 2380
    networks:
      - etcdnet

集群启动服务

MacBook-Pro etcd % docker-compose up -d
Creating network "etcd_etcdnet" with the default driver
Creating etcd2 ... done
Creating etcd1 ... done
Creating etcd3 ... done

MacBook-Pro etcd % docker ps
CONTAINER ID   IMAGE                        COMMAND                  CREATED          STATUS          PORTS                                                           NAMES
85044bbb6d81   quay.io/coreos/etcd:v3.5.0   "etcd -name etcd1 -a…"   12 seconds ago   Up 10 seconds   0.0.0.0:64640->2379/tcp, 0.0.0.0:64641->2380/tcp                etcd1
692ae553cf5c   quay.io/coreos/etcd:v3.5.0   "etcd -name etcd2 -a…"   12 seconds ago   Up 11 seconds   0.0.0.0:64638->2379/tcp, 0.0.0.0:64639->2380/tcp                etcd2
911035389db3   quay.io/coreos/etcd:v3.5.0   "etcd -name etcd3 -a…"   12 seconds ago   Up 10 seconds   0.0.0.0:64643->2379/tcp, 0.0.0.0:64642->2380/tcp                etcd3

集群状态验证

Golang连接

golang连接需要使用“go.etcd.io/etcd/client/v3”依赖包

校验是否能够连接

package main

import (
	"log"
	"time"

	clientv3 "go.etcd.io/etcd/client/v3"
)

func main() {
	config := clientv3.Config{
		// etcd的多个节点服务地址
		Endpoints: []string{"127.0.0.1:2379"},
		// 创建client的首次连接超时时间
		DialTimeout: 5 * time.Second,
	}

	client, err := clientv3.New(config)
	if err != nil {
		log.Panic(err)
		return
	}
	defer client.Close()
	log.Println("connect success")
}

增、删、改、查

package main

import (
	"context"
	"log"
	"time"

	clientv3 "go.etcd.io/etcd/client/v3"
)

func main() {
        // 配置
	config := clientv3.Config{
		// etcd的多个节点服务地址
		Endpoints: []string{"127.0.0.1:2379"},
		// 创建client的首次连接超时时间
		DialTimeout: 5 * time.Second,
	}
        
        // 创建etcd客户端
	client, err := clientv3.New(config)
	if err != nil {
		log.Panic(err)
		return
	}
	defer client.Close()

        // 操作增删改查
	etcd := NewEtcdInfo(client)

	key := "/demo/key"
	etcd.Put(key, "value")
	etcd.Get(key)
	etcd.Update(key, "update_value")
	etcd.Get(key)
	etcd.Delete(key)
}

type EtcdInfo struct {
	ctx    context.Context
	client *clientv3.Client
}

func NewEtcdInfo(client *clientv3.Client) *EtcdInfo {
	etcd := new(EtcdInfo)
	etcd.client = client
	etcd.ctx = context.Background()
	return etcd
}

// 设置值
func (e *EtcdInfo) Put(key, value string) {
	// 增加值
	res, err := e.client.Put(e.ctx, key, value)

	if err != nil {
		log.Panicf("put fail err:%v", err)
		return
	}
	log.Printf("pus res:%v", *res)
}

// 获取值
func (e *EtcdInfo) Get(key string) {
	// 增加值
	res, err := e.client.Get(e.ctx, key)

	if err != nil {
		log.Panicf("put fail err:%v", err)
		return
	}

	for _, item := range res.Kvs {
		log.Printf("key:%v, value:%v \n", string(item.Key), string(item.Value))
	}
}

// 修改值
func (e *EtcdInfo) Update(key, value string) {
	res, err := e.client.Put(e.ctx, key, value, clientv3.WithPrevKV())
	if err != nil {
		log.Panicf("update fail err:%v", err)
		return
	}
	log.Printf("update value:%v", string(res.PrevKv.Value))
}

func (e *EtcdInfo) Delete(key string) {
	resp, err := e.client.Delete(e.ctx, key)
	if err != nil {
		log.Panicf("delete fail err:%v", err)
		return
	}
	log.Printf("delete value:%v \n", resp.PrevKvs)
}

参考

Running etcd under Docker | etcd
Releases · etcd-io/etcd (github.com)
coreos/etcd · Quay
Docker安装etcd_w3cschool
etcd 使用: golang 例子 - 九卷 - 博客园 (cnblogs.com)