Skip to content

Commit

Permalink
UPSTREAM: <carry>: kube-controller-manager: allow running bare kube-c…
Browse files Browse the repository at this point in the history
…ontroller-manager

UPSTREAM: <carry>: (squash) kube-controller-manager: allow running bare kube-controller-manager
  • Loading branch information
deads2k authored and soltysh committed Sep 7, 2021
1 parent 1c7dca0 commit 3d7cad6
Show file tree
Hide file tree
Showing 14 changed files with 983 additions and 6 deletions.
5 changes: 4 additions & 1 deletion cmd/kube-controller-manager/app/apps.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ func startDaemonSetController(ctx ControllerContext) (http.Handler, bool, error)
if !ctx.AvailableResources[schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "daemonsets"}] {
return nil, false, nil
}
dsc, err := daemon.NewDaemonSetsController(
dsc, err := daemon.NewNodeSelectorAwareDaemonSetsController(
ctx.OpenShiftContext.OpenShiftDefaultProjectNodeSelector,
ctx.OpenShiftContext.KubeDefaultProjectNodeSelector,
ctx.InformerFactory.Core().V1().Namespaces(),
ctx.InformerFactory.Apps().V1().DaemonSets(),
ctx.InformerFactory.Apps().V1().ControllerRevisions(),
ctx.InformerFactory.Core().V1().Pods(),
Expand Down
2 changes: 2 additions & 0 deletions cmd/kube-controller-manager/app/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import (

// Config is the main context object for the controller manager.
type Config struct {
OpenShiftContext OpenShiftContext

ComponentConfig kubectrlmgrconfig.KubeControllerManagerConfiguration

SecureServing *apiserver.SecureServingInfo
Expand Down
9 changes: 9 additions & 0 deletions cmd/kube-controller-manager/app/config/patch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package config

// OpenShiftContext is additional context that we need to launch the kube-controller-manager for openshift.
// Basically, this holds our additional config information.
type OpenShiftContext struct {
OpenShiftConfig string
OpenShiftDefaultProjectNodeSelector string
KubeDefaultProjectNodeSelector string
}
29 changes: 25 additions & 4 deletions cmd/kube-controller-manager/app/controllermanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,23 @@ controller, and serviceaccounts controller.`,
},
Run: func(cmd *cobra.Command, args []string) {
verflag.PrintAndExitIfRequested()
cliflag.PrintFlags(cmd.Flags())

if err := ShimFlagsForOpenShift(s, cmd); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}

c, err := s.Config(KnownControllers(), ControllersDisabledByDefault.List())
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}

if err := ShimForOpenShift(s, c); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}

if err := Run(c.Complete(), wait.NeverStop); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
Expand Down Expand Up @@ -246,6 +255,10 @@ func Run(c *config.CompletedConfig, stopCh <-chan struct{}) error {
}
saTokenControllerInitFunc := serviceAccountTokenControllerStarter{rootClientBuilder: rootClientBuilder}.startServiceAccountTokenController

if err := createPVRecyclerSA(c.OpenShiftContext.OpenShiftConfig, rootClientBuilder); err != nil {
klog.Fatalf("error creating recycler serviceaccount: %v", err)
}

if err := StartControllers(controllerContext, saTokenControllerInitFunc, NewControllerInitializers(controllerContext.LoopMode), unsecuredMux); err != nil {
klog.Fatalf("error starting controllers: %v", err)
}
Expand Down Expand Up @@ -302,6 +315,8 @@ func Run(c *config.CompletedConfig, stopCh <-chan struct{}) error {

// ControllerContext defines the context object for controller
type ControllerContext struct {
OpenShiftContext config.OpenShiftContext

// ClientBuilder will provide a client for this controller to use
ClientBuilder clientbuilder.ControllerClientBuilder

Expand Down Expand Up @@ -468,7 +483,12 @@ func GetAvailableResources(clientBuilder clientbuilder.ControllerClientBuilder)
// the shared-informers client and token controller.
func CreateControllerContext(s *config.CompletedConfig, rootClientBuilder, clientBuilder clientbuilder.ControllerClientBuilder, stop <-chan struct{}) (ControllerContext, error) {
versionedClient := rootClientBuilder.ClientOrDie("shared-informers")
sharedInformers := informers.NewSharedInformerFactory(versionedClient, ResyncPeriod(s)())
var sharedInformers informers.SharedInformerFactory
if InformerFactoryOverride == nil {
sharedInformers = informers.NewSharedInformerFactory(versionedClient, ResyncPeriod(s)())
} else {
sharedInformers = InformerFactoryOverride
}

metadataClient := metadata.NewForConfigOrDie(rootClientBuilder.ConfigOrDie("metadata-informers"))
metadataInformers := metadatainformer.NewSharedInformerFactory(metadataClient, ResyncPeriod(s)())
Expand Down Expand Up @@ -499,6 +519,7 @@ func CreateControllerContext(s *config.CompletedConfig, rootClientBuilder, clien
}

ctx := ControllerContext{
OpenShiftContext: s.OpenShiftContext,
ClientBuilder: clientBuilder,
InformerFactory: sharedInformers,
ObjectOrMetadataInformerFactory: informerfactory.NewInformerFactory(sharedInformers, metadataInformers),
Expand Down Expand Up @@ -596,10 +617,10 @@ func (c serviceAccountTokenControllerStarter) startServiceAccountTokenController
ctx.InformerFactory.Core().V1().ServiceAccounts(),
ctx.InformerFactory.Core().V1().Secrets(),
c.rootClientBuilder.ClientOrDie("tokens-controller"),
serviceaccountcontroller.TokensControllerOptions{
applyOpenShiftServiceServingCertCA(serviceaccountcontroller.TokensControllerOptions{
TokenGenerator: tokenGenerator,
RootCA: rootCA,
},
}),
)
if err != nil {
return nil, true, fmt.Errorf("error creating Tokens controller: %v", err)
Expand Down
8 changes: 8 additions & 0 deletions cmd/kube-controller-manager/app/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ type KubeControllerManagerOptions struct {
Master string
Kubeconfig string
ShowHiddenMetricsForVersion string
OpenShiftContext kubecontrollerconfig.OpenShiftContext
}

// NewKubeControllerManagerOptions creates a new KubeControllerManagerOptions with a default config.
Expand Down Expand Up @@ -266,6 +267,11 @@ func (s *KubeControllerManagerOptions) Flags(allControllers []string, disabledBy
fs := fss.FlagSet("misc")
fs.StringVar(&s.Master, "master", s.Master, "The address of the Kubernetes API server (overrides any value in kubeconfig).")
fs.StringVar(&s.Kubeconfig, "kubeconfig", s.Kubeconfig, "Path to kubeconfig file with authorization and master location information.")
var dummy string
fs.MarkDeprecated("insecure-experimental-approve-all-kubelet-csrs-for-group", "This flag does nothing.")
fs.StringVar(&dummy, "insecure-experimental-approve-all-kubelet-csrs-for-group", "", "This flag does nothing.")
fs.StringVar(&s.OpenShiftContext.OpenShiftConfig, "openshift-config", s.OpenShiftContext.OpenShiftConfig, "indicates that this process should be compatible with openshift start master")
fs.MarkHidden("openshift-config")
utilfeature.DefaultMutableFeatureGate.AddFlag(fss.FlagSet("generic"))

return fss
Expand Down Expand Up @@ -371,6 +377,8 @@ func (s *KubeControllerManagerOptions) ApplyTo(c *kubecontrollerconfig.Config) e
c.ComponentConfig.Generic.Port = int32(s.InsecureServing.BindPort)
c.ComponentConfig.Generic.Address = s.InsecureServing.BindAddress.String()

c.OpenShiftContext = s.OpenShiftContext

return nil
}

Expand Down
70 changes: 70 additions & 0 deletions cmd/kube-controller-manager/app/patch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package app

import (
"path"

"github.com/spf13/cobra"

"k8s.io/client-go/informers"
cliflag "k8s.io/component-base/cli/flag"
"k8s.io/klog/v2"
"k8s.io/kubernetes/cmd/kube-controller-manager/app/config"
"k8s.io/kubernetes/cmd/kube-controller-manager/app/options"
)

var InformerFactoryOverride informers.SharedInformerFactory

func ShimForOpenShift(controllerManagerOptions *options.KubeControllerManagerOptions, controllerManager *config.Config) error {
if len(controllerManager.OpenShiftContext.OpenShiftConfig) == 0 {
return nil
}

// TODO this gets removed when no longer take flags and no longer build a recycler template
openshiftConfig, err := getOpenShiftConfig(controllerManager.OpenShiftContext.OpenShiftConfig)
if err != nil {
return err
}

// TODO this should be replaced by using a flex volume to inject service serving cert CAs into pods instead of adding it to the sa token
if err := applyOpenShiftServiceServingCertCAFunc(path.Dir(controllerManager.OpenShiftContext.OpenShiftConfig), openshiftConfig); err != nil {
return err
}

// skip GC on some openshift resources
// TODO this should be replaced by discovery information in some way
if err := applyOpenShiftGCConfig(controllerManager); err != nil {
return err
}

// Overwrite the informers, because we have our custom generic informers for quota.
// TODO update quota to create its own informer like garbage collection
if informers, err := newInformerFactory(controllerManager.Kubeconfig); err != nil {
return err
} else {
InformerFactoryOverride = informers
}

return nil
}

func ShimFlagsForOpenShift(controllerManagerOptions *options.KubeControllerManagerOptions, cmd *cobra.Command) error {
if len(controllerManagerOptions.OpenShiftContext.OpenShiftConfig) == 0 {
return nil
}

// TODO this gets removed when no longer take flags and no longer build a recycler template
openshiftConfig, err := getOpenShiftConfig(controllerManagerOptions.OpenShiftContext.OpenShiftConfig)
if err != nil {
return err
}
// apply the config based controller manager flags. They will override.
// TODO this should be replaced by the installer setting up the flags for us
if err := applyOpenShiftConfigFlags(controllerManagerOptions, openshiftConfig, cmd); err != nil {
return err
}

klog.V(1).Infof("Flags after OpenShift shims:")
cliflag.PrintFlags(cmd.Flags())

return nil
}
118 changes: 118 additions & 0 deletions cmd/kube-controller-manager/app/patch_flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package app

import (
"fmt"
"io/ioutil"

"github.com/spf13/cobra"
"github.com/spf13/pflag"

kerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/json"
"k8s.io/apimachinery/pkg/util/validation/field"
kyaml "k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/kubernetes/cmd/kube-controller-manager/app/options"
)

func getOpenShiftConfig(configFile string) (map[string]interface{}, error) {
configBytes, err := ioutil.ReadFile(configFile)
if err != nil {
return nil, err
}
jsonBytes, err := kyaml.ToJSON(configBytes)
if err != nil {
return nil, err
}
config := map[string]interface{}{}
if err := json.Unmarshal(jsonBytes, &config); err != nil {
return nil, err
}

return config, nil
}

func applyOpenShiftConfigFlags(controllerManagerOptions *options.KubeControllerManagerOptions, openshiftConfig map[string]interface{}, cmd *cobra.Command) error {
if err := applyOpenShiftConfigControllerArgs(controllerManagerOptions, openshiftConfig, cmd); err != nil {
return err
}
if err := applyOpenShiftConfigDefaultProjectSelector(controllerManagerOptions, openshiftConfig); err != nil {
return err
}
if err := applyOpenShiftConfigKubeDefaultProjectSelector(controllerManagerOptions, openshiftConfig); err != nil {
return err
}
return nil
}

func applyOpenShiftConfigDefaultProjectSelector(controllerManagerOptions *options.KubeControllerManagerOptions, openshiftConfig map[string]interface{}) error {
projectConfig, ok := openshiftConfig["projectConfig"]
if !ok {
return nil
}

castProjectConfig := projectConfig.(map[string]interface{})
defaultNodeSelector, ok := castProjectConfig["defaultNodeSelector"]
if !ok {
return nil
}
controllerManagerOptions.OpenShiftContext.OpenShiftDefaultProjectNodeSelector = defaultNodeSelector.(string)

return nil
}

// this is an optimization. It can be filled in later. Looks like there are several special cases for this plugin upstream
// TODO find this
func applyOpenShiftConfigKubeDefaultProjectSelector(controllerManagerOptions *options.KubeControllerManagerOptions, openshiftConfig map[string]interface{}) error {
controllerManagerOptions.OpenShiftContext.KubeDefaultProjectNodeSelector = ""
return nil
}

func applyOpenShiftConfigControllerArgs(controllerManagerOptions *options.KubeControllerManagerOptions, openshiftConfig map[string]interface{}, cmd *cobra.Command) error {
var controllerArgs interface{}
kubeMasterConfig, ok := openshiftConfig["kubernetesMasterConfig"]
if !ok {
controllerArgs, ok = openshiftConfig["extendedArguments"]
if !ok || controllerArgs == nil {
return nil
}
} else {
castKubeMasterConfig := kubeMasterConfig.(map[string]interface{})
controllerArgs, ok = castKubeMasterConfig["controllerArguments"]
if !ok || controllerArgs == nil {
controllerArgs, ok = openshiftConfig["extendedArguments"]
if !ok || controllerArgs == nil {
return nil
}
}
}

args := map[string][]string{}
for key, value := range controllerArgs.(map[string]interface{}) {
for _, arrayValue := range value.([]interface{}) {
args[key] = append(args[key], arrayValue.(string))
}
}
if err := applyFlags(args, cmd.Flags()); len(err) > 0 {
return kerrors.NewAggregate(err)
}
return nil
}

// applyFlags stores the provided arguments onto a flag set, reporting any errors
// encountered during the process.
func applyFlags(args map[string][]string, flags *pflag.FlagSet) []error {
var errs []error
for key, value := range args {
if flag := flags.Lookup(key); flag != nil {
for _, s := range value {
if err := flag.Value.Set(s); err != nil {
errs = append(errs, field.Invalid(field.NewPath(key), s, fmt.Sprintf("could not be set: %v", err)))
break
}
}
} else {
errs = append(errs, field.Invalid(field.NewPath("flag"), key, "is not a valid flag"))
}
}
return errs
}
40 changes: 40 additions & 0 deletions cmd/kube-controller-manager/app/patch_gc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package app

import (
gcconfig "k8s.io/kubernetes/pkg/controller/garbagecollector/config"

"k8s.io/kubernetes/cmd/kube-controller-manager/app/config"
)

func applyOpenShiftGCConfig(controllerManager *config.Config) error {
// TODO make this configurable or discoverable. This is going to prevent us from running the stock GC controller
// IF YOU ADD ANYTHING TO THIS LIST, MAKE SURE THAT YOU UPDATE THEIR STRATEGIES TO PREVENT GC FINALIZERS
controllerManager.ComponentConfig.GarbageCollectorController.GCIgnoredResources = append(controllerManager.ComponentConfig.GarbageCollectorController.GCIgnoredResources,
// explicitly disabled from GC for now - not enough value to track them
gcconfig.GroupResource{Group: "authorization.openshift.io", Resource: "rolebindingrestrictions"},
gcconfig.GroupResource{Group: "network.openshift.io", Resource: "clusternetworks"},
gcconfig.GroupResource{Group: "network.openshift.io", Resource: "egressnetworkpolicies"},
gcconfig.GroupResource{Group: "network.openshift.io", Resource: "hostsubnets"},
gcconfig.GroupResource{Group: "network.openshift.io", Resource: "netnamespaces"},
gcconfig.GroupResource{Group: "oauth.openshift.io", Resource: "oauthclientauthorizations"},
gcconfig.GroupResource{Group: "oauth.openshift.io", Resource: "oauthclients"},
gcconfig.GroupResource{Group: "quota.openshift.io", Resource: "clusterresourcequotas"},
gcconfig.GroupResource{Group: "user.openshift.io", Resource: "groups"},
gcconfig.GroupResource{Group: "user.openshift.io", Resource: "identities"},
gcconfig.GroupResource{Group: "user.openshift.io", Resource: "users"},
gcconfig.GroupResource{Group: "image.openshift.io", Resource: "images"},

// virtual resource
gcconfig.GroupResource{Group: "project.openshift.io", Resource: "projects"},
// virtual and unwatchable resource, surfaced via rbac.authorization.k8s.io objects
gcconfig.GroupResource{Group: "authorization.openshift.io", Resource: "clusterroles"},
gcconfig.GroupResource{Group: "authorization.openshift.io", Resource: "clusterrolebindings"},
gcconfig.GroupResource{Group: "authorization.openshift.io", Resource: "roles"},
gcconfig.GroupResource{Group: "authorization.openshift.io", Resource: "rolebindings"},
// these resources contain security information in their names, and we don't need to track them
gcconfig.GroupResource{Group: "oauth.openshift.io", Resource: "oauthaccesstokens"},
gcconfig.GroupResource{Group: "oauth.openshift.io", Resource: "oauthauthorizetokens"},
)

return nil
}
Loading

0 comments on commit 3d7cad6

Please sign in to comment.