Skip to content

Commit 37dcf54

Browse files
authored
Merge pull request #34 from cybozu-go/add-sequential-creation-update
Implement sequential creation and update of NodeImageSets
2 parents 1d5610a + df2a9f2 commit 37dcf54

File tree

3 files changed

+297
-21
lines changed

3 files changed

+297
-21
lines changed

cmd/imageprefetch-controller/main.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ func init() {
3636
}
3737

3838
type Config struct {
39-
imagePullNodeLimit int
39+
imagePullNodeLimit int
40+
maxConcurrentNodeImageSetCreations int
4041
}
4142

4243
func main() {
@@ -59,6 +60,8 @@ func main() {
5960
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
6061
flag.IntVar(&config.imagePullNodeLimit, "image-pull-node-limit", 1,
6162
"The maximum number of nodes that can pull images concurrently.")
63+
flag.IntVar(&config.maxConcurrentNodeImageSetCreations, "max-concurrent-nodeimageset-creations", 1,
64+
"The maximum number of NodeImageSets to create or update concurrently.")
6265
opts := zap.Options{
6366
Development: true,
6467
}
@@ -135,9 +138,10 @@ func main() {
135138
}
136139

137140
if err = (&controller.ImagePrefetchReconciler{
138-
Client: mgr.GetClient(),
139-
Scheme: mgr.GetScheme(),
140-
ImagePullNodeLimit: config.imagePullNodeLimit,
141+
Client: mgr.GetClient(),
142+
Scheme: mgr.GetScheme(),
143+
ImagePullNodeLimit: config.imagePullNodeLimit,
144+
MaxConcurrentNodeImageSetCreations: config.maxConcurrentNodeImageSetCreations,
141145
}).SetupWithManager(mgr); err != nil {
142146
setupLog.Error(err, "unable to create controller", "controller", "ImagePrefetch")
143147
os.Exit(1)

internal/controller/imageprefetch_controller.go

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ import (
4040
// ImagePrefetchReconciler reconciles a ImagePrefetch object
4141
type ImagePrefetchReconciler struct {
4242
client.Client
43-
Scheme *runtime.Scheme
44-
ImagePullNodeLimit int
43+
Scheme *runtime.Scheme
44+
ImagePullNodeLimit int
45+
MaxConcurrentNodeImageSetCreations int
4546
}
4647

4748
// +kubebuilder:rbac:groups=ofen.cybozu.io,resources=imageprefetches,verbs=get;list;watch;create;update;patch;delete
@@ -273,8 +274,22 @@ func scoreNode(node corev1.Node, zoneCount map[string]int) int {
273274
func (r *ImagePrefetchReconciler) createOrUpdateNodeImageSet(ctx context.Context, imgPrefetch *ofenv1.ImagePrefetch, selectedNodes []string) error {
274275
logger := log.FromContext(ctx)
275276

277+
var nodeImageSetList ofenv1.NodeImageSetList
278+
if err := r.List(ctx, &nodeImageSetList, client.MatchingLabels(map[string]string{
279+
constants.OwnerImagePrefetchNamespace: imgPrefetch.Namespace,
280+
constants.OwnerImagePrefetchName: imgPrefetch.Name,
281+
})); err != nil {
282+
return fmt.Errorf("failed to list NodeImageSets: %w", err)
283+
}
284+
285+
maxNodeImageSetsToProcess := getMaxNodeImageSetsToCreate(nodeImageSetList, r.MaxConcurrentNodeImageSetCreations, len(selectedNodes), imgPrefetch.Generation)
276286
selectNodes := map[string]struct{}{}
277287
for i, nodeName := range selectedNodes {
288+
// Limit the number of NodeImageSets created or updated in one reconciliation loop
289+
if i >= maxNodeImageSetsToProcess {
290+
return nil
291+
}
292+
278293
selectNodes[nodeName] = struct{}{}
279294
nodeImageSetName, err := getNodeImageSetName(imgPrefetch, nodeName)
280295
if err != nil {
@@ -308,8 +323,8 @@ func (r *ImagePrefetchReconciler) createOrUpdateNodeImageSet(ctx context.Context
308323
}
309324

310325
// Delete unnecessary NodeImageSets
311-
nodeImageSetList := &ofenv1.NodeImageSetList{}
312-
if err := r.List(ctx, nodeImageSetList, client.MatchingLabels(map[string]string{
326+
nodeImageSetList = ofenv1.NodeImageSetList{}
327+
if err := r.List(ctx, &nodeImageSetList, client.MatchingLabels(map[string]string{
313328
constants.OwnerImagePrefetchNamespace: imgPrefetch.Namespace,
314329
constants.OwnerImagePrefetchName: imgPrefetch.Name,
315330
})); err != nil {
@@ -333,6 +348,23 @@ func (r *ImagePrefetchReconciler) createOrUpdateNodeImageSet(ctx context.Context
333348
return nil
334349
}
335350

351+
func getMaxNodeImageSetsToCreate(currentNodeImageSets ofenv1.NodeImageSetList, maxConcurrentNodeImageSetCreations int, desiredNodeImageSetsCount int, generation int64) int {
352+
var readyNodeImageSetsCount = 0
353+
354+
for _, nodeImageSet := range currentNodeImageSets.Items {
355+
if meta.IsStatusConditionTrue(nodeImageSet.Status.Conditions, ofenv1.ConditionImageAvailable) &&
356+
nodeImageSet.Status.ImagePrefetchGeneration == generation &&
357+
len(nodeImageSet.Spec.Images) == len(nodeImageSet.Status.ContainerImageStatuses) {
358+
readyNodeImageSetsCount++
359+
}
360+
}
361+
362+
if readyNodeImageSetsCount < desiredNodeImageSetsCount {
363+
return readyNodeImageSetsCount + maxConcurrentNodeImageSetCreations
364+
}
365+
return desiredNodeImageSetsCount
366+
}
367+
336368
func (r *ImagePrefetchReconciler) applyNodeImageSet(ctx context.Context, nodeImageSet *ofenv1apply.NodeImageSetApplyConfiguration, name string) error {
337369
obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(nodeImageSet)
338370
if err != nil {

0 commit comments

Comments
 (0)