@@ -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 (
2326func 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+
120145func formatSize (bytes int64 ) string {
121146 const (
122147 mib = 1024 * 1024
0 commit comments