allow systemd to delegate a scope to ol for managing cgroups by m0mosenpai · Pull Request #447 · open-lambda/open-lambda · GitHub
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
2 changes: 1 addition & 1 deletion .github/workflows/pkg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
run: cargo install cross --locked
- name: Build OpenLambda
run: |
make ol imgs/lambda wasm-worker wasm-functions native-functions container-proxy
make ol-bin imgs/lambda wasm-worker wasm-functions native-functions container-proxy
sudo make install-python-bindings
- name: Test PyPI Packages
run: sudo ./scripts/package_tests.py
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
/test.json

# binaries
ol
ol-bin
ol-wasm
ol-container-proxy

Expand Down
12 changes: 7 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ endif
.PHONY: container-proxy
.PHONY: fmt check-fmt

all: ol imgs/ol-wasm wasm-worker wasm-functions native-functions container-proxy
all: ol-bin imgs/ol-wasm wasm-worker wasm-functions native-functions container-proxy

wasm-worker:
cd wasm-worker && cargo build ${BUILD_FLAGS}
Expand Down Expand Up @@ -76,19 +76,21 @@ container-proxy:
cd container-proxy && cargo build ${BUILD_FLAGS}
cp ./container-proxy/target/${BUILDTYPE}/open-lambda-container-proxy ./ol-container-proxy

ol: ${OL_GO_FILES}
cd ${OL_DIR} && ${GO} build -o ../ol
ol-bin: ${OL_GO_FILES}
cd ${OL_DIR} && ${GO} build -o ../ol-bin

build: ol wasm-worker container-proxy
build: ol-bin wasm-worker container-proxy

install: build
cp ol ${INSTALL_PREFIX}/bin/
cp ol-bin ${INSTALL_PREFIX}/bin/
cp ol-wasm ${INSTALL_PREFIX}/bin/
cp ol-container-proxy ${INSTALL_PREFIX}/bin/
cp autocomplete/bash_autocomplete /etc/bash_completion.d/ol

sudo-install: build
sudo cp ol ${INSTALL_PREFIX}/bin/
sudo cp ol-bin ${INSTALL_PREFIX}/bin/
sudo cp ol-wasm ${INSTALL_PREFIX}/bin/
sudo cp ol-container-proxy ${INSTALL_PREFIX}/bin/
sudo cp autocomplete/bash_autocomplete /etc/bash_completion.d/ol
Expand Down Expand Up @@ -127,6 +129,6 @@ lint-wasm-worker:
lint: lint-wasm-worker lint-functions lint-python lint-go

clean:
rm -f ol imgs/ol-min imgs/ol-wasm
rm -f ol-bin imgs/ol-min imgs/ol-wasm
${MAKE} -C lambda clean
${MAKE} -C sock clean
35 changes: 35 additions & 0 deletions go/common/cgroup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package common

import (
"fmt"
"os"
"path/filepath"
"strings"
)

// EnsureCgroupConfigured fails if neither cgroup_root nor OL_SYSTEMD is set.
func EnsureCgroupConfigured() error {
if Conf != nil && Conf.Cgroup_root != "" {
return nil
}
if os.Getenv("OL_SYSTEMD") == "1" {
return nil
}
return fmt.Errorf("no cgroup root: set cgroup_root in config or run the worker via 'ol'")
}

func CgroupRoot() (string, error) {
if Conf != nil && Conf.Cgroup_root != "" {
return Conf.Cgroup_root, nil
}
data, err := os.ReadFile("/proc/self/cgroup")
if err != nil {
return "", fmt.Errorf("read /proc/self/cgroup: %w", err)
}
line := strings.TrimSpace(string(data))
parts := strings.SplitN(line, "::", 2)
if len(parts) != 2 {
return "", fmt.Errorf("unexpected /proc/self/cgroup format: %q", line)
}
return filepath.Join("/sys/fs/cgroup", parts[1]), nil
}
8 changes: 3 additions & 5 deletions go/common/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ type Config struct {
// worker directory, which contains handler code, pid file, logs, etc.
Worker_dir string `json:"worker_dir"`

// configure the cgroup pool root - defaults to '/proc/self/cgroup'
Cgroup_root string `json:"cgroup_root"`

// Url/ip the worker server listens to
Worker_url string `json:"worker_url"`

Expand Down Expand Up @@ -492,8 +495,3 @@ func GetOlPath(ctx *cli.Context) (string, error) {
}
return filepath.Abs(olPath)
}

// CgroupPoolPath returns the cgroup pool root path for the given OL directory.
func CgroupPoolPath(olPath string) string {
return filepath.Join("/sys/fs/cgroup", filepath.Base(olPath)+"-sandboxes")
}
16 changes: 3 additions & 13 deletions go/worker/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (

"github.com/open-lambda/open-lambda/go/common"
"github.com/open-lambda/open-lambda/go/worker/event"
"github.com/open-lambda/open-lambda/go/worker/sandbox/cgroups"

"github.com/urfave/cli/v2"
)
Expand All @@ -40,27 +39,18 @@ func udsGet(requestPath string) (*http.Response, error) {

// initCmd corresponds to the "init" command of the admin tool.
func initCmd(ctx *cli.Context) error {
if os.Getuid() != 0 {
return fmt.Errorf("'ol worker init' must be run with sudo")
}

olPath, err := common.GetOlPath(ctx)
if err != nil {
return fmt.Errorf("init failed to get OL path: %w", err)
return err
}

if err := common.LoadDefaults(olPath); err != nil {
return fmt.Errorf("init failed to load config defaults: %w", err)
return err
}

if err := initOLDir(olPath, ctx.String("image"), ctx.Bool("newbase")); err != nil {
return fmt.Errorf("init failed to create OL directory: %w", err)
}

if err := cgroups.InitPoolRoot(common.CgroupPoolPath(olPath)); err != nil {
return fmt.Errorf("init failed to create cgroup pool: %w", err)
return err
}

fmt.Printf("\nYou may optionally modify the defaults here: %s\n\n",
filepath.Join(olPath, "config.json"))
fmt.Printf("Next start a worker using the \"ol worker up\" command.\n")
Expand Down
25 changes: 17 additions & 8 deletions go/worker/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"github.com/open-lambda/open-lambda/go/worker/embedded"
)


func initOLBaseDir(baseDir string, dockerBaseImage string) error {
if dockerBaseImage == "" {
dockerBaseImage = "ol-wasm"
Expand Down Expand Up @@ -280,8 +279,14 @@ func runningToStoppedClean() error {
// It cleans up cgroups and mounts associated with the OpenLambda instance at `olPath`.
// Returns errors encountered during cleanup operations.
func stoppedDirtyToStoppedClean(olPath string) error {
// Clean up child cgroups, preserving the pool root
cgRoot := common.CgroupPoolPath(olPath)
// Clean up cgroups associated with sandboxes
if err := common.EnsureCgroupConfigured(); err != nil {
return err
}
cgRoot, err := common.CgroupRoot()
if err != nil {
return fmt.Errorf("failed to resolve cgroup root: %s", err)
}
fmt.Printf("Attempting to clean up cgroups at %s\n", cgRoot)

cgroupErrorCount := 0
Expand All @@ -301,21 +306,25 @@ func stoppedDirtyToStoppedClean(olPath string) error {
if err != nil {
return fmt.Errorf("error reading cgroup root: %s", err.Error())
}
kill := filepath.Join(cgRoot, "cgroup.kill")
if err := os.WriteFile(kill, []byte(fmt.Sprintf("%d", 1)), os.ModeAppend); err != nil {
fmt.Printf("Could not kill processes in cgroup: %s\n", err.Error())
cgroupErrorCount += 1
}
for _, file := range files {
if strings.HasPrefix(file.Name(), "cg-") {
cg := filepath.Join(cgRoot, file.Name())
fmt.Printf("Attempting to remove %s\n", cg)
kill := filepath.Join(cg, "cgroup.kill")
if err := os.WriteFile(kill, []byte(fmt.Sprintf("%d", 1)), os.ModeAppend); err != nil {
// Print an error if killing processes in the cgroup fails.
fmt.Printf("Could not kill processes in cgroup: %s\n", err.Error())
cgroupErrorCount += 1
}
if err := syscall.Rmdir(cg); err != nil {
// Print an error if removing a cgroup fails.
fmt.Printf("could not remove cgroup: %s\n", err.Error())
cgroupErrorCount += 1
}
}
}
_ = syscall.Rmdir(filepath.Join(cgRoot, "worker"))
_ = syscall.Rmdir(cgRoot)
}

sandboxErrorCount := 0
Expand Down
6 changes: 3 additions & 3 deletions go/worker/sandbox/cgroups/cgroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ func (cg *CgroupImpl) Destroy() {
}
}

// GroupPath returns the path to this cgroup directory.
// GroupPath returns the path to the Cgroup pool for OpenLambda
func (cg *CgroupImpl) GroupPath() string {
return fmt.Sprintf("%s/%s", cg.pool.poolPath, cg.name)
return fmt.Sprintf("%s/%s", cg.pool.GroupPath(), cg.name)
}

func (cg *CgroupImpl) MemoryEvents() map[string]int64 {
Expand All @@ -107,7 +107,7 @@ func (cg *CgroupImpl) MemoryEvents() map[string]int64 {

// ResourcePath returns the path to a specific resource in this cgroup
func (cg *CgroupImpl) ResourcePath(resource string) string {
return fmt.Sprintf("%s/%s/%s", cg.pool.poolPath, cg.name, resource)
return fmt.Sprintf("%s/%s/%s", cg.pool.GroupPath(), cg.name, resource)
}

func (cg *CgroupImpl) TryWriteInt(resource string, val int64) error {
Expand Down
96 changes: 63 additions & 33 deletions go/worker/sandbox/cgroups/pool.go
Loading
Loading