kubectl create / apply synchronously until each object is created

4/17/2020

I have the following yaml file, where I create a kubernetes CRD and a Custom Resource, as an instance of that CRD.

apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: mycrds.example.com
spec:
  group: example.com
  version: v1
  names:
    kind: MyCrd
    plural: mycrds
    singular: mycrd
  scope: Namespaced
---
apiVersion: example.com/v1
kind: MyCrd
metadata:
  name: example-instance
  namespace: default
spec:
  selectors:
    cluster:
      matchName:
        - '*'

If I do kubectl apply or kubectl create on this file, I get an error sometimes that no matches for kind "MyCrd" in version "example.com/v1" because the CRD registration is not yet complete. This does not happen always also.

Sample error messages:

$ kubectl apply -f crd-and-instance.yaml
customresourcedefinition.apiextensions.k8s.io/mycrds.example.com created
error: unable to recognize "/home/psankar/Downloads/crd-and-instance.yaml": no matches for kind "MyCrd" in version "example.com/v1"

$ # Same command executed after 2-3 seconds

$ kubectl apply -f crd-and-instance.yaml
customresourcedefinition.apiextensions.k8s.io/mycrds.example.com unchanged
mycrd.example.com/example-instance created

This does not happen always. Sometimes, the CRD gets registered fast and the kubectl create/apply command works fine in the first attempt.

I know that I can achieve this via shell script like:

kubectl create crd.yaml
kubectl wait until crd is published
kubectl create crdInstance.yaml

But I do not want to do this and want a single yaml file without any accompanying shell script. Is this possible ?

-- Sankar
kubectl
kubernetes

1 Answer

4/17/2020

kubectl apply -f is just an API call to k8s api-server which creates a resource in k8s etcd storage. It neither guarantees that the required resource is actually created nor checks its status. The resource may stuck in roll-out due to missing external dependencies, get in crash loop etc.

In order to make the sequence work synchronously you need to inject some sort of health checking (e.g. querying HTTP endpoint of the created resource). Another approach is just to delay creation by including sleep X seconds between the calls to let k8s finalize the creation. Of course, this will not check if the resource was actually created or failed.

-- Anton Matsiuk
Source: StackOverflow