Skip to content

Commit 03be29e

Browse files
authored
Merge pull request kubernetes#1624 from deads2k/standardize-conditions
provide recommended .status.conditions schema
2 parents 54b4307 + e4e9985 commit 03be29e

File tree

2 files changed

+181
-0
lines changed

2 files changed

+181
-0
lines changed
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
# KEP-1623: Standardize Conditions.
2+
3+
<!-- toc -->
4+
- [Release Signoff Checklist](#release-signoff-checklist)
5+
- [Summary](#summary)
6+
- [Motivation](#motivation)
7+
- [Goals](#goals)
8+
- [Non-Goals](#non-goals)
9+
- [Proposal](#proposal)
10+
- [Noteworthy choices](#noteworthy-choices)
11+
- [Graduation Criteria](#graduation-criteria)
12+
- [Upgrade / Downgrade Strategy](#upgrade--downgrade-strategy)
13+
- [Version Skew Strategy](#version-skew-strategy)
14+
- [Implementation History](#implementation-history)
15+
- [Drawbacks](#drawbacks)
16+
- [Alternatives](#alternatives)
17+
<!-- /toc -->
18+
19+
## Release Signoff Checklist
20+
21+
<!--
22+
**ACTION REQUIRED:** In order to merge code into a release, there must be an
23+
issue in [kubernetes/enhancements] referencing this KEP and targeting a release
24+
milestone **before the [Enhancement Freeze](https://git.k8s.io/sig-release/releases)
25+
of the targeted release**.
26+
27+
For enhancements that make changes to code or processes/procedures in core
28+
Kubernetes i.e., [kubernetes/kubernetes], we require the following Release
29+
Signoff checklist to be completed.
30+
31+
Check these off as they are completed for the Release Team to track. These
32+
checklist items _must_ be updated for the enhancement to be released.
33+
-->
34+
35+
- [ ] Enhancement issue in release milestone, which links to KEP dir in [kubernetes/enhancements] (not the initial KEP PR)
36+
- [ ] KEP approvers have approved the KEP status as `implementable`
37+
- [ ] Design details are appropriately documented
38+
- [ ] Test plan is in place, giving consideration to SIG Architecture and SIG Testing input
39+
- [ ] Graduation criteria is in place
40+
- [ ] "Implementation History" section is up-to-date for milestone
41+
- [ ] User-facing documentation has been created in [kubernetes/website], for publication to [kubernetes.io]
42+
- [ ] Supporting documentation e.g., additional design documents, links to mailing list discussions/SIG meetings, relevant PRs/issues, release notes
43+
44+
<!--
45+
**Note:** This checklist is iterative and should be reviewed and updated every time this enhancement is being considered for a milestone.
46+
-->
47+
48+
[kubernetes.io]: https://kubernetes.io/
49+
[kubernetes/enhancements]: https://git.k8s.io/enhancements
50+
[kubernetes/kubernetes]: https://git.k8s.io/kubernetes
51+
[kubernetes/website]: https://git.k8s.io/website
52+
53+
## Summary
54+
55+
While many Kuberentes APIs have `.status.conditions`, the schema of `condition` varies a lot between them.
56+
There is very little commonality at the level of serialization, proto-encoding, and required vs optional.
57+
Conditions are central enough to the API to make a common golang type with a fixed schema.
58+
The schema can be a strong recommendation to all API authors.
59+
60+
## Motivation
61+
62+
Allow general consumers to expect a common schema for `.status.conditions` and share golang logic for common Get, Set, Is for `.status.conditions`.
63+
The pattern is well-established and we have a good sense of the schema we now want.
64+
65+
### Goals
66+
67+
1. For all new APIs, have a common type for `.status.conditions`.
68+
2. Provide common utility methods for `HasCondition`, `IsConditionTrue`, `SetCondition`, etc.
69+
3. Provide recommended defaulting functions that set required fields and can be embedded into conversion/default functions.
70+
71+
### Non-Goals
72+
73+
1. Update all existing APIs to make use of the new condition type.
74+
75+
## Proposal
76+
77+
Introduce a type into k8s.io/apimachinery/pkg/apis/meta/v1 for `Condition` that looks like
78+
```go
79+
type Condition struct {
80+
// Type of condition in CamelCase or in foo.example.com/CamelCase.
81+
// Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
82+
// useful (see .node.status.conditions), the ability to deconflict is important.
83+
// +required
84+
Type string `json:"type" protobuf:"bytes,1,opt,name=type"`
85+
// Status of the condition, one of True, False, Unknown.
86+
// +required
87+
Status ConditionStatus `json:"status" protobuf:"bytes,2,opt,name=status"`
88+
// If set, this represents the .metadata.generation that the condition was set based upon.
89+
// For instance, if .metadata.generation is currently 12, but the .status.condition[x].observedGeneration is 9, the condition is out of date
90+
// with respect to the current state of the instance.
91+
// +optional
92+
ObservedGeneration int64 `json:"observedGeneration,omitempty" protobuf:"varint,3,opt,name=observedGeneration"`
93+
// Last time the condition transitioned from one status to another.
94+
// This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
95+
// +required
96+
LastTransitionTime metav1.Time `json:"lastTransitionTime" protobuf:"bytes,4,opt,name=lastTransitionTime"`
97+
// The reason for the condition's last transition in CamelCase.
98+
// The specific API may choose whether or not this field is considered a guaranteed API.
99+
// This field may not be empty.
100+
// +required
101+
Reason string `json:"reason" protobuf:"bytes,5,opt,name=reason"`
102+
// A human readable message indicating details about the transition.
103+
// This field may be empty.
104+
// +required
105+
Message string `json:"message" protobuf:"bytes,6,opt,name=message"`
106+
}
107+
```
108+
109+
This is not strictly compatible with any of our existing conditions because of either proto ordinals,
110+
required vs optional, or omitEmpty or not.
111+
However, it encapsulates the best of what we've learned and will allow new APIs to have a unified type.
112+
113+
### Noteworthy choices
114+
1. `lastTransitionTime` is required.
115+
Some current implementations allow this to be missing, but this makes it difficult for consumers.
116+
By requiring it, the actor setting the field can set it to the best possible value instead of having clients try to guess.
117+
2. `reason` is required and must not be empty.
118+
The actor setting the value should always describe why the condition is the way it is, even if that value is "unknown unknowns".
119+
No other actor has the information to make a better choice.
120+
3. `lastHeartbeatTime` is removed.
121+
This field caused excessive write loads as we scaled.
122+
If an API needs this concept, it should codify it separately and possibly using a different resource.
123+
4. `observedGeneration` does not follow the standard requirement of "all optional fields are pointers".
124+
This rule originated from the need to distinguish intent of zero value versus unset.
125+
The `.metadata.generation` is never set to zero.
126+
See the [CR strategy](https://github.com/kubernetes/apiextensions-apiserver/blob/release-1.18/pkg/registry/customresource/strategy.go#L88)
127+
and [deployment strategy](https://github.com/kubernetes/kubernetes/blob/release-1.18/pkg/registry/apps/deployment/strategy.go)
128+
as examples.
129+
Because `.metadata.generation` is never zero-value, it is not necessary to distinguish between absent and zero-value observedGeneration.
130+
Whether a client omits `observedGeneration` (because it is unaware of the new field) or explicitly sets it to 0, the
131+
meaning is the same: the condition does not correspond to a known generation.
132+
This also provides parity the `.metadata.generation` field [Generation int64 \`json:"generation,omitempty" protobuf:"varint,7,opt,name=generation"\`](https://github.com/kubernetes/apimachinery/blob/release-1.18/pkg/apis/meta/v1/types.go#L182-L185).
133+
134+
### Graduation Criteria
135+
136+
Because meta/v1 APIs are necessarily v1, this would go direct to GA.
137+
Using a meta/v1beta1 isn't a meaningful distinction since this type is embedded into other types which own their own versions.
138+
139+
### Upgrade / Downgrade Strategy
140+
141+
This KEP isn't proposing that existing types be changed.
142+
This means that individual upgrade/downgrade situations will be handled discretely.
143+
By providing recommended defaulting functions, individual APIs will be able to more easily transition to the new condition type.
144+
145+
### Version Skew Strategy
146+
147+
Standard defaulting and conversion will apply.
148+
APIs which have extra values for this type may have to go through an intermediate version that drops them or accept
149+
that certain optional fields of their conditions will be dropped.
150+
Depending on the individual APIs and when their extra fields are deprecated, this could be acceptable choice.
151+
152+
## Implementation History
153+
154+
## Drawbacks
155+
156+
1. There may be some one-time pain when new versions are created for APIs that wish to consume this common schema.
157+
Switching is not strictly required, but it is encouraged.
158+
159+
## Alternatives
160+
161+
1. We could recommend a schema and not provide one. This doesn't seem very nice to consumers.
162+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
title: KEP Template
2+
kep-number: 1623
3+
authors:
4+
- "@deads2k"
5+
owning-sig: sig-api-machinery
6+
participating-sigs:
7+
- sig-api-machinery
8+
- sig-apps
9+
- sig-architecture
10+
status: implementable
11+
creation-date: 2020-03-23
12+
reviewers:
13+
- "@lavalamp"
14+
- "@smarterclayton"
15+
approvers:
16+
- "@derekwaynecarr"
17+
- "@liggitt"
18+
see-also:
19+
replaces:

0 commit comments

Comments
 (0)