深度剖析Kubernetes API Server三部曲 - part 3

在本系列的前两部分中我们介绍了API Server的总体流程,以及API对象如何存储到etcd中。在本文中我们将探讨如何扩展API资源。
在一开始的时候,扩展API资源的唯一方法是扩展相关API源代码,集成为你所需的资源。或者,推动一个全新的类型为新的核心对象API合入社区代码。但是,这样就会导致核心API资源类型的不断增加,直至API过载。为了避免这种API资源的无限制扩展,在Kubernetes中提供两种扩展核心API的方法:

  1. 使用自定义资源定义(CRDs),最开始的时候被称为第三方资源(TPRs)。通过CRD你能够简单而灵活的方式定义自己的资源对象类型,并让API server处理整个生命周期。
  2. 使用与主API Servers 并行运行的用户API Servers(UAS)。这种方式,可能更多的设计代码开发,可能需要你投入较多的时间及精力。当然,这种方式也能够让你对API资源有更细致,全面的了解。
    在本文中,我们主要对CRD相关定义以及使用进行探讨。
    CRDs的声明及创建
    在本系列文章第一部分所提到过的,每个API资源根据Group群组分类,每个对象都有一个对应的版本号与HTTP路径相关联。现在如果想要实现一个CRD,首先需要的是就是命名一个新的API Group群组,这个API群组不能与已经存在的群组重复。在你自己新建的API群组中,你可以拥有任意数量的资源,并且它们可以与其他群组中的资源具有相同的名称。下面我们来列举一个实际的例子:

    在之前我们有介绍过,每个版本的由API群组管理的Kubernetes资源是跟HTTP路径相关的。CRD类似于面向对象编程中一个类的定义,而实际使用的CR可以看做为它的一组实例。首先我们对例子中的一些字段作说明,第一行中的CRD apiVersion在kube-apiserver 1.7 之后都是这样定义的。从第5行之后我们定义了spec 的相关字段。在第6行spec.group是定义了你创建的CRD的API群组(在本例子中定义为了example.com)。第7行定义了CRD对象的版本。每个资源只有一个固定版本,但在API群组中还是能有多个不同版本的资源。第8行的spec.names有两个必填项:kind,按照惯例第一个字母大写,plural,按照惯例全为小写,这个字段与最终生成的HTTP路径相关,比如在本例子中,最终的HTTP路径为https://<server/apis/example.com/v1/namespaces/default/databases。还有一个可选的singular字段,默认为小写类型值,可以在kubectl的上下文中使用。此外,在spec.names中还有许多可选字段,这些字段将会由API Server自动生成并填充。
    上面的kind主要是用来描述对象的类型,而resource 资源是与HTTP路径相关的。大多数情况下这两个是匹配的;但是在某些特定情况下在相同的API HTTP路径下可能返回不通的kind(比如Status 错误对象会返回另一种kind)。
    值得注意的是resource 资源(在本例中是databases)和group群组(本例中是example.com)必须与metadata.name 字段匹配(本例为第四行databases. example.com)。
    现在我们根据上面的YAML文件来创建一个CRD:
    $ kubectl create -f databases-crd.yaml
    customresourcedefinition "databases.example.com" created
    由于这个创建过程是异步进行的,所以你必须检查一下你创建的CRD的状态,确认你创建的CRD没有与其它资源冲突,并且API Server已经调用相关处理函数完成创建。你可以在脚本或代码中通过轮询完成这个过程。最后我们能得到以下状态:
    $ kubectl get crd databases.example.com -o yaml
    apiVersion: apiextensions.k8s.io/v1beta1
    kind: CustomResourceDefinition
    metadata:
    creationTimestamp: 2017-08-09T09:21:43Z
    name: databases.example.com
    resourceVersion: "792"
    selfLink: /apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions/databases.example.com
    uid: 28c94a05-7ce4-11e7-888c-42010a9a0fd5
    spec:
    group: example.com
    names:
    kind: Database
    listKind: DatabaseList
    plural: databases
    singular: database
    scope: Namespaced
    version: v1
    status:
    acceptedNames:
    kind: Database
    listKind: DatabaseList
    plural: databases
    singular: database
    conditions:
    • lastTransitionTime: null
      message: no conflicts found
      reason: NoConflicts
      status: "True"
      type: NamesAccepted
    • lastTransitionTime: 2017-08-09T09:21:43Z
      message: the initial names have been accepted
      reason: InitialNamesAccepted
      status: "True"
      type: Established
      以上,我们可以看到通过kubectl可以看到我们之前创建的CRD,并且显示出了CRD的一些状态信息。
      CRDs的使用
      在通过kubectl proxy将Kubernetes API 开启本地代理后,查看我们刚才创建的CRD:
      $ http 127.0.0.1:8001/apis/example.com
      HTTP/1.1 200 OK
      Content-Length: 223
      Content-Type: application/json
      Date: Wed, 09 Aug 2017 09:25:44 GMT

{
"apiVersion": "v1",
"kind": "APIGroup",
"name": "example.com",
"preferredVersion": {
"groupVersion": "example.com/v1",
"version": "v1"
},
"serverAddressByClientCIDRs": null,
"versions": [
{
"groupVersion": "example.com/v1",
"version": "v1"
}
]
}
请注意,在默认情况下十分钟内,kubectl是查看存储在~/.kube/cache/discovery目录的缓存。所以,可能会需要10分钟后你才能看到你新创建的CRD资源。但是,当没有缓存时,kubectl发现不了所需的资源时,那么会重新缓存它。
接下来,我们来看一个CRD实例:
$ cat wordpress-database.yaml
apiVersion: example.com/v1
kind: Database
metadata:
name: wordpress
spec:
user: wp
password: secret
encoding: unicode

$ kubectl create -f wordpress-databases.yaml
database "wordpress" created

$ kubectl get databases.example.com
NAME KIND
wordpress Database.v1.example.com
想要通过API来监控资源的创建与更新,你可以通过对某个resourceVersion(我们通过curl来实例对指定版本的database做监控)之后的修改做监控watch。
$ http 127.0.0.1:8001/apis/example.com/v1/namespaces/default/databases
HTTP/1.1 200 OK
Content-Length: 593
Content-Type: application/json
Date: Wed, 09 Aug 2017 09:38:49 GMT

{
"apiVersion": "example.com/v1",
"items": [
{
"apiVersion": "example.com/v1",
"kind": "Database",
"metadata": {
"clusterName": "",
"creationTimestamp": "2017-08-09T09:38:30Z",
"deletionGracePeriodSeconds": null,
"deletionTimestamp": null,
"name": "wordpress",
"namespace": "default",
"resourceVersion": "2154",
"selfLink": "/apis/example.com/v1/namespaces/default/databases/wordpress",
"uid": "8101a7af-7ce6-11e7-888c-42010a9a0fd5"
},
"spec": {
"encoding": "unicode",
"password": "secret",
"user": "wp"
}
}
],
"kind": "DatabaseList",
"metadata": {
"resourceVersion": "2179",
"selfLink": "/apis/example.com/v1/namespaces/default/databases"
}
}
我们可以对/apis/example.com/v1/namespaces/default/databases/wordpressCRD的HTTP路径通过curl命令对的"resourceVersion": "2154"进行监控watch:
$ curl -f 127.0.0.1:8001/apis/example.com/v1/namespaces/default/databases?watch=true&resourceVersion=2154
现在我们新开一个shell对话窗口,删除wordpress CRD资源,我们可以查看刚才的监控watch窗口是否接收到了这个消息:
$ kubectl delete databases.example.com/wordpress
请注意:我们能够使用kubectl delete database wordpress删除CRD资源,是因为之前在Kubernetes没有定义有database 资源。此外,database 是我们CRD中的spec.name.singular字段,从英语语法派生而来。
我们可以看到之前监控watch CRD databases从API Server处返回的更新状态:
{"type":"DELETED","object":{"apiVersion":"example.com/v1","kind":"Database","metadata":{"clusterName":"","creationTimestamp":"2017-0[0/515]
:38:30Z","deletionGracePeriodSeconds":null,"deletionTimestamp":null,"name":"wordpress","namespace":"default","resourceVersion":"2154","selfLink":"/apis/example.com/v1/namespaces/
default/databases/wordpress","uid":"8101a7af-7ce6-11e7-888c-42010a9a0fd5"},"spec":{"encoding":"unicode","password":"secret","user":"wp"}}}
上述shell会话的运行及输出结果如下图所示:

最后,让我们看一下CRD database 的各个数据是如何存储在etcd中的。下面是我们直接通过HTTP API进入etcd访问得到的数据:
$ curl -s localhost:2379/v2/keys/registry/example.com/databases/default | jq .
{
"action": "get",
"node": {
"key": "/registry/example.com/databases/default",
"dir": true,
"nodes": [
{
"key": "/registry/example.com/databases/default/wordpress",
"value": "{\"apiVersion\":\"example.com/v1\",\"kind\":\"Database\",\"metadata\":{\"clusterName\":\"\",\"creationTimestamp\":\"2017-08-09T14:53:40Z\",\"deletionGracePeriodSeconds\":null,\"deletionTimestamp\":null,\"name\":\"wordpress\",\"namespace\":\"default\",\"selfLink\":\"\",\"uid\":\"8837f788-7d12-11e7-9d28-080027390640\"},\"spec\":{\"encoding\":\"unicode\",\"password\":\"secret\",\"user\":\"wp\"}}\n",
"modifiedIndex": 670,
"createdIndex": 670
}
],
"modifiedIndex": 670,
"createdIndex": 670
}
}
从上面可以看到,CRD数据在etcd中最终以一个未解析的的状态存在。现在将CRD删除,所有的CRD实例也会跟着删除,这是一个级联删除操作。
目前CRDs的使用现状,局限及将来的展望
CRDs的发展现状如下所示:

  1. 在Kubernetes 1.7版本中CRDs开始取代ThirdPartyResources (TPRs) ,并且TPRs 将会在Kubernetes 1.8被删除。
  2. 将TPRs迁移到CRDs实例可以参考文档migration。
  3. 支持一个CRD中只有单个version 版本,当然,一个群组中可能有多个version版本。
  4. CRDs提供一个API方案,在用户角度看它与Kubernetes原生的API资源基本没有区别
  5. CRDs是多版本多分支稳定的基础。关于CRD资源的JSON-Schema的格式有效性校验可以参考文档CRD validation proposal。相关资源回收可以参考文档Garbage collection。
    接下去我们来看一下一些CRDs的局限:
  6. CRD不提供版本转换功能,也就是说,每个CRD只能有一个版本(预计不会在近期或中期内看到支持CRD版本转换)。
  7. 在Kubernetes1.7当中,目前并没有对于CRD的相关校验validation。
  8. 没有快速,实时的准入(admission )机制(但是可以支持webhooks 形式的初始化及准入)。
  9. 在Kubernetes1.7中你不能定义子资源(sub-resources),比如scale或者status,不过目前有在这方面proposal 的讨论。
  10. CRD目前不支持默认值配置,即不支持为特定的字段配默认值(在Kubernetes1.7后续的版本中可能会支持)。
    为了解决上述的问题,并且灵活的扩展Kubernetes,你可以运行一个与主API Server并行的用户API Servers。我们将在本博文的以后部分中详细介绍如何编写UAS,并编写一个custom controller 完整使用CRD 。https://www.huaweicloud.com/product/cce.html

原文地址:http://blog.51cto.com/13831707/2167034

时间: 2024-08-29 13:53:15

深度剖析Kubernetes API Server三部曲 - part 3的相关文章

深度剖析Kubernetes API Server三部曲 - part 1

欢迎来到深入学习Kubernetes API Server的系列文章,在本系列文章中我们将深入的探究Kubernetes API Server的相关实现.如果你对Kubernetes 的内部实现机制比较感兴趣或者正在进行Kubernetes 项目的相关开发工作,那么本系列文章能够为你提供一些帮助.了解学习过go语言,会在某些方面帮助你更好的理解本系列文章.在本期文章中,我们首先会对Kubernetes API Server进行一个总体的大致说明,然后对API的技术术语及请求流作说明.在下几期的文

深度剖析Kubernetes API Server三部曲 - part 2

在上一部分中我们对API server总体,相关术语及request请求流进行探讨说明.在本部分文章中,我们主要聚焦于探究如何对Kubernetes请添加链接描述 对象的状态以一种可靠,持久的方式进行管理.之前的文章中提到过 API Server自身是无状态的,并且它是唯一能够与分布式存储etcd直接通信的组件.etcd的简要说明在*nix操作系统中,我们一般使用/etc来存储相关配置数据.实际上etcd的名字就是由此发展而来,在etc后面加上个"d"表示"distribut

Kubernetes API Server原理

Kubernetes API Server功能 Kubernete API Server的核心功能主要是为Kubernetes的各类资源对象(如 node,pod,service等)提供了增.删.改.查以及watch的HTTP Rest接口.API server是集群中各个功能模块之间数据交互和通信的中心枢纽,除此之外它还有以下特性: 集群管理的API入口 资源配额控制的入口 提供完备的集群安全机制 常规API接口 Kubernetes的 API server通过 kube-apiserver进

Kubernetes API server工作原理

作为Kubernetes的使用者,每天用得最多的命令就是kubectl XXX了. kubectl其实就是一个控制台,主要提供的功能: 1. 提供Kubernetes集群管理的REST API接口,包括认证授权.数据校验以及集群状态变更: 2. 提供其他模块之间的数据交互和通信的枢纽(其他模块通过API Server查询或修改数据,只有API Server才直接操作etcd) 也就是说,我们在终端里输入的每个kubectl命令,实际上都是一个发往Kubernetes API server的Res

kubernetes API Server 权限管理实践

API Server 权限管理应用 API Server权限控制方式介绍 API Server权限控制分为三种:Authentication(身份认证).Authorization(授权).AdmissionControl(准入控制). 身份认证: 当客户端向Kubernetes非只读端口发起API请求时,Kubernetes通过三种方式来认证用户的合法性.kubernetes中,验证用户是否有权限操作api的方式有三种:证书认证,token认证,基本信息认证. 证书认证 设置apiserver

Centos7部署kubernetes API服务(四)

1.准备软件包 [[email protected] bin]# pwd /usr/local/src/kubernetes/server/bin [[email protected] bin]# cp kube-apiserver kube-controller-manager kube-scheduler /opt/kubernetes/bin/ 2.创建生成CSR的JSON配置文件 [[email protected] bin]# cd /usr/local/src/ssl/ [[emai

Kubernetes 源码分析 -- API Server之编解码

--------------------- 作者:weixin_34037977 来源:CSDN 原文:https://blog.csdn.net/weixin_34037977/article/details/87058105 在Kubernetes源码分析-- API Server之API Install篇中,我们了解到K8S可以支持多版本的API,但是Rest API的不同版本中接口的输入输出参数的格式是有差别的,Kubernetes是怎么处理这个问题的呢?另外Kubernetes支持ya

Kubernetes(八)自签Api server ssl证书

APIserver是整个集群的入口,只有它启动了,别的组件才可以启动:我们基于https访问,所以需要自签证书: 一.查看脚本 cd TLS/k8s 得到以下5个文件 ca-config.json ca-csr.json generate_k8s_cert.sh kube-proxy-csr.json server-csr.json #为api server启用https所使用证书 应用程序访问https api(自签证书)可用通过以下2种方式 1.证书添加IP可信任 2.携带CA证书 注意:在

Kubernetes(九)单Master 部署API Server、controller-manager、scheduler

一.在master节点下载二进制包 https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.16.md#v1161 二.选择kubernetes-server-linux-amd64.tar.gz下载 wget https://storage.googleapis.com/kubernetes-release/release/v1.16.6/kubernetes-server-linux-amd64.tar.gz 三.解压