在之前的学习过程中,都是在Master节点上使用 kubectl 命令与相应的配置文件对集群资源进行操作。 实际上真正操作集群资源的是 Kubernetes API Server , kubeclt 工具也是通过该服务提供的接口对资源进行操作的。
什么是API Server
Kubernetes API Server 是运行在Master节点上的kube-apiserver进程提供的服务。 该服务是集群内各个功能模块之间数据交互和通信的中心枢纽,是整个系统的数据总线和数据中心。
由于API Server承担了系统内关键的数据通信部分,所以API Server的性能高低决定了集群性能的高低。
API Server架构与设计
API Server的架构从上到下可以分为四层
-
API层。提供针对资源CRUD的和监控的接口和健康检查、日志、性能指标等运维相关接口。
-
访问控制层。当客户端访问API的时候,负责对用户的权限做验证,根据配置的的各种资源访问权限判断是否可以访问。
-
注册表层。Kubernetes把所有资源对象都保存在注册表中,针对注册表中的各种资源对象定义了相关数据类型和创建、转换、编码的方法。
-
ETCD数据库层。用于持久化存储资源对象的。K8S使用etcd的watch API接口设计了
List-Watch高性能资源同步机制,使得系统可以管理大规模的集群和快速及时的处理集群中的各种事件。
List Watch机制
首先 kube-apiserver 借助etcd的watch API接口,可以监听到在etcd上发生的数据操作事件,例如Pod的创建、更新、删除等。
然后,为了不让除了 kube-apiserver 之外的组件同样访问到底层数据库, kube-apiserver 也实现了一套与etcd监听相似的接口提供给上层业务,使得其他业务可以不访问底层数据库就监听到数据的变化。
例如上图中虚线框 List-Watch 2 , kube-scheduler 组件通过监听即使获得了 kube-controller-manager 发起的创建Pod的事件,对新建Pod进行调度等操作。
最后,在数据同步上客户端先获取到了调用API Server的接口获取到全量数据,然后通过goroutine监听列表数据变化异步写入内存,实现高性能的数据同步。
API升级带来的数据转化问题
在通过godoc学习编写配置文件的时候,我们看到了实际上K8S在同一个类型的资源有很多版本,例如 app/v1 、 app/v1beta1 、 app/v1beta2 。
另外通过网上的一些博客文章也可以发现之前有些资源是在 v1beta 中的,而现在已经迁移到 v1 中了。
通过版本号可以解决接口版本兼容问题,但是还有一个版本之间数据转化的问题。比如数据对象经历了 v1beta1 、 v1beta2 ... v1betaN-1 最终变为 v1 版本。
此时该数据对象就存在N个版本,如果这N个版本之间的数据两两直接转换,就存在很多种逻辑组合,变成一种典型的网状网络。 另外每增加一个新的版本,就需要增加N份相应的转化配置。
于是API Server引入了一个中间版本(internal),所有的版本最终都会转为此版本进行使用,以此减少互相转化的成本。
如何调用Kubernetes API Server
在Master节点上该服务可以通过本地接口来访问,端口通过kube-apiserver启动参数 --insecure-port=8080 和 --secure-port=6443 进行配置。
进程的启动参数可以通过 ps -o cmd -C kube-apiserver 来查看。
不过在我使用 kubeadm 初始化集群的时候, kube-apiserver 实际上是以集群中Pod的形式启动的。
$ kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
...
kube-apiserver-ali 1/1 Running 0 39m
...
所以我可以通过修改 /etc/kubernetes/manifests/kube-apiserver.yaml 的Pod配置文件来修改端口。
具体的参数意义可以在官网查阅 kube-apiserver 。
在上述工作做好之后,通过 curl localhost:8080 便可以访问到API Server提供的服务
$ curl localhost:8080
{
"paths": [
"/api",
...
]
}
举个例子,例如要查看指定pod的状态,便可以通过如下方式进行调用
$ curl localhost:8080/api/v1/namespaces/default/pods/<pod-name>
{
"kind": "Pod",
"apiVersion": "v1",
"metadata": {
...
},
"spec": {
...
},
"status": {
...
}
}
除了curl以外,也可以通过k8s的api库来调用,例如 github.com/kubernetes/…
篇幅限制,就不贴他们的实例代码了,有兴趣的可以在这里看 github.com/kubernetes/…