Kubernetes-etcd 运行机制

etcd 节点运行机制

  • etcd 是 CoreOS 团队于 2013 年 6 月发起的开源项目,它的目标是构建一个高可用的分布式键值(key-value)数据库。etcd 内部采用 raft 协议作为一致性算法,etcd 基于 Go 语言实现。
  • GitHub 地址:https://github.com/etcd-io/etcd
  • 官方网站:https://etcd.io/
Etcd具有下面这些属性:
    完全复制:集群中的每个节点都可以使用完整的存档
    高可用性:Etcd 可用于避免硬件的单点故障或网络问题
    一致性:每次读取都会返回跨多主机的最新写入
    简单:包括一个定义良好、面向用户的 API(gRPC)
    安全:实现了带有可选的客户端证书身份验证的自动化TLS
    快速:每秒 10000 次写入的基准速度
    可靠:使用 Raft 算法实现了存储的合理分布 Etcd 的工作原理

启动脚本参数

root@k8s-etcd-1:~# 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=etcd1 \ #当前 node 名称
  --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://192.168.26.165:2380 \ #通告自己的集群端口
  --listen-peer-urls=https://192.168.26.165:2380 \ #集群之间通讯端口
  --listen-client-urls=https://192.168.26.165:2379,http://127.0.0.1:2379 \ #客户端访问地址
  --advertise-client-urls=https://192.168.26.165:2379 \ #通告自己的客户端端口
  --initial-cluster-token=etcd-cluster-0 \ #创建集群使用的 token,一个集群内的节点保持一致
  --initial-cluster=etcd1=https://192.168.26.165:2380,etcd2=https://192.168.26.175:2380,etcd3=https://192.168.26.185:2380 \ #集群所有的节点信息
  --initial-cluster-state=new \ #新建集群的时候的值为 new,如果时已经存在的集群为 exitsting
  --data-dir=/var/lib/etcd #数据存储路径
Restart=always
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

查看成员信息

  • etcd 有多个不同的 API 访问版本,v1 版本已经废弃,etcd v2 和 v3 本质上是共享同一套 raft 协议代码的两个独立的应用,接口不一样,存储不一样,数据互相隔离。也就是说如果从 Etcd v2 升级到 Etcd v3,原来v2 的数据还是只能用 v2 的接口访问,v3 的接口创建的数据也只能访问通过 v3 的接口访问。
WARNING:
Environment variable ETCDCTL_API is not set; defaults to etcdctl v2. #默认使用V2版本
Set environment variable ETCDCTL_API=3 to use v3 API or ETCDCTL_API=2 to use v2 API. #设置API版本
root@k8s-etcd-1:~# ETCDCTL_API=3 etcdctl member --help
NAME:
    member - Membership related commands

USAGE:
    etcdctl member <subcommand> [flags]

API VERSION:
    3.4

COMMANDS:
    add Adds a member into the cluster
    list    Lists all members in the cluster
    promote Promotes a non-voting member in the cluster
    remove  Removes a member from the cluster
    update  Updates a member in the cluster

OPTIONS:
  -h, --help[=false]    help for member

GLOBAL OPTIONS:
      --cacert=""             verify certificates of TLS-enabled secure servers using this CA bundle
      --cert=""                   identify secure client using this TLS certificate file
      --command-timeout=5s          timeout for short running command (excluding dial timeout)
      --debug[=false]               enable client-side debug logging
      --dial-timeout=2s             dial timeout for client connections
  -d, --discovery-srv=""          domain name to query for SRV records describing cluster endpoints
      --discovery-srv-name=""         service name to query when using DNS discovery
      --endpoints=[127.0.0.1:2379]      gRPC endpoints
      --hex[=false]             print byte strings as hex encoded strings
      --insecure-discovery[=true]       accept insecure SRV records describing cluster endpoints
      --insecure-skip-tls-verify[=false]    skip server certificate verification
      --insecure-transport[=true]       disable transport security for client connections
      --keepalive-time=2s           keepalive time for client connections
      --keepalive-timeout=6s            keepalive timeout for client connections
      --key=""                    identify secure client using this TLS key file
      --password=""               password for authentication (if this option is used, --user option shouldn't include password)
      --user=""                   username[:password] for authentication (prompt if password is not supplied)
  -w, --write-out="simple"            set the output format (fields, json, protobuf, simple, table)
root@k8s-etcd-1:~# ETCDCTL_API=3 /usr/bin/etcdctl member list --endpoints=https://192.168.26.165:2379   --cacert=/etc/kubernetes/ssl/ca.pem   --cert=/etc/etcd/ssl/etcd.pem   --key=/etc/etcd/ssl/etcd-key.pem  
23aa83f2c44ef89b, started, etcd2, https://192.168.26.175:2380, https://192.168.26.175:2379, false
31b52124cdcd310a, started, etcd3, https://192.168.26.185:2380, https://192.168.26.185:2379, false
f2e0a61b10c52d89, started, etcd1, https://192.168.26.165:2380, https://192.168.26.165:2379, false

验证当前 etcd 所有成员状态

root@k8s-etcd-1:~# export NODE_IPS="192.168.26.165 192.168.26.175 192.168.26.185"
root@k8s-etcd-1:~# echo $NODE_IPS
192.168.26.165 192.168.26.175 192.168.26.185
root@k8s-etcd-1:~# for ip in ${NODE_IPS} ; do ETCDCTL_API=3 /usr/bin/etcdctl   --endpoints=https://${ip}:2379   --cacert=/etc/kubernetes/ssl/ca.pem   --cert=/etc/etcd/ssl/etcd.pem   --key=/etc/etcd/ssl/etcd-key.pem   endpoint health ; done
https://192.168.26.165:2379 is healthy: successfully committed proposal: took = 7.076204ms
https://192.168.26.175:2379 is healthy: successfully committed proposal: took = 7.687458ms
https://192.168.26.185:2379 is healthy: successfully committed proposal: took = 8.340643ms

查看 etcd 数据信息

root@k8s-etcd-1:~# ETCDCTL_API=3 etcdctl get / --prefix --keys-only #以路径的方式所有 key 信息
/registry/apiregistration.k8s.io/apiservices/v1.

/registry/apiregistration.k8s.io/apiservices/v1.admissionregistration.k8s.io

/registry/apiregistration.k8s.io/apiservices/v1.apiextensions.k8s.io

/registry/apiregistration.k8s.io/apiservices/v1.apps

/registry/apiregistration.k8s.io/apiservices/v1.authentication.k8s.io

/registry/apiregistration.k8s.io/apiservices/v1.authorization.k8s.io

/registry/apiregistration.k8s.io/apiservices/v1.autoscaling
root@k8s-etcd-1:~# ETCDCTL_API=3 etcdctl get  /registry/services/specs/kube-system/kube-dns
/registry/services/specs/kube-system/kube-dns
k8s

v1Service 
                                                                                                                                 kube-dns 
       kube-system"*$329c60f2-8084-491e-a33d-c34cf60b441b2񭲐Z 
k8s-apkube-dnsZ%
kubernetes.io/cluster-servicetrueZ 
kubernetes.io/nameCoreDNSb 
0kubectl.kubernetes.io/last-applied-configuration₻"apiVersion":"v1","kind":"Service","metadata":{"annotations":{"prometheus.io/port":"9153","prometheus.io/scrape":"true"},"labels":{"k8s-app":"kube-dns","kubernetes.io/cluster-service":"true","kubernetes.io/name":"CoreDNS"},"name":"kube-dns","namespace":"kube-system"},"spec":{"clusterIP":"172.20.0.2","ports":[{"name":"dns","port":53,"protocol":"UDP"},{"name":"dns-tcp","port":53,"protocol":"TCP"},{"name":"metrics","port":9153,"protocol":"TCP"}],"selector":{"k8s-app":"kube-dns"}}}
b 
# ETCDCTL_API=3 etcdctl get --prefix /calico #查看etcd中calico的相关数据

etcd 增删改查数据

#添加数据
root@k8s-etcd-1:~# ETCDCTL_API=3 /usr/bin/etcdctl put /testkey "test for bokebi"
OK

#查询数据
root@k8s-etcd-1:~# ETCDCTL_API=3 /usr/bin/etcdctl get /testkey 
/testkey
test for bokebi

#改动数据
root@k8s-etcd-1:~# ETCDCTL_API=3 /usr/bin/etcdctl put /testkey "test for 123456" #直接覆盖就是更新数据
OK

#验证修改数据
root@k8s-etcd-1:~# ETCDCTL_API=3 /usr/bin/etcdctl get /testkey 
/testkey
test for 123456

#删除数据
root@k8s-etcd-1:~# ETCDCTL_API=3 /usr/bin/etcdctl del /testkey 
1

#验证删除数据
root@k8s-etcd-1:~# ETCDCTL_API=3 /usr/bin/etcdctl get /testkey 

etcd 数据 watch 机制

  • 基于不断监看数据,发生变化就主动触发通知客户端,Etcd v3 的 watch 机制支持 watch 某个固定的 key,也支持 watch 一个范围。

  • 相比 Etcd v2, Etcd v3 的一些主要变化:

    • 接口通过 grpc 提供 rpc 接口,放弃了 v2 的 http 接口,优势是长连接效率提升明显,缺点是使用不如以前方便,尤其对不方便维护长连接的场景。
    • 废弃了原来的目录结构,变成了纯粹的 kv,用户可以通过前缀匹配模式模拟目录。
    • 内存中不再保存 value,同样的内存可以支持存储更多的 key。
    • watch 机制更稳定,基本上可以通过 watch 机制实现数据的完全同步。
    • 提供了批量操作以及事务机制,用户可以通过批量事务请求来实现 Etcd v2 的 CAS 机制(批量事务支持if条件判断)。
  • watch测试:

#在 k8s-etcd-1 上 watch 一个 key,没有此 key 也可以执行 watch,后期可以再创建。
root@k8s-etcd-1:~# ETCDCTL_API=3 /usr/bin/etcdctl watch /testkey

#在 k8s-etcd-2 修改数据,验证 k8s-etcd-1 是否能够发现数据变化。
root@k8s-etcd-2:~# ETCDCTL_API=3 /usr/bin/etcdctl put /testkey "test for bokebi"
OK

#在 k8s-etcd-1 上发生的变化
root@k8s-etcd-1:~# ETCDCTL_API=3 /usr/bin/etcdctl watch /testkey
PUT
/testkey
test for bokebi

etcd 数据备份与恢复机制

  • WAL 是 write ahead log 的缩写,顾名思义,也就是在执行真正的写操作之前先写一个日志。
  • wal: 存放预写式日志,最大的作用是记录了整个数据变化的全部历程。在 etcd 中,所有数据的修改在提交前,都要先写入到 WAL 中。

etcd v2 版本数据备份与恢复

  • v2 版本帮助信息
root@k8s-etcd-1:~# ETCDCTL_API=2 etcdctl backup --help
NAME:
   etcdctl backup - backup an etcd directory

USAGE:
   etcdctl backup [command options]  

OPTIONS:
   --data-dir value        Path to the etcd data dir #当前 etcd 源数据目录,默认路径为 /var/lib/etcd
   --wal-dir value         Path to the etcd wal dir
   --backup-dir value      Path to the backup dir
   --backup-wal-dir value  Path to the backup wal dir #备份目录
   --with-v3               Backup v3 backend data
  • v2 版本备份数据
root@k8s-etcd-1:~# ETCDCTL_API=2 etcdctl backup --data-dir /var/lib/etcd/ --backup-dir /opt/etcd_backup #这个目录必须是不存在的目录。否则会报错
2019-07-11 18:59:57.674432 I | wal: segmented wal file
/opt/etcd_backup/member/wal/0000000000000001-0000000000017183.wal is created

root@k8s-etcd-1:/opt/etcd_backup# tree #查看备份目录的数据结构
.
└── member
    ├── snap
    │   ├── 00000000000082fc-00000000000493e4.snap
    │   └── db
    └── wal #存放预写式日志
        └── 0000000000000000-0000000000000000.wal
  • v2 版本恢复帮助信息
root@k8s-etcd-1:~# etcd --help | grep force
        --force-new-cluster 'false' #强制在集群中创建新的节点
                force to create a new one-member cluster.
root@k8s-etcd-1:~# etcd --data-dir=/var/lib/etcd/default.etcd --force-new-cluster &
  • 启动文件
root@k8s-etcd-1:~# vim /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=etcd2 \

...省略...

--data-dir=/opt/etcd_backup #存储数据的备份目录 -force-new-cluster #强制设置为为新集群
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target

etcd v3 版本数据备份与恢复

  • 在没有备份的情况下,新增节点须在启动文件添加参数, --datadir=/ opt/etcd-testdir 而且将 IP 地址设置为和之前的节点 IP 相同
V3版本备份数据:
root@k8s-etcd-1:~# ETCDCTL_API=3 etcdctl snapshot save snapshot.db
Snapshot saved at snapshot.db

V3版本恢复数据:
root@k8s-etcd-1:~# ETCDCTL_API=3 etcdctl snapshot restore snapshot.db --datadir=/
opt/etcd-testdir #将数据恢复到一个新的不存在的目录中
2019-07-11 18:57:46.526757 I | mvcc: restore compact to 74541
2019-07-11 18:57:46.536114 I | etcdserver/membership: added member 8e9e05c52164694d
[http://localhost:2380] to cluster cdf818194e3a8c32

#自动备份数据
root@k8s-etcd-1:~# mkdir /data/etcd-backup-dir/ -p
root@k8s-etcd-1:~# cat script.sh
#!/bin/bash
source /etc/profile
DATE=`date +%Y- %m-%d_%H-%M-%S`
ETCDCTL_API=3 /usr/bin/etcdctl snapshot save /data/etcd-backup-dir/etcdsnapshot-${
DATE}.db
点赞

发表回复

电子邮件地址不会被公开。必填项已用 * 标注