Skip to content

Commit

Permalink
Merge pull request #199 from ffromani/sched-run-control-plane
Browse files Browse the repository at this point in the history
sched: manifests: run on the control plane
  • Loading branch information
ffromani authored Jun 20, 2023
2 parents ff1b920 + 596cbf4 commit f806d05
Show file tree
Hide file tree
Showing 15 changed files with 456 additions and 30 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ jobs:
kind create cluster --config=hack/kind-config-e2e-positive.yaml --image kindest/node:v1.26.4@sha256:f4c0d87be03d6bea69f5e5dc0adb678bb498a190ee5c38422bf751541cebe92e
kubectl label node kind-worker node-role.kubernetes.io/worker=''
hack/wait-nodes-ready.sh
kubectl describe nodes
- name: run E2E tests
run: |
Expand Down Expand Up @@ -77,6 +78,7 @@ jobs:
kind create cluster --config=hack/kind-config-e2e-negative.yaml --image kindest/node:v1.26.4@sha256:f4c0d87be03d6bea69f5e5dc0adb678bb498a190ee5c38422bf751541cebe92e
kubectl label node kind-worker node-role.kubernetes.io/worker=''
hack/wait-nodes-ready.sh
kubectl describe nodes
- name: run E2E tests
run: |
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ require (
k8s.io/utils v0.0.0-20221107191617-1a15be271d1d
sigs.k8s.io/controller-runtime v0.13.1
sigs.k8s.io/scheduler-plugins v0.24.9
sigs.k8s.io/yaml v1.3.0
)

require (
Expand Down Expand Up @@ -82,7 +83,6 @@ require (
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

replace (
Expand Down
4 changes: 4 additions & 0 deletions pkg/commands/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ func NewRemoveCommand(commonOpts *CommonOptions) *cobra.Command {
RTEConfigData: commonOpts.RTEConfigData,
PullIfNotPresent: commonOpts.PullIfNotPresent,
CacheResyncPeriod: commonOpts.SchedResyncPeriod,
CtrlPlaneAffinity: commonOpts.SchedCtrlPlaneAffinity,
})
if err != nil {
// intentionally keep going to remove as much as possible
Expand Down Expand Up @@ -184,6 +185,7 @@ func NewDeploySchedulerPluginCommand(commonOpts *CommonOptions, opts *DeployOpti
RTEConfigData: commonOpts.RTEConfigData,
PullIfNotPresent: commonOpts.PullIfNotPresent,
CacheResyncPeriod: commonOpts.SchedResyncPeriod,
CtrlPlaneAffinity: commonOpts.SchedCtrlPlaneAffinity,
Verbose: commonOpts.SchedVerbose,
})
},
Expand Down Expand Up @@ -295,6 +297,7 @@ func NewRemoveSchedulerPluginCommand(commonOpts *CommonOptions, opts *DeployOpti
RTEConfigData: commonOpts.RTEConfigData,
PullIfNotPresent: commonOpts.PullIfNotPresent,
CacheResyncPeriod: commonOpts.SchedResyncPeriod,
CtrlPlaneAffinity: commonOpts.SchedCtrlPlaneAffinity,
Verbose: commonOpts.SchedVerbose,
})
},
Expand Down Expand Up @@ -383,6 +386,7 @@ func deployOnCluster(commonOpts *CommonOptions, opts *DeployOptions) error {
RTEConfigData: commonOpts.RTEConfigData,
PullIfNotPresent: commonOpts.PullIfNotPresent,
CacheResyncPeriod: commonOpts.SchedResyncPeriod,
CtrlPlaneAffinity: commonOpts.SchedCtrlPlaneAffinity,
Verbose: commonOpts.SchedVerbose,
}); err != nil {
return err
Expand Down
1 change: 1 addition & 0 deletions pkg/commands/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ func RenderManifests(commonOpts *CommonOptions) error {
PullIfNotPresent: commonOpts.PullIfNotPresent,
ProfileName: commonOpts.SchedProfileName,
CacheResyncPeriod: commonOpts.SchedResyncPeriod,
CtrlPlaneAffinity: commonOpts.SchedCtrlPlaneAffinity,
Verbose: commonOpts.SchedVerbose,
}

Expand Down
42 changes: 22 additions & 20 deletions pkg/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,26 +44,27 @@ const (
)

type CommonOptions struct {
Debug bool
UserPlatform platform.Platform
UserPlatformVersion platform.Version
Log logr.Logger
DebugLog logr.Logger
Replicas int
RTEConfigData string
PullIfNotPresent bool
UpdaterType string
UpdaterPFPEnable bool
UpdaterNotifEnable bool
UpdaterCRIHooksEnable bool
UpdaterSyncPeriod time.Duration
UpdaterVerbose int
SchedProfileName string
SchedResyncPeriod time.Duration
SchedVerbose int
rteConfigFile string
plat string
platVer string
Debug bool
UserPlatform platform.Platform
UserPlatformVersion platform.Version
Log logr.Logger
DebugLog logr.Logger
Replicas int
RTEConfigData string
PullIfNotPresent bool
UpdaterType string
UpdaterPFPEnable bool
UpdaterNotifEnable bool
UpdaterCRIHooksEnable bool
UpdaterSyncPeriod time.Duration
UpdaterVerbose int
SchedProfileName string
SchedResyncPeriod time.Duration
SchedVerbose int
SchedCtrlPlaneAffinity bool
rteConfigFile string
plat string
platVer string
}

func ShowHelp(cmd *cobra.Command, args []string) error {
Expand Down Expand Up @@ -124,6 +125,7 @@ func InitFlags(flags *pflag.FlagSet, commonOpts *CommonOptions) {
flags.StringVar(&commonOpts.SchedProfileName, "sched-profile-name", DefaultSchedulerProfileName, "inject scheduler profile name.")
flags.DurationVar(&commonOpts.SchedResyncPeriod, "sched-resync-period", DefaultSchedulerResyncPeriod, "inject scheduler resync period.")
flags.IntVar(&commonOpts.SchedVerbose, "sched-verbose", 4, "set the scheduler verbosiness.")
flags.BoolVar(&commonOpts.SchedCtrlPlaneAffinity, "sched-ctrlplane-affinity", true, "toggle the scheduler control plane affinity.")
}

func PostSetupOptions(commonOpts *CommonOptions) error {
Expand Down
3 changes: 3 additions & 0 deletions pkg/deployer/sched/sched.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type Options struct {
RTEConfigData string
PullIfNotPresent bool
CacheResyncPeriod time.Duration
CtrlPlaneAffinity bool
Verbose int
}

Expand All @@ -55,6 +56,7 @@ func Deploy(env *deployer.Environment, opts Options) error {
Replicas: opts.Replicas,
PullIfNotPresent: opts.PullIfNotPresent,
CacheResyncPeriod: opts.CacheResyncPeriod,
CtrlPlaneAffinity: opts.CtrlPlaneAffinity,
Verbose: opts.Verbose,
})
if err != nil {
Expand Down Expand Up @@ -92,6 +94,7 @@ func Remove(env *deployer.Environment, opts Options) error {
Replicas: opts.Replicas,
PullIfNotPresent: opts.PullIfNotPresent,
CacheResyncPeriod: opts.CacheResyncPeriod,
CtrlPlaneAffinity: opts.CtrlPlaneAffinity,
Verbose: opts.Verbose,
})
if err != nil {
Expand Down
5 changes: 3 additions & 2 deletions pkg/manifests/sched/sched.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ type RenderOptions struct {
PullIfNotPresent bool
ProfileName string
CacheResyncPeriod time.Duration
CtrlPlaneAffinity bool
Verbose int
}

Expand All @@ -105,8 +106,8 @@ func (mf Manifests) Render(logger logr.Logger, options RenderOptions) (Manifests
return ret, err
}

schedupdate.SchedulerDeployment(ret.DPScheduler, options.PullIfNotPresent, options.Verbose)
schedupdate.ControllerDeployment(ret.DPController, options.PullIfNotPresent)
schedupdate.SchedulerDeployment(ret.DPScheduler, options.PullIfNotPresent, options.CtrlPlaneAffinity, options.Verbose)
schedupdate.ControllerDeployment(ret.DPController, options.PullIfNotPresent, options.CtrlPlaneAffinity)
if mf.plat == platform.OpenShift {
ret.Namespace.Name = NamespaceOpenShift
}
Expand Down
72 changes: 72 additions & 0 deletions pkg/objectupdate/affinity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2023 Red Hat, Inc.
*/

package objectupdate

import corev1 "k8s.io/api/core/v1"

const (
NodeRoleControlPlane = "node-role.kubernetes.io/control-plane"
NodeRoleControlPlaneDeprecated = "node-role.kubernetes.io/master"
)

func SetPodSchedulerAffinityOnControlPlane(podSpec *corev1.PodSpec) {
if podSpec == nil {
return
}

for _, label := range []string{
NodeRoleControlPlane,
NodeRoleControlPlaneDeprecated,
} {
if toleration := findTolerationByKey(podSpec.Tolerations, label); toleration == nil {
podSpec.Tolerations = append(podSpec.Tolerations, corev1.Toleration{
Key: label,
Effect: corev1.TaintEffectNoSchedule,
})
}
}
if podSpec.Affinity == nil {
podSpec.Affinity = &corev1.Affinity{}
}
if podSpec.Affinity.NodeAffinity == nil {
podSpec.Affinity.NodeAffinity = &corev1.NodeAffinity{}
}
if podSpec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution == nil {
podSpec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution = &corev1.NodeSelector{
NodeSelectorTerms: []corev1.NodeSelectorTerm{
{
MatchExpressions: []corev1.NodeSelectorRequirement{
{
Key: NodeRoleControlPlane,
Operator: corev1.NodeSelectorOpExists,
},
},
},
},
}
}
}

func findTolerationByKey(tolerations []corev1.Toleration, key string) *corev1.Toleration {
for idx := range tolerations {
toleration := &tolerations[idx]
if toleration.Key == key {
return toleration
}
}
return nil
}
97 changes: 97 additions & 0 deletions pkg/objectupdate/affinity_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2023 Red Hat, Inc.
*/

package objectupdate

import (
"testing"

"sigs.k8s.io/yaml"

corev1 "k8s.io/api/core/v1"
)

func TestSetPodSchedulerAffinityOnControlPlane(t *testing.T) {

type testCase struct {
name string
podSpec *corev1.PodSpec
expectedYAML string
}

testCases := []testCase{
{
name: "nil",
expectedYAML: "null\n",
},
{
name: "empty",
podSpec: &corev1.PodSpec{},
expectedYAML: podSpecOnlyAffinity,
},
{
name: "partial affinity",
podSpec: &corev1.PodSpec{
Affinity: &corev1.Affinity{
NodeAffinity: &corev1.NodeAffinity{},
},
},
expectedYAML: podSpecOnlyAffinity,
},
{
name: "partial tolerations",
podSpec: &corev1.PodSpec{
Tolerations: []corev1.Toleration{
{
Key: NodeRoleControlPlane,
Effect: corev1.TaintEffectNoSchedule,
},
},
},
expectedYAML: podSpecOnlyAffinity,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
got := tc.podSpec.DeepCopy()
SetPodSchedulerAffinityOnControlPlane(got)
data, err := yaml.Marshal(got)
if err != nil {
t.Errorf("error marshalling yaml: %v", err)
}
gotYAML := string(data)
if gotYAML != tc.expectedYAML {
t.Errorf("output mismatch:\ngot=%v\nexpected=%v\n", gotYAML, tc.expectedYAML)
}
})
}
}

const podSpecOnlyAffinity = `affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/control-plane
operator: Exists
containers: null
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/control-plane
- effect: NoSchedule
key: node-role.kubernetes.io/master
`
13 changes: 11 additions & 2 deletions pkg/objectupdate/sched/sched.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,15 @@ import (
"github.com/k8stopologyawareschedwg/deployer/pkg/flagcodec"
"github.com/k8stopologyawareschedwg/deployer/pkg/images"
"github.com/k8stopologyawareschedwg/deployer/pkg/manifests"
"github.com/k8stopologyawareschedwg/deployer/pkg/objectupdate"
)

const (
SchedulerConfigFileName = "scheduler-config.yaml" // TODO duplicate from yaml
schedulerPluginName = "NodeResourceTopologyMatch"
)

func SchedulerDeployment(dp *appsv1.Deployment, pullIfNotPresent bool, verbose int) {
func SchedulerDeployment(dp *appsv1.Deployment, pullIfNotPresent, ctrlPlaneAffinity bool, verbose int) {
cnt := &dp.Spec.Template.Spec.Containers[0] // shortcut

cnt.Image = images.SchedulerPluginSchedulerImage
Expand All @@ -45,11 +46,19 @@ func SchedulerDeployment(dp *appsv1.Deployment, pullIfNotPresent bool, verbose i
flags := flagcodec.ParseArgvKeyValue(cnt.Args)
flags.SetOption("--v", fmt.Sprintf("%d", verbose)) // TODO: keep in sync with the manifest (-v vs --v)
cnt.Args = flags.Argv()

if ctrlPlaneAffinity {
objectupdate.SetPodSchedulerAffinityOnControlPlane(&dp.Spec.Template.Spec)
}
}

func ControllerDeployment(dp *appsv1.Deployment, pullIfNotPresent bool) {
func ControllerDeployment(dp *appsv1.Deployment, pullIfNotPresent, ctrlPlaneAffinity bool) {
dp.Spec.Template.Spec.Containers[0].Image = images.SchedulerPluginControllerImage
dp.Spec.Template.Spec.Containers[0].ImagePullPolicy = pullPolicy(pullIfNotPresent)

if ctrlPlaneAffinity {
objectupdate.SetPodSchedulerAffinityOnControlPlane(&dp.Spec.Template.Spec)
}
}

func SchedulerConfig(cm *corev1.ConfigMap, schedulerName string, cacheResyncPeriod time.Duration) error {
Expand Down
Loading

0 comments on commit f806d05

Please sign in to comment.