HAOJX

kuberntes开发教程系列(1):认识kuberntes API

字数统计: 2.4k阅读时长: 9 min
2019/09/06 Share

kuberntes主节点控制平面由:API Server , controller manager和scheduler组成

kuberntes的核心是他的api服务器,但是api服务器是如何工作的呢,下面我们就仔细研究下他的HTTP接口

API服务器的HTTP接口

从客户机的角度来看, 由于性能原因, 用JSON 或者protocol buffer协议来暴露其RESTful HTTP API

API服务器的HTTP接口再处理请求的时候,使用HTTP verbs(或者说是http方法)来查询和操作kuberntes资源

  • 使用HTTP GET 来检索具有特定资源类型或者资源集合或者资源列表 比如pod
  • 使用HTTP POST 动词来更新现有资源,比如更改pod的容器镜像
  • 使用HTTP PATCH 来对现有资源进行部分更新, 使用的参考, 参见kuberntes官网的文档 Use a JSON merge patch to update a Deployment
  • 使用HTTP DELETE来删除资源

在实际使用中我们用kubectl来操作我们想要的资源, 用kubectl来充当http的发起者, 然后使用相关HTTP verbs来做相应的请求, 这是官网的kubectl操作手册kuberntes-api-v1.14 , 可以看到日常我们使用的kubectl get , kubectl patch 等等

API相关概念

先让我们认识下kuberntes API的相关概念术语

Kind

每一个object都有一个kind字段, 在JSON中是用小写kind表示 , 在golang中是用大写Kind表示 , 以pod做例子, 对于pod这种类型的kind, 有三种类别

  • 表示系统中持久化的实体(a persistent entity in the system) , 比如Pod 或者Endpoints, 他们是存在于多个namespaces当中
  • 第二种就是: Lists 它表示一种或者多种kind的集合 , 比如PodLists 或者NodeLists , 当你使用kubectl get pods 就能得到他们
  • 第三种就是拥有特种用途的类型 , 他们用于特定操作和非持久化实体 , 比如/binding 或者/scale , 这2个子http path就是用于特定资源的特定操作的, scale就是扩缩容 , 还有比如对于kuberntes的服务发现来说 使用apigroup和apiresource 对于错误结果, 用status来表示

在kuberntes当中 , 一个gloang type对应一个kind类型 ,所以对于golang来说 , kind是用单数表示而且首字母大写

API group

API group就是 kinds的集合, 是一种类型的集合 比如在kuberntes当中 , Job和ScheduledJob这样的批处理对象就是同属于一个 API group: batch , 他们同属于离线业务

version

每个API group可以同时存在与多个versions当中 , 比如v1beta1 , v1alpha1 , v1中

Resource

通常来说, 一个小写的复数词 ,比如pods , 他标识一组HTTP端口 , 或者说是标识一组HTTP path , 他表示系统中某种对象类型的CRUD语义 ,比如

  • …../pods , 他表示列出了该类型的所以实例,这种情况下它返回一个podLists
  • ……/pods/nginxs 他表示列出了列表中某个具体 的 , 他返回一个pod

除了可以实现CRUD, 资源还可以有进一步的端点来执行特定操作 , 比如…/pod/nginx/port-forward, …/pod/nginx/exec, or …/pod/nginx/logs

resource和kind经常可能弄混,他们的区别是什么呢

  • resource对应HTTP路径
  • kind是这些端点返回和接受的对象类型,以及持久化到etcd里的对象类型

resource是API group和version的一部分, 统称为GroupVersionResource (or GVR) , GVR唯一的定义了一个HTTP路径, 例如 默认名称空间的路径是/apis/batch/v1/namespaces/default/jobs.

prku_0203.png

每个kind都存在于一个api group和version中 , 并通过GroupVersionKind (GVK) 来标识

GVR和GVK是相关联的 , GVK通过GVR标识的HTTP路径来提供服务, 将GVK映射到GVR的过程就叫做REST mapping.

Kubernetes API Versioning

kuberntes可以在不同API路径上支持多个API版本 , 不同的API版本意味着不同的稳定性和支持

  • Alpha level (e.g., v1alpha1) , 通常来说是禁用的, 它是用来测试的, 可以在下次版本更迭的时候不经过通知就删除
  • Beta level (e.g., v2beta3) , 默认是启用的 , 意味着经过了良好的测试, 然而的beta或稳定版中,语义可能发生变化
  • Stable 意味着GA, 比如v1 它将会出现在后续版本中

在kuberntes HTTP API空间中 我们也区分核心组和非核心组 , 核心组是指/api/v1以下的所以内容 , 非核心组指的就是/apis/$NAME/$VERSION的内容了 , 由于历史的原因核心组并不像规定的那样位于/apis/core/v1下面 , 那是因为在API组这个概念引入之前,核心组就已经存在了

当然还有第三中的HTTP路径 , 即不与资源对齐的路径 , 比如/metrics, /logs, or /healthz , 他们是有特殊功用的一些路径

如何使用命令行来使用API

1
$ kubectl proxy --port=8080

这个命令可以让kuberntes代理到我们本地计算机, 允许我们通过直接向HTTP发请求, 返回一个JSON

比如

1
$ curl http://127.0.0.1:8080/apis/batch/v1

当然在最近版的版的kubectl上 可以用kubectl来代替curl

1
kubectl get --raw /apis/batch/v1

你可以使用命令来看api-resource

1
$ kubectl api-resourcesNAME

API如何处理请求

如图

服务器请求处理流程

服务器处理请求流程

DefaultBuildHandlerChain()到底发生了什么呢, 让我们看下源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//源代码位置:kuberntes/apiserver/pkg/server/config.go

func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler {
handler := genericapifilters.WithAuthorization(apiHandler, c.Authorization.Authorizer, c.Serializer)
handler = genericfilters.WithMaxInFlightLimit(handler, c.MaxRequestsInFlight, c.MaxMutatingRequestsInFlight, c.LongRunningFunc)
handler = genericapifilters.WithImpersonation(handler, c.Authorization.Authorizer, c.Serializer)
handler = genericapifilters.WithAudit(handler, c.AuditBackend, c.AuditPolicyChecker, c.LongRunningFunc)
failedHandler := genericapifilters.Unauthorized(c.Serializer, c.Authentication.SupportsBasicAuth)
failedHandler = genericapifilters.WithFailedAuthenticationAudit(failedHandler, c.AuditBackend, c.AuditPolicyChecker)
handler = genericapifilters.WithAuthentication(handler, c.Authentication.Authenticator, failedHandler, c.Authentication.APIAudiences)
handler = genericfilters.WithCORS(handler, c.CorsAllowedOriginList, nil, nil, nil, "true")
handler = genericfilters.WithTimeoutForNonLongRunningRequests(handler, c.LongRunningFunc, c.RequestTimeout)
handler = genericfilters.WithWaitGroup(handler, c.LongRunningFunc, c.HandlerChainWaitGroup)
handler = genericapifilters.WithRequestInfo(handler, c.RequestInfoResolver)
handler = genericfilters.WithPanicRecovery(handler)
return handler
}

先来看第一个:

  • WithPanicRecovery() Takes care of recovery and log panics 位于server/filters/wrap.go

  • WithRequestInfo()

    将RequestInfo附加在上下文 定义在endpoints/filters/requestinfo.go

  • WithWaitGroup()

    将所以非长时间的请求添加到等待组, 用于优雅的关闭 ,定义在server/filters/waitgroup.go

  • WithTimeoutForNonLongRunningRequests()

    超时非长时间运行的请求(如大多数 GET、 PUT、 POST 和 DELETE 请求) ,与长时间运行的请求(如 watches 和 proxy 请求)形成对比 定义在server/filters/timeout.go

  • WithCORS()

    提供了一个 CORS 实现。 是跨区域资源共享的缩写,是一种允许 JavaScript 嵌入到 HTML 页面中,使 XMLHttpRequests 成为一个不同于 JavaScript 起源的域的机制 , 定义在server/filters/cors.go

  • WithAuthentication()

    尝试验证人或机器用户的身份,并将用户信息存储在提供的上下文中。 一旦成功,就会从请求中删除 Authorization HTTP 标头。 如果身份验证失败,则返回 HTTP 401状态代码 定义在endpoints/filters/authentication.go

  • WithAudit()

    用所有传入请求的审计日志信息处理程序。 审计日志条目包含诸如请求的源 IP、用户调用操作以及请求的命名空间等信息 定义在admission/audit.go

  • WithImpersonation()

    通过检查试图更改用户的请求(类似于 sudo)来处理用户的模拟 定义在endpoints/filters/impersonation.go

  • WithMaxInFlightLimit()

    限制in-flight请求的数量 定义在server/filters/maxinflight.go

  • WithAuthorization()

    通过调用授权模块检查权限,并将所有授权请求传递给多路复用器,多路复用器将请求分发给正确的处理程序。 如果用户没有足够的权限,则返回 HTTP 403状态代码。 现在的 Kubernetes 使用的是以角色为基础的准入控制器(RBAC) 定义在endpoints/filters/authorization.go

在处理完这些过滤器之后 , 实际的请求开始处理, 即到了上图中的第一个框(API HTTP handler)

  • 对于/, /version, /apis, /healthz和非RESTful APIs这些请求 , 立即开始处理

  • 对 RESTful 资源的请求进入请求管道,包括

    • admission

      传入的对象要通过一个admission chain , 这个chain上有20不同的admission plug-ins ,这些admission plug-ins可以是上图第三个框(Mutating admission)或者是第四个框(object schema vaildation)或者是二者兼具 .

      在mutating阶段 , 传入的请求可以被更改 , 通过admission configuration来更改 , 比如镜像拉去策略可以设置成Always, IfNotPresent Never

      在object schema validation阶段就是纯粹的验证了, 比如pod的字段有效性 ,或者创建namespace之前验证其存不存在

    • validation

      对传入的对象进行更大逻辑的验证 , 比如字符串检查 , 验证pod的容器名称 , 它存在与系统中的每个对象中

    • etcd-backed CRUD logic

      这里实现了“ The HTTP Interface of The API Server”中的不同动词; 例如,更新逻辑从 etcd 中读取对象,检查是否有其他用户在“ Optimistic Concurrency”意义上修改了对象,如果没有,则将请求对象写入 etcd

备注: admission chain里的20中plug-ins如下:

在kuberntes1.14中,他们的顺序是:AlwaysAdmit, NamespaceAutoProvision, NamespaceLifecycle, NamespaceExists, SecurityContextDeny, LimitPodHardAntiAffinityTopology, PodPreset, LimitRanger, ServiceAccount, NodeRestriction, TaintNodesByCondition, AlwaysPullImages, ImagePolicyWebhook, PodSecurityPolicy, PodNodeSelector, Priority, DefaultTolerationSeconds, PodTolerationRestriction, DenyEscalatingExec, DenyExecOnPrivileged, EventRateLimit, ExtendedResourceToleration, PersistentVolumeLabel, DefaultStorageClass, StorageObjectInUseProtection, OwnerReferencesPermissionEnforcement, PersistentVolumeClaimResize, MutatingAdmissionWebhook, ValidatingAdmissionWebhook, ResourceQuota, and AlwaysDeny

CATALOG
  1. 1. API服务器的HTTP接口
  2. 2. API相关概念
    1. 2.1. Kind
  3. 3. API group
  4. 4. version
  5. 5. Resource
  6. 6. Kubernetes API Versioning
  7. 7. 如何使用命令行来使用API
  8. 8. API如何处理请求