mirror of
https://github.com/openfaas/faasd.git
synced 2025-06-20 13:06:38 +00:00
Pre-pull images for updates
The update flow used to delete the active function before synchronously pulling the next and starting it. That meant functions would always face downtime during the pull. This changes the order to pre-pull and reduce any down time. Signed-off-by: Alex Ellis (OpenFaaS Ltd) <alexellis2@gmail.com>
This commit is contained in:
committed by
Alex Ellis
parent
87f993847c
commit
c4936133f6
@ -9,6 +9,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd"
|
||||
"github.com/containerd/containerd/cio"
|
||||
@ -68,7 +69,11 @@ func MakeDeployHandler(client *containerd.Client, cni gocni.CNI, secretMountPath
|
||||
}
|
||||
}
|
||||
|
||||
func deploy(ctx context.Context, req types.FunctionDeployment, client *containerd.Client, cni gocni.CNI, secretMountPath string, alwaysPull bool) error {
|
||||
// prepull is an optimization which means an image can be pulled before a deployment
|
||||
// request, since a deployment request first deletes the active function before
|
||||
// trying to deploy a new one.
|
||||
func prepull(ctx context.Context, req types.FunctionDeployment, client *containerd.Client, alwaysPull bool) error {
|
||||
start := time.Now()
|
||||
r, err := reference.ParseNormalizedNamed(req.Image)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -87,7 +92,33 @@ func deploy(ctx context.Context, req types.FunctionDeployment, client *container
|
||||
}
|
||||
|
||||
size, _ := image.Size(ctx)
|
||||
log.Printf("Deploy %s size: %d\n", image.Name(), size)
|
||||
log.Printf("[Prepull] Deploy %s size: %d, took: %fs\n", image.Name(), size, time.Since(start).Seconds())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func deploy(ctx context.Context, req types.FunctionDeployment, client *containerd.Client, cni gocni.CNI, secretMountPath string, alwaysPull bool) error {
|
||||
start := time.Now()
|
||||
|
||||
r, err := reference.ParseNormalizedNamed(req.Image)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
imgRef := reference.TagNameOnly(r).String()
|
||||
|
||||
snapshotter := ""
|
||||
if val, ok := os.LookupEnv("snapshotter"); ok {
|
||||
snapshotter = val
|
||||
}
|
||||
|
||||
image, err := service.PrepareImage(ctx, client, imgRef, snapshotter, alwaysPull)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to pull image %s", imgRef)
|
||||
}
|
||||
|
||||
size, _ := image.Size(ctx)
|
||||
log.Printf("[deploy] Deploy %s size: %d, took: %fs\n", image.Name(), size, time.Since(start).Seconds())
|
||||
|
||||
envs := prepareEnv(req.EnvProcess, req.EnvVars)
|
||||
mounts := getMounts()
|
||||
|
@ -56,6 +56,12 @@ func MakeUpdateHandler(client *containerd.Client, cni gocni.CNI, secretMountPath
|
||||
}
|
||||
|
||||
ctx := namespaces.WithNamespace(context.Background(), faasd.FunctionNamespace)
|
||||
|
||||
if err := prepull(ctx, req, client, alwaysPull); err != nil {
|
||||
log.Printf("[Update] error with pre-pull: %s, %s\n", name, err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
if function.replicas != 0 {
|
||||
err = cninetwork.DeleteCNINetwork(ctx, cni, client, name)
|
||||
if err != nil {
|
||||
@ -63,19 +69,19 @@ func MakeUpdateHandler(client *containerd.Client, cni gocni.CNI, secretMountPath
|
||||
}
|
||||
}
|
||||
|
||||
containerErr := service.Remove(ctx, client, name)
|
||||
if containerErr != nil {
|
||||
log.Printf("[Update] error removing %s, %s\n", name, containerErr)
|
||||
http.Error(w, containerErr.Error(), http.StatusInternalServerError)
|
||||
if err := service.Remove(ctx, client, name); err != nil {
|
||||
log.Printf("[Update] error removing %s, %s\n", name, err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
deployErr := deploy(ctx, req, client, cni, secretMountPath, alwaysPull)
|
||||
if deployErr != nil {
|
||||
log.Printf("[Update] error deploying %s, error: %s\n", name, deployErr)
|
||||
http.Error(w, deployErr.Error(), http.StatusBadRequest)
|
||||
// The pull has already been done in prepull, so we can force this pull to "false"
|
||||
pull := false
|
||||
|
||||
if err := deploy(ctx, req, client, cni, secretMountPath, pull); err != nil {
|
||||
log.Printf("[Update] error deploying %s, error: %s\n", name, err)
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user