美文网首页Docker&Kubernetes
Kubernetes自定义资源

Kubernetes自定义资源

作者: 我是黄小邪 | 来源:发表于2020-07-23 17:53 被阅读0次

    参考连接:
    https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md
    https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/

    Kubernetes API

    • 在Kubernetes中,所有的事物都被抽象成一种资源,并且提供相应的REST API (API Server)对这些资源进行操作
      例如:查看某个Deployment
    # 启动代理 kubectl proxy --port=8080 后可直接通过本地8080端口访问api-server
    
    # 查看 deployments 列表
    curl -XGET http://127.0.0.1:8080/apis/apps/v1/deployments/
    
    # 查看某一个deployment
    curl -XGET http://127.0.0.1:8080/apis/apps/v1/namespaces/default/deployments/nginx-deployment
    
    #删除Deployment
    curl -XDELETE http://127.0.0.1:8080/apis/apps/v1/namespaces/default/deployments/nginx-deployment
    
    • Kubernetes中对资源更改类的API都是声明式的
      所谓 "声明式",就是告诉Kubernetes系统我们需要什么 ,也就是"期望状态",然后Kubernetes系统(controller组件)自己去计算执行路径使”实际状态“达到”期望状态“ 。相对于命令式的API来说有以下几个好处:
      1. 天然支持幂等操作
      2. 支持多个客户端同时进行操作,且业务层不需要考虑加锁
    • 对资源操作的API URI一般为 /apis/<group>/<version>/<resource> 或者是 /apis/<group>/<version>/namespaces/<namespace>/<resourceName>
    #yaml
    apiVersion: apps/v1
    kind:  Deployment
    spec:
        ...
    

    group和version通常一起在apiVersion字段中一起出现。
    空("",/apis/v1)、单个单词("extensions", "apps"等)、以及以"*.k8s.io"为结尾的group是k8s保留的group,我们自定义API时group建议用域名或者子域名(widget.mycompany.com)

    • 提供扩展机制实现自定义资源

    Kubernetes object

    在Kubernetes系统中,对象是持久化的实体,用来描述一个集群,通常一个对象可以包含如下信息

    1. 什么容器化的应用在运行(以及在哪个Node 上)
    2. 应用可以使用的资源
    3. 应用运行时的一些策略,比如重启策略、升级策略,以及容错策略
    

    一旦你创建了一个对象后,Kubernetes会确保这个对象一直处于你所期望的状态

    object 结构

    1. apiVersion
      对象所属的API的group和version

    2. kind
      对象所属的资源类型

    3. Metadata

      • 每个对象在嵌套对象Metadata中必须包含以下几个值
        namespace:用来划分虚拟集群,不同的namespace可以对资源进行隔离,一个namespace下的资源没有办法直接使用name访问其他namespace的资源(可以使用fully qualified domain name),默认是 default. (namespace 详细说明文档)。
        name: 当前namespace下唯一标识此对象的字符串,在访问对象时,在URL对象中会使用此值. (标识符文档)。
        uid:唯一的时空值(通常是RFC 4122生成的标识),用于区分已删除并重新创建的同名对象。一般由系统自动生成。

      • 每个对象在嵌套对象Metadata中应该包含以下值
        resourceVersion:一个字符串,标识对象内部的版本号。主要用来控制并发修改,这个字段由服务端生成及修改,客户端不能修改,在提交修改对象时传给服务端,如果与服务端的不一致,则修改失败(HTTP返回值为409, 更多并发控制参考)。
        generation:表示所需spec的特定生成的序列号,由系统生成,每一次修改spec时会单调递增。
        creationTimestamp:一个字符串,代表创建对象的日期和时间的RFC 3339日期。
        deletionTimestamp:一个字符串,代表将删除该资源的日期和时间的RFC 3339日期。当用户请求正常删除时,此字段由服务器设置,客户端无法直接设置。在此字段中的时间过后,资源将被删除
        labels:字符串键和值的映射,可用于组织和分类对象(请参阅标签docs
        annotations:字符串键和值的映射,外部工具可以使用它来存储和检索有关此对象的任意元数据(请参见 批注docs

    4. spec 和 status
      按照约定,Kubernetes API区分对象的所需状态的规范(称为“ spec”的嵌套对象字段)和当前时间的对象状态(称为“ status”的嵌套对象字段)。
      spec:对所需状态的完整描述,包括了用户提供的配置设置(例如:可以部署在哪些Nodes上,运行什么样容器,有多少个副本等等),并与API对象一起保存在稳定的存储中。如果删除了spec,则将从系统中清除该对象。
      status:记录了系统中对象的当前状态,通常与API对象保存在一起。
      通过POST或PUT修改object时,spec 会立即更新并且可见,然后系统对应的组件会使status与spec保持一致。但是会忽略对status的修改,对status的修改需要操作子资源 “/status”

    可以用一个yaml来表示要创建的对象,例如:

    apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
    kind: Deployment
    metadata:
      name: nginx-deployment
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx:1.7.9
            ports:
            - containerPort: 80
    

    通过yaml文件创建资源

    kubectl create -f nginx.yaml
    

    自定义资源

    自定义资源是 k8s API的一种扩展机制,在一个运行的k8s集群中,可以通过动态注册出现和消失。集群管理员可以独立于集群本身更新自定义资源。

    Should I add a custom resource to my Kubernetes Cluster?

    Should I use a configMap or a custom resource?

    Use a ConfigMap if any of the following apply:
    
    *   There is an existing, well-documented config file format, such as a `mysql.cnf` or `pom.xml`.
    *   You want to put the entire config file into one key of a configMap.
    *   The main use of the config file is for a program running in a Pod on your cluster to consume the file to configure itself.
    *   Consumers of the file prefer to consume via file in a Pod or environment variable in a pod, rather than the Kubernetes API.
    *   You want to perform rolling updates via Deployment, etc., when the file is updated.
    
    > **Note:** Use a [secret](https://kubernetes.io/docs/concepts/configuration/secret/) for sensitive data, which is similar to a configMap but more secure.
    
    Use a custom resource (CRD or Aggregated API) if most of the following apply:
    
    *   You want to use Kubernetes client libraries and CLIs to create and update the new resource.
    *   You want top-level support from `kubectl`; for example, `kubectl get my-object object-name`.
    *   You want to build new automation that watches for updates on the new object, and then CRUD other objects, or vice versa.
    *   You want to write automation that handles updates to the object.
    *   You want to use Kubernetes API conventions like `.spec`, `.status`, and `.metadata`.
    *   You want the object to be an abstraction over a collection of controlled resources, or a summarization of other resources
    
    

    添加自定义资源

    k8s提供两种方式添加自定义资源

    1. CRD,比较简单,无需任何编程即可创建
    2. API Aggregation,需要编程,但可以更好地控制API行为,例如如何存储数据以及在API版本之间进行转换


    用CRD的方式创建一个自定义资源

    创建 CustomResourceDefinition

    创建新的CustomResourceDefinition(CRD)时,Kubernetes API Server将为您指定的每个版本创建一个新的RESTful资源路径。如CRD scope字段中所指定,CRD可以是命名空间或群集作用域。与现有的内置对象一样,删除名称空间也会删除该名称空间中的所有自定义对象。CustomResourceDefinitions本身是非命名空间的,并且可用于所有命名空间。

    例如,将以下CustomResourceDefinition保存到resourcedefinition.yaml:

    apiVersion: apiextensions.k8s.io/v1
    kind: CustomResourceDefinition
    metadata:
      # name must match the spec fields below, and be in the form: <plural>.<group>
      name: crontabs.stable.example.com
    spec:
      # group name to use for REST API: /apis/<group>/<version>
      group: stable.example.com
      # list of versions supported by this CustomResourceDefinition
      versions:
        - name: v1
          # Each version can be enabled/disabled by Served flag.
          served: true
          # One and only one version must be marked as the storage version.
          storage: true
          schema:
            openAPIV3Schema:
              type: object
              properties:
                spec:
                  type: object
                  properties:
                    cronSpec:
                      type: string
                    image:
                      type: string
                    replicas:
                      type: integer
      # either Namespaced or Cluster
      scope: Namespaced
      names:
        # plural name to be used in the URL: /apis/<group>/<version>/<plural>
        plural: crontabs
        # singular name to be used as an alias on the CLI and for display
        singular: crontab
        # kind is normally the CamelCased singular type. Your resource manifests use this.
        kind: CronTab
        # shortNames allow shorter string to match your resource on the CLI
        shortNames:
        - ct
    

    并创建它

    kubectl apply -f resourcedefinition.yaml
    

    然后在以下位置创建一个新的namespace的RESTful API端点

    /apis/stable.example.com/v1/namespaces/*/crontabs/...
    

    通过使用此endpoint URL可以创建和管理自定义对象

    创建自定义对象

    创建CustomResourceDefinition对象后,可以创建自定义对象。自定义对象可以包含自定义字段。这些字段可以包含任意JSON。在以下示例中,cronSpec和image字段是在kind的自定义对象中设置的CronTab
    将以下YAML保存到my-crontab.yaml:

    apiVersion: "stable.example.com/v1"
    kind: CronTab
    metadata:
      name: my-new-cron-object
    spec:
      cronSpec: "* * * * */5"
      image: my-awesome-cron-image
    

    并创建它

    kubectl apply -f my-crontab.yaml
    

    然后,您可以使用kubectl管理CronTab对象。例如:

    $ kubectl get crontab 
    NAME                 AGE
    my-new-cron-object   46s
    

    使用kubectl时,资源名称不区分大小写,并且您可以使用CRD中定义的单数或复数形式以及任何短名称,例如:查看原始的YAML数据

    $ kubectl get ct -o yaml
    
    apiVersion: v1
    items:
    - apiVersion: stable.example.com/v1
      kind: CronTab
      metadata:
        annotations:
          kubectl.kubernetes.io/last-applied-configuration: |
            {"apiVersion":"stable.example.com/v1","kind":"CronTab","metadata":{"annotations":{},"name":"my-new-cron-object","namespace":"default"},"spec":{"cronSpec":"* * * * */5","image":"my-awesome-cron-image"}}
        creationTimestamp: "2020-07-22T18:39:36Z"
        generation: 1
        name: my-new-cron-object
        namespace: default
        resourceVersion: "36291"
        selfLink: /apis/stable.example.com/v1/namespaces/default/crontabs/my-new-cron-object
        uid: 75ed49cb-759c-45d9-8ce4-366ecb110717
      spec:
        cronSpec: '* * * * */5'
        image: my-awesome-cron-image
    

    删除CustomResourceDefinition

    删除CustomResourceDefinition时,服务器将卸载RESTful API端点并删除其中存储的所有自定义对象

    $ kubectl delete -f resourcedefinition.yaml
    $ kubectl get crontabs
    
    Error from server (NotFound): Unable to list "stable.example.com/v1, Resource=crontabs": the server could not find the requested resource (get crontabs.stable.example.com)
    

    自定义控制器

    上面我们创建了一个自定义资源和自定义对象,例如 my-new-cron-object 中制定了容器的image,但是并没有对应的Pod运行起来。 因为自定义资源需要和自定义控制器结合起来,才能完成自定义对象的意图。

    目前有以下几种方式创建自定义控制器

    相关文章

      网友评论

        本文标题:Kubernetes自定义资源

        本文链接:https://www.haomeiwen.com/subject/okslkktx.html