Skip to content

Commit

Permalink
feat: support node selector and runtime class name for devbox. suppor…
Browse files Browse the repository at this point in the history
…t custom resource name. (#5330)
  • Loading branch information
lingdie authored Jan 7, 2025
1 parent 96b51a3 commit 365aede
Show file tree
Hide file tree
Showing 14 changed files with 358 additions and 340 deletions.
20 changes: 11 additions & 9 deletions controllers/devbox/api/v1alpha1/devbox_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,10 @@ package v1alpha1

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

type ResourceName string

const (
// ResourceCPU CPU, in cores. (500m = .5 cores)
ResourceCPU ResourceName = "cpu"
// ResourceMemory Memory, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
ResourceMemory ResourceName = "memory"
// FinalizerName is the finalizer for Devbox
FinalizerName = "devbox.sealos.io/finalizer"
DevBoxPartOf = "devbox"
Expand All @@ -52,7 +45,12 @@ const (
NetworkTypeTailnet NetworkType = "Tailnet"
)

type ResourceList map[ResourceName]resource.Quantity
type RuntimeRef struct {
// +kubebuilder:validation:Required
Name string `json:"name"`
// +kubebuilder:validation:Optional
Namespace string `json:"namespace,omitempty"`
}

type NetworkSpec struct {
// +kubebuilder:validation:Required
Expand Down Expand Up @@ -109,7 +107,7 @@ type DevboxSpec struct {
// +kubebuilder:validation:Enum=Running;Stopped
State DevboxState `json:"state"`
// +kubebuilder:validation:Required
Resource ResourceList `json:"resource"`
Resource corev1.ResourceList `json:"resource"`

// +kubebuilder:validation:Optional
// +kubebuilder:default=false
Expand All @@ -127,6 +125,10 @@ type DevboxSpec struct {
// +kubebuilder:validation:Required
NetworkSpec NetworkSpec `json:"network,omitempty"`

// +kubebuilder:validation:Optional
RuntimeClassName string `json:"runtimeClassName,omitempty"`
// +kubebuilder:validation:Optional
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
// +kubebuilder:validation:Optional
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
// +kubebuilder:validation:Optional
Expand Down
29 changes: 15 additions & 14 deletions controllers/devbox/api/v1alpha1/zz_generated.deepcopy.go

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

75 changes: 58 additions & 17 deletions controllers/devbox/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"k8s.io/client-go/rest"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
Expand All @@ -42,7 +43,9 @@ import (

devboxv1alpha1 "github.com/labring/sealos/controllers/devbox/api/v1alpha1"
"github.com/labring/sealos/controllers/devbox/internal/controller"
"github.com/labring/sealos/controllers/devbox/internal/controller/utils/matcher"
"github.com/labring/sealos/controllers/devbox/internal/controller/utils/registry"
utilresource "github.com/labring/sealos/controllers/devbox/internal/controller/utils/resource"
// +kubebuilder:scaffold:imports
)

Expand All @@ -65,19 +68,24 @@ func main() {
var secureMetrics bool
var enableHTTP2 bool
var tlsOpts []func(*tls.Config)
// debug flag
var debugMode bool
// registry flag
var registryAddr string
var registryUser string
var registryPassword string
var authAddr string
// resource flag
var requestCPURate float64
var requestMemoryRate float64
var requestEphemeralStorage string
var limitEphemeralStorage string
var debugMode bool
flag.StringVar(&registryAddr, "registry-addr", "sealos.hub:5000", "The address of the registry")
flag.StringVar(&registryUser, "registry-user", "admin", "The user of the registry")
flag.StringVar(&registryPassword, "registry-password", "passw0rd", "The password of the registry")
flag.StringVar(&authAddr, "auth-addr", "sealos.hub:5000", "The address of the auth")
var maximumLimitEphemeralStorage string
// pod matcher flag
var enablePodResourceMatcher bool
var enablePodEnvMatcher bool
var enablePodPortMatcher bool
var enablePodEphemeralStorageMatcher bool

flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+
"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.")
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
Expand All @@ -88,11 +96,24 @@ func main() {
"If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.")
flag.BoolVar(&enableHTTP2, "enable-http2", false,
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
// debug flag
flag.BoolVar(&debugMode, "debug", false, "If set, debug mode will be enabled")
// registry flag
flag.StringVar(&registryAddr, "registry-addr", "sealos.hub:5000", "The address of the registry")
flag.StringVar(&registryUser, "registry-user", "admin", "The user of the registry")
flag.StringVar(&registryPassword, "registry-password", "passw0rd", "The password of the registry")
// resource flag
flag.Float64Var(&requestCPURate, "request-cpu-rate", 10, "The request rate of cpu limit in devbox.")
flag.Float64Var(&requestMemoryRate, "request-memory-rate", 10, "The request rate of memory limit in devbox.")
flag.StringVar(&requestEphemeralStorage, "request-ephemeral-storage", "500Mi", "The request value of ephemeral storage in devbox.")
flag.StringVar(&limitEphemeralStorage, "limit-ephemeral-storage", "10Gi", "The limit value of ephemeral storage in devbox.")
flag.StringVar(&requestEphemeralStorage, "request-ephemeral-storage", "500Mi", "The default request value of ephemeral storage in devbox.")
flag.StringVar(&limitEphemeralStorage, "limit-ephemeral-storage", "10Gi", "The default limit value of ephemeral storage in devbox.")
flag.StringVar(&maximumLimitEphemeralStorage, "maximum-limit-ephemeral-storage", "50Gi", "The maximum limit value of ephemeral storage in devbox.")
// pod matcher flag, pod resource matcher, env matcher, port matcher will be enabled by default, ephemeral storage matcher will be disabled by default
flag.BoolVar(&enablePodResourceMatcher, "enable-pod-resource-matcher", true, "If set, pod resource matcher will be enabled")
flag.BoolVar(&enablePodEnvMatcher, "enable-pod-env-matcher", true, "If set, pod env matcher will be enabled")
flag.BoolVar(&enablePodPortMatcher, "enable-pod-port-matcher", true, "If set, pod port matcher will be enabled")
flag.BoolVar(&enablePodEphemeralStorageMatcher, "enable-pod-ephemeral-storage-matcher", false, "If set, pod ephemeral storage matcher will be enabled")

opts := zap.Options{
Development: true,
}
Expand Down Expand Up @@ -182,16 +203,36 @@ func main() {
os.Exit(1)
}

podMatchers := []matcher.PodMatcher{}
if enablePodResourceMatcher {
podMatchers = append(podMatchers, matcher.ResourceMatcher{})
}
if enablePodEnvMatcher {
podMatchers = append(podMatchers, matcher.EnvVarMatcher{})
}
if enablePodPortMatcher {
podMatchers = append(podMatchers, matcher.PortMatcher{})
}
if enablePodEphemeralStorageMatcher {
podMatchers = append(podMatchers, matcher.EphemeralStorageMatcher{})
}

if err = (&controller.DevboxReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
CommitImageRegistry: registryAddr,
Recorder: mgr.GetEventRecorderFor("devbox-controller"),
RequestCPURate: requestCPURate,
RequestMemoryRate: requestMemoryRate,
RequestEphemeralStorage: requestEphemeralStorage,
LimitEphemeralStorage: limitEphemeralStorage,
DebugMode: debugMode,
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
CommitImageRegistry: registryAddr,
Recorder: mgr.GetEventRecorderFor("devbox-controller"),
RequestRate: utilresource.RequestRate{
CPU: requestCPURate,
Memory: requestMemoryRate,
},
EphemeralStorage: utilresource.EphemeralStorage{
DefaultRequest: resource.MustParse(requestEphemeralStorage),
DefaultLimit: resource.MustParse(limitEphemeralStorage),
MaximumLimit: resource.MustParse(maximumLimitEphemeralStorage),
},
PodMatchers: podMatchers,
DebugMode: debugMode,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Devbox")
os.Exit(1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2803,14 +2803,21 @@ spec:
required:
- type
type: object
nodeSelector:
additionalProperties:
type: string
type: object
resource:
additionalProperties:
anyOf:
- type: integer
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: ResourceList is a set of (resource name, quantity) pairs.
type: object
runtimeClassName:
type: string
squash:
default: false
type: boolean
Expand Down
1 change: 0 additions & 1 deletion controllers/devbox/config/manager/manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ spec:
- --registry-addr={{ .registryAddr }}
- --registry-user={{ .registryUser }}
- --registry-password={{ .registryPassword }}
- --auth-addr={{ .authAddr }}
image: controller:latest
name: manager
securityContext:
Expand Down
10 changes: 7 additions & 3 deletions controllers/devbox/config/samples/devbox_v1alpha1_devbox.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,23 @@ metadata:
labels:
app.kubernetes.io/name: devbox
app.kubernetes.io/managed-by: kustomize
name: devbox-sample
name: devbox-gpu-sample
spec:
state: Running
runtimeClassName: nvidia
resource:
cpu: 2
memory: 4000Mi
nvidia.com/gpu: 1
runtimeRef:
name: go-1-22-5
name: go-1-22-5-2024-11-12-0651
namespace: devbox-system
nodeSelector:
nvidia.com/gpu.product: Tesla-P40
network:
type: NodePort
extraPorts:
- containerPort: 443
name: 'https'
- containerPort: 80
name: 'http'
name: 'http'
93 changes: 0 additions & 93 deletions controllers/devbox/config/samples/devbox_v1alpha1_runtime.yaml

This file was deleted.

Loading

0 comments on commit 365aede

Please sign in to comment.