欢迎访问网易云社区,了解更多网易技术产品运营经验。

前言

默认读者有kubernetes基础概念的背景知识,因此基础概念例如有状态、pod、Replica Sets、Deployments、statefulsets等不在此文详细阐述。 可以看我之前的一些关于kubernetes的文章:

kubernetes 1.3管中窥豹- RS(Replica Sets)

kubernetes pod&container生命周期浅析

kubernetes1.6管中窥豹-StatefulSets概念、约束、原理及实例

本文主要介绍一个1.7+以后出现的新概念CRD(CustomResourceDefinition )的概念、使用场景及实例。

CRD历史来源
k8s1.6~1.7 TRP(CRD的前身):Third Party Resource。
k8s1.7+ CRD: Custom Resource Definition。

CRD的概念

Custom resources:是对K8S API的扩展,代表了一个特定的kubetnetes的定制化安装。在一个运行中的集群中,自定义资源可以动态注册到集群中。注册完毕以后,用户可以通过kubelet创建和访问这个自定义的对象,类似于操作pod一样。

Custom controllers:Custom resources可以让用户简单的存储和获取结构化数据。只有结合控制器才能变成一个真正的declarative API(被声明过的API)。控制器可以把资源更新成用户想要的状态,并且通过一系列操作维护和变更状态。定制化控制器是用户可以在运行中的集群内部署和更新的一个控制器,它独立于集群本身的生命周期。 定制化控制器可以和任何一种资源一起工作,当和定制化资源结合使用时尤其有效。

Operator模式 是一个customer controllers和Custom resources结合的例子。它可以允许开发者将特殊应用编码至kubernetes的扩展API内。

如何添加一个Custom resources到我的kubernetes集群呢? kubernetes提供了两种方式将Custom resources添加到集群。

1. Custom Resource Definitions (CRDs):更易用、不需要编码。但是缺乏灵活性。

2. API Aggregation:需要编码,允许通过聚合层的方式提供更加定制化的实现。

本文重点讲解Custom Resource Definitions (CRD)的使用方法。

CRD使用场景

假设需要在原生kubernetes完成一些额外的功能开发,而且想使用restful风格的API 去调用这个功能。比如像开发容器保存镜像或者重启镜像等操作(一般都通过命令发送给容器内部完成)。就可以在原生kubernetes上增加一个CRD,命名为task。通过task触发一些逻辑。当使用apiserver下发这个task创建时,Custom controllers watch到这个task就开始处理相关业务逻辑,然后通过agent调用docker命令完成容器保存镜像功能并且重启容器。当Custom controllers watch到pod重新运行的时候,本次操作完成。 流程图如下:

CRD使用示例

如果想要完成上述场景的功能,需要定义一个CRD,并且创建出来。 举例如下,以下是一个可以在1.9集群环境中创建成功的crd yaml文件。

apiVersion: apiextensions.k8s.io/v1beta1kind: CustomResourceDefinitionmetadata:
  # name must match the spec fields below, and be in the form: <plural>.<group>  name: tasks.163yun.comspec:
  # group name to use for REST API: /apis/<group>/<version>  group: 163yun.com
  # version name to use for REST API: /apis/<group>/<version>  version: v1
  # either Namespaced or Cluster  scope: Namespaced  names:
    # plural name to be used in the URL: /apis/<group>/<version>/<plural>    plural: tasks
    # singular name to be used as an alias on the CLI and for display    singular: task
    # kind is normally the CamelCased singular type. Your resource manifests use this.    kind: Task
    # shortNames allow shorter string to match your resource on the CLI    shortNames:
    - task

其中几个关键要素是name、group、scope以及names里面的一些定义。

name:用于定义CRD的名字,后缀需要跟group一致,例如tasks.163yun.com,前缀需要跟names中的plural一致。

group以及version用于标识restAPI:即/apis//。 上文中的接口前面一部分就是/apis/163yun.com/v1

scope: 表明作用于,可以是基于namespace的,也可以是基于集群的。 如果是基于namespace的。则API格式为:/apis/{group}/v1/namespaces/{namespace}/{spec.names.plural}/… 如果是基于cluster的。则API格式为:/apis/{group}/v1/{spec.names.plural}/… 上文创建的CRD的API则为:/apis/163yun.com/v1/namespaces/{namespace}/tasks

names:描述了一些自定义资源的名字以及类型的名字(重点是plural定义以及kind定义,因为会在url或者查询资源中用的到)。

当以上面的模板创建出来一个CRD后,可以查到crd的信息:

root@hzyq-k8s-qa-16-master:~/cxq# kubectl  get CustomResourceDefinition tasks.163yun.com   -o yaml 
apiVersion: apiextensions.k8s.io/v1beta1kind: CustomResourceDefinitionmetadata:  creationTimestamp: 2018-03-16T06:17:03Z  generation: 1  name: tasks.163yun.com  resourceVersion: "35442027"  selfLink: /apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions/tasks.163yun.com  uid: a538030c-28e1-11e8-b047-fa163ef9812dspec:  group: 163yun.com  names:    kind: Task    listKind: TaskList    plural: tasks    shortNames:
    - task    singular: task  scope: Namespaced  version: v1status:  acceptedNames:    kind: Task    listKind: TaskList    plural: tasks    shortNames:
    - task    singular: task  conditions:
  - lastTransitionTime: 2018-03-16T06:17:03Z    message: no conflicts found    reason: NoConflicts    status: "True"    type: NamesAccepted
  - lastTransitionTime: 2018-03-16T06:17:03Z    message: the initial names have been accepted    reason: InitialNamesAccepted    status: "True"    type: Established

这时查询crd中定义的task类型的资源,是空的:

root@hzyq-k8s-qa-16-master:~/cxq# kubectl  get  task   -o yaml 
apiVersion: v1items: []kind: Listmetadata:  resourceVersion: ""  selfLink: ""

这时需要自定义一个task类型的模板,创建,以使得task可以触发自定义的一些事件

root@hzyq-k8s-qa-16-master:~/cxq# cat cxq-task.yaml 
apiVersion: "163yun.com/v1"kind: Taskmetadata:  name: cxq-nce-taskspec:  cronSpec: "* * * * /5"  image: my-awesome-cron-image
root@hzyq-k8s-qa-16-master:~/cxq# kubectl create -f cxq-task.yaml 
task "cxq-nce-task" created
root@hzyq-k8s-qa-16-master:~/cxq#  kubectl get task -o yamlapiVersion: v1items:- apiVersion: 163yun.com/v1  kind: Task  metadata:    clusterName: ""    creationTimestamp: 2018-03-16T06:43:10Z    labels: {}    name: cxq-nce-task    namespace: default    resourceVersion: "35444352"    selfLink: /apis/163yun.com/v1/namespaces/default/tasks/cxq-nce-task    uid: 4ad237aa-28e5-11e8-b047-fa163ef9812d  spec:    cronSpec: '* * * * /5'    image: my-awesome-cron-imagekind: Listmetadata:  resourceVersion: ""  selfLink: ""

注意由于CRD和自定义的Task资源本身是namespace无关的,因此对所有namespace都可见。如果指定了scope为namespace。那么创建的自定义task也需要指定namespace,如果不指定的话,系统会自动将task分配到default 的namespace下。

这时可以通过task的url去对自定义的task资源进行操作,或者watch。结合上一节的流程图来完成实现自定义功能的目的。以下是调用watch接口对task资源进行长连接监控(变化)。

root@hzyq-k8s-qa-16-master:~/cxq# curl http://10.180.156.79:8080/apis/163yun.com/v1/namespaces/default/tasks?watch=true
{"type":"ADDED","object":{"apiVersion":"163yun.com/v1","kind":"Task","metadata":{"clusterName":"","creationTimestamp":"2018-03-16T06:43:10Z","labels":{},"name":"cxq-nce-task","namespace":"default","resourceVersion":"35444352","selfLink":"/apis/163yun.com/v1/namespaces/default/tasks/cxq-nce-task","uid":"4ad237aa-28e5-11e8-b047-fa163ef9812d"},"spec":{"cronSpec":"* * * * /5","image":"my-awesome-cron-image"}}}

总结

CRD提供了一种无须编码就可以扩展原生kubenetes API接口的方式。很适合在云应用中扩展kubernetes的自定义接口和功能。在一些无须太多定制和灵活的开发场景下,CRD的方式已经足够使用。如果想更为灵活的添加逻辑就需要参考API Aggregation的使用了。

网易云容器服务为用户提供了无服务器容器,让企业能够快速部署业务,轻松运维服务。容器服务支持弹性伸缩、垂直扩容、灰度升级、服务发现、服务编排、错误恢复及性能监测等功能。点击免费试用

相关阅读:浅谈 kubernetes service 那些事(上篇)

浅谈 kubernetes service 那些事 (下篇)

本文来自网易实践者社区,经作者崔晓晴授权发布。

相关文章:
【推荐】 初识Continuation

kubernetes1.9管中窥豹-CRD概念、使用场景及实例的更多相关文章

  1. Oracle dbms_lock.sleep()存储过程使用技巧-场景-分析-实例

    <Oracle dbms_lock.sleep()存储过程使用技巧>-场景-分析-实例 摘要:今天是2014年3月10日,北京,雾霾,下午组织相关部门开会.会议的结尾一名开发工程师找到了我 ...

  2. Unity学习笔记(一)——基本概念之场景(Scene)

    场景,顾名思义就是我们在游戏中所看到的物品.建筑.人物.背景.声音.特效等,基本上和我们玩游戏时所看到的游戏“场景”是同一个概念. Unity 3D中,“场景”是一个视图,我们通过“场景”这个视图,来 ...

  3. android launchmode(四种启动模式)应用场景及实例

    模式介绍 [1] standard 模式 这是默认模式,每次激活Activity时都会创建Activity实例,并放入任务栈中. [2] singleTop 模式 如果在任务的栈顶正好存在该Activ ...

  4. Cocos2d-JS引入其他场景小实例

    创建新项目,目标是把LogoNode.js场景引入app.js 新建LogoNode.js var LogoLayer = cc.Layer.extend({ ctor:function () { t ...

  5. Spring Aop重要概念介绍及应用实例结合分析

    转自:http://bbs.csdn.net/topics/390811099 此前对于AOP的使用仅限于声明式事务,除此之外在实际开发中也没有遇到过与之相关的问题.最近项目中遇到了以下几点需求,仔细 ...

  6. Java面向对象_继承——基本概念以及管理化妆品实例分析

    一.继承的基本概念: 1.继承是面向对象三大特征之一 2.被继承的类成为父类(超类),继承父类的类成为子类(派生类) 3.继承是指一个对象直接使用另一个对象的属性和方法 4.通过继承可以实现代码重用 ...

  7. Python面向对象-概念、类、实例

    OOP——Object Oriented Programming,面向对象编程,是一种程序设计思想.该思想将对象作为程序的基本单元,一个对象包含了数据和操作数据的函数. 区别于面向过程的程序设计即把计 ...

  8. RPC远程调用概念 &amp;&amp; demo实例

    RPC是指远程过程调用,直观说法就是A通过网络调用B的过程方法. 也就是说两台serverA.B,一个应用部署在Aserver上,想要调用Bserver上应用提供的函数/方法,因为不在一个内存空间,不 ...

  9. redis应用场景及实例

    Redis在很多方面与其他数据库解决方案不同:它使用内存提供主存储支持,而仅使用硬盘做持久性的存储;它的数据模型非常独特,用的是单线程.另一个大区别在于,你可以在开发环境中使用Redis的功能,但却不 ...

随机推荐

  1. windows系统如何真正隐藏文件夹[转载]

    方法一(推荐)eg:现需隐藏e盘bak目录下的tools文件夹e:\bak\tools运行:cmd键入:attrib +s +a +h +r e:\bak\tools然后,你再进去看e盘bak目录下, ...

  2. [leetcode]250. Count Univalue Subtrees统计节点值相同的子树

    Given a binary tree, count the number of uni-value subtrees. A Uni-value subtree means all nodes of ...

  3. js variable 变量

    局部作用域 由于JavaScript的变量作用域实际上是函数内部,我们在for循环等语句块中是无法定义具有局部作用域的变量的: 'use strict'; function foo() { for ( ...

  4. php中的declare

    <?php // 事件的回调函数 function func_tick() { echo "call...\r\n"; } // 注册事件的回调函数 register_tic ...

  5. ubuntu自动拉黑破解ssh服务的IP

    2013年的脚本,今天拿出来备份一下. vim /root/secure_ssh.sh #!/bin/bash cat /var/log/auth.log|awk '/Failed/{print $( ...

  6. jar 包 的用处 ,dozer、poi、itext 、jxl 、jbarcode 、itextrenderer jquery 效果

    1.dozer 做类型转换的, 新建 xml 文件 描述两个实体的对应关系 ,DozerBeanMapper mapper =new DozerBeanMapper().addMappingFiles ...

  7. setTimeout setInterval 详解

      http://www.jb51.net/article/74606.htm   var tttt=setTimeout('northsnow()',1000);//执行一次 clearTimeou ...

  8. 人类基因组三代组装: cano

    git clone https://github.com/marbl/canu.git cd canu/src make -j <number of threads> 使用实例: canu ...

  9. 2018.10.16 spoj Can you answer these queries V(线段树)

    传送门 线段树经典题. 就是让你求左端点在[l1,r1][l1,r1][l1,r1]之间,右端点在[l2,r2][l2,r2][l2,r2]之间且满足l1≤l2,r1≤r2l1\le l2,r1 \l ...

  10. Django入门与实践-第23章:分页实现(完结)

    http://127.0.0.1:8000/boards/1/ #从现在起,我们将在 board_topics 这个视图中来操作. python manage.py shell from django ...