和 etcd 交互

    默认,为了向后兼容 etcdctl 使用 v2 API 来和 etcd 服务器通讯。为了让 etcdctl 使用 v3 API 来和etcd通讯,API 版本必须通过环境变量 设置为版本3。

    在查找适当命令以便对 etcd 执行各种操作时,etcdctl 版本和 Server API 版本很有用。

    以下是查找版本的命令:

    1. $ etcdctl version
    2. etcdctl version: 3.1.0-alpha.0+git
    3. API version: 3.1

    写入键

    应用通过写入键来储存键到 etcd 中。每个存储的键通过 Raft 协议复制到 etcd 集群的所有成员来实现一致性和可靠性。

    这是设置键 foo 的值为 bar 的命令:

    1. $ etcdctl put foo bar
    2. OK

    而且可以通过附加租约的方式为键设置特定时间间隔。

    这是将键 foo1 的值设置为 bar1 并维持 10s 的命令:

    1. $ etcdctl put foo1 bar1 --lease=1234abcd
    2. OK

    注意: 上面命令中的租约id 1234abcd 是创建租约时返回的. 这个 id 随即被附加到键。

    读取键

    应用可以从 etcd 集群中读取键的值。查询可以读取单个 key,或者某个范围的键。

    假设 etcd 集群存储有下面的键:

    1. foo = bar
    2. foo1 = bar1
    3. foo2 = bar2
    4. foo3 = bar3

    这是读取键 foo 的值的命令:

    1. $ etcdctl get foo
    2. foo
    3. bar

    这是以16进制格式读取键的值的命令:

    1. $ etcdctl get foo --hex
    2. \x66\x6f\x6f # 键
    3. \x62\x61\x72 # 值

    这是只读取键 foo 的值的命令:

    1. $ etcdctl get foo --print-value-only
    2. bar

    这是范围覆盖从 foo to foo3 的键的命令:

    1. $ etcdctl get foo foo3
    2. foo
    3. bar
    4. foo1
    5. bar1
    6. foo2
    7. bar2

    注意 foo3 不在范围之内,因为范围是半开区间 [foo, foo3), 不包含 foo3.

    这是范围覆盖以 foo 为前缀的所有键的命令:

    1. $ etcdctl get --prefix foo
    2. foo
    3. bar
    4. foo1
    5. bar1
    6. foo2
    7. bar2
    8. foo3
    9. bar3

    这是范围覆盖以 foo 为前缀的所有键的命令,结果数量限制为2:

    1. $ etcdctl get --prefix --limit=2 foo
    2. foo
    3. bar
    4. foo1
    5. bar1

    读取键过往版本的值

    假设 etcd 集群已经有下列键:

    1. foo = bar # revision = 2
    2. foo1 = bar1 # revision = 3
    3. foo = bar_new # revision = 4
    4. foo1 = bar1_new # revision = 5

    这里是访问键的过往版本的例子:

    1. $ etcdctl get --prefix foo # 访问键的最新版本
    2. foo
    3. bar_new
    4. foo1
    5. bar1_new
    6. $ etcdctl get --prefix --rev=4 foo # 访问修订版本为 4 时的键的版本
    7. foo
    8. bar_new
    9. foo1
    10. bar1
    11. foo
    12. bar
    13. foo1
    14. bar1
    15. foo
    16. bar
    17. $ etcdctl get --prefix --rev=1 foo # 访问修订版本为 1 时的键的版本

    应用可能想读取大于等于指定键 的 byte 值的键.

    假设 etcd 集群已经有下列键:

    这是读取大于等于键 b 的 byte 值的键的命令:

    1. $ etcdctl get --from-key b
    2. b
    3. 456
    4. z
    5. 789

    删除键

    应用可以从 etcd 集群中删除一个键或者特定范围的键。

    假设 etcd 集群已经有下列键:

    1. foo = bar
    2. foo1 = bar1
    3. foo3 = bar3
    4. zoo = val
    5. zoo1 = val1
    6. zoo2 = val2
    7. a = 123
    8. b = 456
    9. z = 789

    这是删除键 foo 的命令:

    1. $ etcdctl del foo
    2. 1 # 删除了一个键

    这是删除从 foo to foo9 范围的键的命令:

    1. $ etcdctl del foo foo9
    2. 2 # 删除了两个键

    这是删除键 zoo 并返回被删除的键值对的命令:

    1. $ etcdctl del --prev-kv zoo
    2. 1 # 一个键被删除
    3. zoo # 被删除的键
    4. val # 被删除的键的值

    这是删除前缀为 zoo 的键的命令:

    1. $ etcdctl del --prefix zoo
    2. 2 # 删除了两个键

    这是删除大于等于键 b 的 byte 值的键的命令:

    1. $ etcdctl del --from-key b
    2. 2 # 删除了两个键

    观察键的变化

    应用可以观察一个键或者范围内的键来监控任何更新。

    这是在键 foo 上进行观察的命令:

    1. $ etcdctl watch foo
    2. # 在另外一个终端: etcdctl put foo bar
    3. foo
    4. bar

    这是以16进制格式在键 foo 上进行观察的命令:

    1. $ etcdctl watch foo --hex
    2. # 在另外一个终端: etcdctl put foo bar
    3. PUT
    4. \x66\x6f\x6f # 键
    5. \x62\x61\x72 # 值

    这是观察从 foo to foo9 范围内键的命令:

    1. $ etcdctl watch foo foo9
    2. # 在另外一个终端: etcdctl put foo bar
    3. PUT
    4. foo
    5. bar
    6. # 在另外一个终端: etcdctl put foo1 bar1
    7. PUT
    8. foo1
    9. bar1

    这是观察前缀为 foo 的键的命令:

    1. $ etcdctl watch --prefix foo
    2. # 在另外一个终端: etcdctl put foo bar
    3. PUT
    4. foo
    5. bar
    6. # 在另外一个终端: etcdctl put fooz1 barz1
    7. PUT
    8. fooz1
    9. barz1
    1. $ etcdctl watch -i
    2. $ watch foo
    3. $ watch zoo
    4. PUT
    5. foo
    6. # 在另外一个终端: etcdctl put zoo val
    7. PUT
    8. zoo
    9. val

    观察 key 的历史改动

    应用可能想观察 etcd 中键的历史改动。例如,应用想接收到某个键的所有修改。如果应用一直连接到 etcd,那么 watch 就足够好了。但是,如果应用或者 etcd 出错,改动可能发生在出错期间,这样应用就没能实时接收到这个更新。为了保证更新被交付,应用必须能够观察到键的历史变动。为了做到这点,应用可以在观察时指定一个历史修订版本,就像读取键的过往版本一样。

    假设我们完成了下列操作序列:

    这是观察历史改动的例子:

    1. # 从修订版本 2 开始观察键 `foo` 的改动
    2. $ etcdctl watch --rev=2 foo
    3. PUT
    4. foo
    5. bar
    6. PUT
    7. foo
    8. bar_new
    1. # 从修订版本 3 开始观察键 `foo` 的改动
    2. $ etcdctl watch --rev=3 foo
    3. PUT
    4. foo
    5. bar_new

    这是从上一次历史修改开始观察的例子(注:貌似原文有误,这里应该是观察变更时同时返回修改之前的值):

    1. # 在键 `foo` 上观察变更并返回被修改的值和上个修订版本的值
    2. $ etcdctl watch --prev-kv foo
    3. # 在另外一个终端: etcdctl put foo bar_latest
    4. PUT
    5. foo # 键
    6. bar_new # 在修改前键foo的上一个值
    7. foo # 键
    8. bar_latest # 修改后键foo的值

    如我们提到的,etcd 保存修订版本以便应用可以读取键的过往版本。但是,为了避免积累无限数量的历史数据,压缩过往的修订版本就变得很重要。压缩之后,etcd 删除历史修订版本,释放资源来提供未来使用。所有修订版本在压缩修订版本之前的被替代的数据将不可访问。

    这是压缩修订版本的命令:

    1. $ etcdctl compact 5
    2. compacted revision 5
    3. # 在压缩修订版本之前的任何修订版本都不可访问
    4. $ etcdctl get --rev=4 foo
    5. Error: rpc error: code = 11 desc = etcdserver: mvcc: required revision has been compacted

    注意: etcd 服务器的当前修订版本可以在任何键(存在或者不存在)以json格式使用get命令来找到。下面展示的例子中 mykey 是在 etcd 服务器中不存在的:

    1. $ etcdctl get mykey -w=json
    2. {"header":{"cluster_id":14841639068965178418,"member_id":10276657743932975437,"revision":15,"raft_term":4}}

    授予租约

    应用可以为 etcd 集群里面的键授予租约。当键被附加到租约时,它的存活时间被绑定到租约的存活时间,而租约的存活时间相应的被 time-to-live (TTL)管理。在租约授予时每个租约的最小TTL值由应用指定。租约的实际 TTL 值是不低于最小 TTL,由 etcd 集群选择。一旦租约的 TTL 到期,租约就过期并且所有附带的键都将被删除。

    这是授予租约的命令:

    1. # 授予租约,TTL为10秒
    2. $ etcdctl lease grant 10
    3. lease 32695410dcc0ca06 granted with TTL(10s)
    4. # 附加键 foo 到租约32695410dcc0ca06
    5. $ etcdctl put --lease=32695410dcc0ca06 foo bar
    6. OK

    撤销租约

    应用通过租约 id 可以撤销租约。撤销租约将删除所有它附带的 key。

    假设我们完成了下列的操作:

    1. $ etcdctl lease grant 10
    2. lease 32695410dcc0ca06 granted with TTL(10s)
    3. $ etcdctl put --lease=32695410dcc0ca06 foo bar
    4. OK

    这是撤销同一个租约的命令:

    1. $ etcdctl lease revoke 32695410dcc0ca06
    2. lease 32695410dcc0ca06 revoked
    3. $ etcdctl get foo
    4. # 空应答,因为租约撤销导致foo被删除

    维持租约

    应用可以通过刷新键的 TTL 来维持租约,以便租约不过期。

    假设我们完成了下列操作:

    1. $ etcdctl lease grant 10
    2. lease 32695410dcc0ca06 granted with TTL(10s)

    这是维持同一个租约的命令:

    1. $ etcdctl lease keep-alive 32695410dcc0ca06
    2. lease 32695410dcc0ca06 keepalived with TTL(10)
    3. lease 32695410dcc0ca06 keepalived with TTL(10)
    4. lease 32695410dcc0ca06 keepalived with TTL(10)
    5. ...

    应用程序可能想知道租约信息,以便可以更新或检查租约是否仍然存在或已过期。应用程序也可能想知道有那些键附加到了特定租约。

    假设我们完成了下列操作序列:

    1. # 授予租约,TTL为500秒
    2. $ etcdctl lease grant 500
    3. lease 694d5765fc71500b granted with TTL(500s)
    4. # 将键 zoo1 附加到租约 694d5765fc71500b
    5. $ etcdctl put zoo1 val1 --lease=694d5765fc71500b
    6. OK
    7. # 将键 zoo2 附加到租约 694d5765fc71500b
    8. $ etcdctl put zoo2 val2 --lease=694d5765fc71500b
    9. OK
    1. lease 694d5765fc71500b granted with TTL(500s), remaining(258s)

    这是获取租约信息和租约附带的键的命令: