Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions deploy/helm/charts/platform/components/operator/files/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ rules:
- dynamographdeployments
- dynamographdeploymentscalingadapters
- dynamomodels
- dynamoworkermetadatas
- lpxgraphdeployments
verbs:
- create
Expand All @@ -306,6 +307,7 @@ rules:
- dynamographdeploymentruns/finalizers
- dynamographdeployments/finalizers
- dynamomodels/finalizers
- dynamopoolrelays/finalizers
- lpxgraphdeployments/finalizers
verbs:
- update
Expand All @@ -319,6 +321,7 @@ rules:
- dynamographdeployments/status
- dynamographdeploymentscalingadapters/status
- dynamomodels/status
- dynamopoolrelays/status
- lpxgraphdeployments/status
verbs:
- get
Expand All @@ -337,6 +340,14 @@ rules:
- list
- patch
- watch
- apiGroups:
- nvidia.com
resources:
- dynamopoolrelays
verbs:
- get
- list
- watch
- apiGroups:
- nvidia.com
resources:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,18 +105,6 @@ rules:
- get
- list
- watch
- apiGroups:
- nvidia.com
resources:
- dynamoworkermetadatas
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- nvidia.com
resources:
Expand Down
2 changes: 2 additions & 0 deletions deploy/operator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ This operator automates the deployment and lifecycle management of Dynamo resour

- **DynamoGraphDeploymentRequest (DGDR)** - Simplified SLA-driven deployment interface
- **DynamoGraphDeployment (DGD)** - Direct deployment configuration
- **DynamoPoolRelay** - Relay Service and Pods for one DGD

Built with [Kubebuilder](https://book.kubebuilder.io/), it follows Kubernetes best practices and supports declarative configuration through CustomResourceDefinitions (CRDs).

### Custom Resources

- **DynamoGraphDeploymentRequest**: High-level interface for SLA-driven configuration generation. Automatically handles profiling and generates an optimized DGD spec based on your performance requirements.
- **DynamoGraphDeployment**: Lower-level interface for direct deployment configuration with full control over all parameters.
- **DynamoPoolRelay**: Active Relay Pods for one DGD. See the [operator setup](../../docs/fern/pages/kubernetes/kv-aware-routing/pool-relay.md#deploy-with-the-operator) and [sample](samples/dynamo-pool-relay.yaml).


## Developer guide
Expand Down
88 changes: 88 additions & 0 deletions deploy/operator/api/v1alpha1/dynamopoolrelay_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package v1alpha1

import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// DynamoPoolRelaySpec configures Relay Pods for the DGD with the same name and namespace.
type DynamoPoolRelaySpec struct {
// ClusterID is the Relay's stable logical cluster ID across restarts.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=128
// +kubebuilder:validation:Pattern=`^[^[:space:]\p{Z}\x85\x1c-\x1f](.*[^[:space:]\p{Z}\x85\x1c-\x1f])?$`
ClusterID string `json:"clusterId"`

// PodTemplate configures Relay Pods. Its main container needs an image with
// dynamo.pool_relay and --sources-file support from the operator's revision.
// The controller sets the main command, listener probes, source volume,
// service account, and Relay identity and discovery environment variables.
// Reserved env names: DYN_NAMESPACE, DYN_DISCOVERY_BACKEND,
// DYN_KUBE_DISCOVERY_MODE, DYN_SYSTEM_PORT, DYN_TCP_RESPONSE_STREAM_HOST,
// DYN_TCP_RESPONSE_STREAM_PORT, DYN_CLUSTER_ID, DYN_RELAY_BIND,
// DYN_RELAY_CONNECTION_REVISION, DYN_RELAY_NAMESPACES, DYN_RELAY_WATCH_ALL,
// DYN_RELAY_ENDPOINT_PREFIXES, POD_NAME, POD_NAMESPACE, and POD_UID.
// The main container cannot use envFrom because it could override those values.
// +kubebuilder:validation:Required
PodTemplate *corev1.PodTemplateSpec `json:"podTemplate"`

// Replicas sets the number of active Relay Pods. Each watches the DGD.
// +optional
// +kubebuilder:default=2
// +kubebuilder:validation:Minimum=1
Replicas *int32 `json:"replicas,omitempty"`
}

// DynamoPoolRelayStatus reports listener availability. It does not report KV or model readiness.
type DynamoPoolRelayStatus struct {
// ObservedGeneration is the Relay resource generation last reconciled by the operator.
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
// Endpoint is the cluster-local `<dgd>-pool-relay.<namespace>.svc:5561` address.
// It is empty after withdrawal or a failed reconciliation.
// +optional
Endpoint string `json:"endpoint,omitempty"`
Comment thread
hhzhang16 marked this conversation as resolved.
Resolved
// AvailableReplicas is the number of Relay Pods the Deployment reports available.
// +optional
AvailableReplicas int32 `json:"availableReplicas,omitempty"`
// Conditions includes Ready for listener availability, not model or KV readiness.
// Its reason is ListenerAvailable, DeploymentProgressing, DGDNotFound,
// DGDTerminating, UnsupportedDiscovery, UnsupportedSourceScope, NoWorkers,
// InvalidConfiguration, ReconcileFailed, or ResourceOwnershipConflict.
// +optional
// +listType=map
// +listMapKey=type
Conditions []metav1.Condition `json:"conditions,omitempty"`
}

// DynamoPoolRelay deploys active-active Relay Pods for one DGD.
// The resource name matches its DGD; the Service name adds the -pool-relay suffix.
// The DGD needs Kubernetes pod-mode discovery and at least one worker component.
// Worker and frontend components cannot use globalDynamoNamespace. The DGD name
// must produce a DNS-1035 Service name, so it starts with a lowercase letter,
// uses only lowercase letters, digits, and hyphens, and is at most 52 characters.
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:scope=Namespaced,shortName=dprelay
// +kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].status`
// +kubebuilder:printcolumn:name="Endpoint",type=string,JSONPath=`.status.endpoint`
type DynamoPoolRelay struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec DynamoPoolRelaySpec `json:"spec"`
// +optional
Status DynamoPoolRelayStatus `json:"status,omitempty"`
}

// DynamoPoolRelayList contains DynamoPoolRelay resources.
// +kubebuilder:object:root=true
type DynamoPoolRelayList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []DynamoPoolRelay `json:"items"`
}
5 changes: 5 additions & 0 deletions deploy/operator/api/v1alpha1/groupversion_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ var (
// DynamoGraphDeploymentRequestGVK is the v1alpha1 DynamoGraphDeploymentRequest kind.
DynamoGraphDeploymentRequestGVK = GroupVersion.WithKind("DynamoGraphDeploymentRequest")

// DynamoPoolRelayGVK is the v1alpha1 DynamoPoolRelay kind.
DynamoPoolRelayGVK = GroupVersion.WithKind("DynamoPoolRelay")

// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)

Expand All @@ -65,6 +68,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&DynamoGraphDeploymentScalingAdapterList{},
&DynamoModel{},
&DynamoModelList{},
&DynamoPoolRelay{},
&DynamoPoolRelayList{},
)
metav1.AddToGroupVersion(scheme, GroupVersion)
return nil
Expand Down
106 changes: 106 additions & 0 deletions deploy/operator/api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions deploy/operator/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import (
nvidiacomv1beta2 "github.com/ai-dynamo/dynamo/deploy/operator/api/v1beta2"
internalcert "github.com/ai-dynamo/dynamo/deploy/operator/internal/cert"
"github.com/ai-dynamo/dynamo/deploy/operator/internal/controller"
poolrelaycontroller "github.com/ai-dynamo/dynamo/deploy/operator/internal/controller/poolrelay"
commonController "github.com/ai-dynamo/dynamo/deploy/operator/internal/controller_common"
"github.com/ai-dynamo/dynamo/deploy/operator/internal/crdmigrator"
lpxv1alpha1 "github.com/ai-dynamo/dynamo/deploy/operator/internal/dynamo/lpx/scheduler/v1alpha1"
Expand Down Expand Up @@ -615,6 +616,9 @@ func registerControllers(
}); err != nil {
return err
}
if err := poolrelaycontroller.Setup(mgr, operatorCfg, runtimeConfig); err != nil {
return err
}
if err := controller.SetupDynamoGraphDeploymentScalingAdapter(mgr, setupOptions); err != nil {
return err
}
Expand Down
Loading
Loading