From 77cbcba0906d70736f20d6f1513f1f3b3d054af3 Mon Sep 17 00:00:00 2001 From: biecho Date: Sun, 30 Oct 2022 12:15:39 -0600 Subject: [PATCH] When pulling images check for stale cached images --- ctriface/iface.go | 82 +++++++++++++------ ctriface/iface_test.go | 4 +- .../self-hosted-kind/scripts/setup-runner.sh | 3 + taps/tapManager.go | 1 - 4 files changed, 60 insertions(+), 30 deletions(-) diff --git a/ctriface/iface.go b/ctriface/iface.go index 6cef27890..0f2bdd6ff 100644 --- a/ctriface/iface.go +++ b/ctriface/iface.go @@ -50,10 +50,10 @@ import ( _ "google.golang.org/grpc/codes" //tmp _ "google.golang.org/grpc/status" //tmp + "github.com/go-multierror/multierror" "github.com/vhive-serverless/vhive/memory/manager" "github.com/vhive-serverless/vhive/metrics" "github.com/vhive-serverless/vhive/misc" - "github.com/go-multierror/multierror" _ "github.com/davecgh/go-spew/spew" //tmp ) @@ -314,42 +314,70 @@ func getImageURL(image string) string { func (o *Orchestrator) getImage(ctx context.Context, imageName string) (*containerd.Image, error) { image, found := o.cachedImages[imageName] - if !found { - var err error - log.Debug(fmt.Sprintf("Pulling image %s", imageName)) - - imageURL := getImageURL(imageName) - local, _ := isLocalDomain(imageURL) - if local { - // Pull local image using HTTP - resolver := docker.NewResolver(docker.ResolverOptions{ - Client: http.DefaultClient, - Hosts: docker.ConfigureDefaultRegistries( - docker.WithPlainHTTP(docker.MatchAllHosts), - ), - }) - image, err = o.client.Pull(ctx, imageURL, - containerd.WithPullUnpack, - containerd.WithPullSnapshotter(o.snapshotter), - containerd.WithResolver(resolver), - ) - } else { - // Pull remote image - image, err = o.client.Pull(ctx, imageURL, - containerd.WithPullUnpack, - containerd.WithPullSnapshotter(o.snapshotter), - ) - } + + imageUrl := getImageURL(imageName) + if !found || imageIsOutdated(image, imageUrl) { + image, err := o.pullImage(ctx, imageUrl) if err != nil { return &image, err } o.cachedImages[imageName] = image + return &image, nil } return &image, nil } +func imageIsOutdated(cachedImage containerd.Image, imageUrl string) bool { + remoteImageDigest, err := remoteImageDigest(imageUrl) + return err == nil && cachedImage.Target().Digest.String() != remoteImageDigest +} + +func remoteImageDigest(imageUrl string) (string, error) { + cmd := fmt.Sprintf("skopeo inspect docker://%s | jq -r '.Digest'", imageUrl) + + start := time.Now() + out, err := exec.Command("bash", "-c", cmd).Output() + elapsed := time.Since(start) + log.Printf("Remote digest fetching took %s", elapsed) + + return string(out), err +} + +func (o *Orchestrator) pullImage(ctx context.Context, imageUrl string) (containerd.Image, error) { + log.Debugf("Pulling image %s\n", imageUrl) + + local, _ := isLocalDomain(imageUrl) + + if local { + return o.pullLocalImage(ctx, imageUrl) + } + return o.pullRemoteImage(ctx, imageUrl) +} + +func (o *Orchestrator) pullRemoteImage(ctx context.Context, imageUrl string) (containerd.Image, error) { + return o.client.Pull(ctx, imageUrl, + containerd.WithPullUnpack, + containerd.WithPullSnapshotter(o.snapshotter), + ) +} + +// Pull local image using HTTP +func (o *Orchestrator) pullLocalImage(ctx context.Context, imageUrl string) (containerd.Image, error) { + resolver := docker.NewResolver(docker.ResolverOptions{ + Client: http.DefaultClient, + Hosts: docker.ConfigureDefaultRegistries( + docker.WithPlainHTTP(docker.MatchAllHosts), + ), + }) + return o.client.Pull(ctx, imageUrl, + containerd.WithPullUnpack, + containerd.WithPullSnapshotter(o.snapshotter), + containerd.WithResolver(resolver), + ) +} + func getK8sDNS() []string { //using googleDNS as a backup dnsIPs := []string{"8.8.8.8"} diff --git a/ctriface/iface_test.go b/ctriface/iface_test.go index cda2e97a0..9a39e8d58 100644 --- a/ctriface/iface_test.go +++ b/ctriface/iface_test.go @@ -1,6 +1,6 @@ // MIT License // -// Copyright (c) 2020 Dmitrii Ustiugov, Plamen Petrov and EASE lab +// # Copyright (c) 2020 Dmitrii Ustiugov, Plamen Petrov and EASE lab // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -41,7 +41,7 @@ var ( isUPFEnabled = flag.Bool("upf", false, "Set UPF enabled") isLazyMode = flag.Bool("lazy", false, "Set lazy serving on or off") //nolint:deadcode,unused,varcheck - isWithCache = flag.Bool("withCache", false, "Do not drop the cache before measurements") + isWithCache = flag.Bool("withCache", false, "Do not drop the cache before measurements") ) func TestPauseSnapResume(t *testing.T) { diff --git a/scripts/self-hosted-kind/scripts/setup-runner.sh b/scripts/self-hosted-kind/scripts/setup-runner.sh index 7805dad02..26dfe5ca7 100644 --- a/scripts/self-hosted-kind/scripts/setup-runner.sh +++ b/scripts/self-hosted-kind/scripts/setup-runner.sh @@ -24,6 +24,9 @@ set -e +# Needed for 'skopeo' +echo "deb http://mirrors.kernel.org/ubuntu kinetic main universe" | sudo tee -a /etc/apt/sources.list + # Install base- and setup-dependencies apt-get update apt-get install --yes \ diff --git a/taps/tapManager.go b/taps/tapManager.go index d079d1e79..646cf412d 100644 --- a/taps/tapManager.go +++ b/taps/tapManager.go @@ -126,7 +126,6 @@ func setupForwardRules(tapName, hostIface string) error { } } - conn := nftables.Conn{} // 1. nft add table ip filter