1. Kubernetes API Server 概述
1.1 基本概念
Kubernetes API Server(API Server)是 Kubernetes 的核心组件之一,负责暴露 Kubernetes API 给用户和客户端,接收和处理来自客户端的请求,并将其存储到 etcd 中。Kubernetes API Server 主要作用是提供 Kubernetes 各类资源对象(如 Pod、Deployment、Service等)的增、删、改、查及 Watch 等 HTTP REST 接口,是集群内各个功能模块直接数据交互和通信的中心枢纽,是整个系统的数据总线和数据中心。同时,它还是集群管理的 API 入口,提供了认证、授权、准入控制、资源配额等集群安全机制。
除了提供 RESTful API 之外,API Server 还可以通过 kubectl 命令行工具、客户端库和第三方工具与 Kubernetes 集群进行交互。同时,它也是整个 Kubernetes 集群的中心化组件之一,对整个 Kubernetes 系统的运行状态、节点健康等信息进行监控和管理。
我们之前讲解的针对 Kubernetes 资源的各种操作,都是将请求先发给了 Kubernetes API Server,再由它帮我们处理。所以它的地位确实是很重要的。
Kubernetes API Server 通过一个名为 kube-apiserver 的进程提供服务,该进程运行在 Master 上。属于静态 pod。
[root@master mtuser]# kubectl get pod -A | grep kube-apiserver
kube-system kube-apiserver-master 1/1 Running 1 22d
在默认情况下, kube-apiserver 进程在本机的 8080 端口(对应参数 --insecure-port
)提供 REST 服务。我们可以同时启动 HTTPS 安全端口(--secure-port=6443
)来启动安全机制,加强 REST API 访问的安全性。
这里我们要简单说一下,Kubernetes API Server 本身也是一个 Service,它的名称是 kubernetes,并且它的 ClusterIP 地址是 ClusterIP 地址池里的第一个地址,另外,它的端口是 HTTPS 端口 443,可以查看:
[root@master mtuser]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 25d
1.2 小实验
我们简单测试下 Kubernetes API Server 提供的接口,我们可以使用 curl 命令行:
登录 Master 并运行下面的 curl 令,得到 JSON 方式返回的 Kubernetes API的版本信息
[root@master mtuser]# curl localhost:8080/api
{"kind": "APIVersions","versions": ["v1"],"serverAddressByClientCIDRs": [{"clientCIDR": "0.0.0.0/0","serverAddress": "192.168.18.129:6443"}]
}
运行下面的 curl 命令,分别返回集群中的 Pod 列表、Service 列表、RC 列表:
curl localhost:8080/api/v1/pods
curl localhost:8080/api/v1/services
curl localhost:8080/api/v1/replicationcontrollers
2. etcd 简介
etcd 是一个开源的分布式键值存储系统,主要用于存储分布式系统中的关键数据。它由 CoreOS 团队开发,并使用 Go 语言编写,基于 Raft 协议实现了数据的分布式复制和一致性保证。etcd 能够在分布式环境中实现数据的高可用和可靠性,广泛用于容器编排系统(如 Kubernetes)、分布式锁、配置管理等领域。
Kubernetes 将 etcd 作为集群的数据库用于存储集群状态信息、配置信息等。
etcd 的数据模型类似于一个简单的键值数据库(key-value),其中的每个键都关联着一个对应的值。etcd 还支持监视(watch)机制,即客户端可以注册对指定键值的监视,一旦该键值发生变化,etcd 就会立即通知相应的客户端。这使得 etcd 能够作为分布式系统中的重要协调工具,例如在 Kubernetes 集群中用于存储集群状态信息、配置信息等。
3. API Server 架构解析
API Server 架构从上到下可以分为以下几层,如图:
- API 层:主要是 REST 方式提供各种 API 接口,除了有 Kubernetes 资源对象的 CRUD (创建、读取、更新、删除)和 watch 等主要 API,还有健康检查、UI、日志、性能指标等运维监控相关的 API。Kubernetes 从 1.11 版本开始废弃 Heapster 监控组件,转而使用 Metrics Server 提供 Metrics 的 API 接口,进一步完善自身的监控能力
- 访问控制层:当客户端访问 API 接口时,访问控制层负责对用户身份鉴权、验明用户身份,核准用户对 Kubernetes 资源对象的访问控制权限,然后根据配置的各种资源访问许可逻辑(Admission Control),判断是否允许访问
- 注册表层:Kubernetes 把所有资源对象都保存在注册表中(Registry)中,针对注册表中各种资源对象都定义了资源对象的类型、如何创建资源对象、如何转换资源对象不同的版本,以及如何将资源编码和解码为 JSON 和 ProtoBuf 格式存储
- etcd 数据库:用于持久化存储 Kubernetes 资源对象的 KV 数据库。etcd 的 watch API 接口对于 API Server 来说至关重要,因为通过这个接口,API Server 创新性的设计了 List-Watch 这种高性能的资源对象实时同步机制,使 Kubernetes 可以管理超大规模的集群、及时响应和快速处理集群中的各种事件。
4. API Server 的 List-Watch 机制
Kubernetes API Server 使用了一种 List-Watch 机制来实现资源对象的监控和更新。该机制可以用来实现对 Kubernetes 资源对象的实时监控,从而支持实时状态查询和事件响应。
在 Kubernetes 中,每一个 API Server 实例都维护着一个 etcd 集群的连接,通过该连接可以与 etcd 存储中心进行数据交互。当一个客户端向 API Server 发送一个资源对象的请求时,API Server 会首先查询 etcd 存储中心,以获取当前资源对象的状态。如果客户端需要实时监控资源对象的状态,则 API Server 将会启用 List-Watch 机制,将监控请求注册到 etcd 存储中心中,并返回一个带有当前资源对象状态的响应。随着 etcd 存储中心中的资源对象状态发生变化,API Server 将会自动通知客户端,客户端可以通过 Watch 事件机制获取这些状态变化的通知。
我们以一个 Pod 完整的调度过程,来说明一下 API Server 的 List-Watch 机制。
首先,借助 etcd 提供的 Watch API 接口,API Server 可以监听(Watch) 在 etcd 上发生的数据操作事件,比如 Pod 创建事件、更新事件、删除事件等,在这发生之后,etcd 会及时通知 API Server。上图中 API Server 和 etcd 之间的交互箭头表名了这个过程:当一个 ReplicaSet 对象被创建并保存到 etcd 中后(图中 2. 创建 ReplicaSet 箭头),etcd 会立即发送一个对应的 Create 事件给 API Server (图中 3.发送创建 ReplicaSet 事件箭头),与其类似的 (6、7、10、11) 箭头都是针对 Pod 的创建、更新事件。
然后,为了让 Kubernetes 中的其它组件在不访问 etcd 数据库的情况下,也能及时获取资源的变化事件,API Server 模仿 etcd 的 Watch 接口提供自己的 Watch 接口,这样一来,这些组件就能近乎实时的获取自己感兴趣的任意资源对象的相关事件通知了。上图中 controller-manager、scheduler、kubelet 等组件与 API Server 之间的 3 个标记为 “List-Watch” 的虚线框表明了这个过程。同时,在监听自己感兴趣的资源时,客户端可以增加过滤条件,以 List-Watch 为例,node1 节点上的 kubelet 进程只对自己节点上的 Pod 事件感兴趣。
最后,Kubernetes List-Watch 用于实现数据同步的代码逻辑。客户端首先调用 API Server 的 List 接口获取资源对象的全量数据并将其缓存到内存中,然后启动对应资源对象的 Watch 协程,在接收到 Watch 事件后,再根据事件类型(比如新增、修改或删除)对内存中的全量资源对象列表做出相应的同步修改。从实现来看,这是一种全量结合增量的、高性能的、近乎实时的数据同步方式。
在资源对象的增删改查操作中,最复杂的应该是"改"更新操作,因为关键资源对象都是有状态的对象,例如 Pod、Deployment 等。很多时候,只需要修改已有的某个资源对象的某些属性,并保持其属性不变,对于这样的特殊又实用的更新操作,用户无需提供完整资源对象 yam 文件,只需将修改属性写入 YAML 文件中提交就可以。
5. 独特的 Kubernetes Proxy API 接口
Kubernetes API Server 最主要的 REST 接口是资源对象的增、删、改、查,另外还有一类特殊的 REST 接口——k8s Proxy API 接口,这类接口的作用是代理 REST 请求,即 Kubernetes API Server 把收到的 REST 请求转发到某个 Node 上的 kubelet 守护进程的 REST 端口上,由该 kubelet 进程负责响应。
5.1 Kubernetes Proxy API 关于Node 的相关接口
关于 Node 相关的接口的 REST 路径为:/api/v1/proxy/nodes/{name}
,其中 {name} 为节点的名称或 IP 地址。
包括以下几个具体的接口:
/api/v1/proxy/nodes/{name}/pods/ #列出指定节点内所有Pod的信息
/api/v1/proxy/nodes/{name}/stats/ #列出指定节点内物理资源的统计信息
/api/v1/prxoy/nodes/{name}/spec/ #列出指定节点的概要信息
例如,当前 Node 的名称为 node1,用以下命令即可获取在该节点上运行的所有 Pod :
curl localhost:8080/api/v1/nodes/node1/proxy/pods
需要说明的是:这里获取的 Pod 信息来自 Node 而非 etcd,两者时间点可能存在偏差。