@@ -49,6 +49,8 @@ const (
4949 balloonKey = "balloon." + PolicyName + "." + kubernetes .ResmgrKeyNamespace
5050 // hideHyperthreadsKey is a pod annotation key for pod/container-specific hyperthread allowance.
5151 hideHyperthreadsKey = "hide-hyperthreads." + kubernetes .ResmgrKeyNamespace
52+ // schedulingClassKey is a pod annotation key for pod/container-specific scheduling class.
53+ schedulingClassKey = "scheduling-class." + kubernetes .ResmgrKeyNamespace
5254 // reservedBalloonDefName is the name in the reserved balloon definition.
5355 reservedBalloonDefName = "reserved"
5456 // defaultBalloonDefName is the name in the default balloon definition.
@@ -1509,6 +1511,7 @@ func (p *balloons) applyBalloonDef(balloons *[]*Balloon, blnDef *BalloonDef, fre
15091511func (p * balloons ) validateConfig (bpoptions * BalloonsOptions ) error {
15101512 seenNames := map [string ]struct {}{}
15111513 undefinedLoadClasses := map [string ]struct {}{}
1514+ undefinedSchedulingClasses := map [string ]struct {}{}
15121515 compositeBlnDefs := map [string ]* BalloonDef {}
15131516 for _ , blnDef := range bpoptions .BalloonDefs {
15141517 if blnDef .Name == "" {
@@ -1581,6 +1584,9 @@ func (p *balloons) validateConfig(bpoptions *BalloonsOptions) error {
15811584 for _ , load := range blnDef .Loads {
15821585 undefinedLoadClasses [load ] = struct {}{}
15831586 }
1587+ if blnDef .SchedulingClass != "" {
1588+ undefinedSchedulingClasses [blnDef .SchedulingClass ] = struct {}{}
1589+ }
15841590 }
15851591 for lcIndex , loadClass := range bpoptions .LoadClasses {
15861592 delete (undefinedLoadClasses , loadClass .Name )
@@ -1594,6 +1600,12 @@ func (p *balloons) validateConfig(bpoptions *BalloonsOptions) error {
15941600 if len (undefinedLoadClasses ) > 0 {
15951601 return balloonsError ("loads defined in balloonTypes but missing from loadClasses: %v" , undefinedLoadClasses )
15961602 }
1603+ for _ , schedClass := range bpoptions .SchedulingClasses {
1604+ delete (undefinedSchedulingClasses , schedClass .Name )
1605+ }
1606+ if len (undefinedSchedulingClasses ) > 0 {
1607+ return balloonsError ("schedulingClass(es) defined in balloonTypes but missing from schedulingClasses: %v" , undefinedSchedulingClasses )
1608+ }
15971609 var circularCheck func (name string , seen map [string ]int ) error
15981610 circularCheck = func (name string , seen map [string ]int ) error {
15991611 if seen [name ] > 0 {
@@ -2124,13 +2136,89 @@ func (bln *Balloon) updateGroups(c cache.Container, delta int) {
21242136 }
21252137}
21262138
2139+ // applyProcessScheduling configures container's scheduling and IO priorities
2140+ func applyProcessScheduling (c cache.Container , sc * SchedulingClass ) {
2141+ if sc == nil {
2142+ return
2143+ }
2144+ log .Debug (" - applying scheduling class %q to %s" , sc .Name , c .PrettyName ())
2145+ if sc .Policy != "" {
2146+ if pol , err := sc .Policy .ToNRI (); err == nil {
2147+ c .SetSchedulingPolicy (pol )
2148+ log .Debug (" - scheduling policy %q (%s)" , sc .Policy , pol )
2149+ } else {
2150+ log .Debug (" - invalid scheduling policy %q in scheduling class %q: %v" , sc .Policy , sc .Name , err )
2151+ }
2152+ }
2153+ if sc .Priority != nil {
2154+ c .SetSchedulingPriority (int32 (* sc .Priority ))
2155+ log .Debug (" - scheduling priority %d" , * sc .Priority )
2156+ }
2157+ if len (sc .Flags ) > 0 {
2158+ if flags , err := sc .Flags .ToNRI (); err == nil {
2159+ c .SetSchedulingFlags (flags )
2160+ log .Debug (" - scheduling flags %q" , sc .Flags )
2161+ } else {
2162+ log .Debug (" - invalid scheduling flags %q in scheduling class %q: %v" , sc .Flags , sc .Name , err )
2163+ }
2164+ }
2165+ if sc .Nice != nil {
2166+ c .SetSchedulingNice (int32 (* sc .Nice ))
2167+ log .Debug (" - nice value %d" , * sc .Nice )
2168+ }
2169+ if sc .Runtime != nil {
2170+ c .SetSchedulingRuntime (* sc .Runtime )
2171+ log .Debug (" - scheduling runtime %d" , * sc .Runtime )
2172+ }
2173+ if sc .Deadline != nil {
2174+ c .SetSchedulingDeadline (* sc .Deadline )
2175+ log .Debug (" - scheduling deadline %d" , * sc .Deadline )
2176+ }
2177+ if sc .Period != nil {
2178+ c .SetSchedulingPeriod (* sc .Period )
2179+ log .Debug (" - scheduling period %d" , * sc .Period )
2180+ }
2181+ if sc .IOClass != "" {
2182+ if ioClass , err := sc .IOClass .ToNRI (); err == nil {
2183+ c .SetSchedulingIOClass (ioClass )
2184+ log .Debug (" - IO class %q" , sc .IOClass )
2185+ } else {
2186+ log .Debug (" - invalid IO class %q in scheduling class %q: %v" , sc .IOClass , sc .Name , err )
2187+ }
2188+ }
2189+ if sc .IOPriority != nil {
2190+ c .SetSchedulingIOPriority (int32 (* sc .IOPriority ))
2191+ log .Debug (" - IO priority %d" , * sc .IOPriority )
2192+ }
2193+ }
2194+
2195+ func (p * balloons ) applyProcessProperties (c cache.Container , bln * Balloon ) {
2196+ effSc := bln .Def .SchedulingClass
2197+ if annSc , annExists := c .GetEffectiveAnnotation (schedulingClassKey ); annExists {
2198+ if annSc != effSc {
2199+ log .Debug (" - container %s overrides balloon scheduling class %q with annotation %q" ,
2200+ c .PrettyName (), effSc , annSc )
2201+ }
2202+ effSc = annSc
2203+ }
2204+ if effSc != "" {
2205+ for _ , sc := range p .bpoptions .SchedulingClasses {
2206+ if sc .Name == effSc {
2207+ applyProcessScheduling (c , sc )
2208+ break
2209+ }
2210+ }
2211+ }
2212+ }
2213+
21272214// assignContainer adds a container to a balloon
21282215func (p * balloons ) assignContainer (c cache.Container , bln * Balloon ) {
21292216 log .Info ("assigning container %s to balloon %s" , c .PrettyName (), bln )
21302217 podID := c .GetPodID ()
21312218 bln .PodIDs [podID ] = append (bln .PodIDs [podID ], c .GetID ())
21322219 bln .updateGroups (c , 1 )
21332220 p .updatePinning (bln )
2221+ p .applyProcessProperties (c , bln )
21342222}
21352223
21362224// dismissContainer removes a container from a balloon
0 commit comments