List an operator's CRDs, then read a field's docs with kubectl explain (CKA)
Most CKA questions ask you to change something. This one asks you to change nothing at all, and it is still worth two marks. An application is already installed in the cluster, and you have to produce two files about it: the list of custom resource definitions it registered, and the documentation for one field buried inside one of those custom resources. Both are single commands, and both have a detail in the wording that decides whether you get the marks. Let's run it on a live cluster.
🎥 Watch the video: https://www.youtube.com/watch?v=lCXp7g1aJ0M
This is a CKA Cluster Architecture, Installation & Configuration walkthrough. Every command below is real output from a live cluster, and you can reproduce the whole thing yourself (scripts at the end).
The scenario
Here is the setup. The cert-manager application is already running in the cluster, in the pki-system namespace, and it is not the only operator that has installed custom resource definitions here. Two deliverables. First, save the list of the custom resource definitions that belong to cert-manager into a file called crd-inventory.yaml, using kubectl's default output format, and that phrase is the whole trick of part one. Second, using kubectl, extract the documentation for the subject field inside a Certificate's spec, and save it to subject-doc.yaml. For that one, any output format kubectl supports is accepted. Nothing in the cluster gets modified.
- cert-manager is already installed, in ns 'pki-system', alongside other operators
- 1. Save cert-manager's CRDs to crd-inventory.yaml, in the DEFAULT output format
- 2. Save the docs for a Certificate's spec.subject field to subject-doc.yaml
- Read-only: nothing in the cluster changes
How CRDs document themselves
One idea makes both halves easy. A custom resource definition adds a new type to the Kubernetes API, and the definition carries an OpenAPI schema that describes every field of that type, including the description text the author wrote. The API server publishes that schema alongside the schemas of the built-in types. That is why kubectl explain works on a custom resource exactly as well as it works on a Pod: it is reading the cluster's own schema, not a documentation website, so it works with no internet access, which matters on exam day. The same applies to kubectl api-resources, which lists every type the API server currently serves, along with its API group and its short names. The cluster documents itself, and both parts of this question are just asking you to know that.
What is installed
Start by looking at what is actually there. The application is running in pki-system, three deployments worth of it, healthy. Now list the custom resource definitions in the cluster, and notice the shape of that list: twelve of them, and only some belong to cert-manager. The others are Gateway API definitions from a different operator entirely. This is why the question says the CRDs of the cert-manager application, and not simply all the CRDs. If you want the same information from the resource side, kubectl api-resources with an API group filter shows the types cert-manager serves, with their short names and their kinds, which is a handy thing to know exists.
$ kubectl get pods -n pki-system
NAME READY STATUS RESTARTS AGE
cert-manager-689c4c5575-snfgw 1/1 Running 0 125m
cert-manager-cainjector-6fbb9c8cd6-lrjvh 1/1 Running 0 125m
cert-manager-webhook-646c95c5ff-p599p 1/1 Running 0 125m
$ kubectl get crd
NAME CREATED AT
backendtlspolicies.gateway.networking.k8s.io 2026-07-31T17:49:43Z
certificaterequests.cert-manager.io 2026-07-31T17:49:06Z
certificates.cert-manager.io 2026-07-31T17:49:06Z
challenges.acme.cert-manager.io 2026-07-31T17:49:06Z
clusterissuers.cert-manager.io 2026-07-31T17:49:06Z
gatewayclasses.gateway.networking.k8s.io 2026-07-31T17:49:43Z
gateways.gateway.networking.k8s.io 2026-07-31T17:49:43Z
grpcroutes.gateway.networking.k8s.io 2026-07-31T17:49:43Z
httproutes.gateway.networking.k8s.io 2026-07-31T17:49:43Z
issuers.cert-manager.io 2026-07-31T17:49:06Z
orders.acme.cert-manager.io 2026-07-31T17:49:06Z
referencegrants.gateway.networking.k8s.io 2026-07-31T17:49:43Z
$ kubectl api-resources --api-group=cert-manager.io
NAME SHORTNAMES APIVERSION NAMESPACED KIND
certificaterequests cr,crs cert-manager.io/v1 true CertificateRequest
certificates cert,certs cert-manager.io/v1 true Certificate
clusterissuers ciss cert-manager.io/v1 false ClusterIssuer
issuers iss cert-manager.io/v1 true Issuer
Deliverable one
Part one, then. Get the custom resource definitions, filter to the ones whose names carry the cert-manager API group, and redirect that into crd-inventory.yaml. Read the command carefully, because what is interesting is what is missing: there is no -o flag anywhere. The default table is the format the question asked for, so the correct move is to not reach for anything. Read the file back and there are the six definitions, certificates, certificate requests, issuers, cluster issuers, and the two ACME ones, challenges and orders. Six lines, exactly what the grader is looking for.
$ kubectl get crd | grep cert-manager > crd-inventory.yaml
(no output: it all went into the file)
$ cat crd-inventory.yaml
certificaterequests.cert-manager.io 2026-07-31T17:49:06Z
certificates.cert-manager.io 2026-07-31T17:49:06Z
challenges.acme.cert-manager.io 2026-07-31T17:49:06Z
clusterissuers.cert-manager.io 2026-07-31T17:49:06Z
issuers.cert-manager.io 2026-07-31T17:49:06Z
orders.acme.cert-manager.io 2026-07-31T17:49:06Z
The format trap
It is worth seeing why that instruction exists. If you reach for -o yaml out of habit, here is what you would have written into the file: twenty six thousand lines. Every definition dumped in full, complete with its entire schema. It is not a slightly different answer, it is a different artifact, and it fails the requirement. One refinement is allowed though. If losing the header bothers you, widen the pattern to keep the header line as well, and you get a table with column names and only the rows you want. Still the default format, still no -o flag, and slightly nicer to read.
$ kubectl get crd -o yaml | wc -l
26006
$ kubectl get crd | grep -E 'NAME|cert-manager'
NAME CREATED AT
certificaterequests.cert-manager.io 2026-07-31T17:49:06Z
certificates.cert-manager.io 2026-07-31T17:49:06Z
challenges.acme.cert-manager.io 2026-07-31T17:49:06Z
clusterissuers.cert-manager.io 2026-07-31T17:49:06Z
issuers.cert-manager.io 2026-07-31T17:49:06Z
orders.acme.cert-manager.io 2026-07-31T17:49:06Z
kubectl explain
Part two asks for documentation, not data, and the tool for that is kubectl explain. Give it the resource followed by the field path, with dots: certificates.spec.subject. Out comes real documentation: a description of what the field is, and then every attribute nested inside it. Countries, localities, organizational units, organizations, postal codes, provinces, a serial number, street addresses, each with its own type and its own sentence of explanation. That is a certificate's X509 subject, described by the people who wrote the custom resource, and it came out of the cluster rather than out of a browser.
$ kubectl explain certificates.spec.subject
GROUP: cert-manager.io
KIND: Certificate
VERSION: v1
FIELD: subject <Object>
DESCRIPTION:
Requested set of X509 certificate subject attributes.
More info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6
The common name attribute is specified separately in the `commonName` field.
Cannot be set if the `literalSubject` field is set.
FIELDS:
countries <[]string>
Countries to be used on the Certificate.
localities <[]string>
Cities to be used on the Certificate.
organizationalUnits <[]string>
...
Deliverable two
So redirect that same command into subject-doc.yaml. The question said any output format kubectl supports is acceptable here, which is a way of saying it does not care, so the plain explain output is fine as it stands. Now read the top of the file back, and there is the header: the group, the kind and the version, so there is no ambiguity about which type this documents, then the field, its type, and the description with a link to the RFC. Then list the directory. Two files, both non-empty, both produced by kubectl alone, and not one object in the cluster was touched.
$ kubectl explain certificates.spec.subject > subject-doc.yaml
(no output: it all went into the file)
$ head -n 12 subject-doc.yaml
GROUP: cert-manager.io
KIND: Certificate
VERSION: v1
FIELD: subject <Object>
DESCRIPTION:
Requested set of X509 certificate subject attributes.
More info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6
The common name attribute is specified separately in the `commonName` field.
$ ls -l
total 8
-rw-r--r-- 1 jeffv jeffv 408 Jul 31 15:54 crd-inventory.yaml
-rw-r--r-- 1 jeffv jeffv 1006 Jul 31 15:54 subject-doc.yaml
Going deeper
Two things worth knowing before we leave. The field path keeps going: add another dot and the name of one of those attributes, and kubectl explains just that leaf, its type, a list of strings, and its description. Any depth, any field, same command. And if you are wondering where that text physically comes from, read it straight out of the definition object with a jsonpath into the schema. The same sentences, sitting in the CRD's OpenAPI schema, which is what the API server hands to kubectl. Nothing magic, and nothing that needs the internet.
$ kubectl explain certificates.spec.subject.organizations
GROUP: cert-manager.io
KIND: Certificate
VERSION: v1
FIELD: organizations <[]string>
DESCRIPTION:
Organizations to be used on the Certificate.
$ kubectl get crd certificates.cert-manager.io -o jsonpath='{.spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.subject.description}'
Requested set of X509 certificate subject attributes.
More info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6
The common name attribute is specified separately in the `commonName` field.
Cannot be set if the `literalSubject` field is set.
Exam tips
Things to carry into the exam. Default output format means no -o flag at all, so resist the habit; when a question specifies a format, that is a graded requirement, not advice. Do not assume an operator lives in a namespace named after itself, check where it actually is. Filter CRDs by the API group in their names, and remember an application can own more than one group, as cert-manager does with its ACME definitions, so a narrow grep can silently drop rows. kubectl explain takes plurals, singulars and short names, so certificates, certificate and cert all work, and the field path is dotted from the top of the object. Add the --recursive flag when you want the whole field tree at once and no descriptions. And when you cannot remember which types exist at all, kubectl api-resources is the map. Finally, read the file back after every redirect; an empty file scores zero just as surely as a wrong one.
- 'Default output format' = no -o flag; it is a graded requirement
- Never assume the namespace an operator was installed into
- Filter CRDs by API group; cert-manager also owns acme.cert-manager.io
- kubectl explain takes plural, singular or short name, plus a dotted field path
- --recursive prints the whole field tree; api-resources maps the types
- cat the file after every redirect: an empty deliverable scores zero
Recap
- kubectl get crd | grep cert-manager > crd-inventory.yaml (no -o flag)
- kubectl explain certificates.spec.subject > subject-doc.yaml
- A CRD ships an OpenAPI schema; the API server publishes it; explain reads it
- Read-only question, two easy marks; subscribe + dev.to writeup
Reproduce this yourself
The entire scenario is scripted on a throwaway kind cluster: https://github.com/The-Cyber-Sidekick/TCS_CKA_2026_Exam_Scenarios
git clone https://github.com/The-Cyber-Sidekick/TCS_CKA_2026_Exam_Scenarios.git
cd TCS_CKA_2026_Exam_Scenarios/learning/scenarios/scenario15-crd-inventory-explain
./setup.sh # creates the cluster AND arms the scenario
# solve it by hand, or:
./solution.sh # apply the answer key and verify
If this helped, subscribe to The Cyber SideKick on YouTube for more CKA drills, and grab the newsletter at https://thecybersidekick.beehiiv.com.
Top comments (0)