Kubernetes自定义资源

参考连接:
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/// 或者是 /apis///namespaces//
#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: .
  name: crontabs.stable.example.com
spec:
  # group name to use for REST API: /apis//
  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///
    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运行起来。 因为自定义资源需要和自定义控制器结合起来,才能完成自定义对象的意图。

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

  • using KUDO (Kubernetes Universal Declarative Operator)
  • using kubebuilder
  • using Metacontroller along with WebHooks that you implement yourself
  • using the Operator Framework

你可能感兴趣的:(Kubernetes自定义资源)