golang etcd容器构建与客户端操作踩坑实操

1.问题说明

在用 go-zero 实现相关服务时一直报错,从报错信息看应该是 etcd 的容器有问题,应该是之前的构建哪里出错了,所以重新构建 etcd 容器应用。

记录下主要的踩坑情况:

  • 1.连接 etcd 容器没有问题,但是写入数据时一直报错,报超时错,可以看下面的操作记录,但本人就构建了一个单节点的 etcd,也用不到 etcd 集群功能
# ./etcdctl --endpoints=0.0.0.0:2379 --write-out=table endpoint health
{"level":"warn","ts":"2024-08-01T10:50:35.003109+0800","logger":"client","caller":"v3@v3.5.12/retry_interceptor.go:62","msg":"retrying of unary invoker failed","target":"etcd-endpoints://0xc0002e2a80/0.0.0.0:2379","attempt":0,"error":"rpc error: code = DeadlineExceeded desc = latest balancer error: last connection error: connection error: desc = \"error reading server preface: read tcp 127.0.0.1:49164->127.0.0.1:2379: read: connection reset by peer\""}
+--------------+--------+--------------+---------------------------+
|   ENDPOINT   | HEALTH |     TOOK     |           ERROR           |
+--------------+--------+--------------+---------------------------+
| 0.0.0.0:2379 |  false | 5.007223857s | context deadline exceeded |
+--------------+--------+--------------+---------------------------+
Error: unhealthy cluster
  • 2.通过 golang 实现 etcd 客户端时,一直报依赖的问题,最后发现 v3.3 问题很多,后面就切 v3.5了,之后依赖问题解决

下面记录下整体的工作流。

2. etcd 容器构建

具体操作参考:

以下是具体的一些操作。

这里的容器用到的镜像是:quay.io/coreos/etcd:v3.5.12,所以你需要 docker pull 先拉取下来。

接下来是具体的一些容器构建的工作。

# 创建目录,数据与配置目录
mkdir -p /data/containers/etcd/{data,config}

# 创建配置文件
vi /data/containers/etcd/config/etcd.conf.yml
---
name: etcd-s1
data-dir: /var/etcd
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: etcd-s1=http://0.0.0.0:2380
initial-cluster-token: etcd-cluster
initial-cluster-state: new
logger: zap
log-level: info
#log-outputs: stderr
---

说明:
特殊参数说明:

name: etcd member 名称,可根据实际情况修改
data-dir: etcd 数据目录,可根据实际情况修改
listen-client-urls:  client 流量监听地址,没特殊需求按文档填写即可
advertise-client-urls: 该 member 向外部通告的客户端 url 列表,单节点部署时不需要修改,集群部署模式需修改为容器所在节点对外提供服务的 IP
listen-peer-urls:  peer 流量监听地址,没特殊需求按文档填写即可
initial-advertise-peer-urls:  该 member 向同一集群内其他 member 通告的 peer url 列表,单节点部署时不需要修改,集群部署模式需修改为容器所在节点对外提供服务的 IP
initial-cluster:  初始化集群节点信息,单节点部署时不需要修改,集群部署模式需要填写集群中所有 member 的信息
initial-cluster-token:  初始化集群时使用的 token,随便写
initial-cluster-state:  初始化集群状态,可选的值为 new  或者  existing,通常采用 new


# 编写 compose 文件
ubuntu:/data/containers/etcd#  vi docker-compose.yaml
--- 
version: '3'

services:
  etcd:
    container_name: etcd-s1
    image: quay.io/coreos/etcd:v3.5.12
    command: /usr/local/bin/etcd --config-file=/var/lib/etcd/conf/etcd.conf.yml
    volumes:
      - ${DOCKER_VOLUME_DIRECTORY:-.}/data:/var/etcd
      - ${DOCKER_VOLUME_DIRECTORY:-.}/config/etcd.conf.yml:/var/lib/etcd/conf/etcd.conf.yml
      - "/etc/localtime:/etc/localtime:ro"
    ports:
      - 2379:2379
      - 2380:2380
    restart: always


networks:
  app_net:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.238.238.0/24
---

启动容器, 在 compose 文件目录

docker-compose up -d

root@ubuntu:/data/containers/etcd# docker-compose up -d
WARNING: Some networks were defined but are not used by any service: app_net
Creating network "etcd_default" with the default driver
Creating etcd-s1 ... done
root@ubuntu:/data/containers/etcd# docker ps
CONTAINER ID   IMAGE                         COMMAND                  CREATED         STATUS         PORTS                                                           NAMES
24162db8e44b   quay.io/coreos/etcd:v3.5.12   "/usr/local/bin/etcd…"   4 seconds ago   Up 2 seconds   0.0.0.0:2379-2380->2379-2380/tcp, :::2379-2380->2379-2380/tcp   etcd-s1

顺便测试下容器,用到 etcdctl 工具,下载参见参考文档:

root@ubuntu:~/etcd/etcd-v3.5.12-linux-amd64# ./etcdctl --endpoints=0.0.0.0:2379 --write-out=table endpoint health
+--------------+--------+-------------+-------+
|   ENDPOINT   | HEALTH |    TOOK     | ERROR |
+--------------+--------+-------------+-------+
| 0.0.0.0:2379 |   true | 31.864411ms |       |
+--------------+--------+-------------+-------+
root@ubuntu:~/etcd/etcd-v3.5.12-linux-amd64# ./etcdctl --endpoints=0.0.0.0:2379 put foo bar
OK
root@ubuntu:~/etcd/etcd-v3.5.12-linux-amd64# ./etcdctl --endpoints=0.0.0.0:2379 get foo
foo
bar

走到这里,说明你的 etcd 单节点容器目前可用了,恭喜你。

3.goalng etcd 客户端实现

先看看具体的实现:

package main

import (
	"context"
	"fmt"
	"time"

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

// demo, etcd client put/get
func main() {
	cli, err := clientv3.New(clientv3.Config{
		Endpoints: []string{"172.30.5.240:2379"},
		DialTimeout: 5 * time.Second,
	})

	if err != nil {
		// handle error!
		fmt.Printf("connect to etcd failed, err:%v\n", err)
		return
	}
	fmt.Println("connect to etcd success")
	defer cli.Close()


	// put
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	_, err = cli.Put(ctx, "test", fmt.Sprintf("test-val: %v", time.Now().Format(time.RFC3339)))
	cancel()
	if err != nil {
		fmt.Printf("put to etcd failed, err:%v\n", err)
		return
	}
	// get
	ctx, cancel = context.WithTimeout(context.Background(), time.Second)
	resp, err := cli.Get(ctx, "test")
	cancel()
	if err != nil {
		fmt.Printf("get from etcd failed, err:%v\n", err)
		return
	}
	for _, ev := range resp.Kvs {
		fmt.Printf("%s:%s\n", ev.Key, ev.Value)
	}
}

我的依赖 - go.mod:

module go-etcd

go 1.19

require (
	github.com/coreos/go-semver v0.3.0 // indirect
	github.com/coreos/go-systemd/v22 v22.3.2 // indirect
	github.com/gogo/protobuf v1.3.2 // indirect
	github.com/golang/protobuf v1.5.4 // indirect
	go.etcd.io/etcd/api/v3 v3.5.15 // indirect
	go.etcd.io/etcd/client/pkg/v3 v3.5.15 // indirect
	go.etcd.io/etcd/client/v3 v3.5.15 // indirect    // 这里需要注意版本问题,v3.3问题挺多,建议用3.5后的
	go.uber.org/atomic v1.7.0 // indirect
	go.uber.org/multierr v1.6.0 // indirect
	go.uber.org/zap v1.17.0 // indirect
	golang.org/x/net v0.23.0 // indirect
	golang.org/x/sys v0.18.0 // indirect
	golang.org/x/text v0.14.0 // indirect
	google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect
	google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect
	google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
	google.golang.org/grpc v1.59.0 // indirect
	google.golang.org/protobuf v1.33.0 // indirect
)

以下是运行结果:

connect to etcd success
test:test-val: 2024-08-01T11:13:06+08:00

恭喜你,已经掌握 golang etcd 的客户端实现。

posted on 2024-08-01 11:36  进击的davis  阅读(76)  评论(0编辑  收藏  举报

导航