Skip to content

Commit

Permalink
balloons: add support for isolcpus
Browse files Browse the repository at this point in the history
The isolcpus boot parameter allows you to isolate specific CPUs from
the general SMP balancing and scheduler algorithms. Currently, when a
balloon picks up CPUs, it does not differentiate between isolated and
non-isolated CPUs. This change improves the balloon's logic to:

 1: Distinguish between isolated and non-isolated CPUs.
 2: Allow users to preferably select isolated CPUs, though this is not guaranteed.
 3: Avoid using isolated CPUs unless specifically requested by the user via CR.

Signed-off-by: Feruzjon Muyassarov <[email protected]>
  • Loading branch information
fmuyassarov committed Jul 2, 2024
1 parent 17e1028 commit b2f1e06
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 0 deletions.
20 changes: 20 additions & 0 deletions cmd/plugins/balloons/policy/balloons-policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ const (
// virtDevReservedCpus is the name of a virtual device close to
// CPUs that are configured as ReservedResources.
virtDevReservedCpus = "reserved CPUs"
// virtDevIsolatedCpus is the name of a virtual device close to
// host isolated CPUs.
virtDevIsolatedCpus = "isolated CPUs"
)

// balloons contains configuration and runtime attributes of the balloons policy
Expand Down Expand Up @@ -558,6 +561,7 @@ func (p *balloons) newBalloon(blnDef *BalloonDef, confCpus bool) (*Balloon, erro
preferFarFromDevices: blnDef.PreferFarFromDevices,
virtDevCpusets: map[string][]cpuset.CPUSet{
virtDevReservedCpus: {p.reserved},
virtDevIsolatedCpus: {p.options.System.Isolated()},
},
}
if blnDef.AllocatorTopologyBalancing != nil {
Expand Down Expand Up @@ -994,6 +998,9 @@ func (p *balloons) validateConfig(bpoptions *BalloonsOptions) error {
blnDef.Name, blnDef.MaxBalloons)
}
}
if blnDef.PreferIsolCpus && blnDef.ShareIdleCpusInSame != "" {
log.Warn("WARNING: using PreferIsolCpus with ShareIdleCpusInSame is highly discouraged")
}
}
return nil
}
Expand Down Expand Up @@ -1030,6 +1037,7 @@ func (p *balloons) setConfig(bpoptions *BalloonsOptions) error {
if err = p.validateConfig(bpoptions); err != nil {
return balloonsError("invalid configuration: %w", err)
}
p.fillCloseToDevices(bpoptions.BalloonDefs)
p.fillFarFromDevices(bpoptions.BalloonDefs)

// Preparation and configuration validation is now done
Expand Down Expand Up @@ -1189,6 +1197,14 @@ func (p *balloons) fillBuiltinBalloonDefs(bpoptions *BalloonsOptions) (*BalloonD
return reservedBalloonDef, defaultBalloonDef, nil
}

func (p *balloons) fillCloseToDevices(blnDefs []*BalloonDef) {
for _, blnDef := range blnDefs {
if blnDef.PreferIsolCpus {
blnDef.PreferCloseToDevices = append(blnDef.PreferCloseToDevices, virtDevIsolatedCpus)
}
}
}

// fillFarFromDevices adds BalloonDefs implicit device anti-affinities
// towards devices that other BalloonDefs prefer to be close to.
func (p *balloons) fillFarFromDevices(blnDefs []*BalloonDef) {
Expand All @@ -1201,6 +1217,9 @@ func (p *balloons) fillFarFromDevices(blnDefs []*BalloonDef) {
// beginning of the list will be more effectively avoided than
// devices later in the list.
avoidDevs := []string{}
if p.options.System.Isolated().Size() != 0 {
avoidDevs = append(avoidDevs, virtDevIsolatedCpus)
}
for _, blnDef := range blnDefs {
for _, closeDev := range blnDef.PreferCloseToDevices {
if _, ok := devDefClose[closeDev]; !ok {
Expand Down Expand Up @@ -1361,6 +1380,7 @@ func (p *balloons) shareIdleCpus(addCpus, removeCpus cpuset.CPUSet) []*Balloon {
}
}
}
addCpus = addCpus.Difference(p.options.System.Isolated())
if addCpus.Size() > 0 {
for blnIdx, bln := range p.balloons {
topoLevel := bln.Def.ShareIdleCpusInSame
Expand Down
4 changes: 4 additions & 0 deletions config/crd/bases/config.nri_balloonspolicies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ spec:
items:
type: string
type: array
preferIsolCpus:
default: false
description: 'preferIsolCpus: prefer kernel isolated cpus'
type: boolean
preferNewBalloons:
description: |-
PreferNewBalloons: prefer creating new balloons over adding
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ spec:
items:
type: string
type: array
preferIsolCpus:
default: false
description: 'preferIsolCpus: prefer kernel isolated cpus'
type: boolean
preferNewBalloons:
description: |-
PreferNewBalloons: prefer creating new balloons over adding
Expand Down
3 changes: 3 additions & 0 deletions deployment/helm/balloons/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ config:
minBalloons: 0
allocatorPriority: normal
shareIdleCPUsInSame: system
preferIsolCpus: false
reservedPoolNamespaces:
- kube-system
log:
Expand All @@ -30,6 +31,8 @@ config:
instrumentation:
reportPeriod: 60s
samplingRatePerMillion: 0
httpEndpoint: :8891
prometheusExport: true

# configGroupLabel: config.nri/group

Expand Down
3 changes: 3 additions & 0 deletions pkg/apis/config/v1alpha1/resmgr/policy/balloons/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ type BalloonDef struct {
// TODO: PreferFarFromDevices is considered too untested for usage. Hence,
// for the time being we prevent its usage through CRDs.
PreferFarFromDevices []string `json:"-"`
// preferIsolCpus: prefer kernel isolated cpus
// +kubebuilder:default:=false
PreferIsolCpus bool `json:"preferIsolCpus,omitempty"`
}

// String stringifies a BalloonDef
Expand Down

0 comments on commit b2f1e06

Please sign in to comment.