What is the best method for checking to see if a custom resource definition exists before running a script, using only kubectl
command line?
We have a yaml file that contains definitions for a NATS cluster ServiceAccount
, Role
, ClusterRoleBinding
and Deployment
. The image used in the Deployment
creates the crd
, and the second script uses that crd
to deploy a set of pods
. At the moment our CI pipeline needs to run the second script a few times, only completing successfully once the crd
has been fully created. I've tried to use kubectl wait
but cannot figure out what condition to use that applies to the completion of a crd
.
Below is my most recent, albeit completely wrong, attempt, however this illustrates the general sequence we'd like.
kubectl wait --for=condition=complete kubectl apply -f 1.nats-cluster-operator.yaml kubectl apply -f 2.nats-cluster.yaml
Use Wait command We utilize the 'wait' command to recess until the pods meet the requirements. Use kubectl apply to relate the variations to the cluster and wait a randomly set amount of time (60 seconds) to check the status of the pod. At this point, we expect the fresh deployment to be active and the old one removed.
To create a new CRD, we use “apiextensions.k8s.io/v1beta1” as the value. The kind key specifies what kind of object you want to create. As we are about to create a CRD, we put “CustomResourceDefinition” as the value. The metadata key is used to define the data that can uniquely identify the object.
A custom resource definition (CRD) is a powerful feature introduced in Kubernetes 1.7. The standard Kubernetes distribution ships with many built-in API objects and resources. CRDs enable IT admins to introduce unique objects or types into the Kubernetes cluster to meet their custom requirements.
The key difference between kubectl apply and create is that apply creates Kubernetes objects through a declarative syntax, while the create command is imperative. The command set kubectl apply is used at a terminal's command-line window to create or modify Kubernetes resources defined in a manifest file.
The condition for a CRD would be established
:
kubectl -n <namespace-here> wait --for condition=established --timeout=60s crd/<crd-name-here>
You may want to adjust --timeout
appropriately.
In case you are wanting to wait for a resource that may not exist yet, you can try something like this:
{ grep -q -m 1 "crontabs.stable.example.com"; kill $!; } < <(kubectl get crd -w)
or
{ sed -n /crontabs.stable.example.com/q; kill $!; } < <(kubectl get crd -w)
I understand the question would prefer to only use kubectl
, however this answer helped in my case. The downside to this method is that the timeout will have to be set in a different way and that the condition itself is not actually checked.
In order to check the condition more thoroughly, I made the following:
#!/bin/bash
condition-established() {
local name="crontabs.stable.example.com"
local condition="Established"
jq --arg NAME $name --arg CONDITION $condition -n \
'first(inputs | if (.metadata.name==$NAME) and (.status.conditions[]?.type==$CONDITION) then
null | halt_error else empty end)'
# This is similar to the first, but the full condition is sent to stdout
#jq --arg NAME $name --arg CONDITION $condition -n \
# 'first(inputs | if (.metadata.name==$NAME) and (.status.conditions[]?.type==$CONDITION) then
# .status.conditions[] | select(.type==$CONDITION) else empty end)'
}
{ condition-established; kill $!; } < <(kubectl get crd -w -o json)
echo Complete
To explain what is happening, $!
refers to the command run by bash's process substitution. I'm not sure how well this might work in other shells.
I tested with the CRD from the official kubernetes documentation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With