diff --git a/Dockerfile b/Dockerfile index 2ea09a80ed..f1278f0133 100644 --- a/Dockerfile +++ b/Dockerfile @@ -735,7 +735,7 @@ COPY --chmod=0644 hack/udevd/90-selinux.rules /rootfs/usr/lib/udev/rules.d/ COPY --chmod=0644 hack/lvm.conf /rootfs/etc/lvm/lvm.conf RUN < 0 { + var overrides oci.Spec + + jsonOverrides, err := json.Marshal(cfg.Config().Machine().BaseRuntimeSpecOverrides()) + if err != nil { + return fmt.Errorf("error marshaling runtime spec overrides: %w", err) + } + + if err := json.Unmarshal(jsonOverrides, &overrides); err != nil { + return fmt.Errorf("error unmarshaling runtime spec overrides: %w", err) + } + + if err := merge.Merge(defaultSpec, &overrides); err != nil { + return fmt.Errorf("error merging runtime spec overrides: %w", err) + } + } + + contents, err := json.Marshal(defaultSpec) + if err != nil { + return fmt.Errorf("error marshaling runtime spec: %w", err) + } + + if err := safe.WriterModify(ctx, r, files.NewEtcFileSpec(files.NamespaceName, constants.CRIBaseRuntimeSpec), + func(r *files.EtcFileSpec) error { + spec := r.TypedSpec() + + spec.Contents = contents + spec.Mode = 0o600 + spec.SelinuxLabel = constants.EtcSelinuxLabel + + return nil + }); err != nil { + return fmt.Errorf("error modifying resource: %w", err) + } + + r.ResetRestartBackoff() + } +} diff --git a/internal/app/machined/pkg/controllers/files/cri_base_runtime_spec_test.go b/internal/app/machined/pkg/controllers/files/cri_base_runtime_spec_test.go new file mode 100644 index 0000000000..1c1d7452d7 --- /dev/null +++ b/internal/app/machined/pkg/controllers/files/cri_base_runtime_spec_test.go @@ -0,0 +1,106 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package files_test + +import ( + "encoding/json" + "testing" + "time" + + "github.com/containerd/containerd/v2/pkg/oci" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" + + "github.com/siderolabs/talos/internal/app/machined/pkg/controllers/ctest" + filesctrl "github.com/siderolabs/talos/internal/app/machined/pkg/controllers/files" + "github.com/siderolabs/talos/pkg/machinery/config/container" + "github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1" + "github.com/siderolabs/talos/pkg/machinery/constants" + "github.com/siderolabs/talos/pkg/machinery/resources/config" + "github.com/siderolabs/talos/pkg/machinery/resources/files" +) + +type CRIBaseRuntimeSpecSuite struct { + ctest.DefaultSuite +} + +func (suite *CRIBaseRuntimeSpecSuite) TestDefaults() { + cfg := config.NewMachineConfig( + container.NewV1Alpha1( + &v1alpha1.Config{ + ConfigVersion: "v1alpha1", + MachineConfig: &v1alpha1.MachineConfig{ + MachineType: "controlplane", + }, + }, + ), + ) + + suite.Require().NoError(suite.State().Create(suite.Ctx(), cfg)) + + ctest.AssertResource(suite, constants.CRIBaseRuntimeSpec, func(etcFile *files.EtcFileSpec, asrt *assert.Assertions) { + contents := etcFile.TypedSpec().Contents + + var ociSpec oci.Spec + + asrt.NoError(json.Unmarshal(contents, &ociSpec)) + + asrt.Empty(ociSpec.Process.Rlimits) + }) +} + +func (suite *CRIBaseRuntimeSpecSuite) TestOverrides() { + cfg := config.NewMachineConfig( + container.NewV1Alpha1( + &v1alpha1.Config{ + ConfigVersion: "v1alpha1", + MachineConfig: &v1alpha1.MachineConfig{ + MachineType: "controlplane", + MachineBaseRuntimeSpecOverrides: v1alpha1.Unstructured{ + Object: map[string]any{ + "process": map[string]any{ + "rlimits": []map[string]any{ + { + "type": "RLIMIT_NOFILE", + "hard": 1024, + "soft": 1024, + }, + }, + }, + }, + }, + }, + }, + ), + ) + + suite.Require().NoError(suite.State().Create(suite.Ctx(), cfg)) + + ctest.AssertResource(suite, constants.CRIBaseRuntimeSpec, func(etcFile *files.EtcFileSpec, asrt *assert.Assertions) { + contents := etcFile.TypedSpec().Contents + + var ociSpec oci.Spec + + asrt.NoError(json.Unmarshal(contents, &ociSpec)) + + asrt.NotEmpty(ociSpec.Process.Rlimits) + asrt.Equal("RLIMIT_NOFILE", ociSpec.Process.Rlimits[0].Type) + asrt.Equal(uint64(1024), ociSpec.Process.Rlimits[0].Hard) + asrt.Equal(uint64(1024), ociSpec.Process.Rlimits[0].Soft) + }) +} + +func TestCRIBaseRuntimeSpecSuite(t *testing.T) { + t.Parallel() + + suite.Run(t, &CRIBaseRuntimeSpecSuite{ + DefaultSuite: ctest.DefaultSuite{ + Timeout: 10 * time.Second, + AfterSetup: func(suite *ctest.DefaultSuite) { + suite.Require().NoError(suite.Runtime().RegisterController(&filesctrl.CRIBaseRuntimeSpecController{})) + }, + }, + }) +} diff --git a/internal/app/machined/pkg/runtime/v1alpha2/v1alpha2_controller.go b/internal/app/machined/pkg/runtime/v1alpha2/v1alpha2_controller.go index 1887c96717..c910de37f8 100644 --- a/internal/app/machined/pkg/runtime/v1alpha2/v1alpha2_controller.go +++ b/internal/app/machined/pkg/runtime/v1alpha2/v1alpha2_controller.go @@ -145,6 +145,7 @@ func (ctrl *Controller) Run(ctx context.Context, drainer *runtime.Drainer) error &etcd.PKIController{}, &etcd.SpecController{}, &etcd.MemberController{}, + &files.CRIBaseRuntimeSpecController{}, &files.CRIConfigPartsController{}, &files.CRIRegistryConfigController{}, &files.EtcFileController{ diff --git a/internal/integration/api/common.go b/internal/integration/api/common.go index 006fcac11a..cb6533aef9 100644 --- a/internal/integration/api/common.go +++ b/internal/integration/api/common.go @@ -9,9 +9,12 @@ package api import ( "context" "strings" + "testing" "time" "github.com/siderolabs/talos/internal/integration/base" + "github.com/siderolabs/talos/pkg/machinery/config/machine" + "github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1" ) // CommonSuite verifies some default settings such as ulimits. @@ -157,6 +160,105 @@ func (suite *CommonSuite) TestDNSResolver() { } } +// TestBaseOCISpec verifies that the base OCI spec can be modified. +func (suite *CommonSuite) TestBaseOCISpec() { + if suite.Cluster != nil && suite.Cluster.Provisioner() == "docker" { + suite.T().Skip("skipping ulimits test since provisioner is docker") + } + + if testing.Short() { + suite.T().Skip("skipping test in short mode.") + } + + node := suite.RandomDiscoveredNodeInternalIP(machine.TypeWorker) + + k8sNode, err := suite.GetK8sNodeByInternalIP(suite.ctx, node) + suite.Require().NoError(err) + + nodeName := k8sNode.Name + + suite.T().Logf("adjusting base OCI specs on %s/%s", node, nodeName) + + suite.AssertRebooted( + suite.ctx, node, func(nodeCtx context.Context) error { + suite.PatchMachineConfig(nodeCtx, &v1alpha1.Config{ + MachineConfig: &v1alpha1.MachineConfig{ + MachineBaseRuntimeSpecOverrides: v1alpha1.Unstructured{ + Object: map[string]any{ + "process": map[string]any{ + "rlimits": []map[string]any{ + { + "type": "RLIMIT_NOFILE", + "hard": 1024, + "soft": 1024, + }, + }, + }, + }, + }, + }, + }) + + return nil + }, assertRebootedRebootTimeout, + ) + + suite.ClearConnectionRefused(suite.ctx, node) + + ociUlimits1PodDef, err := suite.NewPod("oci-ulimits-test-1") + suite.Require().NoError(err) + + ociUlimits1PodDef = ociUlimits1PodDef.WithNodeName(nodeName) + + suite.Require().NoError(ociUlimits1PodDef.Create(suite.ctx, 5*time.Minute)) + + stdout, stderr, err := ociUlimits1PodDef.Exec( + suite.ctx, + "ulimit -n", + ) + suite.Require().NoError(err) + + suite.Require().Equal("", stderr) + suite.Require().Equal("1024\n", stdout) + + suite.Assert().NoError(ociUlimits1PodDef.Delete(suite.ctx)) + + // revert the patch + suite.AssertRebooted( + suite.ctx, node, func(nodeCtx context.Context) error { + suite.PatchMachineConfig(nodeCtx, map[string]any{ + "machine": map[string]any{ + "baseRuntimeSpecOverrides": map[string]any{ + "$patch": "delete", + }, + }, + }) + + return nil + }, assertRebootedRebootTimeout, + ) + + suite.ClearConnectionRefused(suite.ctx, node) + + ociUlimits2PodDef, err := suite.NewPod("oci-ulimits-test-2") + suite.Require().NoError(err) + + ociUlimits2PodDef = ociUlimits2PodDef.WithNodeName(nodeName) + + suite.Require().NoError(ociUlimits2PodDef.Create(suite.ctx, 5*time.Minute)) + + stdout, stderr, err = ociUlimits2PodDef.Exec( + suite.ctx, + "ulimit -n", + ) + suite.Require().NoError(err) + + suite.Require().Equal("", stderr) + suite.Require().Equal("1048576\n", stdout) + + suite.Assert().NoError(ociUlimits2PodDef.Delete(suite.ctx)) +} + func init() { allSuites = append(allSuites, &CommonSuite{}) } diff --git a/internal/integration/base/api.go b/internal/integration/base/api.go index 14f4ecf875..0ac6d95af7 100644 --- a/internal/integration/base/api.go +++ b/internal/integration/base/api.go @@ -297,7 +297,7 @@ func (apiSuite *APISuite) AssertRebootedNoChecks(ctx context.Context, node strin ctx, ctxCancel := context.WithTimeout(ctx, timeout) defer ctxCancel() - nodeCtx := client.WithNodes(ctx, node) + nodeCtx := client.WithNode(ctx, node) var ( bootIDBefore string diff --git a/pkg/machinery/config/config/machine.go b/pkg/machinery/config/config/machine.go index 242cda16ad..bbdc52d3f8 100644 --- a/pkg/machinery/config/config/machine.go +++ b/pkg/machinery/config/config/machine.go @@ -45,6 +45,7 @@ type MachineConfig interface { NodeLabels() NodeLabels NodeAnnotations() NodeAnnotations NodeTaints() NodeTaints + BaseRuntimeSpecOverrides() map[string]any } // SeccompProfile defines the requirements for a config that pertains to seccomp diff --git a/pkg/machinery/config/schemas/config.schema.json b/pkg/machinery/config/schemas/config.schema.json index 79ed5f880c..ca96108771 100644 --- a/pkg/machinery/config/schemas/config.schema.json +++ b/pkg/machinery/config/schemas/config.schema.json @@ -2829,6 +2829,13 @@ "markdownDescription": "Configures the seccomp profiles for the machine.", "x-intellij-html-description": "\u003cp\u003eConfigures the seccomp profiles for the machine.\u003c/p\u003e\n" }, + "baseRuntimeSpecOverrides": { + "type": "object", + "title": "baseRuntimeSpecOverrides", + "description": "Override (patch) settings in the default OCI runtime spec for CRI containers.\n\nIt can be used to set some default container settings which are not configurable in Kubernetes,\nfor example default ulimits.\nNote: this change applies to all newly created containers, and it requires a reboot to take effect.\n", + "markdownDescription": "Override (patch) settings in the default OCI runtime spec for CRI containers.\n\nIt can be used to set some default container settings which are not configurable in Kubernetes,\nfor example default ulimits.\nNote: this change applies to all newly created containers, and it requires a reboot to take effect.", + "x-intellij-html-description": "\u003cp\u003eOverride (patch) settings in the default OCI runtime spec for CRI containers.\u003c/p\u003e\n\n\u003cp\u003eIt can be used to set some default container settings which are not configurable in Kubernetes,\nfor example default ulimits.\nNote: this change applies to all newly created containers, and it requires a reboot to take effect.\u003c/p\u003e\n" + }, "nodeLabels": { "patternProperties": { ".*": { diff --git a/pkg/machinery/config/types/v1alpha1/v1alpha1_examples.go b/pkg/machinery/config/types/v1alpha1/v1alpha1_examples.go index 0f27ea98ed..5deabe6db6 100644 --- a/pkg/machinery/config/types/v1alpha1/v1alpha1_examples.go +++ b/pkg/machinery/config/types/v1alpha1/v1alpha1_examples.go @@ -816,3 +816,19 @@ func kmsKeyExample() *EncryptionKeyKMS { KMSEndpoint: "https://192.168.88.21:4443", } } + +func machineBaseRuntimeSpecOverridesExample() Unstructured { + return Unstructured{ + Object: map[string]any{ + "process": map[string]any{ + "rlimits": []map[string]any{ + { + "type": "RLIMIT_NOFILE", + "hard": 1024, + "soft": 1024, + }, + }, + }, + }, + } +} diff --git a/pkg/machinery/config/types/v1alpha1/v1alpha1_provider.go b/pkg/machinery/config/types/v1alpha1/v1alpha1_provider.go index fb16da8211..b82744c513 100644 --- a/pkg/machinery/config/types/v1alpha1/v1alpha1_provider.go +++ b/pkg/machinery/config/types/v1alpha1/v1alpha1_provider.go @@ -104,6 +104,11 @@ func (m *MachineConfig) NodeTaints() config.NodeTaints { return m.MachineNodeTaints } +// BaseRuntimeSpecOverrides implements the config.Provider interface. +func (m *MachineConfig) BaseRuntimeSpecOverrides() map[string]any { + return m.MachineBaseRuntimeSpecOverrides.Object +} + // Cluster implements the config.Provider interface. func (c *Config) Cluster() config.ClusterConfig { if c == nil || c.ClusterConfig == nil { diff --git a/pkg/machinery/config/types/v1alpha1/v1alpha1_types.go b/pkg/machinery/config/types/v1alpha1/v1alpha1_types.go index 1d33621970..babc305af1 100644 --- a/pkg/machinery/config/types/v1alpha1/v1alpha1_types.go +++ b/pkg/machinery/config/types/v1alpha1/v1alpha1_types.go @@ -290,6 +290,18 @@ type MachineConfig struct { // - value: machineSeccompExample() MachineSeccompProfiles []*MachineSeccompProfile `yaml:"seccompProfiles,omitempty" talos:"omitonlyifnil"` // description: | + // Override (patch) settings in the default OCI runtime spec for CRI containers. + // + // It can be used to set some default container settings which are not configurable in Kubernetes, + // for example default ulimits. + // Note: this change applies to all newly created containers, and it requires a reboot to take effect. + // examples: + // - name: override default open file limit + // value: machineBaseRuntimeSpecOverridesExample() + // schema: + // type: object + MachineBaseRuntimeSpecOverrides Unstructured `yaml:"baseRuntimeSpecOverrides,omitempty"` + // description: | // Configures the node labels for the machine. // // Note: In the default Kubernetes configuration, worker nodes are restricted to set diff --git a/pkg/machinery/config/types/v1alpha1/v1alpha1_types_doc.go b/pkg/machinery/config/types/v1alpha1/v1alpha1_types_doc.go index 0dafdc7a91..3f86898359 100644 --- a/pkg/machinery/config/types/v1alpha1/v1alpha1_types_doc.go +++ b/pkg/machinery/config/types/v1alpha1/v1alpha1_types_doc.go @@ -249,6 +249,13 @@ func (MachineConfig) Doc() *encoder.Doc { Description: "Configures the seccomp profiles for the machine.", Comments: [3]string{"" /* encoder.HeadComment */, "Configures the seccomp profiles for the machine." /* encoder.LineComment */, "" /* encoder.FootComment */}, }, + { + Name: "baseRuntimeSpecOverrides", + Type: "Unstructured", + Note: "", + Description: "Override (patch) settings in the default OCI runtime spec for CRI containers.\n\nIt can be used to set some default container settings which are not configurable in Kubernetes,\nfor example default ulimits.\nNote: this change applies to all newly created containers, and it requires a reboot to take effect.", + Comments: [3]string{"" /* encoder.HeadComment */, "Override (patch) settings in the default OCI runtime spec for CRI containers." /* encoder.LineComment */, "" /* encoder.FootComment */}, + }, { Name: "nodeLabels", Type: "map[string]string", @@ -298,9 +305,10 @@ func (MachineConfig) Doc() *encoder.Doc { doc.Fields[20].AddExample("", machineLoggingExample()) doc.Fields[21].AddExample("", machineKernelExample()) doc.Fields[22].AddExample("", machineSeccompExample()) - doc.Fields[23].AddExample("node labels example.", map[string]string{"exampleLabel": "exampleLabelValue"}) - doc.Fields[24].AddExample("node annotations example.", map[string]string{"customer.io/rack": "r13a25"}) - doc.Fields[25].AddExample("node taints example.", map[string]string{"exampleTaint": "exampleTaintValue:NoSchedule"}) + doc.Fields[23].AddExample("override default open file limit", machineBaseRuntimeSpecOverridesExample()) + doc.Fields[24].AddExample("node labels example.", map[string]string{"exampleLabel": "exampleLabelValue"}) + doc.Fields[25].AddExample("node annotations example.", map[string]string{"customer.io/rack": "r13a25"}) + doc.Fields[26].AddExample("node taints example.", map[string]string{"exampleTaint": "exampleTaintValue:NoSchedule"}) return doc } diff --git a/pkg/machinery/config/types/v1alpha1/v1alpha1_validation.go b/pkg/machinery/config/types/v1alpha1/v1alpha1_validation.go index 3a58b6e508..40a40e2881 100644 --- a/pkg/machinery/config/types/v1alpha1/v1alpha1_validation.go +++ b/pkg/machinery/config/types/v1alpha1/v1alpha1_validation.go @@ -7,6 +7,7 @@ package v1alpha1 import ( "context" "encoding/base64" + "encoding/json" "errors" "fmt" "net" @@ -19,6 +20,7 @@ import ( "github.com/cosi-project/runtime/pkg/state" "github.com/hashicorp/go-multierror" + "github.com/opencontainers/runtime-spec/specs-go" sideronet "github.com/siderolabs/net" "github.com/siderolabs/talos/pkg/machinery/config/config" @@ -326,6 +328,20 @@ func (c *Config) Validate(mode validation.RuntimeMode, options ...validation.Opt result = multierror.Append(result, errors.New(".persist should be enabled")) } + if len(c.Machine().BaseRuntimeSpecOverrides()) > 0 { + // try to unmarshal the overrides to ensure they are valid + jsonSpec, err := json.Marshal(c.Machine().BaseRuntimeSpecOverrides()) + if err != nil { + result = multierror.Append(result, fmt.Errorf("failed to marshal base runtime spec overrides: %w", err)) + } else { + var ociSpec specs.Spec + + if err := json.Unmarshal(jsonSpec, &ociSpec); err != nil { + result = multierror.Append(result, fmt.Errorf("failed to unmarshal base runtime spec overrides: %w", err)) + } + } + } + if opts.Strict { for _, w := range warnings { result = multierror.Append(result, fmt.Errorf("warning: %s", w)) diff --git a/pkg/machinery/config/types/v1alpha1/v1alpha1_validation_test.go b/pkg/machinery/config/types/v1alpha1/v1alpha1_validation_test.go index 7764eb2d94..36d30d4f26 100644 --- a/pkg/machinery/config/types/v1alpha1/v1alpha1_validation_test.go +++ b/pkg/machinery/config/types/v1alpha1/v1alpha1_validation_test.go @@ -1878,6 +1878,39 @@ func TestValidate(t *testing.T) { }, expectedError: "1 error occurred:\n\t* authorization-webhook-* flags cannot be used in conjunction with AuthorizationConfig, use either AuthorizationConfig or authorization-webhook-* flags\n\n", }, + { + name: "MachineBaseRuntimeSpecOverrides", + config: &v1alpha1.Config{ + ConfigVersion: "v1alpha1", + MachineConfig: &v1alpha1.MachineConfig{ + MachineType: "controlplane", + MachineCA: &x509.PEMEncodedCertificateAndKey{ + Crt: []byte("foo"), + Key: []byte("bar"), + }, + MachineBaseRuntimeSpecOverrides: v1alpha1.Unstructured{ + Object: map[string]any{ + "process": map[string]any{ + "rlimits": []map[string]any{ + { + "type": "RLIMIT_NOFILE", + "hard": 1024, + "soft": 1024, + }, + }, + }, + }, + }, + }, + ClusterConfig: &v1alpha1.ClusterConfig{ + ControlPlane: &v1alpha1.ControlPlaneConfig{ + Endpoint: &v1alpha1.Endpoint{ + endpointURL, + }, + }, + }, + }, + }, } { t.Run(test.name, func(t *testing.T) { t.Parallel() diff --git a/pkg/machinery/constants/constants.go b/pkg/machinery/constants/constants.go index fde142945e..08c7a969c9 100644 --- a/pkg/machinery/constants/constants.go +++ b/pkg/machinery/constants/constants.go @@ -566,6 +566,9 @@ const ( // CRICustomizationConfigPart is the path to the CRI generated registry configuration relative to /etc. CRICustomizationConfigPart = "cri/conf.d/20-customization.part" + // CRIBaseRuntimeSpec is the path to the base runtime spec for the CRI. + CRIBaseRuntimeSpec = "cri/conf.d/base-spec.json" + // TalosConfigEnvVar is the environment variable for setting the Talos configuration file path. TalosConfigEnvVar = "TALOSCONFIG" diff --git a/website/content/v1.9/reference/configuration/v1alpha1/config.md b/website/content/v1.9/reference/configuration/v1alpha1/config.md index f1771d23f5..487d9945ea 100644 --- a/website/content/v1.9/reference/configuration/v1alpha1/config.md +++ b/website/content/v1.9/reference/configuration/v1alpha1/config.md @@ -422,6 +422,14 @@ seccompProfiles: value: defaultAction: SCMP_ACT_LOG {{< /highlight >}} | | +|`baseRuntimeSpecOverrides` |Unstructured |
Override (patch) settings in the default OCI runtime spec for CRI containers.
It can be used to set some default container settings which are not configurable in Kubernetes,
for example default ulimits.
Note: this change applies to all newly created containers, and it requires a reboot to take effect.
Show example(s){{< highlight yaml >}} +baseRuntimeSpecOverrides: + process: + rlimits: + - hard: 1024 + soft: 1024 + type: RLIMIT_NOFILE +{{< /highlight >}}
| | |`nodeLabels` |map[string]string |
Configures the node labels for the machine.
Note: In the default Kubernetes configuration, worker nodes are restricted to set
labels with some prefixes (see [NodeRestriction](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction) admission plugin).
Show example(s){{< highlight yaml >}} nodeLabels: exampleLabel: exampleLabelValue diff --git a/website/content/v1.9/schemas/config.schema.json b/website/content/v1.9/schemas/config.schema.json index 79ed5f880c..ca96108771 100644 --- a/website/content/v1.9/schemas/config.schema.json +++ b/website/content/v1.9/schemas/config.schema.json @@ -2829,6 +2829,13 @@ "markdownDescription": "Configures the seccomp profiles for the machine.", "x-intellij-html-description": "\u003cp\u003eConfigures the seccomp profiles for the machine.\u003c/p\u003e\n" }, + "baseRuntimeSpecOverrides": { + "type": "object", + "title": "baseRuntimeSpecOverrides", + "description": "Override (patch) settings in the default OCI runtime spec for CRI containers.\n\nIt can be used to set some default container settings which are not configurable in Kubernetes,\nfor example default ulimits.\nNote: this change applies to all newly created containers, and it requires a reboot to take effect.\n", + "markdownDescription": "Override (patch) settings in the default OCI runtime spec for CRI containers.\n\nIt can be used to set some default container settings which are not configurable in Kubernetes,\nfor example default ulimits.\nNote: this change applies to all newly created containers, and it requires a reboot to take effect.", + "x-intellij-html-description": "\u003cp\u003eOverride (patch) settings in the default OCI runtime spec for CRI containers.\u003c/p\u003e\n\n\u003cp\u003eIt can be used to set some default container settings which are not configurable in Kubernetes,\nfor example default ulimits.\nNote: this change applies to all newly created containers, and it requires a reboot to take effect.\u003c/p\u003e\n" + }, "nodeLabels": { "patternProperties": { ".*": {