만약 kubernetes를 통해 어떤 어플리케이션을 개발했다고 가정하자. 어플리케이션은 쿠버네티스 클러스터에서 동작하며, 간단한 실행을 위해 cli를 따로 작성할 수 있다. 예를 들어 어떤 컨테이너를 실행하는 쿠버네티스 어플리케이션을 개발한 경우, 해당 컨테이너만을 가져오는 cli를 작성한다는 뜻이다. 하지만 cli를 작성하는 일은 꽤 번거로운 작업인데, 이를 kubectl에서 실행할 수 있도록 CustomResourceDefinition을 생성해볼 수 있다.

다음과 같이 작성한다.

apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  # name은 spec 필드의 <plural>.<group>과 같아야 한다.
  name: crontabs.stable.example.com
spec:
  # group은 REST API에서 다음과 같이 쓰인다: /apis/<group>/<version>
  group: stable.example.com
  # versions의 리스트들은 이 CustomResourceDefinition에서 쓰인다.
  versions:
    - name: v1
      # 각 version은 Served 플래그를 통해 사용 유무를 결정한다.
      served: true
      # 한 개 혹은 오직 하나의 버전만이 스토리지 버전으로 표시된다.
      storage: true
  # Namespaced나 Cluster
  scope: Namespaced
  names:
    # plural은 URL에서 쓰인다: /apis/<group>/<version>/<plural>
    plural: crontabs
    # singular는 cli에서의 alias나 표시 용도로 쓰인다.
    singular: crontab
    # kind는 보통 singular의 CamelCased로 쓰인다. 우리가 정의한 리소스 매니패스트는 이걸 사용한다.
    kind: CronTab
    # shortNames는 cli에서 매칭할 수 있는 짧은 이름이다.(service/svc와 같은 관계인듯)
    shortNames:
    - ct
  preserveUnknownFields: false
  validation:
    openAPIV3Schema:
      type: object
      properties:
        spec:
          type: object
          properties:
            cronSpec:
              type: string
            image:
              type: string
            replicas:
              type: integer

예를 들어 위 CustomResourceDefinition의 경우 group을 stable.example.com로, versions의 name은 v1로 지정했으므로 리소스의 apiVersion을 stable.example.com/v1로 지정하여 아래와 같이 리소스 오브젝트의 YAML파일을 작성할 수 있다.

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

이 리소스를 생성한 후에는 위에서 생성한 crontab을 사용하여 리소스를 확인할 수 있다.

$ kubectl get pod
No resources found.
$ kubectl get pod --all-namespaces
NAMESPACE        NAME                                    READY   STATUS        RESTARTS   AGE
kube-system      coredns-695688789-b77bc                 1/1     Running       0          66d
...
$ kubectl get crontab
NAME                 AGE
my-new-cron-object   36s
$ kubectl describe crontab my-new-cron-object
Name:         my-new-cron-object
Namespace:    default
Labels:       <none>
Annotations:  <none>
API Version:  stable.example.com/v1
Kind:         CronTab
Metadata:
  Creation Timestamp:  2019-07-17T15:15:43Z
  Generation:          1
  Resource Version:    6086604
  Self Link:           /apis/stable.example.com/v1/namespaces/default/crontabs/my-new-cron-object
  UID:                 bed758f3-a8a5-11e9-af88-9af0eb148f46
Spec:
  Cron Spec:  * * * * */5
  Image:      nginx
Events:       <none>

팟 리소스에서도 확인할 수 없다. 아예 새로운 리소스 crontab이 만들어진 것이다. 이를 통해 cli를 생성하는 수고를 덜 수 있겠다.

실제로 쓰이는 곳은 다음과 같다.

argo

argo의 cli도 제공하지만, customresourcedefinition을 통해 kubectl로도 컨트롤할 수 있다.

apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: workflows.argoproj.io
spec:
  group: argoproj.io
  names:
    kind: Workflow
    plural: workflows
    shortNames:
    - wf
  scope: Namespaced
  version: v1alpha1