add --controllers to controller manager

pull/6/head
deads2k 2017-01-10 15:11:25 -05:00
parent 199af05cd0
commit d9b75ed82b
9 changed files with 184 additions and 4 deletions

View File

@ -33,6 +33,6 @@ func NewKubeControllerManager() *Server {
return app.Run(s) return app.Run(s)
}, },
} }
s.AddFlags(hks.Flags()) s.AddFlags(hks.Flags(), app.KnownControllers(), app.ControllersDisabledByDefault.List())
return &hks return &hks
} }

View File

@ -5,6 +5,7 @@ licenses(["notice"])
load( load(
"@io_bazel_rules_go//go:def.bzl", "@io_bazel_rules_go//go:def.bzl",
"go_library", "go_library",
"go_test",
) )
go_library( go_library(
@ -98,6 +99,7 @@ go_library(
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/runtime/schema", "//vendor:k8s.io/apimachinery/pkg/runtime/schema",
"//vendor:k8s.io/apimachinery/pkg/runtime/serializer", "//vendor:k8s.io/apimachinery/pkg/runtime/serializer",
"//vendor:k8s.io/apimachinery/pkg/util/sets",
"//vendor:k8s.io/apimachinery/pkg/util/wait", "//vendor:k8s.io/apimachinery/pkg/util/wait",
"//vendor:k8s.io/apiserver/pkg/healthz", "//vendor:k8s.io/apiserver/pkg/healthz",
], ],
@ -118,3 +120,11 @@ filegroup(
], ],
tags = ["automanaged"], tags = ["automanaged"],
) )
go_test(
name = "go_default_test",
srcs = ["controller_manager_test.go"],
library = ":go_default_library",
tags = ["automanaged"],
deps = ["//vendor:k8s.io/apimachinery/pkg/util/sets"],
)

View File

@ -0,0 +1,81 @@
/*
Copyright 2017 The Kubernetes Authors.
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.
*/
// Package app implements a server that runs a set of active
// components. This includes replication controllers, service endpoints and
// nodes.
//
package app
import (
"testing"
"k8s.io/apimachinery/pkg/util/sets"
)
func TestIsControllerEnabled(t *testing.T) {
tcs := []struct {
name string
controllerName string
controllers []string
disabledByDefaultControllers []string
expected bool
}{
{
name: "on by name",
controllerName: "bravo",
controllers: []string{"alpha", "bravo", "-charlie"},
disabledByDefaultControllers: []string{"delta", "echo"},
expected: true,
},
{
name: "off by name",
controllerName: "charlie",
controllers: []string{"alpha", "bravo", "-charlie"},
disabledByDefaultControllers: []string{"delta", "echo"},
expected: false,
},
{
name: "on by default",
controllerName: "alpha",
controllers: []string{"*"},
disabledByDefaultControllers: []string{"delta", "echo"},
expected: true,
},
{
name: "off by default",
controllerName: "delta",
controllers: []string{"*"},
disabledByDefaultControllers: []string{"delta", "echo"},
expected: false,
},
{
name: "off by default implicit, no star",
controllerName: "foxtrot",
controllers: []string{"alpha", "bravo", "-charlie"},
disabledByDefaultControllers: []string{"delta", "echo"},
expected: false,
},
}
for _, tc := range tcs {
actual := IsControllerEnabled(tc.controllerName, sets.NewString(tc.disabledByDefaultControllers...), tc.controllers...)
if actual != tc.expected {
t.Errorf("%v: expected %v, got %v", tc.name, tc.expected, actual)
}
}
}

View File

@ -32,6 +32,7 @@ import (
"time" "time"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apiserver/pkg/healthz" "k8s.io/apiserver/pkg/healthz"
"k8s.io/kubernetes/cmd/kube-controller-manager/app/options" "k8s.io/kubernetes/cmd/kube-controller-manager/app/options"
@ -71,7 +72,7 @@ const (
// NewControllerManagerCommand creates a *cobra.Command object with default parameters // NewControllerManagerCommand creates a *cobra.Command object with default parameters
func NewControllerManagerCommand() *cobra.Command { func NewControllerManagerCommand() *cobra.Command {
s := options.NewCMServer() s := options.NewCMServer()
s.AddFlags(pflag.CommandLine) s.AddFlags(pflag.CommandLine, KnownControllers(), ControllersDisabledByDefault.List())
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "kube-controller-manager", Use: "kube-controller-manager",
Long: `The Kubernetes controller manager is a daemon that embeds Long: `The Kubernetes controller manager is a daemon that embeds
@ -98,6 +99,10 @@ func ResyncPeriod(s *options.CMServer) func() time.Duration {
// Run runs the CMServer. This should never exit. // Run runs the CMServer. This should never exit.
func Run(s *options.CMServer) error { func Run(s *options.CMServer) error {
if err := s.Validate(KnownControllers(), ControllersDisabledByDefault.List()); err != nil {
return err
}
if c, err := configz.New("componentconfig"); err == nil { if c, err := configz.New("componentconfig"); err == nil {
c.Set(s.KubeControllerManagerConfiguration) c.Set(s.KubeControllerManagerConfiguration)
} else { } else {
@ -216,11 +221,46 @@ type ControllerContext struct {
Stop <-chan struct{} Stop <-chan struct{}
} }
func (c ControllerContext) IsControllerEnabled(name string) bool {
return IsControllerEnabled(name, ControllersDisabledByDefault, c.Options.Controllers...)
}
func IsControllerEnabled(name string, disabledByDefaultControllers sets.String, controllers ...string) bool {
hasStar := false
for _, controller := range controllers {
if controller == name {
return true
}
if controller == "-"+name {
return false
}
if controller == "*" {
hasStar = true
}
}
// if we get here, there was no explicit choice
if !hasStar {
// nothing on by default
return false
}
if disabledByDefaultControllers.Has(name) {
return false
}
return true
}
// InitFunc is used to launch a particular controller. It may run additional "should I activate checks". // InitFunc is used to launch a particular controller. It may run additional "should I activate checks".
// Any error returned will cause the controller process to `Fatal` // Any error returned will cause the controller process to `Fatal`
// The bool indicates whether the controller was enabled. // The bool indicates whether the controller was enabled.
type InitFunc func(ctx ControllerContext) (bool, error) type InitFunc func(ctx ControllerContext) (bool, error)
func KnownControllers() []string {
return sets.StringKeySet(newControllerInitializers()).List()
}
var ControllersDisabledByDefault = sets.NewString()
func newControllerInitializers() map[string]InitFunc { func newControllerInitializers() map[string]InitFunc {
controllers := map[string]InitFunc{} controllers := map[string]InitFunc{}
controllers["endpoint"] = startEndpointController controllers["endpoint"] = startEndpointController
@ -330,6 +370,11 @@ func StartControllers(controllers map[string]InitFunc, s *options.CMServer, root
} }
for controllerName, initFn := range controllers { for controllerName, initFn := range controllers {
if !ctx.IsControllerEnabled(controllerName) {
glog.Warningf("%q is disabled", controllerName)
continue
}
time.Sleep(wait.Jitter(s.ControllerStartInterval.Duration, ControllerStartJitter)) time.Sleep(wait.Jitter(s.ControllerStartInterval.Duration, ControllerStartJitter))
glog.V(1).Infof("Starting %q", controllerName) glog.V(1).Infof("Starting %q", controllerName)

View File

@ -16,6 +16,8 @@ go_library(
"//pkg/client/leaderelection:go_default_library", "//pkg/client/leaderelection:go_default_library",
"//pkg/master/ports:go_default_library", "//pkg/master/ports:go_default_library",
"//pkg/util/config:go_default_library", "//pkg/util/config:go_default_library",
"//pkg/util/errors:go_default_library",
"//pkg/util/sets:go_default_library",
"//vendor:github.com/spf13/pflag", "//vendor:github.com/spf13/pflag",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
], ],

View File

@ -19,6 +19,8 @@ limitations under the License.
package options package options
import ( import (
"fmt"
"strings"
"time" "time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -26,6 +28,8 @@ import (
"k8s.io/kubernetes/pkg/client/leaderelection" "k8s.io/kubernetes/pkg/client/leaderelection"
"k8s.io/kubernetes/pkg/master/ports" "k8s.io/kubernetes/pkg/master/ports"
"k8s.io/kubernetes/pkg/util/config" "k8s.io/kubernetes/pkg/util/config"
utilerrors "k8s.io/kubernetes/pkg/util/errors"
"k8s.io/kubernetes/pkg/util/sets"
"github.com/spf13/pflag" "github.com/spf13/pflag"
) )
@ -42,6 +46,7 @@ type CMServer struct {
func NewCMServer() *CMServer { func NewCMServer() *CMServer {
s := CMServer{ s := CMServer{
KubeControllerManagerConfiguration: componentconfig.KubeControllerManagerConfiguration{ KubeControllerManagerConfiguration: componentconfig.KubeControllerManagerConfiguration{
Controllers: []string{"*"},
Port: ports.ControllerManagerPort, Port: ports.ControllerManagerPort,
Address: "0.0.0.0", Address: "0.0.0.0",
ConcurrentEndpointSyncs: 5, ConcurrentEndpointSyncs: 5,
@ -103,7 +108,11 @@ func NewCMServer() *CMServer {
} }
// AddFlags adds flags for a specific CMServer to the specified FlagSet // AddFlags adds flags for a specific CMServer to the specified FlagSet
func (s *CMServer) AddFlags(fs *pflag.FlagSet) { func (s *CMServer) AddFlags(fs *pflag.FlagSet, allControllers []string, disabledByDefaultControllers []string) {
fs.StringSliceVar(&s.Controllers, "controllers", s.Controllers, fmt.Sprintf(""+
"A list of controllers to enable. '*' enables all on-by-default controllers, 'foo' enables the controller "+
"named 'foo', '-foo' disables the controller named 'foo'.\nAll controllers: %s\nDisabled-by-default controllers: %s",
strings.Join(allControllers, ", "), strings.Join(disabledByDefaultControllers, ", ")))
fs.Int32Var(&s.Port, "port", s.Port, "The port that the controller-manager's http service runs on") fs.Int32Var(&s.Port, "port", s.Port, "The port that the controller-manager's http service runs on")
fs.Var(componentconfig.IPVar{Val: &s.Address}, "address", "The IP address to serve on (set to 0.0.0.0 for all interfaces)") fs.Var(componentconfig.IPVar{Val: &s.Address}, "address", "The IP address to serve on (set to 0.0.0.0 for all interfaces)")
fs.BoolVar(&s.UseServiceAccountCredentials, "use-service-account-credentials", s.UseServiceAccountCredentials, "If true, use individual service account credentials for each controller.") fs.BoolVar(&s.UseServiceAccountCredentials, "use-service-account-credentials", s.UseServiceAccountCredentials, "If true, use individual service account credentials for each controller.")
@ -188,3 +197,24 @@ func (s *CMServer) AddFlags(fs *pflag.FlagSet) {
leaderelection.BindFlags(&s.LeaderElection, fs) leaderelection.BindFlags(&s.LeaderElection, fs)
config.DefaultFeatureGate.AddFlag(fs) config.DefaultFeatureGate.AddFlag(fs)
} }
// Validate is used to validate the options and config before launching the controller manager
func (s *CMServer) Validate(allControllers []string, disabledByDefaultControllers []string) error {
var errs []error
allControllersSet := sets.NewString(allControllers...)
for _, controller := range s.Controllers {
if controller == "*" {
continue
}
if strings.HasPrefix(controller, "-") {
controller = controller[1:]
}
if !allControllersSet.Has(controller) {
errs = append(errs, fmt.Errorf("%q is not in the list of known controllers", controller))
}
}
return utilerrors.NewAggregate(errs)
}

View File

@ -43,7 +43,7 @@ func init() {
func main() { func main() {
s := options.NewCMServer() s := options.NewCMServer()
s.AddFlags(pflag.CommandLine) s.AddFlags(pflag.CommandLine, app.KnownControllers(), app.ControllersDisabledByDefault.List())
flag.InitFlags() flag.InitFlags()
logs.InitLogs() logs.InitLogs()

View File

@ -601,6 +601,13 @@ type LeaderElectionConfiguration struct {
type KubeControllerManagerConfiguration struct { type KubeControllerManagerConfiguration struct {
metav1.TypeMeta metav1.TypeMeta
// Controllers is the list of controllers to enable or disable
// '*' means "all enabled by default controllers"
// 'foo' means "enable 'foo'"
// '-foo' means "disable 'foo'"
// first item for a particular name wins
Controllers []string
// port is the port that the controller-manager's http service runs on. // port is the port that the controller-manager's http service runs on.
Port int32 Port int32
// address is the IP address to serve on (set to 0.0.0.0 for all interfaces). // address is the IP address to serve on (set to 0.0.0.0 for all interfaces).

View File

@ -73,6 +73,11 @@ func DeepCopy_componentconfig_KubeControllerManagerConfiguration(in interface{},
in := in.(*KubeControllerManagerConfiguration) in := in.(*KubeControllerManagerConfiguration)
out := out.(*KubeControllerManagerConfiguration) out := out.(*KubeControllerManagerConfiguration)
*out = *in *out = *in
if in.Controllers != nil {
in, out := &in.Controllers, &out.Controllers
*out = make([]string, len(*in))
copy(*out, *in)
}
return nil return nil
} }
} }