Go使用etcd

Sunday, December 12, 2021

1. 概述

在上一篇文章 etcd学习 中我们搭建好了 Etcd 集群,并使用 etcdctl 进行了大部分命令的测试,这篇文章,将使用 golang 来对接 etcd 的这些命令。

这里我们使用的是官方的 golang 客户端

go get go.etcd.io/etcd/client/v3

以下是各个模块及命令的使用情况,所有代码托管在 Github

模块 命令 说明 进度
version version 查看版本信息
endpoint endpoint status 查看节点状态
endpoint hashkv 查看节点历史hash
endpoint health 查看节点健康状况
member member list 获取成员列表
member add 添加成员
member update 更新成员
member promote 提升学习者成员为常规成员
member remove 移除成员
move-leader move-leader 将节点设为leader
auth auth status 查看当前鉴权开启状态
auth disable 禁用鉴权
auth enable 启用鉴权
role role list 获取角色列表
role add 添加角色
role get 查看角色信息
role delete 删除角色
role grant-permission 角色授权
role revoke-permission 撤销角色授权
user user add 添加用户
user list 用户列表
user get 获取用户信息
user delete 删除用户
user passwd 修改密码
user grant-role 用户绑定角色
user revoke-role 撤销用户角色
lease lease list 租约列表
lease grant 生成租约
lease revoke 撤销租约
lease timetolive 查看租约期限信息
lease keep-alive 保持租约不过期
normal put 设置kv
get 查看kv
del 删除kv
watch 监听key
txn txn 开启事务
lock lock 分布式锁
snapshot snapshot save 保存快照
snapshot status 校验快照
snapshot restore 从快照恢复
alarm alarm list 获取警报列表
alarm disarm 解除警报
check check datascale 检查内存使用情况
check perf 查看集群性能
other compaction 压缩 etcd 中的事件历史
completion 生成完成脚本
defrag 对具有给定端点的 etcd 成员的存储进行碎片整理
elect 观察并参与leader选举
make-mirror 在目标 etcd 集群上创建镜像

2. 使用

代码中 helper.PrintJSON(res) 只是一个简单的封装打印的方法,目的就是将响应结果打印为 json

package helper

import (
	"encoding/json"
	"fmt"
)

// PrintJSON 打印Json
func PrintJSON(v interface{}) {
	b, _ := json.Marshal(v)
	fmt.Printf("%s\n", b)
}

2.1 endpoint

endpoint 封装了 endpoint statusendpoint hashkv 两个命令的方法,如下:

package base

import (
	"github.com/jormin/etcd-demo/pkg/helper"
)

// Status 查看状态
func Status() error {
	for _, v := range cli.Endpoints() {
		res, err := cli.Status(ctx, v)
		if err != nil {
			return err
		}
		helper.PrintJSON(res)
	}
	return nil
}

// HashKV 查看节点历史hash
func HashKV() error {
	for _, v := range cli.Endpoints() {
		res, err := cli.HashKV(ctx, v, 0)
		if err != nil {
			return err
		}
		helper.PrintJSON(res)
	}
	return nil
}

2.2 member / move-leader

package base

import "github.com/jormin/etcd-demo/pkg/helper"

// MemberList 节点列表
func MemberList() error {
	res, err := cli.MemberList(ctx)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// MemberAdd 添加常规节点
func MemberAdd(peerAddrs []string) error {
	res, err := cli.MemberAdd(ctx, peerAddrs)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// MemberAddLearner 添加学习者节点
func MemberAddLearner(peerAddrs []string) error {
	res, err := cli.MemberAddAsLearner(ctx, peerAddrs)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// MemberUpdate 成员更新
func MemberUpdate(id uint64, peerAddrs []string) error {
	res, err := cli.MemberUpdate(ctx, id, peerAddrs)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// MemberPromote 提升学习者节点为常规节点
func MemberPromote(id uint64) error {
	res, err := cli.MemberPromote(ctx, id)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// MemberRemove 删除成员
func MemberRemove(id uint64) error {
	res, err := cli.MemberRemove(ctx, id)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// MoveLeader 提升为leader
func MoveLeader(id uint64) error {
	res, err := cli.MoveLeader(ctx, id)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

2.3 auth

package base

import "github.com/jormin/etcd-demo/pkg/helper"

// AuthStatus 获取鉴权开启状态
func AuthStatus() error {
	res, err := cli.AuthStatus(ctx)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// AuthDisable 关闭鉴权
func AuthDisable() error {
	res, err := cli.AuthDisable(ctx)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// AuthEnable 启动鉴权
func AuthEnable() error {
	res, err := cli.AuthEnable(ctx)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

2.4 role

package base

import (
	"github.com/jormin/etcd-demo/pkg/helper"
	clientv3 "go.etcd.io/etcd/client/v3"
)

// RoleList 获取角色列表
func RoleList() error {
	res, err := cli.RoleList(ctx)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// RoleAdd 添加角色
func RoleAdd(role string) error {
	res, err := cli.RoleAdd(ctx, role)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// RoleGet 获取角色信息
func RoleGet(role string) error {
	res, err := cli.RoleGet(ctx, role)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// RoleDelete 删除角色
func RoleDelete(role string) error {
	res, err := cli.RoleDelete(ctx, role)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// RoleGrantPermission 赋予角色权限
func RoleGrantPermission(role string, key, rangeEnd string, permType clientv3.PermissionType) error {
	res, err := cli.RoleGrantPermission(ctx, role, key, rangeEnd, permType)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// RoleRevokePermission 撤销角色权限
func RoleRevokePermission(role string, key, rangeEnd string) error {
	res, err := cli.RoleRevokePermission(ctx, role, key, rangeEnd)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

2.5 user

package base

import (
	"github.com/jormin/etcd-demo/pkg/helper"
	clientv3 "go.etcd.io/etcd/client/v3"
)

// UserList 获取用户列表
func UserList() error {
	res, err := cli.UserList(ctx)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// UserAdd 添加用户
func UserAdd(name, password string) error {
	res, err := cli.UserAdd(ctx, name, password)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// UserAddWithOptions 使用选项添加用户
func UserAddWithOptions(name, password string, options *clientv3.UserAddOptions) error {
	res, err := cli.UserAddWithOptions(ctx, name, password, options)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// UserChangePasswd 修改密码
func UserChangePasswd(name, password string) error {
	res, err := cli.UserChangePassword(ctx, name, password)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// UserGet 获取用户信息
func UserGet(name string) error {
	res, err := cli.UserGet(ctx, name)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// UserDelete 删除用户
func UserDelete(name string) error {
	res, err := cli.UserDelete(ctx, name)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// UserGrantRole 赋予用户角色
func UserGrantRole(name, role string) error {
	res, err := cli.UserGrantRole(ctx, name, role)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// UserRevokeRole 撤销用户角色
func UserRevokeRole(name, role string) error {
	res, err := cli.UserRevokeRole(ctx, name, role)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

2.6 lease

package base

import (
	"github.com/jormin/etcd-demo/pkg/helper"
	clientv3 "go.etcd.io/etcd/client/v3"
)

// LeaseList 获取租约列表
func LeaseList() error {
	res, err := cli.Leases(ctx)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// LeaseGrant 生成租约
func LeaseGrant(ttl int64) error {
	res, err := cli.Grant(ctx, ttl)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// LeaseRevoke 撤销租约
func LeaseRevoke(id int64) error {
	res, err := cli.Revoke(ctx, clientv3.LeaseID(id))
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// LeaseTimeToLive 租约信息
func LeaseTimeToLive(id int64, opts ...clientv3.LeaseOption) error {
	res, err := cli.TimeToLive(ctx, clientv3.LeaseID(id), opts...)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// LeaseKeepAlive 保持租约不过期
func LeaseKeepAlive(id int64) error {
	res, err := cli.KeepAlive(ctx, clientv3.LeaseID(id))
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// LeaseKeepAliveOnce 更新租约一次
func LeaseKeepAliveOnce(id int64) error {
	res, err := cli.KeepAliveOnce(ctx, clientv3.LeaseID(id))
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

2.7 normal

package base

import (
	"github.com/jormin/etcd-demo/pkg/helper"
	clientv3 "go.etcd.io/etcd/client/v3"
)

// Put 设置值
func Put(key, val string, opts ...clientv3.OpOption) error {
	res, err := cli.Put(ctx, key, val, opts...)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// Get 获取值
func Get(key string, opts ...clientv3.OpOption) error {
	res, err := cli.Get(ctx, key, opts...)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// Delete 删除键值对
func Delete(key string, opts ...clientv3.OpOption) error {
	res, err := cli.Delete(ctx, key, opts...)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// Watch 监听
func Watch(key string, opts ...clientv3.OpOption) {
	ch := cli.Watch(ctx, key, opts...)
	for v := range ch {
		for _, val := range v.Events {
			helper.PrintJSON(val)
		}
	}
}

2.8 txn

package base

import (
	"github.com/jormin/etcd-demo/pkg/helper"
	clientv3 "go.etcd.io/etcd/client/v3"
)

// Txn 事务
func Txn(cmp []clientv3.Cmp, success []clientv3.Op, fail []clientv3.Op) error {
	txn := cli.Txn(ctx)
	for _,cs := range cmp {
		txn.If(cs)
	}
	for _,op := range success {
		txn.Then(op)
	}
	for _,op := range fail {
		txn.Else(op)
	}
	res, err := txn.Commit()
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

2.9 lock

package base

import (
	"go.etcd.io/etcd/client/v3/concurrency"
)

// Mutex 分布式锁
func Mutex(ttl int64, pfx string) (*concurrency.Mutex, error) {
	res, err := cli.Grant(ctx, ttl)
	if err != nil {
		return nil, err
	}
	s, err := concurrency.NewSession(
		cli, concurrency.WithContext(ctx), concurrency.WithTTL(int(ttl)), concurrency.WithLease(res.ID),
	)
	if err != nil {
		return nil, err
	}
	return concurrency.NewMutex(s, pfx), nil
}

2.10 snapshot

package base

import (
	clientv3 "go.etcd.io/etcd/client/v3"
	"go.etcd.io/etcd/client/v3/snapshot"
)

// SnapshotSave 生成快照
func SnapshotSave(cfg clientv3.Config, dbPath string) error {
	err := snapshot.Save(ctx, nil, cfg, dbPath)
	if err != nil {
		return err
	}
	return nil
}

2.11 alarm

package base

import (
	"github.com/jormin/etcd-demo/pkg/helper"
	clientv3 "go.etcd.io/etcd/client/v3"
)

// AlarmList 获取警报列表
func AlarmList() error {
	res, err := cli.AlarmList(ctx)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}

// AlarmDisarm 解除警报
func AlarmDisarm(m *clientv3.AlarmMember) error {
	res, err := cli.AlarmDisarm(ctx, m)
	if err != nil {
		return err
	}
	helper.PrintJSON(res)
	return nil
}
Etcd Etcd Go

Etcd服务注册发现实例Etcd学习