@@ -57,6 +57,10 @@ const (
5757 oldSchedulerKey = "scheduling-policy.nri.io"
5858 // Prefix of the key used for sysctl adjustment.
5959 sysctlKey = "sysctl.noderesource.dev"
60+ // Prefix of the key used for memory policy adjustment.
61+ memoryPolicyKey = "memory-policy.noderesource.dev"
62+ // Deprecated: Prefix of the key used for memory policy adjustment.
63+ oldMemoryPolicyKey = "memory-policy.nri.io"
6064)
6165
6266var (
@@ -106,6 +110,13 @@ type scheduler struct {
106110 Period uint64 `json:"period"`
107111}
108112
113+ // memoryPolicy adjustment
114+ type memoryPolicy struct {
115+ Mode string `json:"mode"`
116+ Nodes string `json:"nodes"`
117+ Flags []string `json:"flags"`
118+ }
119+
109120// our injector plugin
110121type plugin struct {
111122 stub stub.Stub
@@ -146,6 +157,10 @@ func (p *plugin) CreateContainer(_ context.Context, pod *api.PodSandbox, ctr *ap
146157 return nil , nil , err
147158 }
148159
160+ if err := adjustMemoryPolicy (pod , ctr , adjust ); err != nil {
161+ return nil , nil , err
162+ }
163+
149164 if verbose {
150165 dump (containerName (pod , ctr ), "ContainerAdjustment" , adjust )
151166 }
@@ -443,6 +458,53 @@ func parseSysctl(ctr string, annotations map[string]string) (map[string]string,
443458 return sysctl , nil
444459}
445460
461+ func adjustMemoryPolicy (pod * api.PodSandbox , ctr * api.Container , a * api.ContainerAdjustment ) error {
462+ pol , err := parseMemoryPolicy (ctr .Name , pod .Annotations )
463+ if err != nil {
464+ log .Errorf ("%s: invalid memory policy annotation: %v" ,
465+ containerName (pod , ctr ), err )
466+ return err
467+ }
468+
469+ if pol == nil {
470+ log .Debugf ("%s: no memory policy annotated..." , containerName (pod , ctr ))
471+ return nil
472+ }
473+
474+ if verbose {
475+ dump (containerName (pod , ctr ), "annotated memory policy" , pol )
476+ }
477+
478+ amp , err := pol .ToNRI ()
479+ if err != nil {
480+ log .Errorf ("%s: invalid memory policy annotation: %v" ,
481+ containerName (pod , ctr ), err )
482+ return fmt .Errorf ("invalid memory policy: %w" , err )
483+ }
484+
485+ a .SetLinuxMemoryPolicy (amp .Mode , amp .Nodes , amp .Flags ... )
486+ log .Infof ("%s: adjusted memory policy to %s..." , containerName (pod , ctr ), amp )
487+
488+ return nil
489+ }
490+
491+ func parseMemoryPolicy (ctr string , annotations map [string ]string ) (* memoryPolicy , error ) {
492+ var (
493+ policy = & memoryPolicy {}
494+ )
495+
496+ annotation := getAnnotation (annotations , memoryPolicyKey , oldMemoryPolicyKey , ctr )
497+ if annotation == nil {
498+ return nil , nil
499+ }
500+
501+ if err := yaml .Unmarshal (annotation , policy ); err != nil {
502+ return nil , fmt .Errorf ("invalid memory policy annotation %q: %w" , string (annotation ), err )
503+ }
504+
505+ return policy , nil
506+ }
507+
446508func getAnnotation (annotations map [string ]string , mainKey , oldKey , ctr string ) []byte {
447509 for _ , key := range []string {
448510 mainKey + "/container." + ctr ,
@@ -570,6 +632,46 @@ func (sc *scheduler) String() string {
570632 return s
571633}
572634
635+ // Convert memoryPolicy to the NRI API representation.
636+ func (mp * memoryPolicy ) ToNRI () (* api.LinuxMemoryPolicy , error ) {
637+ apiPol := & api.LinuxMemoryPolicy {
638+ Nodes : mp .Nodes ,
639+ }
640+
641+ mode , ok := api .MpolMode_value [mp .Mode ]
642+ if ! ok {
643+ return nil , fmt .Errorf ("invalid memory policy mode %q" , mp .Mode )
644+ }
645+ apiPol .Mode = api .MpolMode (mode )
646+
647+ for _ , f := range mp .Flags {
648+ flag , ok := api .MpolFlag_value [f ]
649+ if ! ok {
650+ return nil , fmt .Errorf ("invalid memory policy flag %q" , f )
651+ }
652+ apiPol .Flags = append (apiPol .Flags , api .MpolFlag (flag ))
653+ }
654+
655+ return apiPol , nil
656+ }
657+
658+ func (mp * memoryPolicy ) String () string {
659+ if mp == nil {
660+ return "<no memory policy>"
661+ }
662+
663+ s := fmt .Sprintf ("<memory policy mode=%s" , mp .Mode )
664+ if mp .Nodes != "" {
665+ s += fmt .Sprintf (", nodes=%s" , mp .Nodes )
666+ }
667+ if len (mp .Flags ) > 0 {
668+ s += fmt .Sprintf (", flags=%v" , mp .Flags )
669+ }
670+ s += ">"
671+
672+ return s
673+ }
674+
573675// Construct a container name for log messages.
574676func containerName (pod * api.PodSandbox , container * api.Container ) string {
575677 if pod != nil {
0 commit comments