13 庖丁解牛:etcd
整体概览
+———————————————————-+ | Master | +————————-+ | +——-> | API Server | <——–+ | v +————————-+ v | +—————-+ ^ +——————–+ | Scheduler | Controller Manager | +—————-+ v +——————–+ | +——————————————————+ | Cluster state store | +——————————————————+ | +———————————————————-+ |
在第 3 节《宏观认识:整体架构》 中,我们也认识到了
etcd 的存在,知道了 Master 是 K8S 是集群的大脑,而
etcd 则是大脑的核心。为什么这么说?本节我们一同来看看
etcd 为何如此重要。
## etcd 是什么
先摘录官方文档的一句说明: etcd is a consistent distributed key-value store. Mainly used as a separate coordination service, in distributed systems. And designed to hold small amounts of data that can fit entirely in memory.
etcd 是由 CoreOS 团队发起的一个分布式,强一致的键值存储。它用 Go 语言编写,使用
Raft 协议作为一致性算法。多数情况下会用于分布式系统中的服务注册发现,或是用于存储系统的关键数据。
## etcd 有什么作用
etcd 在 K8S 中,最主要的作用便是其高可用,强一致的键值存储以及监听机制。
在
kube-apiserver 收到对应请求经过一系列的处理后,最终如果是集群所需要存储的数据,便会存储至
etcd 中。主部分主要是集群状态信息和元信息。
我们来实际操作 K8S 集群中的
etcd 看下真实情况。
- 查找集群中的
etcd Pod /# 默认集群中的 etcd 会放到 kube-system Namespace 中 master $ kubectl -n kube-system get pods | grep etcd etcd-master 1/1 Running 0 1h
- 进入该 Pod 并查看
etcd 集群的
member master $ kubectl -n kube-system exec -it etcd-master sh / /# ETCDCTL_API=3 etcdctl –key=/etc/kubernetes/pki/etcd/server.key –cert=/etc/kubernetes/pki/etcd/server.crt –cacert=/etc/kubernetes/pki/etcd/ca.crt member list a874c87fd42044f, started, master, https://127.0.0.1:2380, https://127.0.0.1:2379
这里由于在 K8S 1.11.3 中默认使用的是
etcd 3.2 版本,所以需要加入
ETCDCTL_API=3 的环境变量,且
etcd 从 2 到 3 很明显的一个变化也是使用上的变化,在 2 中是 HTTP 接口的。
我们通过传递证书等相关参数进去,完成校验,查看
member 。
- 查看存储的元信息
etcd 中存储的 K8S 集群元信息基本都是
/registry 下,我们可通过下面的方式进行查看 / /# ETCDCTL_API=3 etcdctl –key=/etc/kubernetes/pki/etcd/server.key –cert=/etc/kubernetes/pki/etcd/server.crt –cacert=/etc/kubernetes/pki/etcd/ca.crt get /registry –prefix –keys-only /registry/apiregistration.k8s.io/apiservices/v1. /registry/clusterroles/system:aggregate-to-admin /registry/configmaps/kube-public/cluster-info /registry/masterleases/172.17.0.53 /registry/namespaces/default /registry/namespaces/kube-public /registry/namespaces/kube-system /registry/pods/kube-system/etcd-master /registry/pods/kube-system/kube-apiserver-master /registry/ranges/serviceips /registry/ranges/servicenodeports … /# 篇幅原因,删掉了很多输出
可以看到有各种类型的资源。我们直接以 Namespaces 为例。
-
查看 Namespaces 信息 / /# ETCDCTL_API=3 etcdctl –key=/etc/kubernetes/pki/etcd/server.key –cert=/etc/kubernetes/pki/etcd/server.crt –cacert=/etc/kubernetes/pki/etcd/ca.crt get /registry/namespaces –prefix –keys-only /registry/namespaces/default /registry/namespaces/kube-public /registry/namespaces/kube-system
-
使用
kubectl 创建名为
moelove 的 Namespaces master $ kubectl create ns moelove namespace/moelove created
- 查看 Namespaces 信息 / /# ETCDCTL_API=3 etcdctl –key=/etc/kubernetes/pki/etcd/server.key –cert=/etc/kubernetes/pki/etcd/server.crt –cacert=/etc/kubernetes/pki/etcd/ca.crt get /registry/namespaces –prefix –keys-only /registry/namespaces/default /registry/namespaces/kube-public /registry/namespaces/kube-system /registry/namespaces/moelove
发现刚创建的
moelove 的 Namespaces 已经在
etcd 中了。
## etcd 是如何被使用的
首先,在
staging/src/k8s.io/apiserver/pkg/server/options/etcd.go 中,存在一处声明: var storageTypes = sets.NewString( storagebackend.StorageTypeUnset, storagebackend.StorageTypeETCD2, storagebackend.StorageTypeETCD3, )
在 1.13 发布时,etcd 2 的相关代码已经移除,其中就包含上面声明中的 storagebackend.StorageTypeETCD2
这里是在过渡期间为了同时兼容
etcd 2 和 3 而增加的。
我们来看下实际对各类资源的操作,还是以对
Namespace 的操作为例:代码在
pkg/registry/core/namespace/storage/storage.go 中,
比如,
Get : func (r /REST) Get(ctx context.Context, name string, options /metav1.GetOptions) (runtime.Object, error) { return r.store.Get(ctx, name, options) }
而
REST 则是这样定义的:
type REST struct { store /genericregistry.Store status /genericregistry.Store }
通过
REST 实现了一个
RESTStorage ,实际使用时,也是调用了
staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go 对接口的封装。
func (e /Store) Get(ctx context.Context, name string, options /metav1.GetOptions) (runtime.Object, error) { obj := e.NewFunc() key, err := e.KeyFunc(ctx, name) if err != nil { return nil, err } if err := e.Storage.Get(ctx, key, options.ResourceVersion, obj, false); err != nil { return nil, storeerr.InterpretGetError(err, e.qualifiedResourceFromContext(ctx), name) } if e.Decorator != nil { if err := e.Decorator(obj); err != nil { return nil, err } } return obj, nil }
在该处实现了对各类基本方法的封装,各种资源类型都会统一去调用。而更上层则是对
storagebackend 的统一封装,最终会调用
etcd 客户端的实现完成想对应的操作,这里就不再多展开了。
总结
在本节中,我们介绍了
etcd 以及它在 K8S 中的作用以及如何使用。我们还介绍了如何通过
etcdctl 工具去操作
etcd 。
在某些极端情况下,也许你需要通过直接操作
etcd 集群去变更数据,这里没有介绍所有的操作命令,感兴趣的可以自行通过下方的链接看官方文档进行学习。
但通常情况下,不建议直接操作
etcd ,除非你已经明确自己在做什么。
另外,由于
etcd 集群使用
Raft 一致性算法,通常情况下
etcd 集群需要部署奇数个节点,如 3,5,7 等。
etcd 集群维护也相对容易,很容易可以做成高可用集群。(这也是保障 K8S 集群高可用的重要一环)
学习了
etcd 之后,下节我们来学习同样很重要的一个组件
Controller Manager ,学习它是如何保障集群符合预期状态的。
参考链接
参考资料
https://learn.lianglianglee.com/%e4%b8%93%e6%a0%8f/Kubernetes%20%e4%bb%8e%e4%b8%8a%e6%89%8b%e5%88%b0%e5%ae%9e%e8%b7%b5/13%20%e5%ba%96%e4%b8%81%e8%a7%a3%e7%89%9b%ef%bc%9aetcd.md
更多学习
更多实时资讯,前沿技术,生活趣事。尽在【老马啸西风】
交流社群:[交流群信息](https://mp.weixin.qq.com/s/rkSvXxiiLGjl3S-ZOZCr0Q)