Skip to content

Commit 632f382

Browse files
awesomenixCopilot
andcommitted
Use containerd GC for image-fetcher cleanup
Mark unpacked pulled layers as GC-eligible during VHD image preloading and trigger a single synchronous containerd GC after the preload batch. This avoids scanning all images per pull while preserving fetch-only image blobs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 7a4da12 commit 632f382

File tree

2 files changed

+28
-2
lines changed

2 files changed

+28
-2
lines changed

image-fetcher/main.go

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ import (
55
"fmt"
66
"os"
77
"runtime"
8+
"time"
89

910
containerd "github.com/containerd/containerd/v2/client"
11+
"github.com/containerd/containerd/v2/core/images"
12+
"github.com/containerd/containerd/v2/core/leases"
1013
"github.com/containerd/containerd/v2/pkg/namespaces"
1114
"github.com/containerd/platforms"
1215
)
@@ -23,6 +26,7 @@ const (
2326
func main() {
2427
if len(os.Args) < 2 {
2528
fmt.Fprintf(os.Stderr, "Usage: %s <image-ref> [image-ref...]\n", os.Args[0])
29+
fmt.Fprintf(os.Stderr, " %s --gc\n", os.Args[0])
2630
fmt.Fprintf(os.Stderr, "Example: %s mcr.microsoft.com/oss/kubernetes/pause:3.9\n", os.Args[0])
2731
os.Exit(1)
2832
}
@@ -45,6 +49,15 @@ func main() {
4549

4650
ctx := namespaces.WithNamespace(context.Background(), ns)
4751

52+
if len(os.Args) == 2 && os.Args[1] == "--gc" {
53+
if err := triggerGarbageCollection(ctx, client); err != nil {
54+
fmt.Fprintf(os.Stderr, "Failed to trigger containerd GC: %v\n", err)
55+
os.Exit(1)
56+
}
57+
fmt.Println("Triggered containerd GC")
58+
return
59+
}
60+
4861
failed := 0
4962
for _, ref := range os.Args[1:] {
5063
if err := fetchImage(ctx, client, ref); err != nil {
@@ -103,10 +116,13 @@ func fetchImage(ctx context.Context, client *containerd.Client, ref string) erro
103116
if size < pullSizeThreshold {
104117
// We use pull here instead of use unpack because some runtimes (e.g. containerd-shim-runsc-v1),
105118
// require pull to trigger unpacking into the correct snapshotter based on the image's platform.
106-
if _, err := client.Pull(ctx, ref,
119+
pullOpts := []containerd.RemoteOpt{
107120
containerd.WithPlatformMatcher(platformMatcher),
108121
containerd.WithPullUnpack,
109-
); err != nil {
122+
containerd.WithChildLabelMap(images.ChildGCLabelsFilterLayers),
123+
}
124+
125+
if _, err := client.Pull(ctx, ref, pullOpts...); err != nil {
110126
return fmt.Errorf("pull failed: %w", err)
111127
}
112128
fmt.Printf("OK %s -> %s (pulled, %s)\n", imageMeta.Name, imageMeta.Target.Digest, formatSize(size))
@@ -117,6 +133,15 @@ func fetchImage(ctx context.Context, client *containerd.Client, ref string) erro
117133
return nil
118134
}
119135

136+
func triggerGarbageCollection(ctx context.Context, client *containerd.Client) error {
137+
ls := client.LeasesService()
138+
l, err := ls.Create(ctx, leases.WithRandomID(), leases.WithExpiration(time.Hour))
139+
if err != nil {
140+
return err
141+
}
142+
return ls.Delete(ctx, l, leases.SynchronousDelete)
143+
}
144+
120145
func formatSize(bytes int64) string {
121146
const (
122147
mib = 1024 * 1024

vhdbuilder/packer/install-dependencies.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,7 @@ while IFS= read -r imageToBePulled; do
699699
done <<< "$ContainerImages"
700700
echo "Waiting for container image pulls to finish. PID: ${image_pids[@]}"
701701
wait ${image_pids[@]}
702+
/opt/azure/containers/image-fetcher --gc
702703
capture_benchmark "${SCRIPT_NAME}_caching_container_images"
703704

704705
retagAKSNodeCAWatcher() {

0 commit comments

Comments
 (0)