Files
kustomize/docs/versioningPolicy.md
2019-07-10 11:41:54 +08:00

243 lines
7.8 KiB
Markdown

# Versioning
Running `kustomize` means one is running a
particular version of a program, using a
particular version of underlying packages, and
reading a particular version of a [kustomization]
file.
## Program Versioning
The command `kustomize version` prints a three
field version tag (e.g. `v3.0.0`) that aspires to
[semantic versioning].
When enough changes have accumulated to
warrant a new release, a [release process]
is followed, and the fields in the version
number are bumped per semver.
## Kustomize packages
At the time of writing, the kustomize program and
the packages it uses (and exports) are in the same
Go module (see the top level `go.mod` file in the
repo).
[trailing major version indicator]: https://github.com/golang/go/wiki/Modules#releasing-modules-v2-or-higher
Thus, they share the module's version number, per
its git tag (e.g. `v3.0.0`), whose major verion
number matches the [trailing major version
indicator] in the module name (e.g. the `/v3` in
`sigs.k8s.io/kustomize/v3`).
The non-internal packages in the Go module
`sigs.k8s.io/kustomize/v3`, introduced in
[v3.0.0](v3.0.0.md), conform to [semantic
versioning].
## Kustomization File Versioning
At the time of writing (circa release of v2.0.0):
- A [kustomization] file is just a YAML file that
can be successfully parsed into a particular Go
struct defined in the `kustomize` binary.
- This struct does not have a version number,
which is the same as saying that its version
number matches the program's version number,
since it's compiled in.
### Field Change Policy
- A field's meaning cannot be changed.
- A field may be deprecated, then removed.
- Deprecation means triggering a _minor_ (semver)
version bump in the program, and
defining a migration path in a non-fatal
error message.
- Removal means triggering a _major_ (semver)
version bump, and fatal error if field encountered
(as with any unknown field).
### The `edit fix` Command
This `kustomize` command reads a Kustomization
file, converts deprecated fields to new
fields, and writes it out again in the latest
format.
This is a type version upgrade mechanism that
works within _major_ program revisions. There is
no downgrade capability, as there's no use case
for it (see discussion below).
### Examples
At the time of writing, in v1.0.x, there were 12
minor releases, with backward compatible
deprecations fixable via `edit fix`.
With the 2.0.0 release, there were three field
removals:
- `imageTag` was deprecated when `images` was
introduced, because the latter offers more
general features for image data manipulation.
`imageTag` was removed in v2.0.0.
- `patches` was deprecated and replaced by
`patchesStrategicMerge` when `patchesJson6902`
was introduced, to make a clearer
distinction between patch specification formats.
`patches` was removed in v2.0.0.
- `secretGenerator/commands` was removed
due to security concerns in v2.0.0
with no deprecation period.
The `edit fix` command in a v2.0.x binary
will no longer recognize these fields.
## Relationship to the k8s API
### Review of k8s API versioning
The k8s API has specific [conventions] and a
process for making [changes].
The presence of an `apiVersion` field in a k8s
native type signals:
- its reliability level (alpha vs beta vs
generally available),
- the existence of code to provide default values
to fields not present in a serialization,
- the existence of code to provide both forward
and backward conversion between different
versions of types.
The k8s API promises a lossless _conversion_
between versions over a specific range. This
means that a recent client can write an object
bearing the newest possible value for its version,
the server will accept it and store it in
"versionless" JSON form in storage, and can
convert it to a range of older versions should
an older client request data.
For native k8s types, this all requires writing Go
code in the kubernetes core repo, to provide
defaulting and conversions.
For CRDs, there's a [proposal] on how to manage
versioning (e.g. a remote service can offer type
defaulting and conversions).
### Kustomization file versioning
The critical difference between k8s API versioning
and kustomization file versioning is
- A k8s API server is able to go _forward_ and
_backward_ in versioning, to work with older
clients, over [some range].
- The `kustomize edit fix` command only moves
_forward_ within a _major_ program
version.
At the time of writing, the YAML in a
kustomization file does not represent a [k8s API]
object, and the kustomize command and associated
library is neither a server of, nor a client to,
the k8s API.
### Additional Kustomization file rules
In addition to the [field change policy] described
above, kustomization files conform to
the following rules.
#### Eschew classic k8s fields
Field names with dedicated meaning in k8s
(`metadata`, `spec`, `status`, etc.) aren't used.
This is enforced via code review.
#### Optional use of k8s `kind` and `apiVersion`
At the time of writing two [special] k8s
resource fields are allowed, but not required, in
a kustomization file: [`kind`] and [`apiVersion`].
If either field is present, they both must be, and
they must have the following values:
``` yaml
kind: Kustomization
apiVersion: kustomize.config.k8s.io/v1beta1
```
They are allowed to exist and have specific values
in a kustomization file only as a sort of
domain-squatting behavior for some future API. A
kustomize user gains nothing from adding these
fields to a kustomization file.
### Why not require `kind` and `apiVersion`
#### Ease of use and setting proper expectations
Use cases for a kustomization file don't include a
server storing muliple k8s kinds and offering
version downgrades.
The kustomization file is more akin to a
`Makefile`. A kustomize command can either read a
kustomization file, or it cannot, and in the later
case will complain as specifically as possible
about why (e.g. `unknown field Foo`).
So requiring a `kind` and `apiVersion` would just
be boilerplate in a user's files, and in all the
examples and tests.
Nevertheless, _a user still benefits from a
versioning policy_ and has a `fix` command to
upgrade files as needed.
#### We can change our minds
When/if the kustomization struct graduates to some
kind of API status, with an expectation of
"versionless" storage and downgrade capability,
whatever it looks like at that moment can be
locked into `/v1beta1` or `/v1` and the `kind`
and `apiVersion` fields can be required from that
moment forward.
[field change policy]: #field-change-policy
[some range]: https://kubernetes.io/docs/reference/using-api/deprecation-policy
[proposal]: https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/customresources-versioning.md
[beta-level rules]: https://github.com/kubernetes/community/blob/master/contributors/devel/api_changes.md#alpha-beta-and-stable-versions
[changes]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api_changes.md
[adapt]: https://github.com/kubernetes-sigs/kustomize/blob/master/pkg/types/kustomization.go#L166
[special]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#resources
[k8s API]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md
[conventions]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md
[release process]: ../releasing/README.md
[kustomization]: glossary.md#kustomization
[`kind`]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#types-kinds
[`apiVersion`]: https://kubernetes.io/docs/concepts/overview/kubernetes-api/#api-versioning
[semantic versioning]: https://semver.org