Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
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
4 changes: 2 additions & 2 deletions docs/crio.conf.5.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ The `crio.api` table contains settings for the kubelet/gRPC interface.
The `crio.runtime` table contains settings pertaining to the OCI runtime used and options for how to set up and manage the OCI runtime.

**default_runtime**="runc"
The _name_ of the OCI runtime to be used as the default.
The _name_ of the OCI runtime to be used as the default. This option supports live configuration reload.

**default_ulimits**=[]
A list of ulimits to be set in containers by default, specified as "<ulimit name>=<soft limit>:<hard limit>", for example:"nofile=1024:2048". If nothing is set here, settings will be inherited from the CRI-O daemon.
Expand Down Expand Up @@ -291,7 +291,7 @@ the container runtime configuration.
Enable CRIU integration, requires that the criu binary is available in $PATH. (default: false)

### CRIO.RUNTIME.RUNTIMES TABLE
The "crio.runtime.runtimes" table defines a list of OCI compatible runtimes. The runtime to use is picked based on the runtime handler provided by the CRI. If no runtime handler is provided, the runtime will be picked based on the level of trust of the workload.
The "crio.runtime.runtimes" table defines a list of OCI compatible runtimes. The runtime to use is picked based on the runtime handler provided by the CRI. If no runtime handler is provided, the runtime will be picked based on the level of trust of the workload. This option supports live configuration reload. This option supports live configuration reload.

**runtime_path**=""
Path to the OCI compatible runtime used for this runtime handler.
Expand Down
42 changes: 27 additions & 15 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -963,21 +963,8 @@ func (c *RuntimeConfig) Validate(systemContext *types.SystemContext, onExecution
return err
}

// check we do have at least a runtime
if _, ok := c.Runtimes[c.DefaultRuntime]; !ok {
// Set the default runtime to "runc" if default_runtime is not set
if c.DefaultRuntime == "" {
logrus.Debugf("Defaulting to %q as the runtime since default_runtime is not set", defaultRuntime)
// The default config sets runc and its path in the runtimes map, so check for that
// first. If it does not exist then we add runc + its path to the runtimes map.
if _, ok := c.Runtimes[defaultRuntime]; !ok {
c.Runtimes[defaultRuntime] = defaultRuntimeHandler()
}
// Set the DefaultRuntime to runc so we don't fail further along in the code
c.DefaultRuntime = defaultRuntime
} else {
return fmt.Errorf("default_runtime set to %q, but no runtime entry table [crio.runtime.runtimes.%s] was found", c.DefaultRuntime, c.DefaultRuntime)
}
if err := c.ValidateDefaultRuntime(); err != nil {
return err
}

if c.LogSizeMax >= 0 && c.LogSizeMax < OCIBufSize {
Expand Down Expand Up @@ -1108,6 +1095,31 @@ func (c *RuntimeConfig) Validate(systemContext *types.SystemContext, onExecution
return nil
}

// ValidateDefaultRuntime ensures that the default runtime is set and valid.
func (c *RuntimeConfig) ValidateDefaultRuntime() error {
// If the default runtime is defined in the runtime entry table, then it is valid
if _, ok := c.Runtimes[c.DefaultRuntime]; ok {
return nil
}

// If a non-empty runtime does not exist in the runtime entry table, this is an error.
if c.DefaultRuntime != "" {
return fmt.Errorf("default_runtime set to %q, but no runtime entry table [crio.runtime.runtimes.%s] was found", c.DefaultRuntime, c.DefaultRuntime)
}

// Set the default runtime to "runc" if default_runtime is not set
logrus.Debugf("Defaulting to %q as the runtime since default_runtime is not set", defaultRuntime)
// The default config sets runc and its path in the runtimes map, so check for that
// first. If it does not exist then we add runc + its path to the runtimes map.
if _, ok := c.Runtimes[defaultRuntime]; !ok {
c.Runtimes[defaultRuntime] = defaultRuntimeHandler()
}
// Set the DefaultRuntime to runc so we don't fail further along in the code
c.DefaultRuntime = defaultRuntime

return nil
}

func defaultRuntimeHandler() *RuntimeHandler {
return &RuntimeHandler{
RuntimeType: DefaultRuntimeType,
Expand Down
32 changes: 32 additions & 0 deletions pkg/config/reload.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ func (c *Config) Reload() error {
if err := c.ReloadRdtConfig(newConfig); err != nil {
return err
}
if err := c.ReloadRuntimes(newConfig); err != nil {
return err
}
cdi.GetRegistry(cdi.WithSpecDirs(newConfig.CDISpecDirs...))

return nil
Expand Down Expand Up @@ -237,3 +240,32 @@ func (c *Config) ReloadRdtConfig(newConfig *Config) error {
}
return nil
}

// ReloadRuntimes reloads the runtimes configuration if changed
func (c *Config) ReloadRuntimes(newConfig *Config) error {
var updated bool
if !RuntimesEqual(c.Runtimes, newConfig.Runtimes) {
logrus.Infof("Updating runtime configuration")
c.Runtimes = newConfig.Runtimes
updated = true
}

if c.DefaultRuntime != newConfig.DefaultRuntime {
c.DefaultRuntime = newConfig.DefaultRuntime
if err := c.ValidateDefaultRuntime(); err != nil {
return fmt.Errorf("unable to reload runtimes: %w", err)
}
logConfig("default_runtime", c.DefaultRuntime)
updated = true
}

if !updated {
return nil
}

if err := c.ValidateRuntimes(); err != nil {
return fmt.Errorf("unabled to reload runtimes: %w", err)
}

return nil
}
83 changes: 83 additions & 0 deletions pkg/config/reload_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"strings"

"github.com/containers/common/pkg/apparmor"
"github.com/cri-o/cri-o/pkg/config"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
Expand Down Expand Up @@ -325,4 +326,86 @@ var _ = t.Describe("Config", func() {
Expect(sut.ApparmorProfile).To(Equal(profile))
})
})

t.Describe("ReloadRuntimes", func() {
It("should succeed without any config change", func() {
// Given
// When
err := sut.ReloadRuntimes(sut)

// Then
Expect(err).To(BeNil())
})

It("should fail for invalid default_runtime", func() {
// Given
newConfig := &config.Config{}
newConfig.DefaultRuntime = "invalid"

// When
err := sut.ReloadRuntimes(newConfig)

// Then
Expect(err).NotTo(BeNil())
})

It("should add a new runtime", func() {
// Given
newRuntimeHandler := &config.RuntimeHandler{
RuntimePath: "/usr/bin/runc",
PrivilegedWithoutHostDevices: true,
}
newConfig := &config.Config{}
newConfig.Runtimes = make(config.Runtimes)
newConfig.Runtimes["new"] = newRuntimeHandler

// When
err := sut.ReloadRuntimes(newConfig)

// Then
Expect(err).To(BeNil())
Expect(sut.Runtimes).To(HaveKeyWithValue("new", newRuntimeHandler))
})

It("should change the default runtime", func() {
// Given
sut.Runtimes["existing"] = &config.RuntimeHandler{
RuntimePath: "/usr/bin/runc",
}
newConfig := &config.Config{}
newConfig.Runtimes = sut.Runtimes
newConfig.DefaultRuntime = "existing"

// When
err := sut.ReloadRuntimes(newConfig)

// Then
Expect(err).To(BeNil())
Expect(sut.DefaultRuntime).To(Equal("existing"))
})

It("should overwrite existing runtime", func() {
// Given
existingRuntime := &config.RuntimeHandler{
RuntimePath: "/usr/bin/runc",
}
sut.Runtimes["existing"] = existingRuntime

newRuntime := &config.RuntimeHandler{
RuntimePath: "/usr/bin/runc",
PrivilegedWithoutHostDevices: true,
}
newConfig := &config.Config{}
newConfig.Runtimes = make(config.Runtimes)
newConfig.Runtimes["existing"] = newRuntime

// When
err := sut.ReloadRuntimes(newConfig)

// Then
Expect(err).To(BeNil())
Expect(sut.Runtimes).To(HaveKeyWithValue("existing", newRuntime))
Expect(sut.Runtimes["existing"].PrivilegedWithoutHostDevices).To(BeTrue())
})
})
})
15 changes: 15 additions & 0 deletions test/reload_config.bats
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ function setup() {
}

function teardown() {
rm -f "$CRIO_CONFIG_DIR/00-new*Runtime.conf"
cleanup_test
}

Expand Down Expand Up @@ -215,3 +216,17 @@ function expect_log_failure() {
# then
expect_log_failure "unable to reload apparmor_profile"
}

@test "reload config should add new runtime" {
# given
cat << EOF > "$CRIO_CONFIG_DIR/00-newRuntime.conf"
[crio.runtime.runtimes.new]
runtime_path = "$RUNTIME_BINARY_PATH"
EOF

# when
reload_crio

#then
wait_for_log '"updating runtime configuration"'
}