Skip to content

Commit

Permalink
Merge pull request containers#420 from klihub/devel/topology-aware/us…
Browse files Browse the repository at this point in the history
…e-podresapi-hints

[podresapi 3/3] topology-aware: use Pod Resource API hints if present.
  • Loading branch information
kad authored Dec 4, 2024
2 parents b412a05 + d05b4e1 commit 331b1ec
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 5 deletions.
4 changes: 2 additions & 2 deletions cmd/plugins/topology-aware/policy/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,11 @@ func TestAllocationMarshalling(t *testing.T) {
}{
{
name: "non-zero Exclusive",
data: []byte(`{"key1":{"Exclusive":"1","Part":1,"CPUType":0,"Container":"1","Pool":"testnode","MemoryPool":0,"MemType":"DRAM,PMEM,HBM","MemSize":0,"ColdStart":0}}`),
data: []byte(`{"key1":{"PrettyName":"","Exclusive":"1","Part":1,"CPUType":0,"Container":"1","Pool":"testnode","MemoryPool":0,"MemType":"DRAM,PMEM,HBM","MemSize":0,"ColdStart":0}}`),
},
{
name: "zero Exclusive",
data: []byte(`{"key1":{"Exclusive":"","Part":1,"CPUType":0,"Container":"1","Pool":"testnode","MemoryPool":0,"MemType":"DRAM,PMEM,HBM","MemSize":0,"ColdStart":0}}`),
data: []byte(`{"key1":{"PrettyName":"","Exclusive":"","Part":1,"CPUType":0,"Container":"1","Pool":"testnode","MemoryPool":0,"MemType":"DRAM,PMEM,HBM","MemSize":0,"ColdStart":0}}`),
},
}
for _, tc := range tcases {
Expand Down
14 changes: 12 additions & 2 deletions cmd/plugins/topology-aware/policy/mocks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"time"

nri "github.com/containerd/nri/pkg/api"
"github.com/containers/nri-plugins/pkg/agent/podresapi"
resmgr "github.com/containers/nri-plugins/pkg/apis/resmgr/v1alpha1"
"github.com/containers/nri-plugins/pkg/cpuallocator"
"github.com/containers/nri-plugins/pkg/resmgr/cache"
Expand Down Expand Up @@ -324,6 +325,9 @@ func (fake *mockSystem) SetCpusOnline(online bool, cpus idset.IDSet) (idset.IDSe
func (fake *mockSystem) NodeDistance(idset.ID, idset.ID) int {
return 10
}
func (fake *mockSystem) NodeHintToCPUs(string) string {
return ""
}

type mockContainer struct {
name string
Expand Down Expand Up @@ -538,6 +542,9 @@ func (m *mockContainer) PreserveMemoryResources() bool {
func (m *mockContainer) MemoryTypes() (libmem.TypeMask, error) {
return libmem.TypeMaskDRAM, nil
}
func (m *mockContainer) GetPodResources() *podresapi.ContainerResources {
return nil
}

type mockPod struct {
name string
Expand Down Expand Up @@ -625,14 +632,17 @@ func (m *mockPod) GetTasks(bool) ([]string, error) {
func (m *mockPod) GetCtime() time.Time {
panic("unimplemented")
}
func (m *mockPod) GetPodResources() *podresapi.PodResources {
return nil
}

type mockCache struct {
returnValueForGetPolicyEntry bool
returnValue1ForLookupContainer cache.Container
returnValue2ForLookupContainer bool
}

func (m *mockCache) InsertPod(*nri.PodSandbox) (cache.Pod, error) {
func (m *mockCache) InsertPod(*nri.PodSandbox, <-chan *podresapi.PodResources) cache.Pod {
panic("unimplemented")
}
func (m *mockCache) DeletePod(string) cache.Pod {
Expand Down Expand Up @@ -695,7 +705,7 @@ func (m *mockCache) GetPolicyEntry(string, interface{}) bool {
func (m *mockCache) Save() error {
return nil
}
func (m *mockCache) RefreshPods([]*nri.PodSandbox) ([]cache.Pod, []cache.Pod, []cache.Container) {
func (m *mockCache) RefreshPods([]*nri.PodSandbox, <-chan podresapi.PodResourcesList) ([]cache.Pod, []cache.Pod, []cache.Container) {
panic("unimplemented")
}
func (m *mockCache) RefreshContainers([]*nri.Container) ([]cache.Container, []cache.Container) {
Expand Down
1 change: 1 addition & 0 deletions cmd/plugins/topology-aware/policy/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,7 @@ func (cs *supply) GetScore(req Request) Score {

// calculate real hint scores
hints := cr.container.GetTopologyHints()
hints.ResolvePartialHints(cs.GetNode().System().NodeHintToCPUs)
score.hints = make(map[string]float64, len(hints))

for provider, hint := range cr.container.GetTopologyHints() {
Expand Down
12 changes: 11 additions & 1 deletion docs/resource-policy/policy/topology-aware.md
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ metadata:
prefer-reserved-cpus.resource-policy.nri.io/container.special: "false"
```

## Allowing or denying mount/device paths via annotations
## Controlling Topology Hints Via Annotations

User is able mark certain pods and containers to have allowed or denied
paths for mounts or devices. What this means is that when the system
Expand Down Expand Up @@ -486,6 +486,16 @@ metadata:
- /xy-zy/another-blacklisted-path5
```

## Using Pod Resource API for Extra Topology Hints

If access to the `kubelet`'s `Pod Resource API` is enabled in the
[Node Agent's](../developers-guide/architecture.md#node-agent) configuration,
it is automatically used to generate per-container topology hints when a
device with locality to a NUMA node is advertised by the API. Annotated allow
and deny lists can be used to selectively disable or enable per-resource hints,
using `podresapi:$RESOURCE_NAME` as the path.


## Container Affinity and Anti-Affinity

### Introduction
Expand Down
20 changes: 20 additions & 0 deletions pkg/sysfs/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ type System interface {

Offlined() cpuset.CPUSet
Isolated() cpuset.CPUSet

NodeHintToCPUs(string) string
}

// System devices
Expand Down Expand Up @@ -742,6 +744,24 @@ func (sys *system) Isolated() cpuset.CPUSet {
return sys.IsolatedCPUs()
}

// Resolve given node topology hints to CPUs.
func (sys *system) NodeHintToCPUs(nodes string) string {
mset, err := cpuset.Parse(nodes)
if err != nil {
log.Error("failed to resolve nodes %q to CPUs: %v", nodes, err)
return ""
}

cset := cpuset.New()
for _, id := range mset.List() {
if n, ok := sys.nodes[id]; ok {
cset = cset.Union(n.CPUSet())
}
}

return cset.Intersection(sys.OnlineCPUs()).String()
}

// Discover Cpus present in the system.
func (sys *system) discoverCPUs() error {
if sys.cpus != nil {
Expand Down
11 changes: 11 additions & 0 deletions pkg/topology/topology.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,17 @@ func MergeTopologyHints(org, hints Hints) (res Hints) {
return
}

// ResolvePartialHints resolves NUMA-only hints to CPU hints using the given function.
func (hints Hints) ResolvePartialHints(resolve func(NUMAs string) string) {
for k, h := range hints {
if h.CPUs == "" && h.NUMAs != "" {
h.CPUs = resolve(h.NUMAs)
log.Debugf("partial NUMA hint %q resolved to CPUs %q", h.NUMAs, h.CPUs)
hints[k] = h
}
}
}

// String returns the hints as a string.
func (h *Hint) String() string {
cpus, nodes, sockets, sep := "", "", "", ""
Expand Down

0 comments on commit 331b1ec

Please sign in to comment.