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
4 changes: 4 additions & 0 deletions pkg/virtualkubelet/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ type Resources struct {
Memory string `yaml:"Memory,omitempty"`
// Pods specifies the maximum number of pods this node can handle
Pods string `yaml:"Pods,omitempty"`
// EphemeralStorage is the ephemeral storage the node advertises (default 1Ti). A node
// that advertises none cannot take a pod that requests some, as sidecars often do
// (Katib's metrics collector requests 500Mi).
EphemeralStorage string `yaml:"EphemeralStorage,omitempty"`
// Accelerators lists hardware accelerators available on this node
Accelerators []Accelerator `yaml:"Accelerators"`
}
Expand Down
34 changes: 34 additions & 0 deletions pkg/virtualkubelet/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ package virtualkubelet

import (
"context"
"os"
"path/filepath"
"testing"

types "github.com/interlink-hq/interlink/pkg/interlink"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
)
Expand Down Expand Up @@ -464,3 +467,34 @@ func TestUpdateNodeTaints_NilLeavesExistingTaintsUnchangedAndUnknownEffectDefaul
},
}, provider.node.Spec.Taints)
}

// A virtual node must advertise ephemeral storage, or a pod whose sidecar requests some
// (Katib's metrics collector: 500Mi) is never scheduled on it.
func TestGetResources_EphemeralStorage(t *testing.T) {
config := Config{Resources: Resources{CPU: "10", Memory: "10Gi", Pods: "10"}}
got := GetResources(config)[v1.ResourceEphemeralStorage]
assert.Equal(t, defaultEphemeralStorage, got.String())

config.Resources.EphemeralStorage = "50Gi"
got = GetResources(config)[v1.ResourceEphemeralStorage]
assert.Equal(t, "50Gi", got.String())
}

func TestLoadConfig_EphemeralStorage(t *testing.T) {
load := func(resources string) (Config, error) {
path := filepath.Join(t.TempDir(), "config.yaml")
require.NoError(t, os.WriteFile(path, []byte("Resources:\n"+resources), 0o600))
return LoadConfig(t.Context(), path)
}

_, err := load(" EphemeralStorage: 50GB\n")
assert.ErrorContains(t, err, "invalid ephemeral storage value 50GB")

config, err := load(" EphemeralStorage: 50Gi\n")
require.NoError(t, err)
assert.Equal(t, "50Gi", config.Resources.EphemeralStorage)

config, err = load(" CPU: \"10\"\n")
require.NoError(t, err)
assert.Empty(t, config.Resources.EphemeralStorage)
}
20 changes: 17 additions & 3 deletions pkg/virtualkubelet/virtualkubelet.go
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,10 @@ func NodeConditionWithInterlink(ready bool, interlinkStatus v1.ConditionStatus,
return append(conditions, interlinkCondition)
}

// defaultEphemeralStorage is advertised when Resources.EphemeralStorage is not set: the
// remote side has its own disks, so the node only must not refuse pods that ask for some.
const defaultEphemeralStorage = "1Ti"

func GetResources(config Config) v1.ResourceList {
gpuCount := map[string]resource.Quantity{}
fpgaCount := map[string]resource.Quantity{}
Expand All @@ -401,10 +405,15 @@ func GetResources(config Config) v1.ResourceList {
}
}

ephemeralStorage := config.Resources.EphemeralStorage
if ephemeralStorage == "" {
ephemeralStorage = defaultEphemeralStorage
}
resourceList := v1.ResourceList{
"cpu": resource.MustParse(config.Resources.CPU),
"memory": resource.MustParse(config.Resources.Memory),
"pods": resource.MustParse(config.Resources.Pods),
"cpu": resource.MustParse(config.Resources.CPU),
"memory": resource.MustParse(config.Resources.Memory),
"pods": resource.MustParse(config.Resources.Pods),
v1.ResourceEphemeralStorage: resource.MustParse(ephemeralStorage),
Comment thread
dciangot marked this conversation as resolved.
Resolved
}

for resourceType, q := range gpuCount {
Expand Down Expand Up @@ -650,6 +659,11 @@ func LoadConfig(ctx context.Context, providerConfig string) (config Config, err
if _, err = resource.ParseQuantity(config.Resources.Pods); err != nil {
return config, fmt.Errorf("invalid pods value %v", config.Resources.Pods)
}
if config.Resources.EphemeralStorage != "" {
if _, err = resource.ParseQuantity(config.Resources.EphemeralStorage); err != nil {
return config, fmt.Errorf("invalid ephemeral storage value %v", config.Resources.EphemeralStorage)
}
}
for _, accelerator := range config.Resources.Accelerators {
if _, err = resource.ParseQuantity(accelerator.Available); err != nil {
return config, fmt.Errorf("invalid value for accelerator %v (model: %v): %v", accelerator.ResourceType, accelerator.Model, err)
Expand Down
Loading