mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
fn: runner status and docker load images (#1116)
* fn: runner status and docker load images Introducing a function run for pure runner Status calls. Previously, Status gRPC calls returned active inflight request counts with the purpose of a simple health checker. However this is not sufficient since it does not show if agent or docker is healthy. With this change, if pure runner is configured with a status image, that image is executed through docker. The call uses zero memory/cpu/tmpsize settings to ensure resource tracker does not block it. However, operators might not always have a docker repository accessible/available for status image. Or operators might not want the status to go over the network. To allow such cases, and in general possibly caching docker images, added a new environment variable FN_DOCKER_LOAD_FILE. If this is set, fn-agent during startup will load these images that were previously saved with 'docker save' into docker.
This commit is contained in:
@@ -25,6 +25,18 @@ type cookie struct {
|
||||
drv *DockerDriver
|
||||
}
|
||||
|
||||
func (c *cookie) configureMem(log logrus.FieldLogger) {
|
||||
if c.task.Memory() == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
mem := int64(c.task.Memory())
|
||||
|
||||
c.opts.Config.Memory = mem
|
||||
c.opts.Config.MemorySwap = mem // disables swap
|
||||
c.opts.Config.KernelMemory = mem
|
||||
}
|
||||
|
||||
func (c *cookie) configureFsSize(log logrus.FieldLogger) {
|
||||
if c.task.FsSize() == 0 {
|
||||
return
|
||||
|
||||
@@ -92,6 +92,13 @@ func NewDocker(conf drivers.Config) *DockerDriver {
|
||||
}
|
||||
}
|
||||
|
||||
if conf.DockerLoadFile != "" {
|
||||
err = loadDockerImages(driver, conf.DockerLoadFile)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatalf("cannot load docker images in %s", conf.DockerLoadFile)
|
||||
}
|
||||
}
|
||||
|
||||
return driver
|
||||
}
|
||||
|
||||
@@ -118,6 +125,12 @@ func checkDockerVersion(driver *DockerDriver, expected string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadDockerImages(driver *DockerDriver, filePath string) error {
|
||||
ctx, log := common.LoggerWithFields(context.Background(), logrus.Fields{"stack": "loadDockerImages"})
|
||||
log.Infof("Loading docker images from %v", filePath)
|
||||
return driver.docker.LoadImages(ctx, filePath)
|
||||
}
|
||||
|
||||
func registryFromEnv() map[string]docker.AuthConfiguration {
|
||||
var auths *docker.AuthConfigurations
|
||||
var err error
|
||||
@@ -208,9 +221,6 @@ func (drv *DockerDriver) CreateCookie(ctx context.Context, task drivers.Containe
|
||||
opts := docker.CreateContainerOptions{
|
||||
Name: task.Id(),
|
||||
Config: &docker.Config{
|
||||
Memory: int64(task.Memory()),
|
||||
MemorySwap: int64(task.Memory()), // disables swap
|
||||
KernelMemory: int64(task.Memory()),
|
||||
Image: task.Image(),
|
||||
OpenStdin: true,
|
||||
AttachStdout: true,
|
||||
@@ -234,6 +244,7 @@ func (drv *DockerDriver) CreateCookie(ctx context.Context, task drivers.Containe
|
||||
drv: drv,
|
||||
}
|
||||
|
||||
cookie.configureMem(log)
|
||||
cookie.configureCmd(log)
|
||||
cookie.configureEnv(log)
|
||||
cookie.configureCPU(log)
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -46,6 +47,7 @@ type dockerClient interface {
|
||||
InspectContainerWithContext(container string, ctx context.Context) (*docker.Container, error)
|
||||
Stats(opts docker.StatsOptions) error
|
||||
Info(ctx context.Context) (*docker.DockerInfo, error)
|
||||
LoadImages(ctx context.Context, filePath string) error
|
||||
}
|
||||
|
||||
// TODO: switch to github.com/docker/engine-api
|
||||
@@ -227,6 +229,24 @@ func filterNoSuchContainer(ctx context.Context, err error) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *dockerWrap) LoadImages(ctx context.Context, filePath string) error {
|
||||
ctx, span := trace.StartSpan(ctx, "docker_load_images")
|
||||
defer span.End()
|
||||
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// No retries here. LoadImage is typically called at startup and we fail/timeout
|
||||
// at first attempt.
|
||||
return d.docker.LoadImage(docker.LoadImageOptions{
|
||||
InputStream: file,
|
||||
Context: ctx,
|
||||
})
|
||||
}
|
||||
|
||||
func (d *dockerWrap) Info(ctx context.Context) (info *docker.DockerInfo, err error) {
|
||||
// NOTE: we're not very responsible and prometheus wasn't loved as a child, this
|
||||
// threads through directly down to the docker call, skipping retires, so that we
|
||||
|
||||
Reference in New Issue
Block a user