golang源码分析:etcd(2)

2023-08-09 15:14:27 浏览数 (3)

启动一个etcd集群有三种方式,Static、etcd Discovery和DNS Discovery。Static很好理解就是启动的时候指定所有节点的ip地址,ectd Discovery 就是借助已经存在的etcd集群的服务发现能力找到新集群的所有节点,方式包括自建etcd集群和使用etcd官方集群两种方式。DNS方式就是使用DNS来实现类似服务发现相同的方式。

获取其它节点的ip端口,可以使用环境变量或者命令行参数两种方式,环境变量和命令行参数两种方式的差别是命令行是小写字母,环境变量是使用ETCD_开头加对应名称的大写方式。

代码语言:javascript复制
ETCD_INITIAL_CLUSTER="infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380"
ETCD_INITIAL_CLUSTER_STATE=new
代码语言:javascript复制
--initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 
--initial-cluster-state new

比如我们静态方式启动etcd集群,对应参数如下:

代码语言:javascript复制

$ etcd --name infra0 --initial-advertise-peer-urls http://10.0.1.10:2380 
  --listen-peer-urls http://10.0.1.10:2380 
  --listen-client-urls http://10.0.1.10:2379,http://127.0.0.1:2379 
  --advertise-client-urls http://10.0.1.10:2379 
  --initial-cluster-token etcd-cluster-1 
  --initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 
  --initial-cluster-state new

  $ etcd --name infra1 --initial-advertise-peer-urls http://10.0.1.11:2380 
  --listen-peer-urls http://10.0.1.11:2380 
  --listen-client-urls http://10.0.1.11:2379,http://127.0.0.1:2379 
  --advertise-client-urls http://10.0.1.11:2379 
  --initial-cluster-token etcd-cluster-1 
  --initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 
  --initial-cluster-state new



  $ etcd --name infra2 --initial-advertise-peer-urls http://10.0.1.12:2380 
  --listen-peer-urls http://10.0.1.12:2380 
  --listen-client-urls http://10.0.1.12:2379,http://127.0.0.1:2379 
  --advertise-client-urls http://10.0.1.12:2379 
  --initial-cluster-token etcd-cluster-1 
  --initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 
  --initial-cluster-state new

服务发现方式就是我们前面提到的两种方式etcd discovery service和DNS SRV records,一个discovery URL代表了一个唯一的etcd集群。我们可以向里面添加集群的大小信息。

代码语言:javascript复制
$ curl -X PUT https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83/_config/size -d value=3

然后向服务发现注册自己的节点信息

代码语言:javascript复制
$ etcd --name infra0 --initial-advertise-peer-urls http://10.0.1.10:2380 
  --listen-peer-urls http://10.0.1.10:2380 
  --listen-client-urls http://10.0.1.10:2379,http://127.0.0.1:2379 
  --advertise-client-urls http://10.0.1.10:2379 
  --discovery https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83
$ etcd --name infra1 --initial-advertise-peer-urls http://10.0.1.11:2380 
  --listen-peer-urls http://10.0.1.11:2380 
  --listen-client-urls http://10.0.1.11:2379,http://127.0.0.1:2379 
  --advertise-client-urls http://10.0.1.11:2379 
  --discovery https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83

如果没有现成的自建etcd集群可以使用官方的公用集群discovery.etcd.io.

代码语言:javascript复制
$ curl https://discovery.etcd.io/new?size=3
https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de

如果是DNS方式可以先创建DNS 的SRV记录

代码语言:javascript复制
Create DNS SRV records
$ dig  noall  answer SRV _etcd-server._tcp.example.com
_etcd-server._tcp.example.com. 300 IN  SRV  0 0 2380 infra0.example.com.
_etcd-server._tcp.example.com. 300 IN  SRV  0 0 2380 infra1.example.com.
_etcd-server._tcp.example.com. 300 IN  SRV  0 0 2380 infra2.example.com.
$ dig  noall  answer SRV _etcd-client._tcp.example.com
_etcd-client._tcp.example.com. 300 IN SRV 0 0 2379 infra0.example.com.
_etcd-client._tcp.example.com. 300 IN SRV 0 0 2379 infra1.example.com.
_etcd-client._tcp.example.com. 300 IN SRV 0 0 2379 infra2.example.com.
$ dig  noall  answer infra0.example.com infra1.example.com infra2.example.com
infra0.example.com.  300  IN  A  10.0.1.10
infra1.example.com.  300  IN  A  10.0.1.11
infra2.example.com.  300  IN  A  10.0.1.12

然后创建节点

代码语言:javascript复制
$ etcd --name infra0 
--discovery-srv example.com 
--initial-advertise-peer-urls http://infra0.example.com:2380 
--initial-cluster-token etcd-cluster-1 
--initial-cluster-state new 
--advertise-client-urls http://infra0.example.com:2379 
--listen-client-urls http://0.0.0.0:2379 
--listen-peer-urls http://0.0.0.0:2380
$ etcd --name infra1 
--discovery-srv example.com 
--initial-advertise-peer-urls http://infra1.example.com:2380 
--initial-cluster-token etcd-cluster-1 
--initial-cluster-state new 
--advertise-client-urls http://infra1.example.com:2379 
--listen-client-urls http://0.0.0.0:2379 
--listen-peer-urls http://0.0.0.0:2380

Gateway 是一个tcp代理可以把外部请求代理给etcd集群。Proxy也是代理,但是只有v2版本支持,它的参数是--proxy

往现有的集群添加节点分为下面两步:

Phase 1 - Inform cluster of new configuration

Phase 2 - Start new member

首先把新节点的配置告知集群,然后把节点加入集群。

节点的核心配置字段如下

代码语言:javascript复制

--name 'default'
  Human-readable name for this member.
--data-dir '${name}.etcd'
  Path to the data directory.
--wal-dir ''
  Path to the dedicated wal directory.
--snapshot-count '100000'
  Number of committed transactions to trigger a snapshot to disk.
--heartbeat-interval '100'
  Time (in milliseconds) of a heartbeat interval.
--election-timeout '1000'
  Time (in milliseconds) for an election to timeout. See tuning documentation for details.
--initial-election-tick-advance 'true'
  Whether to fast-forward initial election ticks on boot for faster election.
--listen-peer-urls 'http://localhost:2380'
  List of URLs to listen on for peer traffic.
--listen-client-urls 'http://localhost:2379'
  List of URLs to listen on for client traffic.
--max-snapshots '5'
  Maximum number of snapshot files to retain (0 is unlimited).
--max-wals '5'
  Maximum number of wal files to retain (0 is unlimited).
--quota-backend-bytes '0'
  Raise alarms when backend size exceeds the given quota (0 defaults to low space quota).
--backend-bbolt-freelist-type 'map'
  BackendFreelistType specifies the type of freelist that boltdb backend uses(array and map are supported types).
--backend-batch-interval ''
  BackendBatchInterval is the maximum time before commit the backend transaction.
--backend-batch-limit '0'
  BackendBatchLimit is the maximum operations before commit the backend transaction.
--max-txn-ops '128'
  Maximum number of operations permitted in a transaction.
--max-request-bytes '1572864'
  Maximum client request size in bytes the server will accept.
--grpc-keepalive-min-time '5s'
  Minimum duration interval that a client should wait before pinging server.
--grpc-keepalive-interval '2h'
  Frequency duration of server-to-client ping to check if a connection is alive (0 to disable).
--grpc-keepalive-timeout '20s'
  Additional duration of wait before closing a non-responsive connection (0 to disable).
--socket-reuse-port 'false'
  Enable to set socket option SO_REUSEPORT on listeners allowing rebinding of a port already in use.
--socket-reuse-address 'false'
  Enable to set socket option SO_REUSEADDR on listeners allowing binding to an address in TIME_WAIT state.
代码语言:javascript复制
--initial-advertise-peer-urls 'http://localhost:2380'
  List of this member's peer URLs to advertise to the rest of the cluster.
--initial-cluster 'default=http://localhost:2380'
  Initial cluster configuration for bootstrapping.
--initial-cluster-state 'new'
  Initial cluster state ('new' or 'existing').
--initial-cluster-token 'etcd-cluster'
  Initial cluster token for the etcd cluster during bootstrap.
  Specifying this can protect you from unintended cross-cluster interaction when running multiple clusters.
--advertise-client-urls 'http://localhost:2379'
  List of this member's client URLs to advertise to the public.
  The client URLs advertised should be accessible to machines that talk to etcd cluster. etcd client libraries parse these URLs to connect to the cluster.
--discovery ''
  Discovery URL used to bootstrap the cluster.
--discovery-fallback 'proxy'
  Expected behavior ('exit' or 'proxy') when discovery services fails.
  "proxy" supports v2 API only.
--discovery-proxy ''
  HTTP proxy to use for traffic to discovery service.
--discovery-srv ''
  DNS srv domain used to bootstrap the cluster.
--discovery-srv-name ''
  Suffix to the dns srv name queried when bootstrapping.
--strict-reconfig-check 'true'
  Reject reconfiguration requests that would cause quorum loss.
--pre-vote 'true'
  Enable to run an additional Raft election phase.
--auto-compaction-retention '0'
  Auto compaction retention length. 0 means disable auto compaction.
--auto-compaction-mode 'periodic'
  Interpret 'auto-compaction-retention' one of: periodic|revision. 'periodic' for duration based retention, defaulting to hours if no time unit is provided (e.g. '5m'). 'revision' for revision number based retention.
--enable-v2 'false'
  Accept etcd V2 client requests. Deprecated and to be decommissioned in v3.6.
--v2-deprecation 'not-yet'
  Phase of v2store deprecation. Allows to opt-in for higher compatibility mode.
  Supported values:
    'not-yet'                // Issues a warning if v2store have meaningful content (default in v3.5)
    'write-only'             // Custom v2 state is not allowed (planned default in v3.6)
    'write-only-drop-data'   // Custom v2 state will get DELETED !
    'gone'                   // v2store is not maintained any longer.(planned default in v3.7)

官方也给我们提供了goreman的方式启动集群,

代码语言:javascript复制
% goreman start
10:28:58 etcd1 | Starting etcd1 on port 5000
10:28:58 etcd2 | Starting etcd2 on port 5100
10:28:58 etcd3 | Starting etcd3 on port 5200
10:28:58 etcd1 | {"level":"warn","ts":"2023-06-11T10:28:58.933612 0800","caller":"embed/config.go:708","msg":"Running http and grpc server on single port. This is not recommended for production."}
10:28:58 etcd1 | {"level":"info","ts":"2023-06-11T10:28:58.934429 0800","caller":"etcdmain/etcd.go:64","msg":"Running: ","args":["bin/etcd","--name","infra1","--listen-client-urls","http://127.0.0.1:2379","--advertise-client-urls","http://127.0.0.1:2379","--listen-peer-urls","http://127.0.0.1:12380","--initial-advertise-peer-urls","http://127.0.0.1:12380","--initial-cluster-token","etcd-cluster-1","--initial-cluster","infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380","--initial-cluster-state","new","--enable-pprof","--logger=za

然后添加一个learner

代码语言:javascript复制
% goreman -f ./Procfile.learner start
10:29:40 etcd4 | Starting etcd4 on port 5000
10:29:40 etcd4 | {"level":"warn","ts":"2023-06-11T10:29:40.196332 0800","caller":"embed/config.go:708","msg":"Running http and grpc server on single port. This is not recommended for production."}
10:29:40 etcd4 | {"level":"info","ts":"2023-06-11T10:29:40.196721 0800","caller":"etcdmain/etcd.go:64","msg":"Running: ","args":["bin/etcd","--name","infra4","--listen-client-urls","http://127.0.0.1:42379","--advertise-client-urls","http://127.0.0.1:42379","--listen-peer-urls","http://127.0.0.1:42380","--initial-advertise-peer-urls","http://127.0.0.1:42380","--initial-cluster-token","etcd-cluster-1","--initial-cluster","infra4=http://127.0.0.1:42380,infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380","--initial-cluster-state","existing","--enable-pprof","--logger=zap","--log-outputs=stderr"]}
10:29:40 etcd4 | {"level":"info","ts":"2023-06-11T10:29:40.196803 0800","caller":"etcdmain/etcd.go:91","msg":"failed to detect default host","error":"default host not supported on darwin_amd64"}

两者对应的配置文件分别如下:

Procfile

代码语言:javascript复制
# Use goreman to run `go install github.com/mattn/goreman@latest`
# Change the path of bin/etcd if etcd is located elsewhere

etcd1: bin/etcd --name infra1 --listen-client-urls http://127.0.0.1:2379 --advertise-client-urls http://127.0.0.1:2379 --listen-peer-urls http://127.0.0.1:12380 --initial-advertise-peer-urls http://127.0.0.1:12380 --initial-cluster-token etcd-cluster-1 --initial-cluster 'infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380' --initial-cluster-state new --enable-pprof --logger=zap --log-outputs=stderr
etcd2: bin/etcd --name infra2 --listen-client-urls http://127.0.0.1:22379 --advertise-client-urls http://127.0.0.1:22379 --listen-peer-urls http://127.0.0.1:22380 --initial-advertise-peer-urls http://127.0.0.1:22380 --initial-cluster-token etcd-cluster-1 --initial-cluster 'infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380' --initial-cluster-state new --enable-pprof --logger=zap --log-outputs=stderr
etcd3: bin/etcd --name infra3 --listen-client-urls http://127.0.0.1:32379 --advertise-client-urls http://127.0.0.1:32379 --listen-peer-urls http://127.0.0.1:32380 --initial-advertise-peer-urls http://127.0.0.1:32380 --initial-cluster-token etcd-cluster-1 --initial-cluster 'infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380' --initial-cluster-state new --enable-pprof --logger=zap --log-outputs=stderr
#proxy: bin/etcd grpc-proxy start --endpoints=127.0.0.1:2379,127.0.0.1:22379,127.0.0.1:32379 --listen-addr=127.0.0.1:23790 --advertise-client-url=127.0.0.1:23790 --enable-pprof

# A learner node can be started using Procfile.learner

Profile.learner

代码语言:javascript复制
# Use goreman to run `go install github.com/mattn/goreman@latest`

# 1. Start the cluster using Procfile
# 2. Add learner node to the cluster
#   % etcdctl member add infra4 --peer-urls="http://127.0.0.1:42380" --learner=true

# 3. Start learner node with goreman
# Change the path of bin/etcd if etcd is located elsewhere
etcd4: bin/etcd --name infra4 --listen-client-urls http://127.0.0.1:42379 --advertise-client-urls http://127.0.0.1:42379 --listen-peer-urls http://127.0.0.1:42380 --initial-advertise-peer-urls http://127.0.0.1:42380 --initial-cluster-token etcd-cluster-1 --initial-cluster 'infra4=http://127.0.0.1:42380,infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380' --initial-cluster-state existing --enable-pprof --logger=zap --log-outputs=stderr

# 4. The learner node can be promoted to voting member by the command
#   % etcdctl member promote <memberid>

完成后我们看下集群情况

代码语言:javascript复制
 % etcdctl --endpoints=http://127.0.0.1:22379 member list
8211f1d0f64f3269, started, infra1, http://127.0.0.1:12380, http://127.0.0.1:2379, false
91bc3c398fb3c146, started, infra2, http://127.0.0.1:22380, http://127.0.0.1:22379, false
fd422379fda50e48, started, infra3, http://127.0.0.1:32380, http://127.0.0.1:32379, false
代码语言:javascript复制
 % etcdctl --endpoints=http://127.0.0.1:22379 endpoint status
http://127.0.0.1:22379, 91bc3c398fb3c146, 3.6.0-alpha.0, 3.6.0, 25 kB, 25 kB, false, false, 2, 8, 8,

1 人点赞