Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor daemonset controller and fetch upstream codebase #883

Merged
merged 1 commit into from
Feb 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 20 additions & 17 deletions apis/apps/defaults/v1alpha1.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,33 +260,36 @@ func SetDefaultsDaemonSet(obj *v1alpha1.DaemonSet) {

if obj.Spec.UpdateStrategy.Type == "" {
obj.Spec.UpdateStrategy.Type = v1alpha1.RollingUpdateDaemonSetStrategyType

// UpdateStrategy.RollingUpdate will take default values below.
obj.Spec.UpdateStrategy.RollingUpdate = &v1alpha1.RollingUpdateDaemonSet{}
}

if obj.Spec.UpdateStrategy.Type == v1alpha1.RollingUpdateDaemonSetStrategyType {
if obj.Spec.UpdateStrategy.RollingUpdate == nil {
obj.Spec.UpdateStrategy.RollingUpdate = &v1alpha1.RollingUpdateDaemonSet{}
}
if obj.Spec.UpdateStrategy.RollingUpdate.Partition == nil {
obj.Spec.UpdateStrategy.RollingUpdate.Partition = new(int32)
*obj.Spec.UpdateStrategy.RollingUpdate.Partition = 0

// Make it compatible with the predicated Surging
if obj.Spec.UpdateStrategy.RollingUpdate.Type == v1alpha1.DeprecatedSurgingRollingUpdateType {
if obj.Spec.UpdateStrategy.RollingUpdate.MaxSurge == nil {
maxSurge := intstr.FromInt(1)
obj.Spec.UpdateStrategy.RollingUpdate.MaxSurge = &maxSurge
}
if obj.Spec.UpdateStrategy.RollingUpdate.MaxUnavailable == nil {
maxUnavailable := intstr.FromInt(0)
obj.Spec.UpdateStrategy.RollingUpdate.MaxUnavailable = &maxUnavailable
}
}

// Default and convert to Standard
if obj.Spec.UpdateStrategy.RollingUpdate.Type == "" || obj.Spec.UpdateStrategy.RollingUpdate.Type == v1alpha1.DeprecatedSurgingRollingUpdateType {
obj.Spec.UpdateStrategy.RollingUpdate.Type = v1alpha1.StandardRollingUpdateType
}

if obj.Spec.UpdateStrategy.RollingUpdate.MaxUnavailable == nil {
maxUnavailable := intstr.FromInt(1)
obj.Spec.UpdateStrategy.RollingUpdate.MaxUnavailable = &maxUnavailable
}

if obj.Spec.UpdateStrategy.RollingUpdate.Type == "" {
obj.Spec.UpdateStrategy.RollingUpdate.Type = v1alpha1.StandardRollingUpdateType
}
// Only when RollingUpdate Type is SurgingRollingUpdateType, it need to initialize the MaxSurge.
if obj.Spec.UpdateStrategy.RollingUpdate.Type == v1alpha1.SurgingRollingUpdateType {
if obj.Spec.UpdateStrategy.RollingUpdate.MaxSurge == nil {
MaxSurge := intstr.FromInt(1)
obj.Spec.UpdateStrategy.RollingUpdate.MaxSurge = &MaxSurge
}
if obj.Spec.UpdateStrategy.RollingUpdate.MaxSurge == nil {
MaxSurge := intstr.FromInt(0)
obj.Spec.UpdateStrategy.RollingUpdate.MaxSurge = &MaxSurge
}
}

Expand Down
142 changes: 61 additions & 81 deletions apis/apps/v1alpha1/daemonset_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package v1alpha1

import (
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
Expand All @@ -26,11 +27,11 @@ import (
type DaemonSetUpdateStrategy struct {
// Type of daemon set update. Can be "RollingUpdate" or "OnDelete". Default is RollingUpdate.
// +optional
Type DaemonSetUpdateStrategyType `json:"type,omitempty" protobuf:"bytes,1,opt,name=type"`
Type DaemonSetUpdateStrategyType `json:"type,omitempty"`

// Rolling update config params. Present only if type = "RollingUpdate".
// +optional
RollingUpdate *RollingUpdateDaemonSet `json:"rollingUpdate,omitempty" protobuf:"bytes,2,opt,name=rollingUpdate"`
RollingUpdate *RollingUpdateDaemonSet `json:"rollingUpdate,omitempty"`
}

type DaemonSetUpdateStrategyType string
Expand All @@ -43,69 +44,76 @@ const (
// Replace the old daemons only when it's killed
OnDeleteDaemonSetStrategyType DaemonSetUpdateStrategyType = "OnDelete"

// StandardRollingUpdateType replace the old daemons by new ones using rolling update i.e replace them on each node one after the other.
// this is the default type for RollingUpdate.
// StandardRollingUpdateType is the Standard way that update pods with recreation that sames to the upstream DaemonSet.
StandardRollingUpdateType RollingUpdateType = "Standard"

// Replace container image without killing the pod.
// InplaceRollingUpdateType update container image without killing the pod if possible.
InplaceRollingUpdateType RollingUpdateType = "InPlaceIfPossible"

// SurgingRollingUpdateType replaces the old daemons by new ones using rolling update i.e replace them on each node one
// after the other, creating the new pod and then killing the old one.
SurgingRollingUpdateType RollingUpdateType = "Surging"
// DeprecatedSurgingRollingUpdateType is a depreciated alias for Standard.
// Deprecated: Just use Standard instead.
DeprecatedSurgingRollingUpdateType RollingUpdateType = "Surging"
)

// Spec to control the desired behavior of daemon set rolling update.
type RollingUpdateDaemonSet struct {
// Type is to specify which kind of rollingUpdate.
Type RollingUpdateType `json:"rollingUpdateType,omitempty" protobuf:"bytes,1,opt,name=rollingUpdateType"`
Type RollingUpdateType `json:"rollingUpdateType,omitempty"`

// The maximum number of DaemonSet pods that can be unavailable during the
// update. Value can be an absolute number (ex: 5) or a percentage of total
// number of DaemonSet pods at the start of the update (ex: 10%). Absolute
// number is calculated from percentage by rounding up.
// This cannot be 0.
// This cannot be 0 if MaxSurge is 0
// Default value is 1.
// Example: when this is set to 30%, at most 30% of the total number of nodes
// that should be running the daemon pod (i.e. status.desiredNumberScheduled)
// can have their pods stopped for an update at any given
// time. The update starts by stopping at most 30% of those DaemonSet pods
// and then brings up new DaemonSet pods in their place. Once the new pods
// are available, it then proceeds onto other DaemonSet pods, thus ensuring
// that at least 70% of original number of DaemonSet pods are available at
// all times during the update.
// +optional
MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty" protobuf:"bytes,2,opt,name=maxUnavailable"`
// can have their pods stopped for an update at any given time. The update
// starts by stopping at most 30% of those DaemonSet pods and then brings
// up new DaemonSet pods in their place. Once the new pods are available,
// it then proceeds onto other DaemonSet pods, thus ensuring that at least
// 70% of original number of DaemonSet pods are available at all times during
// the update.
// +optional
MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty"`

// The maximum number of nodes with an existing available DaemonSet pod that
// can have an updated DaemonSet pod during during an update.
// Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%).
// This can not be 0 if MaxUnavailable is 0.
// Absolute number is calculated from percentage by rounding up to a minimum of 1.
// Default value is 0.
// Example: when this is set to 30%, at most 30% of the total number of nodes
// that should be running the daemon pod (i.e. status.desiredNumberScheduled)
// can have their a new pod created before the old pod is marked as deleted.
// The update starts by launching new pods on 30% of nodes. Once an updated
// pod is available (Ready for at least minReadySeconds) the old DaemonSet pod
// on that node is marked deleted. If the old pod becomes unavailable for any
// reason (Ready transitions to false, is evicted, or is drained) an updated
// pod is immediatedly created on that node without considering surge limits.
// Allowing surge implies the possibility that the resources consumed by the
// daemonset on any given node can double if the readiness check fails, and
// so resource intensive daemonsets should take into account that they may
// cause evictions during disruption.
// This is beta field and enabled/disabled by DaemonSetUpdateSurge feature gate.
// +optional
MaxSurge *intstr.IntOrString `json:"maxSurge,omitempty"`

// A label query over nodes that are managed by the daemon set RollingUpdate.
// Must match in order to be controlled.
// It must match the node's labels.
Selector *metav1.LabelSelector `json:"selector,omitempty" protobuf:"bytes,3,opt,name=selector"`
Selector *metav1.LabelSelector `json:"selector,omitempty"`

// The number of DaemonSet pods remained to be old version.
// Default value is 0.
// Maximum value is status.DesiredNumberScheduled, which means no pod will be updated.
// +optional
Partition *int32 `json:"partition,omitempty" protobuf:"varint,4,opt,name=partition"`
Partition *int32 `json:"partition,omitempty"`

// Indicates that the daemon set is paused and will not be processed by the
// daemon set controller.
// +optional
Paused *bool `json:"paused,omitempty" protobuf:"varint,5,opt,name=paused"`

// Only when type=SurgingRollingUpdateType, it works.
// The maximum number of DaemonSet pods that can be scheduled above the desired number of pods
// during the update. Value can be an absolute number (ex: 5) or a percentage of the total number
// of DaemonSet pods at the start of the update (ex: 10%). The absolute number is calculated from
// the percentage by rounding up. This cannot be 0. The default value is 1. Example: when this is
// set to 30%, at most 30% of the total number of nodes that should be running the daemon pod
// (i.e. status.desiredNumberScheduled) can have 2 pods running at any given time. The update
// starts by starting replacements for at most 30% of those DaemonSet pods. Once the new pods are
// available it then stops the existing pods before proceeding onto other DaemonSet pods, thus
// ensuring that at most 130% of the desired final number of DaemonSet pods are running at all
// times during the update.
// +optional
MaxSurge *intstr.IntOrString `json:"maxSurge,omitempty" protobuf:"bytes,7,opt,name=maxSurge"`
Paused *bool `json:"paused,omitempty"`
}

// DaemonSetSpec defines the desired state of DaemonSet
Expand All @@ -117,7 +125,7 @@ type DaemonSetSpec struct {
// Must match in order to be controlled.
// It must match the pod template's labels.
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors
Selector *metav1.LabelSelector `json:"selector" protobuf:"bytes,1,opt,name=selector"`
Selector *metav1.LabelSelector `json:"selector"`

// An object that describes the pod that will be created.
// The DaemonSet will create exactly one copy of this pod on every node
Expand All @@ -126,28 +134,28 @@ type DaemonSetSpec struct {
// More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#pod-template
// +kubebuilder:pruning:PreserveUnknownFields
// +kubebuilder:validation:Schemaless
Template corev1.PodTemplateSpec `json:"template" protobuf:"bytes,2,opt,name=template"`
Template corev1.PodTemplateSpec `json:"template"`

// An update strategy to replace existing DaemonSet pods with new pods.
// +optional
UpdateStrategy DaemonSetUpdateStrategy `json:"updateStrategy,omitempty" protobuf:"bytes,3,opt,name=updateStrategy"`
UpdateStrategy DaemonSetUpdateStrategy `json:"updateStrategy,omitempty"`

// The minimum number of seconds for which a newly created DaemonSet pod should
// be ready without any of its container crashing, for it to be considered
// available. Defaults to 0 (pod will be considered available as soon as it
// is ready).
// +optional
MinReadySeconds int32 `json:"minReadySeconds,omitempty" protobuf:"varint,4,opt,name=minReadySeconds"`
MinReadySeconds int32 `json:"minReadySeconds,omitempty"`

// BurstReplicas is a rate limiter for booting pods on a lot of pods.
// The default value is 250
BurstReplicas *intstr.IntOrString `json:"burstReplicas,omitempty" protobuf:"bytes,5,opt,name=burstReplicas"`
BurstReplicas *intstr.IntOrString `json:"burstReplicas,omitempty"`

// The number of old history to retain to allow rollback.
// This is a pointer to distinguish between explicit zero and not specified.
// Defaults to 10.
// +optional
RevisionHistoryLimit *int32 `json:"revisionHistoryLimit,omitempty" protobuf:"varint,6,opt,name=revisionHistoryLimit"`
RevisionHistoryLimit *int32 `json:"revisionHistoryLimit,omitempty"`
}

// DaemonSetStatus defines the observed state of DaemonSet
Expand All @@ -158,90 +166,62 @@ type DaemonSetStatus struct {
// The number of nodes that are running at least 1
// daemon pod and are supposed to run the daemon pod.
// More info: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/
CurrentNumberScheduled int32 `json:"currentNumberScheduled" protobuf:"varint,1,opt,name=currentNumberScheduled"`
CurrentNumberScheduled int32 `json:"currentNumberScheduled"`

// The number of nodes that are running the daemon pod, but are
// not supposed to run the daemon pod.
// More info: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/
NumberMisscheduled int32 `json:"numberMisscheduled" protobuf:"varint,2,opt,name=numberMisscheduled"`
NumberMisscheduled int32 `json:"numberMisscheduled"`

// The total number of nodes that should be running the daemon
// pod (including nodes correctly running the daemon pod).
// More info: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/
DesiredNumberScheduled int32 `json:"desiredNumberScheduled" protobuf:"varint,3,opt,name=desiredNumberScheduled"`
DesiredNumberScheduled int32 `json:"desiredNumberScheduled"`

// The number of nodes that should be running the daemon pod and have one
// or more of the daemon pod running and ready.
NumberReady int32 `json:"numberReady" protobuf:"varint,4,opt,name=numberReady"`
NumberReady int32 `json:"numberReady"`

// The most recent generation observed by the daemon set controller.
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty" protobuf:"varint,5,opt,name=observedGeneration"`
ObservedGeneration int64 `json:"observedGeneration,omitempty"`

// The total number of nodes that are running updated daemon pod
UpdatedNumberScheduled int32 `json:"updatedNumberScheduled" protobuf:"varint,6,opt,name=updatedNumberScheduled"`
UpdatedNumberScheduled int32 `json:"updatedNumberScheduled"`

// The number of nodes that should be running the
// daemon pod and have one or more of the daemon pod running and
// available (ready for at least spec.minReadySeconds)
// +optional
NumberAvailable int32 `json:"numberAvailable,omitempty" protobuf:"varint,7,opt,name=numberAvailable"`
NumberAvailable int32 `json:"numberAvailable,omitempty"`

// The number of nodes that should be running the
// daemon pod and have none of the daemon pod running and available
// (ready for at least spec.minReadySeconds)
// +optional
NumberUnavailable int32 `json:"numberUnavailable,omitempty" protobuf:"varint,8,opt,name=numberUnavailable"`
NumberUnavailable int32 `json:"numberUnavailable,omitempty"`

// Count of hash collisions for the DaemonSet. The DaemonSet controller
// uses this field as a collision avoidance mechanism when it needs to
// create the name for the newest ControllerRevision.
// +optional
CollisionCount *int32 `json:"collisionCount,omitempty" protobuf:"varint,9,opt,name=collisionCount"`
CollisionCount *int32 `json:"collisionCount,omitempty"`

// Represents the latest available observations of a DaemonSet's current state.
// +optional
// +patchMergeKey=type
// +patchStrategy=merge
Conditions []DaemonSetCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,10,rep,name=conditions"`
Conditions []appsv1.DaemonSetCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`

// DaemonSetHash is the controller-revision-hash, which represents the latest version of the DaemonSet.
DaemonSetHash string `json:"daemonSetHash" protobuf:"bytes,11,opt,name=daemonSetHash"`
DaemonSetHash string `json:"daemonSetHash"`
}

type DaemonSetConditionType string

// TODO: Add valid condition types of a DaemonSet.

// DaemonSetCondition describes the state of a DaemonSet at a certain point.
type DaemonSetCondition struct {
// Type of DaemonSet condition.
Type DaemonSetConditionType `json:"type" protobuf:"bytes,1,opt,name=type,casttype=DaemonSetConditionType"`
// Status of the condition, one of True, False, Unknown.
Status corev1.ConditionStatus `json:"status" protobuf:"bytes,2,opt,name=status,casttype=k8s.io/api/core/v1.ConditionStatus"`
// Last time the condition transitioned from one status to another.
// +optional
LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty" protobuf:"bytes,3,opt,name=lastTransitionTime"`
// The reason for the condition's last transition.
// +optional
Reason string `json:"reason,omitempty" protobuf:"bytes,4,opt,name=reason"`
// A human readable message indicating details about the transition.
// +optional
Message string `json:"message,omitempty" protobuf:"bytes,5,opt,name=message"`
}

const (
// 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 = ControllerRevisionHashLabelKey
)

// +genclient
// +k8s:openapi-gen=true
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:shortName=daemon
// +kubebuilder:resource:shortName=daemon;ads
// +kubebuilder:printcolumn:name="DesiredNumber",type="integer",JSONPath=".status.desiredNumberScheduled",description="The desired number of pods."
// +kubebuilder:printcolumn:name="CurrentNumber",type="integer",JSONPath=".status.currentNumberScheduled",description="The current number of pods."
// +kubebuilder:printcolumn:name="UpdatedNumberScheduled",type="integer",JSONPath=".status.updatedNumberScheduled",description="The updated number of pods."
Expand Down
28 changes: 6 additions & 22 deletions apis/apps/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading