当看istio源码时,发现使用CRD,本文分析Custom Resource Definition
一些特殊的需求,现有资源类型(deploy service statefulset等)满足不了,可以抽象 Kubernetes 自定义资源满足需求,
k8s 1.7 +增加了 CRD 二次开发能力来扩展 API,通过 CRD 可以向 API 中增加新资源类型,无需修改 Kubernetes 源码或创建自定义的 API server,该功能大大提高了 Kubernetes 的扩展能力。
CRD是一种无需编码就可以扩展原生kubenetes API接口的方式。适合扩展kubernetes的自定义接口和功能。如果想更为灵活的添加逻辑就需要API Aggregation方式
如何添加一个Custom resources到kubernetes呢?
两种方式将Custom resources添加到集群。
- Custom Resource Definitions (CRDs):更易用、不需要编码。但是缺乏灵活性
- API Aggregation:需要编码,允许通过聚合层的方式提供更加定制化的实现
引用网上相当赞的图
向Kubernetes API注册schema的资源,并定义相关API
当创建一个新的自定义资源定义(CRD)时,Kubernetes API Server 通过创建一个新的RESTful资源路径进行应答,无论是在命名空间还是在集群范围内,正如在CRD的
scope
域指定的那样。
与现有的内建对象一样,删除一个命名空间将会删除该命名空间内所有的自定义对象。
CRD本身并不区分命名空间,对所有的命名空间可用
以下的CRD保存到resourcedefinition.yaml,
kubectl apply -f resourcedefinition.yaml
创建一个自定义资源kind: CustomResourceDefinition
,指定API Group的名称stable.example.com
创建一个/apis/http://stable.example.com/v1/namespaces/
可以使用此端点URL来创建和管理自定义对象。 这些对象的kind
就是你在上面创建的CRD中指定的CronTab
对象
apiVersion: apiextensions.k8s.io/v1beta1
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
# 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
在CRD对象创建完成之后,你可以创建自定义对象了。自定义对象可以包含自定义的字段。这些字段可以包含任意的JSON。
以下的示例中,在一个自定义对象
CronTab
种类中设置了cronSpec
和image
字段。这个CronTab
种类来自于你在上面创建的CRD对象。
kubectl apply -f crontab.yml,在CRD对象创建完成之后就创建自定义对象(instances)了,这些自定义对象实例就可以类似Kubernetes的常用对象如Deployment、Service、Pod等一样进行CURD操作了
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * * */5"
image: my-awesome-cron-image
可以看到它包含了自定义的cronSpec
和image
字段,来自于你用于创建它的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: 2019-01-19T09:24:54Z
generation: 1
name: my-new-cron-object
namespace: default
resourceVersion: "10288282"
selfLink: /apis/stable.example.com/v1/namespaces/default/crontabs/my-new-cron-object
uid: 14c61440-1bcc-11e9-b451-00505683f77b
spec:
cronSpec: '* * * * */5'
image: my-awesome-cron-image
kind: List
metadata:
resourceVersion: ""
selfLink: ""
v1.10 开始 CRD 还支持 /status
和 /scale
等两个子资源(Beta),并且从 v1.11 开始默认开启。
v1.10 版本使用前需要在
kube-apiserver
开启--feature-gates=CustomResourceSubresources=true
# resourcedefinition.yaml
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.example.com
spec:
group: stable.example.com
version: v1
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
# subresources describes the subresources for custom resources.
subresources:
# status enables the status subresource.
status: {}
# scale enables the scale subresource.
scale:
# specReplicasPath defines the JSONPath inside of a custom resource that corresponds to Scale.Spec.Replicas.
specReplicasPath: .spec.replicas
# statusReplicasPath defines the JSONPath inside of a custom resource that corresponds to Scale.Status.Replicas.
statusReplicasPath: .status.replicas
# labelSelectorPath defines the JSONPath inside of a custom resource that corresponds to Scale.Status.Selector.
labelSelectorPath: .status.labelSelector
$ kubectl create -f resourcedefinition.yaml
$ kubectl create -f- <
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
name: my-new-cron-object
spec:
cronSpec: "* * * * */5"
image: my-awesome-cron-image
replicas: 3
EOF
$ kubectl scale --replicas=5 crontabs/my-new-cron-object
crontabs "my-new-cron-object" scaled
$ kubectl get crontabs my-new-cron-object -o jsonpath='{.spec.replicas}'
5
只有跟自定义控制器结合起来,资源对象中的声明式API翻译成用户所期望的状态。自定义控制器可以用来管理任何资源类型,一般是跟自定义资源结合使用。
在使用 CRD 扩展 Kubernetes API 时,通常还需要实现一个新建资源的控制器,监听新资源的变化情况,并作进一步的处理。
https://github.com/kubernetes/sample-controller 提供了一个 CRD 控制器的示例,包括
Foo
Foo
对象Foo
资源对象的变化情况[lin@node1 sample-controller]$ ./hack/update-codegen.sh
Generating deepcopy funcs
Generating clientset for samplecontroller:v1alpha1 at k8s.io/sample-controller/pkg/client/clientset
Generating listers for samplecontroller:v1alpha1 at k8s.io/sample-controller/pkg/client/listers
Generating informers for samplecontroller:v1alpha1 at k8s.io/sample-controller/pkg/client/informers[lin@node1 sample-controller]$ go build -v -o samplecontroller
https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/
https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/