The container-layer components of Lingjun Runtime Kit are open source. You can customize resource names, scheduling policies, monitoring metrics, and node enable/disable behavior from the source code. This topic covers the component source structure, image builds, deployment integration, and customization boundaries.
Public preview: This product is currently in public preview. If you have questions or suggestions, submit a ticket.
1. Get the source code
The source code of the open-source components is published in the GitHub repository aliyun/LJ-RuntimeKit. Each component is in its own subdirectory:
|
Component |
Source location |
Main customization areas |
|
Device Plugin |
|
Resource name customization, GPU memory partition granularity |
|
Scheduler Framework |
|
Scheduling scoring policies, resource modeling, Kubernetes version adaptation |
|
Exporter |
|
Custom metrics |
|
Controller (switch control) |
|
Label watch logic, node operation behavior |
Branch and tag conventions:
The main branch always contains the latest usable code.
Tags mark stable releases. Each open-source component version tracks the corresponding Runtime version.
2. Build and create images
Build each component from the root of its source directory using the Makefile:
make build # Compile the binary
make docker # Build the image
For other build targets, see the Makefile in each component directory. After the build completes, push the images to a registry that the cluster nodes can pull from. Make sure the image names and tags in the deployment manifests match the actual build artifacts (for details about deployment files and image configuration, see 3.6 Advanced deployment and customization).
Adapt Scheduler Framework to multiple Kubernetes versions
Scheduler Framework compiles as an out-of-tree plugin and depends on k8s.io/kubernetes and its staging submodules. The hack/ directory of the open-source repository provides a script for switching to a target Kubernetes version:
# 1. Switch dependencies to the target Kubernetes version (for example, v1.28.0)
./hack/download-deps.sh v1.28.0
# 2. Update the vendor directory
go mod tidy && go mod vendor
# 3. Verify the build
make build
The current default dependency is Kubernetes v1.21.2. To adapt to another version, follow the preceding steps. Keep the build dependency version consistent with the target cluster version to avoid API compatibility issues. The precompiled images currently support the following community Kubernetes versions: v1.28, v1.30, v1.32, v1.34, and v1.35.
3. Deploy customized components
Deploy customized components the same way as the precompiled components:
One-click deployment: The Scheduler Framework repository provides the
deploy/deploy-all.shscript for deploying all components or individual components (--components=<name>). It also supports overriding parameters such as the image address and namespace.Per-component deployment: Each component also supports its own deployment methods, such as
make deploy, Helm charts, and kustomize.Version compatibility: Customized components still integrate with the Runtime through the gRPC interface, and the version compatibility policy and minimum version requirements apply the same way. For details, see 5. Version compatibility and 6. Minimum version requirements for features.
-
Configuration-level customization (no recompilation needed): The deployment manifests of the Device Plugin, Scheduler Framework, and Exporter each contain a separate
configmap.yamlfile. This file externalizes protocol constants, such as extended resource names, node label keys, and annotation keys, into a ConfigMap. To change only configuration settings such as resource names without touching the code, edit the corresponding ConfigMap and redeploy. You don't need to recompile the images. Note: All three components share the same set of protocol constants. If the configurations are inconsistent, the components use mismatched resource names for resource reporting, scheduling, and monitoring. Pods might fail to schedule, or monitoring data might be missing. The following example changes the resource names of gpu-core and gpu-memory:protocol.yaml: resources.memory: "alibabacloud.com/gpu-memory.percentage" resources.core: "alibabacloud.com/gpu-core.percentage" resources.gpu: "alibabacloud.com/gpu"These settings are in the ConfigMap files of each component under the deploy directory of the Scheduler Framework one-click deployment —
deploy/<component>/02-configmap.yaml. After editing, runkubectl apply -ffor all three components to update their ConfigMaps, and then restart the corresponding DaemonSets and Deployment to apply the new configuration:# 1. Update the ConfigMaps of the three components kubectl apply -f deploy/deviceplugin/02-configmap.yaml kubectl apply -f deploy/exporter/02-configmap.yaml kubectl apply -f deploy/scheduler/02-configmap.yaml # 2. Restart the components to apply the new configuration kubectl rollout restart ds/lj-runtimekit-device-plugin-ds -n kube-system kubectl rollout restart ds/lj-runtimekit-exporter-ds -n kube-system kubectl rollout restart deploy/lj-runtimekit-scheduler-framework -n kube-systemAlternatively, redeploy all components at once with
deploy-all.sh deployfor the same result.
Customized components are maintained by you. When you upgrade to a new baseline, merge your custom changes into the new version.
4. Component source structure and extension points
4.1 Device Plugin
Source code structure:
|
Directory or file |
Responsibility |
|
|
Program entry point; initializes the gRPC connection and registers the plugin |
|
|
Core Device Plugin logic (ListAndWatch and Allocate forwarding) |
|
|
Proto definitions and the gRPC client wrapper |
|
|
Constant definitions such as socket paths and resource names |
Extension points:
Custom resource names: Override the default extended resource name, such as
aliyun.com/gpu-core, in the configuration file to keep resource names separate across clusters or match existing naming conventions. After the change, update the configurations of the Device Plugin, Scheduler Framework, and Exporter at the same time to keep the resource names consistent.GPU memory partition granularity: The default is 1 GiB. Adjust it with the
--memory-unitstartup parameter to fit GPUs with different memory sizes.
4.2 Scheduler Framework
Source code structure:
|
Directory or file |
Responsibility |
|
|
Program entry point; registers the scheduling plugins |
|
|
StandardPlugin: time-division scheduling (Filter/Score/Reserve/Bind) |
|
|
MigPlugin: spatial partitioning for Multi-Instance GPU (MIG) |
|
|
Constant definitions such as scheduling policy names and resource labels |
|
|
Node GPU resource ledger structure |
|
|
Helm chart (values.yaml contains the scheduler configuration) |
Extension points:
Scheduling plugin extension:
pkg/providesStandardPlugin(time-division scheduling) andMigPlugin(MIG spatial partitioning). Both implement the Filter, Score, Reserve, and Bind extension points of Scheduler Framework. You can extend them with custom scoring policies or affinity constraints.Resource modeling extension: At startup, the scheduler uses informers to watch Nodes, Pods, and Device Plugin reports, and maintains a multi-dimensional
gpuCount × {core, memory}resource ledger for each Node. Each allocation is deducted from the ledger atomically, and deleting a Pod restores the resources to the ledger through the event stream. To add a new resource dimension, extend the ledger structure.
4.3 Exporter
Source code structure:
|
Directory or file |
Responsibility |
|
|
Program entry point |
|
|
gRPC client collection logic (calls Lingjun Runtime Kit interfaces to get metrics) |
|
|
Converts metrics into Prometheus format and exposes them over HTTP |
|
|
Health check logic |
|
|
Helm chart deployment templates |
|
|
Configuration file templates |
Extension points:
Custom metrics: Add new metric collection logic in
pkg/collector/. Fetch raw data through theExporterGetDataListgRPC interface, and convert the data into Prometheus metrics.
4.4 Controller (switch control)
Source code structure:
Controller/
├── cmd/
│ ├── controller/main.go # Controller main program (Kubebuilder framework)
│ └── job-agent/main.go # Job Agent (executes enable/disable on nodes)
├── internal/controller/
│ ├── node_controller.go # Watches Node label changes and creates Jobs
│ └── job_controller.go # Automatically cleans up successful Jobs
├── api/proto/
│ └── config_service.proto # gRPC interface definitions
├── pkg/configpb/ # Generated Go gRPC code
└── config/manager/ # Deployment configuration
Extension points:
Modify
node_controller.goto customize the label watch logic or the trigger condition (the default is to watch forlj_runtimekit_enable=true).Modify
job-agent/main.goto customize the operations performed on nodes.Modify
config_service.prototo extend the communication protocol with the node config-daemon (for interface details, see gRPC API reference).
5. Customization boundaries and considerations
The gRPC interface is the only integration boundary. As long as you don't change the parts that interact with Lingjun Runtime Kit, you don't need to handle proto details. Your customization stays within the component's own policies, such as scheduling, monitoring, orchestration, and storage. If you need to modify or reimplement the interaction with the Runtime, use gRPC API reference as the protocol basis and follow its compatibility policy.
Resource name consistency: When you customize a resource name prefix, update the Device Plugin, Scheduler Framework, and Exporter components at the same time. Otherwise, resource reporting and scheduling won't match. For simple changes that affect only configuration, edit the protocol ConfigMap in each component's deployment manifest to update all three components at once (see section 3). No recompilation is needed. If the change involves code logic, modify the constant definitions in the source code and rebuild the images.
Version compatibility also applies: Customized components and the Runtime still follow the "additive, backward-compatible" interface policy, and the minimum version requirements for features also apply to custom implementations (for details, see 5. Version compatibility and 6. Minimum version requirements for features).
Maintenance responsibility: You are responsible for maintaining customized components. When a new baseline is released, merge your custom changes into the new version. For details about issue ownership and support channels, see Deployment and release guide.