Skip to content

Commit 1f7f525

Browse files
committed
Add ComputeDomainStatus and set it as its deployment pods come online.
Signed-off-by: Kevin Klues <[email protected]>
1 parent dd113e8 commit 1f7f525

File tree

9 files changed

+216
-11
lines changed

9 files changed

+216
-11
lines changed

api/nvidia.com/resource/v1beta1/computedomain.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@ import (
2424
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
2525
// +k8s:openapi-gen=true
2626
// +kubebuilder:resource:scope=Namespaced
27+
// +kubebuilder:subresource:status
2728

2829
// ComputeDomain prepares a set of nodes to run a multi-node workload in.
2930
type ComputeDomain struct {
3031
metav1.TypeMeta `json:",inline"`
3132
metav1.ObjectMeta `json:"metadata,omitempty"`
3233

33-
Spec ComputeDomainSpec `json:"spec,omitempty"`
34+
Spec ComputeDomainSpec `json:"spec,omitempty"`
35+
Status ComputeDomainStatus `json:"status,omitempty"`
3436
}
3537

3638
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
@@ -51,3 +53,26 @@ type ComputeDomainSpec struct {
5153
ResourceClaimName string `json:"resourceClaimName,omitempty"`
5254
DeviceClassName string `json:"deviceClassName,omitempty"`
5355
}
56+
57+
// ComputeDomainStatus provides the status for a ComputeDomain.
58+
type ComputeDomainStatus struct {
59+
// +listType=map
60+
// +listMapKey=name
61+
Nodes []*ComputeDomainNode `json:"nodes,omitempty"`
62+
}
63+
64+
// ComputeDomainNode provides information about each node added to a ComputeDomain.
65+
type ComputeDomainNode struct {
66+
Name string `json:"name"`
67+
IPAddress string `json:"ipAddress"`
68+
CliqueID string `json:"cliqueID"`
69+
}
70+
71+
// GetNodesAsMap returns the list of nodes in a ComputeDomainStatus as a map.
72+
func (s *ComputeDomainStatus) GetNodesAsMap() map[string]*ComputeDomainNode {
73+
m := make(map[string]*ComputeDomainNode)
74+
for _, node := range s.Nodes {
75+
m[node.Name] = node
76+
}
77+
return m
78+
}

api/nvidia.com/resource/v1beta1/zz_generated.deepcopy.go

Lines changed: 42 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/nvidia-dra-imex-controller/deployment.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ func (m *DeploymentManager) addPodManager(ctx context.Context, labelSelector *me
308308
return nil
309309
}
310310

311-
podManager := NewDeploymentPodManager(m.config, m.imexChannelManager, labelSelector, numPods)
311+
podManager := NewDeploymentPodManager(m.config, m.imexChannelManager, labelSelector, numPods, m.getComputeDomain)
312312

313313
if err := podManager.Start(ctx); err != nil {
314314
return fmt.Errorf("error creating Pod manager: %w", err)

cmd/nvidia-dra-imex-controller/deploymentpods.go

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ import (
2929
corev1listers "k8s.io/client-go/listers/core/v1"
3030
"k8s.io/client-go/tools/cache"
3131
"k8s.io/klog/v2"
32+
33+
nvapi "github.com/NVIDIA/k8s-dra-driver/api/nvidia.com/resource/v1beta1"
34+
)
35+
36+
const (
37+
CliqueIDLabelKey = "nvidia.com/gpu.clique"
3238
)
3339

3440
type DeploymentPodManager struct {
@@ -40,14 +46,16 @@ type DeploymentPodManager struct {
4046
informer cache.SharedInformer
4147
lister corev1listers.PodLister
4248

43-
nodeSelector corev1.NodeSelector
49+
getComputeDomain GetComputeDomainFunc
50+
computeDomainNodes []*nvapi.ComputeDomainNode
4451
computeDomainLabel string
4552
numPods int
53+
nodeSelector corev1.NodeSelector
4654

4755
imexChannelManager *ImexChannelManager
4856
}
4957

50-
func NewDeploymentPodManager(config *ManagerConfig, imexChannelManager *ImexChannelManager, labelSelector *metav1.LabelSelector, numPods int) *DeploymentPodManager {
58+
func NewDeploymentPodManager(config *ManagerConfig, imexChannelManager *ImexChannelManager, labelSelector *metav1.LabelSelector, numPods int, getComputeDomain GetComputeDomainFunc) *DeploymentPodManager {
5159
factory := informers.NewSharedInformerFactoryWithOptions(
5260
config.clientsets.Core,
5361
informerResyncPeriod,
@@ -79,9 +87,10 @@ func NewDeploymentPodManager(config *ManagerConfig, imexChannelManager *ImexChan
7987
factory: factory,
8088
informer: informer,
8189
lister: lister,
82-
nodeSelector: nodeSelector,
90+
getComputeDomain: getComputeDomain,
8391
computeDomainLabel: labelSelector.MatchLabels[computeDomainLabelKey],
8492
numPods: numPods,
93+
nodeSelector: nodeSelector,
8594
imexChannelManager: imexChannelManager,
8695
}
8796

@@ -150,23 +159,68 @@ func (m *DeploymentPodManager) onPodAddOrUpdate(ctx context.Context, obj any) er
150159

151160
klog.Infof("Processing added or updated Pod: %s/%s", p.Namespace, p.Name)
152161

162+
cd, err := m.getComputeDomain(p.Labels[computeDomainLabelKey])
163+
if err != nil {
164+
return fmt.Errorf("error getting ComputeDomain: %w", err)
165+
}
166+
if cd == nil {
167+
return nil
168+
}
169+
153170
if p.Spec.NodeName == "" {
154171
return fmt.Errorf("pod not yet scheduled: %s/%s", p.Namespace, p.Name)
155172
}
156173

157-
hostnameLabels := m.nodeSelector.NodeSelectorTerms[0].MatchExpressions[0].Values
158-
if !slices.Contains(hostnameLabels, p.Spec.NodeName) {
159-
hostnameLabels = append(hostnameLabels, p.Spec.NodeName)
174+
var nodeNames []string
175+
for _, node := range m.computeDomainNodes {
176+
nodeNames = append(nodeNames, node.Name)
160177
}
161-
m.nodeSelector.NodeSelectorTerms[0].MatchExpressions[0].Values = hostnameLabels
162178

163-
if len(hostnameLabels) != m.numPods {
164-
return fmt.Errorf("node selector not yet complete")
179+
if !slices.Contains(nodeNames, p.Spec.NodeName) {
180+
node, err := m.GetComputeDomainNode(ctx, p.Spec.NodeName)
181+
if err != nil {
182+
return fmt.Errorf("error getting ComputeDomainNode: %w", err)
183+
}
184+
nodeNames = append(nodeNames, node.Name)
185+
m.computeDomainNodes = append(m.computeDomainNodes, node)
165186
}
166187

188+
if len(nodeNames) != m.numPods {
189+
return fmt.Errorf("not all pods scheduled yet")
190+
}
191+
192+
cd.Status.Nodes = m.computeDomainNodes
193+
if _, err = m.config.clientsets.Nvidia.ResourceV1beta1().ComputeDomains(cd.Namespace).UpdateStatus(ctx, cd, metav1.UpdateOptions{}); err != nil {
194+
return fmt.Errorf("error updating nodes in ComputeDomain status: %w", err)
195+
}
196+
197+
m.nodeSelector.NodeSelectorTerms[0].MatchExpressions[0].Values = nodeNames
167198
if err := m.imexChannelManager.CreateOrUpdatePool(m.computeDomainLabel, &m.nodeSelector); err != nil {
168199
return fmt.Errorf("failed to create or update IMEX channel pool: %w", err)
169200
}
170201

171202
return nil
172203
}
204+
205+
func (m *DeploymentPodManager) GetComputeDomainNode(ctx context.Context, nodeName string) (*nvapi.ComputeDomainNode, error) {
206+
node, err := m.config.clientsets.Core.CoreV1().Nodes().Get(ctx, nodeName, metav1.GetOptions{})
207+
if err != nil {
208+
return nil, fmt.Errorf("error getting Node '%s': %w", nodeName, err)
209+
}
210+
211+
var ipAddress string
212+
for _, addr := range node.Status.Addresses {
213+
if addr.Type == corev1.NodeInternalIP {
214+
ipAddress = addr.Address
215+
break
216+
}
217+
}
218+
219+
n := &nvapi.ComputeDomainNode{
220+
Name: nodeName,
221+
IPAddress: ipAddress,
222+
CliqueID: node.Labels[CliqueIDLabelKey],
223+
}
224+
225+
return n, nil
226+
}

deployments/helm/k8s-dra-gpu-driver/crds/resource.nvidia.com_computedomains.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,32 @@ spec:
5353
- message: Exactly one of 'resourceClaimName' or 'deviceClassName' must
5454
be set.
5555
rule: '(has(self.resourceClaimName) ? !has(self.deviceClassName) : has(self.deviceClassName))'
56+
status:
57+
description: ComputeDomainStatus provides the status for a ComputeDomain.
58+
properties:
59+
nodes:
60+
items:
61+
description: ComputeDomainNode provides information about each node
62+
added to a ComputeDomain.
63+
properties:
64+
cliqueID:
65+
type: string
66+
ipAddress:
67+
type: string
68+
name:
69+
type: string
70+
required:
71+
- cliqueID
72+
- ipAddress
73+
- name
74+
type: object
75+
type: array
76+
x-kubernetes-list-map-keys:
77+
- name
78+
x-kubernetes-list-type: map
79+
type: object
5680
type: object
5781
served: true
5882
storage: true
83+
subresources:
84+
status: {}

deployments/helm/k8s-dra-imex-driver/crds/resource.nvidia.com_computedomains.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,32 @@ spec:
5353
- message: Exactly one of 'resourceClaimName' or 'deviceClassName' must
5454
be set.
5555
rule: '(has(self.resourceClaimName) ? !has(self.deviceClassName) : has(self.deviceClassName))'
56+
status:
57+
description: ComputeDomainStatus provides the status for a ComputeDomain.
58+
properties:
59+
nodes:
60+
items:
61+
description: ComputeDomainNode provides information about each node
62+
added to a ComputeDomain.
63+
properties:
64+
cliqueID:
65+
type: string
66+
ipAddress:
67+
type: string
68+
name:
69+
type: string
70+
required:
71+
- cliqueID
72+
- ipAddress
73+
- name
74+
type: object
75+
type: array
76+
x-kubernetes-list-map-keys:
77+
- name
78+
x-kubernetes-list-type: map
79+
type: object
5680
type: object
5781
served: true
5882
storage: true
83+
subresources:
84+
status: {}

deployments/helm/k8s-dra-imex-driver/templates/clusterrole.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ rules:
88
- apiGroups: ["resource.nvidia.com"]
99
resources: ["computedomains"]
1010
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
11+
- apiGroups: ["resource.nvidia.com"]
12+
resources: ["computedomains/status"]
13+
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
1114
- apiGroups: ["resource.k8s.io"]
1215
resources: ["resourceclaims"]
1316
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

pkg/nvidia.com/clientset/versioned/typed/resource/v1beta1/computedomain.go

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/nvidia.com/clientset/versioned/typed/resource/v1beta1/fake/fake_computedomain.go

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)