-
Notifications
You must be signed in to change notification settings - Fork 198
/
subscription.go
380 lines (313 loc) · 12.7 KB
/
subscription.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
/*
Copyright 2021 The Clusternet Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)
// Important: Run "make generated" to regenerate code after modifying this file
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:subresource:status
// +kubebuilder:resource:scope="Namespaced",shortName=sub;subs,categories=clusternet
// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
// Subscription represents the policy that install a group of resources to one or more clusters.
type Subscription struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec SubscriptionSpec `json:"spec"`
Status SubscriptionStatus `json:"status,omitempty"`
}
// SubscriptionSpec defines the desired state of Subscription
type SubscriptionSpec struct {
// If specified, the Subscription will be handled by specified scheduler.
// If not specified, the Subscription will be handled by default scheduler.
//
// +optional
// +kubebuilder:default=default
SchedulerName string `json:"schedulerName,omitempty"`
// If specified, the Subscription will be handled with SchedulingBySubGroup.
// Used together with SubGroupStrategy in every Subscriber.
// Can work with all supported SchedulingStrategy, such as Replication, Dividing.
//
// +optional
SchedulingBySubGroup *bool `json:"schedulingBySubGroup,omitempty"`
// If specified, the Subscription will be handled with specified SchedulingStrategy.
// Otherwise, with generic SchedulingStrategy.
//
// +optional
// +kubebuilder:validation:Type=string
// +kubebuilder:validation:Enum=Replication;Dividing
// +kubebuilder:default=Replication
SchedulingStrategy SchedulingStrategyType `json:"schedulingStrategy,omitempty"`
// Dividing scheduling config params. Present only if SchedulingStrategy = Dividing.
//
// +optional
DividingScheduling *DividingScheduling `json:"dividingScheduling,omitempty"`
// Subscribers subscribes
//
// +required
// +kubebuilder:validation:Required
Subscribers []Subscriber `json:"subscribers"`
// ClusterTolerations tolerates any matched taints of ManagedCluster.
//
// +optional
ClusterTolerations []corev1.Toleration `json:"clusterTolerations,omitempty"`
// Feeds
//
// +required
// +kubebuilder:validation:Required
Feeds []Feed `json:"feeds"`
}
// SubscriptionStatus defines the observed state of Subscription
type SubscriptionStatus struct {
// Namespaced names of targeted clusters that Subscription binds to.
//
// +optional
BindingClusters []string `json:"bindingClusters,omitempty"`
// Desired replicas of targeted clusters for each feed.
//
// +optional
Replicas map[string][]int32 `json:"replicas,omitempty"`
// SpecHash calculates the hash value of current SubscriptionSpec.
//
// +optional
SpecHash uint64 `json:"specHash,omitempty"`
// Total number of Helm releases desired by this Subscription.
//
// +optional
DesiredReleases int `json:"desiredReleases,omitempty"`
// Total number of completed releases targeted by this Subscription.
//
// +optional
CompletedReleases int `json:"completedReleases,omitempty"`
// AggregatedStatuses shows the aggregated statuses of feeds that are running in each child cluster.
//
// +optional
AggregatedStatuses []AggregatedStatus `json:"aggregatedStatuses,omitempty"`
}
// AggregatedStatus contains aggregated status of current feed.
type AggregatedStatus struct {
// Feed holds references to the resource.
Feed `json:",inline"`
// FeedStatusSummary aggregates the feed statuses from each child cluster.
//
// +optional
FeedStatusSummary FeedStatus `json:"feedStatusSummary,omitempty"`
// FeedStatusDetails shows the feed statuses in each child cluster.
//
// +optional
FeedStatusDetails []FeedStatusPerCluster `json:"feedStatusDetails,omitempty"`
}
// FeedStatusPerCluster shows the feed status running in current cluster.
type FeedStatusPerCluster struct {
// ClusterID indicates the id of current cluster.
//
// +optional
// +kubebuilder:validation:Type=string
// +kubebuilder:validation:Pattern="[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}"
ClusterID types.UID `json:"clusterId,omitempty"`
// ClusterName is the cluster name.
//
// +optional
// +kubebuilder:validation:Type=string
// +kubebuilder:validation:MaxLength=30
// +kubebuilder:validation:Pattern="[a-z0-9]([-a-z0-9]*[a-z0-9])?([a-z0-9]([-a-z0-9]*[a-z0-9]))*"
ClusterName string `json:"clusterName,omitempty"`
// FeedStatus contains the brief feed status in child cluster.
//
// +optional
FeedStatus `json:",inline"`
}
// FeedStatus defines the feed status.
type FeedStatus struct {
// Available indicates whether the feed status is synced successfully to corresponding Description.
//
// +optional
Available bool `json:"available,omitempty"`
// ReplicaStatus indicates the replica status of workload-type feed, such as Deployment/StatefulSet/Job.
//
// +optional
ReplicaStatus `json:"replicaStatus,omitempty"`
}
// ReplicaStatus represents brief information about feed replicas running in child cluster.
// This is used for workload-type feeds.
type ReplicaStatus struct {
// The generation observed by the workload controller.
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
// Total number of non-terminated pods targeted by this workload (their labels match the selector).
// +optional
Replicas int32 `json:"replicas,omitempty"`
// Total number of non-terminated pods targeted by this workload that have the desired template spec.
// +optional
UpdatedReplicas int32 `json:"updatedReplicas,omitempty"`
// currentReplicas is the number of Pods created by the workload controller from the StatefulSet version
// indicated by currentRevision.
// +optional
CurrentReplicas int32 `json:"currentReplicas,omitempty"`
// readyReplicas is the number of pods targeted by this workload with a Ready Condition.
// +optional
ReadyReplicas int32 `json:"readyReplicas,omitempty"`
// Total number of available pods (ready for at least minReadySeconds) targeted by this workload.
// +optional
AvailableReplicas int32 `json:"availableReplicas,omitempty"`
// Total number of unavailable pods targeted by this workload. This is the total number of
// pods that are still required for the workload to have 100% available capacity. They may
// either be pods that are running but not yet available or pods that still have not been created.
// +optional
UnavailableReplicas int32 `json:"unavailableReplicas,omitempty"`
// The number of pending and running pods.
// +optional
Active int32 `json:"active,omitempty"`
// The number of pods which reached phase Succeeded.
// +optional
Succeeded int32 `json:"succeeded,omitempty"`
// The number of pods which reached phase Failed.
// +optional
Failed int32 `json:"failed,omitempty"`
}
// Subscriber defines
type Subscriber struct {
// ClusterAffinity is a label query over managed clusters by labels.
//
// +required
// +kubebuilder:validation:Required
ClusterAffinity *metav1.LabelSelector `json:"clusterAffinity"`
// Static weight of subscriber when dividing replicas.
// Present only for static divided scheduling.
//
// +optional
// +kubebuilder:validation:Minimum=0
Weight int32 `json:"weight,omitempty"`
// SubGroupStrategy defines the subgroup strategy for the clusters matched by this subscriber.
// During the scheduling, all the matching clusters will be treated as a subgroup instead of individual clusters.
// With subgroup, we can describe clusters with different regions, zones, etc.
// Present only when SchedulingBySubGroup is set.
//
// +optional
SubGroupStrategy *SubGroupStrategy `json:"subGroupStrategy,omitempty"`
}
// SubGroupStrategy defines the subgroup strategy
type SubGroupStrategy struct {
// MinClusters is the minimum number of clusters to be selected in this subgroup.
// If this value is more than the total number of clusters in this subgroup, then all clusters will be selected.
//
// +optional
// +kubebuilder:validation:Minimum=0
MinClusters int32 `json:"minClusters,omitempty"`
// TODO: other scenarios
}
// Feed defines the resource to be selected.
type Feed struct {
// Kind is a string value representing the REST resource this object represents.
// In CamelCase.
//
// +required
// +kubebuilder:validation:Required
// +kubebuilder:validation:Type=string
Kind string `json:"kind"`
// APIVersion defines the versioned schema of this representation of an object.
//
// +required
// +kubebuilder:validation:Required
// +kubebuilder:validation:Type=string
APIVersion string `json:"apiVersion"`
// Namespace of the target resource.
//
// +optional
Namespace string `json:"namespace,omitempty"`
// Name of the target resource.
//
// +required
// +kubebuilder:validation:Required
// +kubebuilder:validation:Type=string
Name string `json:"name"`
}
// DividingScheduling describes how to divide replicas into target clusters.
type DividingScheduling struct {
// Type of dividing replica scheduling.
//
// +required
// +kubebuilder:validation:Required
// +kubebuilder:validation:Enum=Static;Dynamic
// +kubebuilder:validation:Type=string
// +kubebuilder:default=Static
Type ReplicaDividingType `json:"type"`
// DynamicDividing describes how to divide replicas into target clusters dynamically.
//
// +optional
DynamicDividing *DynamicDividing `json:"dynamicDividing,omitempty"`
}
// DynamicDividing describes how to divide replicas into target clusters dynamically.
type DynamicDividing struct {
// Type of dynamic dividing replica strategy.
//
// +required
// +kubebuilder:validation:Required
// +kubebuilder:validation:Enum=Spread;Binpack
// +kubebuilder:validation:Type=string
// +kubebuilder:default=Spread
Strategy DynamicDividingStrategy `json:"strategy"`
// TopologySpreadConstraints describes how a group of replicas ought to spread across topology
// domains. Scheduler will schedule pods in a way which abides by the constraints.
// All topologySpreadConstraints are ANDed.
// Present only for spread divided scheduling.
//
// +optional
TopologySpreadConstraints []corev1.TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty"`
// PreferredClusters describes the assigning preference. If we have a preference for cluster group A
// compared to cluster group B (i.e., group A has a larger Weight), desired replicas will be assigned
// to cluster group A as many as possible, while the rest ones will be assigned to cluster group B.
//
// +optional
PreferredClusters []corev1.PreferredSchedulingTerm `json:"preferredClusters,omitempty"`
// MinClusters describes the lower bound number of target clusters.
//
// +optional
MinClusters *int32 `json:"minClusters,omitempty"`
// MaxClusters describes the upper bound number of target clusters.
//
// +optional
MaxClusters *int32 `json:"maxClusters,omitempty"`
}
type SchedulingStrategyType string
const (
// ReplicaSchedulingStrategyType places and maintains a copy of this Subscription on each matched clusters.
ReplicaSchedulingStrategyType SchedulingStrategyType = "Replication"
// DividingSchedulingStrategyType divides the replicas of a Subscription to several matching clusters.
DividingSchedulingStrategyType SchedulingStrategyType = "Dividing"
)
type ReplicaDividingType string
const (
// StaticReplicaDividingType divides replicas by a fixed weight.
StaticReplicaDividingType ReplicaDividingType = "Static"
// DynamicReplicaDividingType divides replicas by cluster resource predictor.
DynamicReplicaDividingType ReplicaDividingType = "Dynamic"
)
type DynamicDividingStrategy string
const (
// SpreadDividingStrategy spreads out replicas as much as possible.
SpreadDividingStrategy DynamicDividingStrategy = "Spread"
// BinpackDividingStrategy aggregates replicas as much as possible.
BinpackDividingStrategy DynamicDividingStrategy = "Binpack"
)
// +kubebuilder:object:root=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// SubscriptionList contains a list of Subscription
type SubscriptionList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []Subscription `json:"items"`
}