程序印象

Kubernets深入系列: API Server - part 1(译)

2018/04/05 Share

作者:STEFAN SCHIMANSKI AND MICHAEL HAUSENBLAS APRIL 28, 2017

翻译:狄卫华

原文:Kubernetes deep dive: API Server – part 1

原文链接:https://blog.openshift.com/kubernetes-deep-dive-api-server-part-1/


本系列翻译链接:


欢迎来到 Kubernetes 深入文章系列。 我们即 Stefan Schimanski (Engineering) 和 Michael Hausenblas (Advocacy) 将深入研究 Kubernetes 的特定方面以及它们在 OpenShift 中的使用方式。 如果您对 Kubernetes 的内部工作机制以及如何调试感兴趣,这篇博客文章系列适合您。 另外,如果您想扩展 Kubernetes 或开始贡献项目,您可能会从中受益。 熟悉 Go 是一个优势,但不是一个必须的要求。

在本文中,我们从 Kubernetes API 服务器的一般性介绍开始,提供一些术语并解释 API 请求流程。 后续的帖子将涵盖 API Server 的存储相关主题和可扩展性点。

API Server 介绍

在概念层面上,Kubernetes 由一群具有不同角色的节点组成。 主节点上的控制平面由 API Server,Controller Manager 和 Scheduler 组成。 API Server 是中央管理组件,是唯一直接与分布式存储通信的组件。 它提供了以下核心功能:

  • 服务 Kubernetes API,由工作节点(worker nodes)在群集内部使用,以及由 kubectl 在外部使用
  • 代理集群组件,如 Kubernetes UI
  • 允许操纵对象的状态,例如 Pods 和 Services
  • 在分布式存储(etcd)中保存对象的状态

img

Kubernetes API 是以 JSON 作为其主要序列化模式的 HTTP API,也支持 Protocol Buffers,Protocol Buffers 方式主要用于集群内部通信。出于可扩展性的考虑,Kubernetes 支持不同 API 路径的多个 API 版本,例如 /api/v1apis/extensions/v1beta1。不同的API版本意味着不同级别的稳定性和支持:

  • Alpha 级别,例如 v1alpha1 在默认情况下处于禁用状态,对功能的支持可能会随时废弃,而不再通知,应仅用于短期测试群集;
  • Beta 级别(例如 v2beta3)在默认情况下处于启用状态,意味着代码已经过很好的测试,但对象的语义可能会在后续测试版或稳定版中以不兼容的方式发生变化;
  • 稳定的级别,例如 v1 会出现在许多后续版本的发布软件中;

现在我们来看看 HTTP API 空间是如何构建的。在顶层我们区分核心组(core group)(由于历史原因, /api/v1 并没有位于路径 /apis/core/v1下面)和系统范围的实体(如/metrics)。

HTTP API 空间下(基于 v1.5)的部分结构如下所示:

img

接下来我们将专注于一个具体的例子:批量操作。 在 Kubernetes 1.5 中,存在两种版本的批处理操作:/apis/batch/v1/apis/batch/v2alpha1,公开可以查询和操作的不同实体集合。

现在我们将注意力转向与 API 交互示例(我们正在使用 Minishift 和代理命令 oc proxy --port=8080此处直接访问API):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ curl http://127.0.0.1:8080/apis/batch/v1
{
"kind": "APIResourceList",
"apiVersion": "v1",
"groupVersion": "batch/v1",
"resources": [
{
"name": "jobs",
"namespaced": true,
"kind": "Job"
},
{
"name": "jobs/status",
"namespaced": true,
"kind": "Job"
}
]
}

此外使用新的 alpha 版本:

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
$ curl http://127.0.0.1:8080/apis/batch/v2alpha1
{
"kind": "APIResourceList",
"apiVersion": "v1",
"groupVersion": "batch/v2alpha1",
"resources": [
{
"name": "cronjobs",
"namespaced": true,
"kind": "CronJob"
},
{
"name": "cronjobs/status",
"namespaced": true,
"kind": "CronJob"
},
{
"name": "jobs",
"namespaced": true,
"kind": "Job"
},
{
"name": "jobs/status",
"namespaced": true,
"kind": "Job"
},
{
"name": "scheduledjobs",
"namespaced": true,
"kind": "ScheduledJob"
},
{
"name": "scheduledjobs/status",
"namespaced": true,
"kind": "ScheduledJob"
}
]
}

通常,Kubernetes API 支持通过标准 HTTP POSTPUTDELETEGET 操作,以 JSON 作为默认有效载荷,在给定路径上创建,更新,删除和检索操作。

大多数 API 对象在当前对象的期望状态的规范和对象的状态之间进行区分。 规范是对所需状态的完整描述,并保存到稳定的存储。

术语

在简要介绍了 API Server 和 HTTP API 空间及其属性之后,我们现在更正式地定义在此上下文中使用的术语。 像 Pods,Services,Endpoints,Deployment 等基元构成了 Kubernetes 整体的对象体系。 我们使用以下术语:

Kind 是一个实体的类型。 每个对象都有一个字段 Kind,用于告诉客户端 - 例如 kubectl 或 oc - 它代表的是一个pod 类型:

1
2
3
4
5
6
7
8
9
10
apiVersion: v1
kind: Pod
metadata:
name: webserver
spec:
containers:
- name: nginx
image: nginx:1.9
ports:
- containerPort: 80

有三类种类 Kind

  1. 对象表示系统中的持久实体。 一个对象可能有多个客户端可用来执行特定操作的资源。 例如:PodNamespace
  2. 列表是一种或多种实体资源的集合。 列表具有一组有限的通用元数据。 例如:PodListsNodeLists
  3. 特殊用途类型用于对象和非持久实体(如 /binding/status)的特定操作,发现使用 APIGroupAPIResource,错误结果Status等。

API Group 是逻辑上相关的 Kinds的集合。 例如所有批处理对象(如 JobScheduledJob )都位于 batch API 组中。

Version 每个 API Group 可以存在多个版本。 例如一个组首先显示为 v1alpha1,然后提升为 v1beta1,最后稳定为 v1。 在一个版本(例如 v1beta1)中创建的对象可以在每个受支持版本(例如 v1)中检索。 API Server 进行无损转换以返回请求版本中的对象。

Resource 是通过 HTTP 发送或检索为 JSON 的系统实体的表示形式;可以作为单个资源(例如 .../namespaces/default)或资源集合(如 .../jobs )显示。

API Group, Version 和 Resource (GVR) 可以唯一定义在一个 HTTP 路径下:

img

更确切地说,Job 的实际路径是 /apis/batch/v1/namespaces/$NAMESPACE/job,因为 job 不是集群范围内的资源,与节点资源相反(节点资源属于集群范围内资源)。 为简洁起见,在文章中我们省略了$NAMESPACE段路径。

需要注意,Kinds 不仅可以存在于不同的版本中,还可以同时存在于不同的 API Group 中。 例如 Deployment 在扩展组中以 alpha 类型开始,最终在其自己的组 apps.k8s.io 中升级为 GA 版本。 因此要唯一标识 Kind,您需要 API Group,Version 和 Kind 名称(GVK)。

请求处理流程

回顾了 Kubernetes API 中使用的术语以后,我们继续讨论如何处理 API 请求。 API 位于 k8s.io/pkg/api 中,处理来自集群内外部客户端的请求。

那么,当HTTP请求到达 Kubernetes API 时,发生了什么? 在高层次上,交互如下:

  1. HTTP请求由在 DefaultBuildHandlerChain() 中注册的一系列过滤器 Filters 处理(参考 config.go),该过滤器对其应用操作(有关过滤器的更多详细信息,请参阅下文)。 过滤器传递并将相应的信息附加到ctx.RequestInfo,例如经过身份验证的用户或返回适当的 HTTP 响应代码;
  2. 接下来,多路复用器 Multiplexer( 参考 container.go )根据 HTTP 路径将请求路由到各自的处理程序;
  3. 路由(如route/*中定义的)将处理程序与 HTTP 路径相管理;
  4. 根据 API Group 注册的处理程序(参考 groupversion.goinstaller.go)接受 HTTP 请求和上下文(如用户,权限等)并从存储中提交请求的对象;

完整的流程看起来如下:

img

再次提醒,为了简洁起见我们省略了上图中 HTTP 路径的 $NAMESPACE 字段。

现在让我们仔细看看 config.go 中设置的 DefaultBuildHandlerChain() 的过滤器处理流程:

  • requestinfo.go 中定义的 WithRequestInfo()RequestInfo 附加到上下文;
  • maxinflight.go 中定义的 WithMaxInFlightLimit() 限制了正在进行的请求的数量;
  • timeout.go 中定义的 WithTimeoutForNonLongRunningRequests() 超出非长时间运行的请求,如大多数GETPUTPOSTDELETE 请求超时,与长时间运行的请求(如 watchporxy 请求);
  • wrap.go 中定义的 WithPanicRecovery() 包装了一个处理程序来恢复和记录 Panic;
  • cors.go 中定义的 WithCORS() 提供 CORS 实现; CORS 代表跨源资源共享,它是一种机制,它允许嵌入在 HTML 页面中的 JavaScript 将 XMLHttpRequest 发送到与源自 JavaScript 的域不同的域;
  • authentication.go 中定义的 WithAuthentication() 尝试以用户身份验证给定的请求,并将用户信息存储在提供的上下文中。成功时 Authorization HTTP 头将从请求中删除;
  • audit.go 中定义的 WithAudit() 使用所有传入请求的审计日志记录信息来修饰处理程序。审计日志条目包含信息,如请求的源IP,用户调用操作以及请求的命名空间等信息;
  • 通过检查尝试更改用户的请求(类似于sudo), impersonation.go 中定义的用户 WithImpersonation() 可处理用户模拟;
  • authorization.go 中定义的 WithAuthorization() 将所有授权请求传递给多路复用器,该多路复用器将请求分派给正确的处理程序,否则返回禁止的错误;

因此,我们总结了第一部分 API Server 的深入研究。下一次我们将仔细研究资源序列化的发生过程以及对象在分布式存储中的持久性。


除特别声明本站文章均属原创(翻译内容除外),如需要转载请事先联系,转载需要注明作者原文链接地址。


CATALOG
  1. 1. API Server 介绍
  2. 2. 术语
  3. 3. 请求处理流程