Deprecate templateGeneration, use controller history instead of PodTemplate, add hash collision avoidance
This commit is contained in:
parent
99edd7b7b2
commit
b79c90d8b8
|
|
@ -118,12 +118,13 @@ type DaemonSetSpec struct {
|
||||||
// +optional
|
// +optional
|
||||||
MinReadySeconds int32 `json:"minReadySeconds,omitempty"`
|
MinReadySeconds int32 `json:"minReadySeconds,omitempty"`
|
||||||
|
|
||||||
|
// DEPRECATED.
|
||||||
// A sequence number representing a specific generation of the template.
|
// A sequence number representing a specific generation of the template.
|
||||||
// Populated by the system. Can be set at creation time. Read-only otherwise.
|
// Populated by the system. Can be set at creation time. Read-only otherwise.
|
||||||
// +optional
|
// +optional
|
||||||
TemplateGeneration int64 `json:"templateGeneration,omitempty"`
|
TemplateGeneration int64 `json:"templateGeneration,omitempty"`
|
||||||
|
|
||||||
// The number of old PodTemplates to retain to allow rollback.
|
// The number of old history to retain to allow rollback.
|
||||||
// This is a pointer to distinguish between explicit zero and not specified.
|
// This is a pointer to distinguish between explicit zero and not specified.
|
||||||
// Defaults to 2.
|
// Defaults to 2.
|
||||||
RevisionHistoryLimit *int32 `json:"revisionHistoryLimit,omitempty"`
|
RevisionHistoryLimit *int32 `json:"revisionHistoryLimit,omitempty"`
|
||||||
|
|
@ -168,13 +169,25 @@ type DaemonSetStatus struct {
|
||||||
// (ready for at least minReadySeconds)
|
// (ready for at least minReadySeconds)
|
||||||
// +optional
|
// +optional
|
||||||
NumberUnavailable int32 `json:"numberUnavailable"`
|
NumberUnavailable int32 `json:"numberUnavailable"`
|
||||||
|
|
||||||
|
// A monotonically increasing counter that tracks hash collisions for
|
||||||
|
// the DaemonSet. Used as a collision avoidance mechanism by the
|
||||||
|
// DaemonSet controller.
|
||||||
|
// +optional
|
||||||
|
Uniquifier *int64 `json:"uniquifier,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// DEPRECATED: DefaultDeploymentUniqueLabelKey is used instead.
|
||||||
// DaemonSetTemplateGenerationKey is the key of the labels that is added
|
// DaemonSetTemplateGenerationKey is the key of the labels that is added
|
||||||
// to daemon set pods and history to distinguish between old and new pod
|
// to daemon set pods to distinguish between old and new pod
|
||||||
// templates during DaemonSet template update.
|
// during DaemonSet template update.
|
||||||
DaemonSetTemplateGenerationKey string = "pod-template-generation"
|
DaemonSetTemplateGenerationKey string = "pod-template-generation"
|
||||||
|
|
||||||
|
// DefaultDaemonSetUniqueLabelKey is the default label key that is added
|
||||||
|
// to existing DaemonSet pods to distinguish between old and new
|
||||||
|
// DaemonSet pods during DaemonSet template updates.
|
||||||
|
DefaultDaemonSetUniqueLabelKey string = "pod-template-hash"
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -185,43 +198,57 @@ const (
|
||||||
The DaemonSet Controller will make DaemonSet updates happen. It will watch
|
The DaemonSet Controller will make DaemonSet updates happen. It will watch
|
||||||
DaemonSets on the apiserver.
|
DaemonSets on the apiserver.
|
||||||
|
|
||||||
|
DaemonSet controller manages [Controller History](controller_history.md) for
|
||||||
|
DaemonSet revision introspection and rollback. It's referred to as "history"
|
||||||
|
throughout the rest of this proposal.
|
||||||
|
|
||||||
For each pending DaemonSet updates, it will:
|
For each pending DaemonSet updates, it will:
|
||||||
|
|
||||||
1. Find all pods controlled by DaemonSet
|
1. Find all pods controlled by DaemonSet
|
||||||
1. Check `DaemonSetUpdateStrategy`:
|
1. Check `DaemonSetUpdateStrategy`:
|
||||||
- If `OnDelete`: do nothing
|
- If `OnDelete`: do nothing
|
||||||
- If `RollingUpdate`:
|
- If `RollingUpdate`:
|
||||||
- Find existing PodTemplates owned by DaemonSet, and sort them by the value
|
- Reconstruct DaemonSet history: filter and sort existing DaemonSet history
|
||||||
of `pod-template-generation` label
|
owned by this DaemonSet
|
||||||
- Clean up PodTemplates based on `.spec.revisionHistoryLimit`
|
- Find the history of DaemonSet's current target state, and create one if
|
||||||
- Always keep the PodTemplate if its `pod-template-generation` label has
|
not found:
|
||||||
the same value of any existing pods owned by the DaemonSet
|
- The `.name` of this history will be unique, generated from pod template
|
||||||
- Remove PodTemplates from the ones with the smallest `pod-template-generation`
|
hash with hash collision resolution. If history creation failed:
|
||||||
to the highest, until `.spec.revisionHistoryLimit` is hit or no
|
- If it's because of name collision:
|
||||||
PodTemplates are allowed to be removed
|
- Compare history with DaemonSet current target state:
|
||||||
- Create a PodTemplate based on DaemonSet
|
- If they're the same, we've already created the history
|
||||||
- PodTemplate `.name` is from DaemonSet `<.name>-<.spec.templateGeneration>`
|
- Otherwise, bump DaemonSet `.status.uniquifier` by 1, exit and
|
||||||
- PodTemplate labels are generated from DaemonSet `.spec.selector`, in
|
retry in the next sync loop
|
||||||
addition to label `pod-template-generation=.spec.templateGeneration`
|
- Otherwise, exit and retry again in the next sync loop.
|
||||||
- PodTemplate's `.spec` is copied from DaemonSet `.spec.template.spec`
|
- The history will be labeled with `pod-template-hash`.
|
||||||
- PodTemplate's `.metadata.annotations` is copied from DaemonSet
|
- DaemonSet controller will add a ControllerRef in the history
|
||||||
`.metadata.annotations`
|
`.ownerReferences`.
|
||||||
- For all pods owned by this DaemonSet:
|
- For all pods owned by this DaemonSet:
|
||||||
- If it doesn't have `pod-template-generation` label, it's an old pod
|
- If its `pod-template-generation` label value equals to DaemonSet's
|
||||||
- If its `pod-template-generation` label value equals to the latest
|
`.spec.templateGeneration`, it's a new pod (don't compare
|
||||||
PodTemplate, it's a new pod
|
`pod-template-hash`, for backward compatibility).
|
||||||
- If its `pod-template-generation` label value equals to a PodTemplate
|
- Add `pod-template-hash` label to the new pod based on current
|
||||||
whose template is the same as the latest PodTemplate, it's a new pod
|
history, if the pod doesn't have this label set yet.
|
||||||
that needs to be relabeled
|
- Otherwise, if the value doesn't match, or the pod doesn't have a
|
||||||
- Otherwise, it's an old pod
|
`pod-template-generation` label, check its `pod-template-hash` label:
|
||||||
|
- If the value matches any of the history's `pod-template-hash` label,
|
||||||
|
it's a pod generated from that history.
|
||||||
|
- If that history matches the current target state of the DaemonSet,
|
||||||
|
it's a new pod.
|
||||||
|
- Otherwise, it's an old pod.
|
||||||
|
- Otherwise, if the pod doesn't have a `pod-template-hash` label, or no
|
||||||
|
matching history is found, it's an old pod.
|
||||||
- If there are old pods found, compare `MaxUnavailable` with DaemonSet
|
- If there are old pods found, compare `MaxUnavailable` with DaemonSet
|
||||||
`.status.numberUnavailable` to see how many old daemon pods can be
|
`.status.numberUnavailable` to see how many old daemon pods can be
|
||||||
killed. Then, kill those pods in the order that unhealthy pods (failed,
|
killed. Then, kill those pods in the order that unhealthy pods (failed,
|
||||||
pending, not ready) are killed first.
|
pending, not ready) are killed first.
|
||||||
- Relabel new pods with current `.spec.templateGeneration`
|
- Clean up history based on `.spec.revisionHistoryLimit`
|
||||||
|
- Always keep live history
|
||||||
1. Find all nodes that should run these pods created by this DaemonSet.
|
1. Find all nodes that should run these pods created by this DaemonSet.
|
||||||
1. Create daemon pods on nodes when they should have those pods running but not
|
1. Create daemon pods on nodes when they should have those pods running but not
|
||||||
yet. Otherwise, delete running daemon pods that shouldn't be running on nodes.
|
yet. Otherwise, delete running daemon pods that shouldn't be running on nodes.
|
||||||
|
- Label new pods with current `.spec.templateGeneration` and
|
||||||
|
`pod-template-hash` value of current history when creating them.
|
||||||
1. Cleanup, update DaemonSet status
|
1. Cleanup, update DaemonSet status
|
||||||
- `.status.numberAvailable` = the total number of DaemonSet pods that have
|
- `.status.numberAvailable` = the total number of DaemonSet pods that have
|
||||||
become `Ready` for `MinReadySeconds`
|
become `Ready` for `MinReadySeconds`
|
||||||
|
|
@ -245,8 +272,7 @@ Users can use `kubectl rollout` to monitor DaemonSet updates:
|
||||||
- `kubectl rollout status daemonset/<DaemonSet-Name>`: to see the DaemonSet
|
- `kubectl rollout status daemonset/<DaemonSet-Name>`: to see the DaemonSet
|
||||||
upgrade status
|
upgrade status
|
||||||
- `kubectl rollout history daemonset/<DaemonSet-Name>`: to view the history of
|
- `kubectl rollout history daemonset/<DaemonSet-Name>`: to view the history of
|
||||||
DaemonSet updates. We use `PodTemplate` created by DaemonSets to store update
|
DaemonSet updates.
|
||||||
history.
|
|
||||||
- `kubectl rollout undo daemonset/<DaemonSet-Name>`: to rollback a DaemonSet
|
- `kubectl rollout undo daemonset/<DaemonSet-Name>`: to rollback a DaemonSet
|
||||||
|
|
||||||
#### API
|
#### API
|
||||||
|
|
@ -266,8 +292,7 @@ one will begin rolling out.
|
||||||
|
|
||||||
## Deleting DaemonSets
|
## Deleting DaemonSets
|
||||||
|
|
||||||
Deleting a DaemonSet (with cascading) will delete all its pods and history
|
Deleting a DaemonSet (with cascading) will delete all its pods and history.
|
||||||
(PodTemplates).
|
|
||||||
|
|
||||||
|
|
||||||
## DaemonSet Strategies
|
## DaemonSet Strategies
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue