Skip to content

Commit 7a8ee61

Browse files
committed
Update CRD Generation Reference Docs
This updates the CRD Generation reference docs to refer to the autogenerated marker docs, and cleans up some examples that were invalid.
1 parent 10145f5 commit 7a8ee61

File tree

3 files changed

+161
-85
lines changed

3 files changed

+161
-85
lines changed
Lines changed: 157 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,150 +1,222 @@
11
# Generating CRDs
22

3-
Kubebuilder provides a tool named `controller-gen` to generate manifests for CustomResourceDefinitions. The tool resides in the [controller-tools](http://sigs.k8s.io/controller-tools) repository and is installed through a Makefile target called `controller-gen`.
3+
KubeBuilder uses a tool called [`controller-gen`][controller-tools] to
4+
generate utility code and Kubernetes object YAML, like
5+
CustomResourceDefinitions.
46

5-
If you examine the `Makefile` in your project, you will see a target named `manifests` for generating manifests. `manifests` target is also listed as prerequisite for other targets like `run`, `tests`, `deploy` etc to ensure CRD manifests are regenerated when needed.
7+
To do this, it makes use of special "marker comments" (comments that start
8+
with `// +`) to indicate additional information about fields, types, and
9+
packages. In the case of CRDs, these are generally pulled from your
10+
`_types.go` files. For more information on markers, see the [marker
11+
reference docs][marker-ref].
612

7-
```sh
8-
# Generate manifests e.g. CRD, RBAC etc.
9-
manifests: controller-gen
10-
$(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases
11-
12-
# find or download controller-gen
13-
# download controller-gen if necessary
14-
controller-gen:
15-
ifeq (, $(shell which controller-gen))
16-
go get sigs.k8s.io/controller-tools/cmd/[email protected]
17-
CONTROLLER_GEN=$(GOBIN)/controller-gen
18-
else
19-
CONTROLLER_GEN=$(shell which controller-gen)
20-
endif
21-
```
22-
23-
When you run `make manifests`, you should see generated CRDs are under `config/crd/bases` directory.
24-
25-
`controller-gen` generates manifests for RBAC as well, but this section covers the generation of CRD manifests.
13+
KubeBuilder provides a `make` target to run controller-gen and generate
14+
CRDs: `make manifests`.
2615

27-
`controller-gen` reads kubebuilder markers of the form `// +kubebuilder:something...` defined as Go comments in the `<your-api-kind>_types.go` file under `apis/...` to produce the CRD manifests. Sections below describe various supported annotations.
16+
When you run `make manifests`, you should see CRDs generated under the
17+
`config/crd/bases` directory. `make manifests` can generate a number of
18+
other artifacts as well -- see the [marker reference docs][marker-ref] for
19+
more details.
2820

2921
## Validation
3022

31-
CRDs support [validation](https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#validation) by definining ([OpenAPI v3 schema](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaObject)) in the validation section. To learn more about the validation feature, refer to the original docs [here](https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#validation). One can specify validation for a field by annotating the field with kubebuilder marker which is of the form`// +kubebuilder:validation:<key=value>`. If you want to specify multiple validations for a field, you can add multiple such markers as demonstrated in the example below.
23+
CRDs support [declarative validation][kube-validation] using an [OpenAPI
24+
v3 schema][openapi-schema] in the `validation` section.
3225

33-
Currently, supporting keys are `Maximum`, `Minimum`, `MaxLength`, `MinLength`, `MaxItems`, `MinItems`, `UniqueItems`, `Enum`, `Pattern`, `ExclusiveMaximum`,
34-
`ExclusiveMinimum`, `MultipleOf`, `Format`. The `// +kubebuilder:validation:Pattern=.+:.+` annotation specifies the Pattern validation requiring that the `Image` field match the regular expression `.+:.+`
26+
In general, [validation markers](./markers/crd-validation.md) may be
27+
attached to fields or to types. If you're defining complex validation, if
28+
you need to re-use validation, or if you need to validate slice elements,
29+
it's often best to define a new type to describe your validation.
3530

36-
**Example:**
31+
For example:
3732

3833
```go
3934
type ToySpec struct {
40-
41-
// +kubebuilder:validation:Maximum=100
42-
// +kubebuilder:validation:Minimum=1
43-
// +kubebuilder:validation:ExclusiveMinimum=true
44-
Power float32 `json:"power,omitempty"`
45-
46-
Bricks int32 `json:"bricks,omitempty"`
4735
// +kubebuilder:validation:MaxLength=15
4836
// +kubebuilder:validation:MinLength=1
4937
Name string `json:"name,omitempty"`
5038

5139
// +kubebuilder:validation:MaxItems=500
5240
// +kubebuilder:validation:MinItems=1
53-
// +kubebuilder:validation:UniqueItems=false
41+
// +kubebuilder:validation:UniqueItems=true
5442
Knights []string `json:"knights,omitempty"`
5543

56-
// +kubebuilder:validation:Enum=Lion;Wolf;Dragon
57-
Alias string `json:"alias,omitempty"`
58-
59-
// +kubebuilder:validation:Enum=1;2;3
60-
Rank int `json:"rank"`
44+
Alias Alias `json:"alias,omitempty"`
45+
Rank Rank `json:"rank"`
6146
}
6247

63-
```
48+
// +kubebuilder:validation:Enum=Lion;Wolf;Dragon
49+
type Alias string
50+
51+
// +kubebuilder:validation:Minimum=1
52+
// +kubebuilder:validation:Maximum=3
53+
// +kubebuilder:validation:ExclusiveMaximum=false
54+
type Rank int32
6455

65-
## Additional printer columns
56+
```
6657

67-
Starting with Kubernetes 1.11, kubectl uses server-side printing. The server
68-
decides which columns are shown by the kubectl get command. You can
69-
[customize these columns using a CustomResourceDefinition](https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#additional-printer-columns).
70-
To add an additional column, add a comment with the following marker format
71-
just above the struct definition of the Kind.
58+
## Additional Printer Columns
7259

73-
Format: `// +kubebuilder:printcolumn:name="Name",type="type",JSONPath="json-path",description="desc",priority="priority",format="format"`
60+
Starting with Kubernetes 1.11, `kubectl get` can ask the server what
61+
columns to display. For CRDs, this can be used to provide useful,
62+
type-specific information with `kubectl get`, similar to the information
63+
provided for built-in types.
7464

75-
Note that `description`, `priority` and `format` are optional. Refer to the
76-
[additonal printer columns docs](https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#additional-printer-columns)
77-
to learn more about the values of `name`, `type`, `JsonPath`, `description`, `priority` and `format`.
65+
The information that gets displayed can be controlled with the
66+
[additionalPrinterColumns field][kube-additional-printer-columns] on your
67+
CRD, which is controlled by the
68+
[`+kubebuilder:printcolumn`][crd-markers] marker on the Go type for
69+
your CRD.
7870

79-
The following example adds the `Spec`, `Replicas`, and `Age` columns.
71+
For instance, in the following example, we add fields to display
72+
information about the knights, rank, and alias fields from the validation
73+
example:
8074

8175
```go
82-
// +kubebuilder:printcolumn:name="Spec",type="integer",JSONPath=".spec.cronSpec",description="status of the kind"
83-
// +kubebuilder:printcolumn:name="Replicas",type="integer",JSONPath=".spec.replicas",description="The number of jobs launched by the CronJob"
84-
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
85-
type CronTab struct {
76+
// +kubebuilder:printcolumn:name="Alias",type=string,JSONPATH=`.spec.alias`
77+
// +kubebuilder:printcolumn:name="Rank",type=integer,JSONPATH=`.spec.rank`
78+
// +kubebuilder:printcolumn:name="Bravely Run Away",type=boolean,JSONPath=`.spec.knights[?(@ == "Sir Robin")]`,description="when danger rears its ugly head, he bravely turned his tail and fled",priority=10
79+
type Toy struct {
8680
metav1.TypeMeta `json:",inline"`
8781
metav1.ObjectMeta `json:"metadata,omitempty"`
8882

89-
Spec CronTabSpec `json:"spec,omitempty"`
90-
Status CronTabStatus `json:"status,omitempty"`
83+
Spec ToySpec `json:"spec,omitempty"`
84+
Status ToyStatus `json:"status,omitempty"`
9185
}
9286

9387
```
9488

89+
## Subresources
9590

96-
## Subresource
97-
Custom resources support `/status` and `/scale` subresources as of kubernetes
98-
1.13 release. You can learn more about the subresources [here](https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#status-subresource).
91+
CRDs can choose to implement the `/status` and `/scale`
92+
[subresources][kube-subresources] as of Kubernetes 1.13.
9993

100-
### 1. Status
101-
To enable `/status` subresource, annotate the kind with `// +kubebuilder:subresource:status` marker.
94+
It's generally reccomended that you make use of the `/status` subresource
95+
on all resources that have a status field.
10296

103-
### 2. Scale
104-
To enable `/scale` subresource, annotate the kind with `// +kubebuilder:subresource:scale:specpath=<jsonpath>,statuspath=<jsonpath>,selectorpath=<jsonpath>` marker.
97+
Both subresources have a corresponding [marker][crd-markers].
10598

106-
Scale subresource marker contains three fields: `specpath`, `statuspath` and `selectorpath`.
99+
### Status
107100

108-
- `specpath` refers to `specReplicasPath` attribute of Scale object, and value `jsonpath` defines the JSONPath inside of a custom resource that corresponds to `Scale.Spec.Replicas`. This is a required field.
109-
- `statuspath` refers to `statusReplicasPath` attribute of Scale object. and the `jsonpath` value of it defines the JSONPath inside of a custom resource that corresponds to `Scale.Status.Replicas`. This is a required field.
110-
- `selectorpath` refers to `labelSelectorPath` attribute of Scale object, and the value `jsonpath` defines the JSONPath inside of a custom resource that corresponds to `Scale.Status.Selector`. This is an optional field.
101+
The status subresource is enabled via `+kubebuilder:subresource:status`.
102+
When enabled, updates at the main resource will not change status.
103+
Similarly, updates to the status subresource cannot change anything but
104+
the status field.
111105

106+
For example:
112107

113-
**Example:**
108+
```go
109+
// +kubebuilder:status:subresource
110+
type Toy struct {
111+
metav1.TypeMeta `json:",inline"`
112+
metav1.ObjectMeta `json:"metadata,omitempty"`
113+
114+
Spec ToySpec `json:"spec,omitempty"`
115+
Status ToyStatus `json:"status,omitempty"`
116+
}
117+
```
118+
119+
### Scale
120+
121+
The scale subresource is enabled via `+kubebuilder:subresource:scale`.
122+
When enabled, users will be able to use `kubectl scale` with your
123+
resource. If the `selectorpath` argument pointed to the string form of
124+
a label selector, the HorizontalPodAutoscaler will be able to autoscale
125+
your resource.
126+
127+
For example:
114128

115129
```go
116-
type ToySpec struct {
117-
Replicas *int32 `json:"replicas"` // Add this field in Toy Spec, so the jsonpath to this field is `.spec.replicas`
130+
type CustomSetSpec struct {
131+
Replicas *int32 `json:"replicas"`
118132
}
119133

120-
// ToyStatus defines the observed state of Toy
121-
type ToyStatus struct {
122-
Replicas int32 `json:"replicas"` // Add this field in Toy Status, so the jsonpath to this field is `.status.replicas`
134+
type CustomSetStatus struct {
135+
Replicas int32 `json:"replicas"`
136+
Selector string `json:"selector"` // this must be the string form of the selector
123137
}
124138

125139

126-
// Toy is the Schema for the toys API
127140
// +kubebuilder:subresource:status
128-
// +kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas
129-
type Toy struct {
141+
// +kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas,selectorpath=.status.selector
142+
type CustomSet struct {
130143
metav1.TypeMeta `json:",inline"`
131144
metav1.ObjectMeta `json:"metadata,omitempty"`
132145

133146
Spec ToySpec `json:"spec,omitempty"`
134147
Status ToyStatus `json:"status,omitempty"`
135148
}
149+
```
150+
151+
## Multiple Versions
152+
153+
As of Kubernetes 1.13, you can have multiple versions of your Kind defined
154+
in your CRD, and use a webhook to convert between them.
155+
156+
For more details on this process, see the [multiversion
157+
tutorial](/multiversion-tutorial/tutorial.md).
158+
159+
By default, KubeBuilder disables generating different validation for
160+
different versions of the Kind in your CRD, to be compatible with older
161+
Kubernetes versions.
162+
163+
You'll need to enable this by switching the line in your makefile that
164+
says `CRD_OPTIONS ?= "crd:trivialVersions=true` to `CRD_OPTIONS ?= crd`
165+
166+
Then, you can use the `+kubebuilder:storageversion` [marker][crd-markers]
167+
to indicate the [GVK](/cronjob-tutorial/gvks.md "Group-Version-Kind") that
168+
should be used to store data by the API server.
169+
170+
## Under the hood
171+
172+
KubeBuilder scaffolds out make rules to run `controller-gen`. The rules
173+
will automatically install controller-gen if it's not on your path using
174+
`go get` with Go modules.
175+
176+
You can also run `controller-gen` directly, if you want to see what it's
177+
doing.
178+
179+
Each controller-gen "generator" is controlled by an option to
180+
controller-gen, using the same syntax as markers. For instance, to
181+
generate CRDs with "trivial versions" (no version conversion webhooks), we
182+
call `controller-gen crd:trivialVersions=false paths=./api/...`.
136183

184+
controller-gen also supports different output "rules" to controller how
185+
and where output goes. Notice the `manifests` make rule (condensed
186+
slightly to only generate CRDs):
187+
188+
```makefile
189+
# Generate manifests for CRDs
190+
manifests: controller-gen
191+
$(CONTROLLER_GEN) crd:trivialVersions=true paths="./..." output:crd:artifacts:config=config/crd/bases
137192
```
138193

139-
In order to enable scale subresource in type definition file, you have to apply the scale subresource right before the kind struct definition, with correct jsonpath values according to the spec and status. And then make sure the jsonpaths are already defined in the Spec and Status struct. Finally, update the `<kind>_types_test.go` files according to the types Spec and Status changes.
194+
It uses the `output:crd:artifacts` output rule to indicate that
195+
CRD-related config (non-code) artifacts should end up in
196+
`config/crd/bases` instead of `config/crd`.
140197

141-
In the above example for the type `Toy`, we added `// +kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas` comment before `Toy` struct definition. `.spec.replicas` refers to the josnpath of Spec struct field (`ToySpec.Replicas`). And jsonpath `.status.healthyReplicas` refers to Status struct field (`ToyStatus.Replicas`).
198+
To see all the options for `controller-gen`, run
142199

143-
## Multiple Versions
200+
```shell
201+
$ controller-gen -h
202+
```
203+
204+
or, for more details:
205+
206+
```shell
207+
$ controller-gen -hhh
208+
```
209+
210+
[marker-ref]: ./markers.md "Markers for Config/Code Generation"
211+
212+
[kube-validation]: https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#validation "Custom Resource Definitions: Validation"
213+
214+
[openapi-schema]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaObject "OpenAPI v3"
215+
216+
[kube-additional-printer-colums]: https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#additional-printer-columns "Custom Resource Definitions: Additional Printer Columns"
217+
218+
[kube-subresources]: https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#status-subresource "Custom Resource Definitions: Status Subresource"
144219

145-
If you are defining multiple versions of a kind in your project, you need to do
146-
the following:
220+
[crd-markers]: ./markers/crd.md "CRD Generation"
147221

148-
- Set `CRD_OPTIONS ?= "crd:trivialVersions=false"` in the Makefile
149-
- Annotate the Go struct with marker `// +kubebuilder:storageversion` for the
150-
indicating the storage version.
222+
[controller-tools]: https://sigs.k8s.io/controller-tools "Controller Tools"

docs/book/src/reference/markers/crd-validation.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ These markers modify how the CRD validation schema is produced for the
44
types and fields they modify. Each corresponds roughly to an OpenAPI/JSON
55
schema option.
66

7+
See [Generating CRDs](/reference/generating-crd.md) for examples.
8+
79
{{#markerdocs CRD validation}}

docs/book/src/reference/markers/crd.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ These markers describe how to construct a custom resource definition from
44
a series of Go types and packages. Generation of the actual validation
55
schema is described by the [validation markers](./crd-validation.md).
66

7+
See [Generating CRDs](/reference/generating-crd.md) for examples.
8+
79
{{#markerdocs CRD}}

0 commit comments

Comments
 (0)