Etcd 基础知识

本文整合了 Etcd 的基础知识体系,包括其核心简介、常用命令行工具 etcdctl 的操作、性能调优指南,以及 Etcd 在 Kubernetes 中的应用与数据管理。

1. etcd简介

简介

etcd 是一款分布式存储中间件,使用 Go 语言编写,并通过 Raft 一致性算法处理和确保分布式一致性,解决了分布式系统中数据一致性的问题

etcd 的核心架构

  1. etcd Server : 对外接收和处理客户端的请求
  2. gRPC Server : etcd 与其他 etcd 节点之间的通信和信息同步
  3. MVCC : 多版本控制,etcd 的存储模块,键值对的每一次操作行为都会被记录存储,这些数据底层存储在 BoltDB 数据库中
  4. Snapshot、WAL : WAL 预写式日志,etcd 中的数据提交前都会记录到日志。 Snapshot 快照,以防 WAL 日志过多,用于存储某一时刻 etcd 的所有数据。SnapshotWAL 相结合,etcd 可以有效地进行数据存储和节点故障恢复等操作。
  5. Raft 模块 : 实现分布式集群的一致性

版本选择

etcd 目前有 V2.xV3.x 两个大版本

主流版本 V3.x

安装

三节点部署, etcdetcdctl 文件 在 /usr/bin 目录下

前置条件

节点 ip

1
2
3
172.20.40.173
172.20.40.196
172.20.40.107

生成 etcd 的server 证书

当前和 k8s 共同部署,k8s 文件均相同, 在 /etc/kubernetes/ssl/ 目录下

1
2
3
/etc/kubernetes/ssl/ca.pem
/etc/kubernetes/ssl/ca-key.pem
/etc/kubernetes/ssl/ca-config.json

/etc/kubernetes/ssl/ca-config.json 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@test-173 test]# cat /etc/kubernetes/ssl/ca-config.json
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "87600h"
}
}
}
}

etcd 使用的 etcd-csr.json 需要修改 IP, 在 /etc/etcd/ssl 目录下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@test-173 ssl]# pwd
/etc/etcd/ssl

[root@test-173 ssl]# cat etcd-csr.json
{
"CN": "etcd",
"hosts": [
"127.0.0.1",
"172.20.40.173" # 需要每个节点对应修改
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "HangZhou",
"L": "XS",
"O": "k8s",
"OU": "System"
}
]
}

在每个节点的 的 /etc/etcd/ssl 目录下执行, 生成 etcd.csr , etcd-key.pem , etcd.pem

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@test-107 ssl]# pwd
/etc/etcd/ssl

[root@test-107 ssl]# ls
etcd-csr.json

[root@test-173 ssl]# cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem -ca-key=/etc/kubernetes/ssl/ca-key.pem -config=/etc/kubernetes/ssl/ca-config.json -profile=kubernetes /etc/etcd/ssl/etcd-csr.json | cfssljson -bare etcd
2021/04/06 13:48:22 [INFO] generate received request
2021/04/06 13:48:22 [INFO] received CSR
2021/04/06 13:48:22 [INFO] generating key: rsa-2048
2021/04/06 13:48:23 [INFO] encoded CSR
2021/04/06 13:48:23 [INFO] signed certificate with serial number 518875750718489889129533277175826954994664517958
2021/04/06 13:48:23 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 ("Information Requirements").
cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem -ca-key=/etc/kubernetes/ssl/ca-key.pem -config=/etc/kubernetes/ssl/ca-config.json -profile=kubernetes /etc/etcd/ssl/etcd-csr.json | cfssljson -bare etcd

[root@test-107 ssl]# ls
etcd.csr etcd-csr.json etcd-key.pem etcd.pem

创建 etcd.service 启动文件

每个节点创建文件,对应修改
eg: 172.20.40.107 名字为 etcd3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[root@test-107 ssl]# cat /etc/systemd/system/etcd.service
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos

[Service]
Type=notify
WorkingDirectory=/var/lib/etcd/
ExecStart=/usr/bin/etcd \
--name=etcd3 \
--cert-file=/etc/etcd/ssl/etcd.pem \
--key-file=/etc/etcd/ssl/etcd-key.pem \
--peer-cert-file=/etc/etcd/ssl/etcd.pem \
--peer-key-file=/etc/etcd/ssl/etcd-key.pem \
--trusted-ca-file=/etc/kubernetes/ssl/ca.pem \
--peer-trusted-ca-file=/etc/kubernetes/ssl/ca.pem \
--initial-advertise-peer-urls=https://172.20.40.107:2380 \
--listen-peer-urls=https://172.20.40.107:2380 \
--listen-client-urls=https://172.20.40.107:2379,http://127.0.0.1:2379 \
--advertise-client-urls=https://172.20.40.107:2379 \
--initial-cluster-token=etcd-cluster-0 \
--initial-cluster=etcd1=https://172.20.40.173:2380,etcd2=https://172.20.40.196:2380,etcd3=https://172.20.40.107:2380 \
--initial-cluster-state=new \
--data-dir=/mnt/etcd_data
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

[root@test-107 ssl]# systemctl daemon-reload && systemctl enable --now etcd.service

验证, 当前正常

客户端交互端口 : 2379

peer通信端口 : 2380

peer : 同一集群的另一个 member

1
2
3
4
5
6
7
8
9
10
[root@test-107 ssl]# etcdctl --endpoints=http://localhost:2379  member list  # 查看集群成员
d20c6ab8456f5fd, started, etcd1, https://172.20.40.173:2380, https://172.20.40.173:2379, false
71c9147302874bdf, started, etcd3, https://172.20.40.107:2380, https://172.20.40.107:2379, false
ce0a9eb4851e47ac, started, etcd2, https://172.20.40.196:2380, https://172.20.40.196:2379, fasle

[root@test-107 ssl]# ETCDCTL_API=3 /usr/bin/etcdctl --endpoints=https://172.20.40.196:2379,https://172.20.40.107:2379,https://172.20.40.173:2379 --cacert=/etc/kubernetes/ssl/ca.pem --cert=/etc/etcd/ssl/etcd.pem --key=/etc/etcd/ssl/etcd-key.pem endpoint health # 查看节点健康

https://172.20.40.107:2379 is healthy: successfully committed proposal: took = 26.66478ms
https://172.20.40.173:2379 is healthy: successfully committed proposal: took = 30.31433ms
https://172.20.40.196:2379 is healthy: successfully committed proposal: took = 37.859764ms

etcd.service 部分参数说明
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
--name:etcd 集群中的节点名,这里可以随意,方便区分且不重复即可。

--listen-client-urls:监听用于客户端通信的 url,同样可以监听多个。

--advertise-client-urls:建议使用的客户端通信 url,该值用于 etcd 代理或 etcd 成员与 etcd 节点通信。

--listen-peer-urls:监听用于节点之间通信的 url,可监听多个,集群内部将通过这些 url 进行数据交互(如选举、数据同步等)。

--initial-advertise-peer-urls:建议用于节点之间通信的 url,节点间将以该值进行通信。

--initial-cluster-token: etcd-cluster-0,节点的 token 值,设置该值后集群将生成唯一 ID,并为每个节点也生成唯一 ID。当使用相同配置文件再启动一个集群时,只要该 token 值不一样,etcd 集群就不会相互影响。

--initial-cluster:集群中所有的 initial-advertise-peer-urls 的合集。

--initial-cluster-state:new,新建集群的标志。

升级

仅需 替换二进制文件 etcd, etcdctl

备份恢复

在任一正常节点执行如下操作

eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
[root@test-173 test]# export ETCDCTL_API=3; /usr/bin/etcdctl --endpoints=172.20.40.107:2379 --cacert=/etc/kubernetes/ssl/ca.pem --cert=/etc/etcd/ssl/etcd.pem --key=/etc/etcd/ssl/etcd-key.pem snapshot save /root/backup/etcd/snapshot-20210406-143852.db


{"level":"info","ts":1617691138.681973,"caller":"snapshot/v3_snapshot.go:119","msg":"created temporary db file","path":"/root/backup/etcd/snapshot-20210406-143852.db.part"}
{"level":"info","ts":"2021-04-06T14:38:58.698+0800","caller":"clientv3/maintenance.go:200","msg":"opened snapshot stream; downloading"}
{"level":"info","ts":1617691138.698508,"caller":"snapshot/v3_snapshot.go:127","msg":"fetching snapshot","endpoint":"172.20.40.107:2379"}
{"level":"info","ts":"2021-04-06T14:38:58.990+0800","caller":"clientv3/maintenance.go:208","msg":"completed snapshot read; closing"}
{"level":"info","ts":1617691138.9978282,"caller":"snapshot/v3_snapshot.go:142","msg":"fetched snapshot","endpoint":"172.20.40.107:2379","size":"10 MB","took":0.315710239}
{"level":"info","ts":1617691139.000513,"caller":"snapshot/v3_snapshot.go:152","msg":"saved","path":"/root/backup/etcd/snapshot-20210406-143852.db"}
Snapshot saved at /root/backup/etcd/snapshot-20210406-143852.db


[root@test-173 test]# export ETCDCTL_API=3; /usr/bin/etcdctl --endpoints=172.20.40.107:2379 --cacert=/etc/kubernetes/ssl/ca.pem --cert=/etc/etcd/ssl/etcd.pem --key=/etc/etcd/ssl/etcd-key.pem snapshot save /root/backup/etcd/snapshot-20210406-143852.db


{"level":"info","ts":1617691138.681973,"caller":"snapshot/v3_snapshot.go:119","msg":"created temporary db file","path":"/root/backup/etcd/snapshot-20210406-143852.db.part"}
{"level":"info","ts":"2021-04-06T14:38:58.698+0800","caller":"clientv3/maintenance.go:200","msg":"opened snapshot stream; downloading"}
{"level":"info","ts":1617691138.698508,"caller":"snapshot/v3_snapshot.go:127","msg":"fetching snapshot","endpoint":"172.20.40.107:2379"}
{"level":"info","ts":"2021-04-06T14:38:58.990+0800","caller":"clientv3/maintenance.go:208","msg":"completed snapshot read; closing"}
{"level":"info","ts":1617691138.9978282,"caller":"snapshot/v3_snapshot.go:142","msg":"fetched snapshot","endpoint":"172.20.40.107:2379","size":"10 MB","took":0.315710239}
{"level":"info","ts":1617691139.000513,"caller":"snapshot/v3_snapshot.go:152","msg":"saved","path":"/root/backup/etcd/snapshot-20210406-143852.db"}
Snapshot saved at /root/backup/etcd/snapshot-20210406-143852.db


### 恢复
systemctl stop etcd.service

cd /root/backup/etcd/ && \
ETCDCTL_API=3 /use/bin/etcdctl snapshot restore snapshot-20210406-143852.db\
--name etcd-3 \
--initial-cluster etcd1=https://172.20.40.173:2380,etcd2=https://172.20.40.196:2380,etcd3=https://172.20.40.107:2380 \
--initial-cluster-token etcd-cluster-0 \
--initial-advertise-peer-urls https://172.20.40.107:2380"

具体可以参考 之前编写的 ansible 文件

用 kubeasz 安装

1
etcdctl --endpoints=https://172.20.19.14:2379,https://172.20.19.9:2379,https://172.20.19.17:2379 --cacert=/etc/kubernetes/ssl/ca.pem --cert=/etc/kubernetes/ssl/etcd.pem --key=/etc/kubernetes/ssl/etcd-key.pem endpoint health

etcd 网关与 gRPC-Gateway

etcd 网关通常用于 etcd 集群的门户,是一个简单的 TCP 代理,将客户端请求转发到 etcd 集群,对外屏蔽了 etcd 集群内部的实际情况,在集群出现故障或者异常时,可以通过 etcd 网关进行切换;

gRPC-Gateway 则是对于 etcdgRPC 通信协议的补充,有些语言的客户端不支持 gRPC 通信协议,此时就可以使用 gRPC-Gateway 对外提供的 HTTP API 接口。通过 HTTP 请求,实现与 gRPC 调用协议同样的功能。


2. etcdctl

使用 v3 版本,export ETCDCTL_API=3

常用操作

etcdctl 支持命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@test-173 test]#  etcdctl -h
NAME:
etcdctl - A simple command line client for etcd3.

USAGE:
etcdctl [flags]

VERSION:
3.4.13

API VERSION:
3.4

...

数据库操作

数据库操作基本围绕着对键值和目录的 CRUD 操作及其对应的生命周期管理。 etcd 这些操作符合 REST 风格的一套 API 操作

键操作

键操作包括最常用的增删改查操作,包括 PUTGETDELETE 等命令。

PUT 设置或者更新某个键的值

1
2
3
4
5
6
[root@test-173 test]# etcdctl put /test/foo1 "Hello world"
OK
[root@test-173 test]# etcdctl put /test/foo2 "Hello world2"
OK
[root@test-173 test]# etcdctl put /test/foo3 "Hello world3"
OK

GET 获取指定键的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@test-173 test]#  etcdctl get /test/foo1
/test/foo1
Hello world

[root@test-173 test]# etcdctl get /test/foo2 --hex # 返回 十六进制格式
\x2f\x74\x65\x73\x74\x2f\x66\x6f\x6f\x32
\x48\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\x32

[root@test-173 test]# etcdctl get /test/foo3 --hex --print-value-only # 返回 十六进制格式,只获取值
\x48\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\x33

[root@test-173 test]# etcdctl get /test/foo1 /test/foo3 --print-value-only # 获取 [/test/foo1, /test/foo3)
Hello world
Hello world2

[root@test-173 test]# etcdctl get --prefix --limit=2 /test/foo --print-value-only # 获取 前缀为 /test/foo 的两个值
Hello world
Hello world2

DELETE 删除一个键或者特定范围的键

1
2
3
4
5
6
7
8
9
10
11
12
[root@test-173 test]# etcdctl del /test/foo1  /test/foo2  # 删除 [/test/foo1, /test/foo2)
1 # 删除了一个健
[root@test-173 test]# etcdctl get /test/foo1
[root@test-173 test]# etcdctl get /test/foo2
/test/foo2
Hello world2

root@test-173 test]# etcdctl del --prev-kv /test/foo2 # 删除键并返回值
1
/test/foo2
Hello world2
[root@test-173 test]# etcdctl get /test/foo2

watch 键值对的改动

watch 监测一个或多个键值的变化,一旦键值发生更新,就会输出最新的值并退出

1
[root@test-173 ~]# etcdctl watch foo1

新开窗口

1
2
3
4
5
6
[root@test-173 ~]# etcdctl put foo1 Hello watch
OK
[root@test-173 ~]# etcdctl put foo bar
OK
[root@test-173 ~]# etcdctl put foo1 bar1
OK

查看 watch 窗口

1
2
3
4
5
6
7
[root@test-173 ~]# etcdctl watch foo1
PUT
foo1
Hello
PUT
foo1
bar1
lease(租约)

一旦租约的 TTL 到期,租约就会过期并且所有附带的键都将被删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
[root@test-173 test]# etcdctl lease grant 100  # 授予租约,TTL 为 100 秒
lease 75fd78a5bc8db873 granted with TTL(100s)

[root@test-173 test]# etcdctl put --lease=75fd78a5bc8db873 foo1 bar # 附加键 foo1 到租约 75fd78a5bc8db873
OK
[root@test-173 test]# etcdctl get foo1
foo1
bar
[root@test-173 test]# etcdctl get foo1 # 两分钟后,发现 已没有值

[root@test-173 test]# etcdctl put --lease=75fd78a5bc8db873 foo1 bar # 租约已失效
{"level":"warn","ts":"2021-04-06T15:14:17.315+0800","caller":"clientv3/retry_interceptor.go:62","msg":"retrying of unary invoker failed","target":"endpoint://client-71d3b0ce-8010-4407-ad17-71c5f1970309/127.0.0.1:2379","attempt":0,"error":"rpc error: code = NotFound desc = etcdserver: requested lease not found"}


[root@test-173 test]# etcdctl lease grant 1000
lease 75fd78a5bc8dbb9b granted with TTL(1000s)
[root@test-173 test]# etcdctl put --lease=75fd78a5bc8dbb9b foo1 bar
OK
[root@test-173 test]# etcdctl get foo1
foo1
bar
[root@test-173 test]# etcdctl lease revoke 75fd78a5bc8dbb9b # 撤销租约
lease 75fd78a5bc8dbb9b revoked
[root@test-173 test]# etcdctl get foo1 # 撤销租约将删除所有附带的 key


## 刷新租约
[root@test-173 test]# etcdctl lease keep-alive 75fd78a5bc8dbe37 # 一直刷新
lease 75fd78a5bc8dbe37 keepalived with TTL(100)
lease 75fd78a5bc8dbe37 keepalived with TTL(100)
lease 75fd78a5bc8dbe37 keepalived with TTL(100)
lease 75fd78a5bc8dbe37 keepalived with TTL(100)

## 新开一个端口
root@test-173 ~]# etcdctl put --lease=75fd78a5bc8dbe37 foo1 bar
OK
[root@test-173 ~]# etcdctl lease timetolive 75fd78a5bc8dbe37 # 获取有关租赁信息
lease 75fd78a5bc8dbe37 granted with TTL(100s), remaining(68s)

[root@test-173 ~]# etcdctl lease timetolive --keys 75fd78a5bc8dbe37 # 获取哪些 key 绑定了租赁信息:
lease 75fd78a5bc8dbe37 granted with TTL(100s), remaining(91s), attached keys([foo1])

3. etcd调优

使用内存模式

未安装时

1
2
3
mkdir /var/lib/etcd
mount -t tmpfs -o size=10G,mode=0755 tmpfs /var/lib/etcd
echo "tmpfs /var/lib/etcd tmpfs defaults,size=10G 0 0" >> /etc/fstab

已经安装了 etcd, 先备份,操作完再恢复

将 etcd 的流量排在第一优先级

2379 2380 端口流量

1
2
3
4
5
6
netDevice="ens33"
tc qdisc add dev $netDevice root handle 1: prio bands 3
tc filter add dev $netDevice parent 1: protocol ip prio 1 u32 match ip sport 2380 0xffff flowid 1:1
tc filter add dev $netDevice parent 1: protocol ip prio 1 u32 match ip dport 2380 0xffff flowid 1:1
tc filter add dev $netDevice parent 1: protocol ip prio 2 u32 match ip sport 2379 0xffff flowid 1:1
tc filter add dev $netDevice parent 1: protocol ip prio 2 u32 match ip dport 2379 0xffff flowid 1:1


4. etcd与k8s

获取 Kubernetes 存储在 etcd 中的 keys

1
2
3
4
5
6
7
8
9
10
11
12
[root@test-173 ~]# ETCDCTL_API=3 etcdctl get / --prefix --keys-only  |grep -Ev "^$"
/calico/ipam/v2/assignment/ipv4/block/170.56.144.192-26
/calico/ipam/v2/assignment/ipv4/block/170.56.170.64-26
/calico/ipam/v2/assignment/ipv4/block/170.56.27.0-26
/calico/ipam/v2/assignment/ipv4/block/170.56.73.192-26
/calico/ipam/v2/handle/k8s-pod-network.006edea2a1463ad925976290e5a0fea9d87e3188731566465ec8459f20b54a9d
/calico/ipam/v2/handle/k8s-pod-network.0397054208d1bce46053df4814d1006f14ae0dd98280555aa5b35d1b8b02c06e
/calico/ipam/v2/handle/k8s-pod-network.070dee87e37e685f2f6adac7ea38a54bb2326ac1c5d56bcae3b9b46086ff5c2b
/calico/ipam/v2/handle/k8s-pod-network.0fad3aa32d7c9bfe0392577fc44a9f7ad9482c9914e0a93b1b94363cd1173585
## 略

[root@test-173 ~]# ETCDCTL_API=3 etcdctl --endpoints=https://172.20.40.196:2379,https://172.20.40.107:2379,https://172.20.40.173:2379 --cacert=/etc/kubernetes/ssl/ca.pem --cert=/etc/etcd/ssl/etcd.pem --key=/etc/etcd/ssl/etcd-key.pem get / --prefix --keys-only |grep -Ev "^$" # 同样结果

查看键值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
[root@test-107 ~]# ETCDCTL_API=3 etcdctl --endpoints=https://172.20.40.196:2379,https://172.20.40.107:2379,https://172.20.40.173:2379 --cacert=/etc/kubernetes/ssl/ca.pem --cert=/etc/etcd/ssl/etcd.pem --key=/etc/etcd/ssl/etcd-key.pem  get /registry/services/endpoints/monitoring/grafana  # 查看键值

/registry/services/endpoints/monitoring/grafana
k8s

v1 Endpoints⚌

grafana
monitoring"*$c5bca02d-dcde-4638-88fa-d32f1606cd722⚌⚌߃Z&
pp.kubernetes.io/componentgrafanaZ!
app.kubernetes.io/namegrafanaZ,
app.kubernetes.io/part-ofkube-prometheusZ"
app.kubernetes.io/version7.4.3bM
0endpoints.kubernetes.io/last-change-trigger-time2021-04-26T18:01:18+08:00z⚌⚌
kube-controller-managerUpdatev⚌FieldsV1:⚌
⚌{"f:metadata":{"f:annotations":{".":{},"f:endpoints.kubernetes.io/last-change-trigger-time":{}},"f:labels":{".":{},"f:app.kubernetes.io/component":{},"f:app.kubernetes.io/name":{},"f:app.kubernetes.io/part-of":{},"f:app.kubernetes.io/version":{}}},"f:subsets":{}}⚌

170.56.73.220_
Pod
172.20.40.173fana-665447c488-245vl"$db4da82f-36ed-49b9-8003-197a61e8ed97*11359764:"
http⚌TCP"


[root@test-107 ~]# ETCDCTL_API=3 etcdctl --endpoints=https://172.20.40.196:2379,https://172.20.40.107:2379,https://172.20.40.173:2379 --cacert=/etc/kubernetes/ssl/ca.pem --cert=/etc/etcd/ssl/etcd.pem --key=/etc/etcd/ssl/etcd-key.pem get /registry/namespaces/default

/registry/namespaces/default
k8s

v1 Namespace⚌

default"*$fb03c357-9393-11eb-898b-fad65d90ce002⚌⚌⚌Z$
field.cattle.io/projectIdp-zrh2mZ
istio-injectionenabledb⚌
cattle.io/status⚌{"Conditions":[{"Type":"ResourceQuotaInit","Status":"True","Message":"","LastUpdateTime":"2021-04-14T05:51:05Z"},{"Type":"InitialRolesPopulated","Status":"True","Message":"","LastUpdateTime":"2021-04-14T05:51:05Z"}]}b,
field.cattle.io/projectIdc-hxllk:p-zrh2mb1
)lifecycle.cattle.io/create.namespace-authtruer#controller.cattle.io/namespace-authz


kubernetes
Active"

键类型

这些键定义了集群中所有资源的配置和状态:

1
2
3
4
5
6
7
8
9
10
Nodes
Namespaces
ServiceAccounts
Roles and RoleBindings, ClusterRoles / ClusterRoleBindings
ConfigMaps
Secrets
Workloads: Deployments, DaemonSets, Pods, …
Cluster's certificates
The resources within each apiVersion
The events that bring the cluster in the current state

元数据资源在 etcd 中的存储格式由前缀、资源类型、namespace 和具体资源名组成

Kubernetes 集群使用了事务 Txn 接口防止并发创建、更新被覆盖等问题。当执行完 BeforeCreate 策略后,API Server 会调用 Storage 模块的 Create 接口写入资源。Storage.Create 接口调用底层存储模块 etcd3,将 user Deployment 资源对象写入 etcd。

Kubernetes 使用 watch 机制获取数据变化的事件,etcd watch 机制提供了流式推送机制,相比于定时轮询减少了高昂的查询开销,方便 API Server 实现数据的监听。服务器端的 store 对象利用 etcd 的 watch 机制,当 watch 机制触发时,数据的变化信息将封装成 event 对象并打包发送出去,客户端则通过不停地监听尝试读取 event chunk。

需要注意的是,Kubernetes 社区提供了通用的Informer 组件,实现了客户端与 API Server 之间的资源和事件同步。Informer 机制的 Reflector 封装了 Watch、List 操作,结合本地 Cache、Indexer,控制器加载完初始状态数据后,接下来的其他操作只需从本地缓存读取,极大降低了 API Server 和 etcd 的压力。