diff --git a/internal/factory/container/container_test.go b/internal/factory/container/container_test.go index 0e4fbc31891..7e2634b09cc 100644 --- a/internal/factory/container/container_test.go +++ b/internal/factory/container/container_test.go @@ -93,7 +93,7 @@ var _ = t.Describe("Container", func() { sb, err := sandbox.New("sandboxID", "", "", "", "test", make(map[string]string), make(map[string]string), "", "", &types.PodSandboxMetadata{}, "", "", false, "", "", "", - []*hostport.PortMapping{}, false, currentTime, "") + []*hostport.PortMapping{}, false, currentTime, "", nil, nil) Expect(err).To(BeNil()) image, err := sut.Image() diff --git a/internal/lib/container_server.go b/internal/lib/container_server.go index bb0b88b1525..b96aefdb1d7 100644 --- a/internal/lib/container_server.go +++ b/internal/lib/container_server.go @@ -200,7 +200,21 @@ func (c *ContainerServer) LoadSandbox(ctx context.Context, id string) (sb *sandb return nil, fmt.Errorf("parsing created timestamp annotation: %w", err) } - sb, err = sandbox.New(id, m.Annotations[annotations.Namespace], name, m.Annotations[annotations.KubeName], filepath.Dir(m.Annotations[annotations.LogPath]), labels, kubeAnnotations, processLabel, mountLabel, &metadata, m.Annotations[annotations.ShmPath], m.Annotations[annotations.CgroupParent], privileged, m.Annotations[annotations.RuntimeHandler], m.Annotations[annotations.ResolvPath], m.Annotations[annotations.HostName], portMappings, hostNetwork, created, m.Annotations[crioann.UsernsModeAnnotation]) + podLinuxOverhead := types.LinuxContainerResources{} + if v, found := m.Annotations[crioann.PodLinuxOverhead]; found { + if err := json.Unmarshal([]byte(v), &podLinuxOverhead); err != nil { + return nil, fmt.Errorf("error unmarshalling %s annotation: %w", crioann.PodLinuxOverhead, err) + } + } + + podLinuxResources := types.LinuxContainerResources{} + if v, found := m.Annotations[crioann.PodLinuxResources]; found { + if err := json.Unmarshal([]byte(v), &podLinuxResources); err != nil { + return nil, fmt.Errorf("error unmarshalling %s annotation: %w", crioann.PodLinuxResources, err) + } + } + + sb, err = sandbox.New(id, m.Annotations[annotations.Namespace], name, m.Annotations[annotations.KubeName], filepath.Dir(m.Annotations[annotations.LogPath]), labels, kubeAnnotations, processLabel, mountLabel, &metadata, m.Annotations[annotations.ShmPath], m.Annotations[annotations.CgroupParent], privileged, m.Annotations[annotations.RuntimeHandler], m.Annotations[annotations.ResolvPath], m.Annotations[annotations.HostName], portMappings, hostNetwork, created, m.Annotations[crioann.UsernsModeAnnotation], &podLinuxOverhead, &podLinuxResources) if err != nil { return nil, err } diff --git a/internal/lib/container_server_test.go b/internal/lib/container_server_test.go index 2134bbc5887..838dd9e2df9 100644 --- a/internal/lib/container_server_test.go +++ b/internal/lib/container_server_test.go @@ -408,6 +408,46 @@ var _ = t.Describe("ContainerServer", func() { Expect(sb).To(BeNil()) Expect(err).NotTo(BeNil()) }) + + It("should fail with wrong PodLinuxOverhead", func() { + // Given + manifest := bytes.Replace(testManifest, + []byte(`"io.kubernetes.cri-o.PodLinuxOverhead": "{}",`), + []byte(`"io.kubernetes.cri-o.PodLinuxOverhead": "wrong",`), 1, + ) + gomock.InOrder( + storeMock.EXPECT(). + FromContainerDirectory(gomock.Any(), gomock.Any()). + Return(manifest, nil), + ) + + // When + sb, err := sut.LoadSandbox(context.Background(), "id") + + // Then + Expect(sb).To(BeNil()) + Expect(err).NotTo(BeNil()) + }) + + It("should fail with wrong PodLinuxResources", func() { + // Given + manifest := bytes.Replace(testManifest, + []byte(`"io.kubernetes.cri-o.PodLinuxResources": "{}",`), + []byte(`"io.kubernetes.cri-o.PodLinuxResources": "wrong",`), 1, + ) + gomock.InOrder( + storeMock.EXPECT(). + FromContainerDirectory(gomock.Any(), gomock.Any()). + Return(manifest, nil), + ) + + // When + sb, err := sut.LoadSandbox(context.Background(), "id") + + // Then + Expect(sb).To(BeNil()) + Expect(err).NotTo(BeNil()) + }) }) t.Describe("LoadContainer", func() { diff --git a/internal/lib/sandbox/history_test.go b/internal/lib/sandbox/history_test.go index e460c3f4588..649f66447bb 100644 --- a/internal/lib/sandbox/history_test.go +++ b/internal/lib/sandbox/history_test.go @@ -20,7 +20,7 @@ var _ = t.Describe("History", func() { otherTestSandbox, err := sandbox.New("sandboxID", "", "", "", "", make(map[string]string), make(map[string]string), "", "", &types.PodSandboxMetadata{}, "", "", false, "", "", "", - []*hostport.PortMapping{}, false, time.Now(), "") + []*hostport.PortMapping{}, false, time.Now(), "", nil, nil) Expect(err).To(BeNil()) Expect(testSandbox).NotTo(BeNil()) sut = &sandbox.History{testSandbox, otherTestSandbox} diff --git a/internal/lib/sandbox/sandbox.go b/internal/lib/sandbox/sandbox.go index f7eb7d7aa66..6ce7327dd89 100644 --- a/internal/lib/sandbox/sandbox.go +++ b/internal/lib/sandbox/sandbox.go @@ -64,6 +64,8 @@ type Sandbox struct { hostNetwork bool usernsMode string containerEnvPath string + podLinuxOverhead *types.LinuxContainerResources + podLinuxResources *types.LinuxContainerResources } // DefaultShmSize is the default shm size @@ -75,7 +77,7 @@ var ErrIDEmpty = errors.New("PodSandboxId should not be empty") // New creates and populates a new pod sandbox // New sandboxes have no containers, no infra container, and no network namespaces associated with them // An infra container must be attached before the sandbox is added to the state -func New(id, namespace, name, kubeName, logDir string, labels, annotations map[string]string, processLabel, mountLabel string, metadata *types.PodSandboxMetadata, shmPath, cgroupParent string, privileged bool, runtimeHandler, resolvPath, hostname string, portMappings []*hostport.PortMapping, hostNetwork bool, createdAt time.Time, usernsMode string) (*Sandbox, error) { +func New(id, namespace, name, kubeName, logDir string, labels, annotations map[string]string, processLabel, mountLabel string, metadata *types.PodSandboxMetadata, shmPath, cgroupParent string, privileged bool, runtimeHandler, resolvPath, hostname string, portMappings []*hostport.PortMapping, hostNetwork bool, createdAt time.Time, usernsMode string, overhead, resources *types.LinuxContainerResources) (*Sandbox, error) { sb := new(Sandbox) sb.criSandbox = &types.PodSandbox{ @@ -101,6 +103,8 @@ func New(id, namespace, name, kubeName, logDir string, labels, annotations map[s sb.portMappings = portMappings sb.hostNetwork = hostNetwork sb.usernsMode = usernsMode + sb.podLinuxOverhead = overhead + sb.podLinuxResources = resources return sb, nil } @@ -286,6 +290,16 @@ func (s *Sandbox) PortMappings() []*hostport.PortMapping { return s.portMappings } +// PodLinuxOverhead returns the overheads associated with this sandbox +func (s *Sandbox) PodLinuxOverhead() *types.LinuxContainerResources { + return s.podLinuxOverhead +} + +// PodLinuxResources returns the sum of container resources for this sandbox +func (s *Sandbox) PodLinuxResources() *types.LinuxContainerResources { + return s.podLinuxResources +} + // AddContainer adds a container to the sandbox func (s *Sandbox) AddContainer(ctx context.Context, c *oci.Container) { _, span := log.StartSpan(ctx) diff --git a/internal/lib/sandbox/sandbox_test.go b/internal/lib/sandbox/sandbox_test.go index a706340a4df..0fe32fd8f38 100644 --- a/internal/lib/sandbox/sandbox_test.go +++ b/internal/lib/sandbox/sandbox_test.go @@ -44,7 +44,7 @@ var _ = t.Describe("Sandbox", func() { sandbox, err := sandbox.New(id, namespace, name, kubeName, logDir, labels, annotations, processLabel, mountLabel, &metadata, shmPath, cgroupParent, privileged, runtimeHandler, - resolvPath, hostname, portMappings, hostNetwork, createdAt, "") + resolvPath, hostname, portMappings, hostNetwork, createdAt, "", nil, nil) // Then Expect(err).To(BeNil()) diff --git a/internal/lib/sandbox/suite_test.go b/internal/lib/sandbox/suite_test.go index 6278e77e783..f88b0e8d88b 100644 --- a/internal/lib/sandbox/suite_test.go +++ b/internal/lib/sandbox/suite_test.go @@ -41,7 +41,7 @@ func beforeEach() { testSandbox, err = sandbox.New("sandboxID", "", "", "", "", make(map[string]string), make(map[string]string), "", "", &types.PodSandboxMetadata{}, "", "", false, "", "", "", - []*hostport.PortMapping{}, false, time.Now(), "") + []*hostport.PortMapping{}, false, time.Now(), "", nil, nil) Expect(err).To(BeNil()) Expect(testSandbox).NotTo(BeNil()) } diff --git a/internal/lib/suite_test.go b/internal/lib/suite_test.go index 23f087d0143..7776f9a79fb 100644 --- a/internal/lib/suite_test.go +++ b/internal/lib/suite_test.go @@ -86,6 +86,8 @@ var _ = BeforeSuite(func() { "io.kubernetes.cri-o.StdinOnce": "{}", "io.kubernetes.cri-o.Volumes": "[{}]", "io.kubernetes.cri-o.HostNetwork": "{}", + "io.kubernetes.cri-o.PodLinuxOverhead": "{}", + "io.kubernetes.cri-o.PodLinuxResources": "{}", "io.kubernetes.cri-o.CNIResult": "{}" }, "linux": { @@ -153,7 +155,7 @@ func beforeEach() { mySandbox, err = sandbox.New(sandboxID, "", "", "", "", make(map[string]string), make(map[string]string), "", "", &types.PodSandboxMetadata{}, "", "", false, "", "", "", - []*hostport.PortMapping{}, false, time.Now(), "") + []*hostport.PortMapping{}, false, time.Now(), "", nil, nil) Expect(err).To(BeNil()) myContainer, err = oci.NewContainer(containerID, "", "", "", diff --git a/pkg/annotations/annotations.go b/pkg/annotations/annotations.go index a3913c2a482..9ce8ed58ff9 100644 --- a/pkg/annotations/annotations.go +++ b/pkg/annotations/annotations.go @@ -53,6 +53,12 @@ const ( // SeccompNotifierActionStop indicates that a container should be stopped if used via the SeccompNotifierActionAnnotation key. SeccompNotifierActionStop = "stop" + + // PodLinuxOverhead indicates the overheads associated with the pod + PodLinuxOverhead = "io.kubernetes.cri-o.PodLinuxOverhead" + + // PodLinuxResources indicates the sum of container resources for this pod + PodLinuxResources = "io.kubernetes.cri-o.PodLinuxResources" ) var AllAllowedAnnotations = []string{ @@ -71,4 +77,6 @@ var AllAllowedAnnotations = []string{ CPUFreqGovernorAnnotation, SeccompNotifierActionAnnotation, UmaskAnnotation, + PodLinuxOverhead, + PodLinuxResources, } diff --git a/server/nri-api.go b/server/nri-api.go index ca06522b487..71379300d80 100644 --- a/server/nri-api.go +++ b/server/nri-api.go @@ -529,20 +529,16 @@ func (p *criPodSandbox) GetPodLinuxOverhead() *api.LinuxResources { if p.Sandbox == nil { return nil } - // TODO(klihub): AFAICT, CRI PodSandboxConfig is not stored, so we can only - // get our hands on it during RunPodSandbox() request processing... - // return api.FromCRILinuxResources(p.Sandbox.GetConfig().GetLinux().GetOverhead()) - return nil + + return api.FromCRILinuxResources(p.Sandbox.PodLinuxOverhead()) } func (p *criPodSandbox) GetPodLinuxResources() *api.LinuxResources { if p.Sandbox == nil { return nil } - // TODO(klihub): AFAICT, CRI PodSandboxConfig is not stored, so we can only - // get our hands on it during RunPodSandbox() request processing... - // return api.FromCRILinuxResources(p.Sandbox.GetConfig().GetLinux().GetResources()) - return nil + + return api.FromCRILinuxResources(p.Sandbox.PodLinuxResources()) } func (p *criPodSandbox) GetLinuxResources() *api.LinuxResources { diff --git a/server/sandbox_run_linux.go b/server/sandbox_run_linux.go index 63b6bbe6470..769bfdfafcf 100644 --- a/server/sandbox_run_linux.go +++ b/server/sandbox_run_linux.go @@ -674,7 +674,21 @@ func (s *Server) runPodSandbox(ctx context.Context, req *types.RunPodSandboxRequ } } - sb, err := libsandbox.New(sbox.ID(), namespace, sbox.Name(), kubeName, logDir, labels, kubeAnnotations, processLabel, mountLabel, metadata, shmPath, cgroupParent, privileged, runtimeHandler, sbox.ResolvPath(), hostname, portMappings, hostNetwork, created, usernsMode) + overhead := sbox.Config().GetLinux().GetOverhead() + overheadJSON, err := json.Marshal(overhead) + if err != nil { + return nil, err + } + g.AddAnnotation(ann.PodLinuxOverhead, string(overheadJSON)) + + resources := sbox.Config().GetLinux().GetResources() + resourcesJSON, err := json.Marshal(resources) + if err != nil { + return nil, err + } + g.AddAnnotation(ann.PodLinuxResources, string(resourcesJSON)) + + sb, err := libsandbox.New(sbox.ID(), namespace, sbox.Name(), kubeName, logDir, labels, kubeAnnotations, processLabel, mountLabel, metadata, shmPath, cgroupParent, privileged, runtimeHandler, sbox.ResolvPath(), hostname, portMappings, hostNetwork, created, usernsMode, overhead, resources) if err != nil { return nil, err } diff --git a/server/suite_test.go b/server/suite_test.go index fb93f85039a..cd0568cc5ea 100644 --- a/server/suite_test.go +++ b/server/suite_test.go @@ -156,7 +156,7 @@ var beforeEach = func() { testSandbox, err = sandbox.New(sandboxID, "", "", "", ".", make(map[string]string), make(map[string]string), "", "", &types.PodSandboxMetadata{}, "", "", false, "", "", "", - []*hostport.PortMapping{}, false, time.Now(), "") + []*hostport.PortMapping{}, false, time.Now(), "", nil, nil) Expect(err).To(BeNil()) testContainer, err = oci.NewContainer(containerID, "", "", "",