Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor controller initialization (part 2) #14293

Merged
merged 1 commit into from
Jun 5, 2017

Conversation

mfojtik
Copy link
Contributor

@mfojtik mfojtik commented May 23, 2017

This is a follow up what started in #13996 and is tracked here: https://trello.com/c/ZtOfFpFz/907-5-use-kubernetes-controller-roles

In a nutshell:

  • We are switching to upstream RBAC roles for upstream controllers (should be already done)
  • We are switching to new initialization of origin controllers (this PR)

@mfojtik mfojtik requested a review from deads2k May 23, 2017 10:41
@mfojtik
Copy link
Contributor Author

mfojtik commented May 23, 2017

@enj @sttts attempt to fix the serviceaccount controllers... basically I created "pre" group for them and start them before we run kubernetes controllers. To make it work, I added RootClientBuilder into ControllerContext only for the pre-initialization (actually only serviceaccount-tokens controllers use it). For other origin controllers I erase that field so they don't accidentialy use it.

@deads2k if we go this path, I think we should move the loop where we start the controllers (initFn) into controllers.go as we duplicate the code between pre-initialization and initialization ;-)

@@ -16,6 +16,9 @@ var (
controllerRoles = []rbac.ClusterRole{}
// controllerRoleBindings is a slice of roles used for controllers
controllerRoleBindings = []rbac.ClusterRoleBinding{}

ReadWrite = []string{"get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@deads2k copied from kube, i guess this will make better experience for people writing the rules? ;-)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't that accessible constants in kube? If not, maybe they should be public.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they are but i was going to avoid importing the upstream bootstrap package just to get them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need the same for auditing. So we probably make them available in k8s.io/apiserver/pkg/endpoints/request

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sttts i will go with TODO for now and once we have stable location we can import

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, we don't use the ReadWrite or Read variables in controller policy.


// serviceaccount-tokens-controller
addControllerRole(rbac.ClusterRole{
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + InfraServiceAccountTokensControllerServiceAccountName},
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@deads2k wonder if we want/need this... this controller will use the RootClientBuilder which means privileged client will be used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nuked this.

@@ -7,6 +7,23 @@ import (
"github.com/openshift/origin/pkg/cmd/server/origin/controller"
)

func (c *MasterConfig) NewOpenShiftControllerPreInitializers() (map[string]controller.InitFunc, error) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe deserve a better name?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only the SA token controller needs to run first, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, not sure about the serviceaccount controller (and pullsecrets/etc.) they ran first in old world.

options.ServiceAccounts = append(options.ServiceAccounts, sa)
}

//REBASE: add new args to NewServiceAccountsController
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@deads2k @sttts still valid comment?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure. What does a blame say? Last rebase or ages ago?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ncdc addded this in Nov/2016... if this refers to args options then maybe the comment is still valid.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was a comment that I was reacting to changes made between kube 1.4 and 1.5. It can be deleted.


func (c *ServiceAccountTokensControllerOptions) RunController(ctx ControllerContext) (bool, error) {
if len(c.ServiceAccountConfig.PrivateKeyFile) == 0 {
return true, fmt.Errorf("skipped starting Service Account Token Manager, no private key specified")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@deads2k want confirm that returning true and error here is ok.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A godoc wouldn't harm. It's not obvious what the bool means.

oc.RunServiceAccountsController()
oc.RunServiceAccountTokensController(controllerManagerOptions)
// used by admission controllers
oc.RunServiceAccountPullSecretsControllers()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will come soon

@@ -59,5 +60,7 @@ func (a *scopeAuthorizer) Authorize(attributes authorizer.Attributes) (bool, str
denyReason = err.Error()
}

glog.V(4).Infof("RBAC DENY: user %q groups %q cannot %v", attributes.GetUser().GetName(), attributes.GetUser().GetGroups(), denyReason)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ignore this pathetic attempt to imitate kube messages ;-)


func (c *ServiceAccountControllerOptions) RunController(ctx ControllerContext) (bool, error) {
if len(c.ManagedNames) == 0 {
return true, fmt.Errorf("Skipped starting Service Account Manager, no managed names specified")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lower case errors

@@ -20,6 +20,7 @@ import (
utilwait "k8s.io/apimachinery/pkg/util/wait"
restclient "k8s.io/client-go/rest"
kctrlmgr "k8s.io/kubernetes/cmd/kube-controller-manager/app"
kubecontroller "k8s.io/kubernetes/cmd/kube-controller-manager/app"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

twice the same import?

@mfojtik mfojtik force-pushed the controller-init branch 3 times, most recently from 05512c3 to c8ea7e1 Compare May 23, 2017 12:00
addControllerRole(rbac.ClusterRole{
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + InfraServiceAccountControllerServiceAccountName},
Rules: []rbac.PolicyRule{
rbac.NewRule(ReadWrite...).Groups(kapiGroup).Resources("serviceaccounts").RuleOrDie(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't use these in the controller_policy upstream. Mutation is rarely uniform in the controllers and the powers are subtly different. Update can require knowledge of resourceversion, patch doesn't. Delete requires knowledge of names, deletecollection does not.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@deads2k i knew you will not like it... i realized that those rules are too broad for controllers where we know what controllers can/cannot do.

serviceAccount := controller.ServiceAccountControllerOptions{
ManagedNames: c.Options.ServiceAccountConfig.ManagedNames,
}
ret["serviceaccount"] = serviceAccount.RunController
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this one ought not require pre-init

ret["serviceaccount"] = serviceAccount.RunController

serviceAccountPullSecrets := controller.ServiceAccountPullSecretsControllerOptions{}
ret["serviceaccount-pull-secrets"] = serviceAccountPullSecrets.RunController
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this one doesn't need to be pre-init

@@ -19,6 +19,10 @@ type ControllerContext struct {

DeprecatedOpenshiftInformers shared.InformerFactory

// RootClient should only be used for pre-initialization controllers
// (iow. serviceaccount-tokens controller)
RootClientBuilder *controller.SimpleControllerClientBuilder
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would try to wire this down separately into the init function when you create the struct the init function lives on. It's not a preferred means of creating the init function (makes it harder to read), but we really don't want this escaping

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i can wire this from MasterConfig I believe and pass it in the struct.

projectcontroller "github.com/openshift/origin/pkg/project/controller"
)

type OriginNamespaceControllerOptions struct{}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we have nothing in here, don't have the struct. Just a bare function.


func (c *ServiceAccountControllerOptions) RunController(ctx ControllerContext) (bool, error) {
if len(c.ManagedNames) == 0 {
return true, fmt.Errorf("skipped starting Service Account Manager, no managed names specified")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return false, nil. returning an error will fatal the process.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so use glog?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so use glog?

You can if you like. The caller actually drops a message in the log saying its skipping it.

ctx.DeprecatedOpenshiftInformers.KubernetesInformers().Core().V1().ServiceAccounts(),
ctx.DeprecatedOpenshiftInformers.KubernetesInformers().Core().V1().Namespaces(),
ctx.ClientBuilder.ClientOrDie(bootstrappolicy.InfraServiceAccountControllerServiceAccountName),
options).Run(1, ctx.Stop)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running only one worker is a little weird.

)

type ServiceAccountControllerOptions struct {
ManagedNames []string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this. Much cleaner than what we had before.


func (c *ServiceAccountTokensControllerOptions) RunController(ctx ControllerContext) (bool, error) {
if len(c.ServiceAccountConfig.PrivateKeyFile) == 0 {
return true, fmt.Errorf("skipped starting Service Account Token Manager, no private key specified")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return false, nil. The bool indicates that this controller was enabled, the error means we couldn't start the controller when we were supposed to. So returning false without an error means "skipped" and return an error means, "couldn't fullfill intent, crashloop."

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see this as outstanding.


privateKey, err := serviceaccount.ReadPrivateKey(c.ServiceAccountConfig.PrivateKeyFile)
if err != nil {
return true, fmt.Errorf("error reading signing key for Service Account Token Manager: %v", err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this one is correct.


type ServiceAccountTokensControllerOptions struct {
ServiceAccountConfig configapi.ServiceAccountConfig
ServiceServingCertConfig configapi.ServiceServingCert
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only the CA file contents please. []byte

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only the CA file contents please. []byte

Reasoning: This should be a runtime optimized config, so content instead of file reference (which is easier for a user) and this controller only needs to know the non-secret information. If we ever separate out these controllers, it doesn't need the full config.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see this as still outstanding.

return true, nil
}

type ServiceAccountPullSecretsControllerOptions struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no options, no struct.

allowedOpenshiftControllers := sets.NewString(
// The serviceaccount-token controller has to be started before any other controller
// runs in order to be able to issue tokens.
"serviceaccount-tokens",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can more or less hard code this one first, then start it directly. The others simply flow from it.


oc.RunSecurityAllocationController()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why did this move?

@deads2k
Copy link
Contributor

deads2k commented May 23, 2017

@mfojtik want to clean up what you have so far and merge it rather than growing bigger?

@mfojtik
Copy link
Contributor Author

mfojtik commented May 23, 2017

@deads2k just cleaning up and addressing comments... yeah I would prefer to add this in iteration to prevent rebasing hell.

@mfojtik
Copy link
Contributor Author

mfojtik commented May 25, 2017

@deads2k this was interrupted by #14321 (merge conflict)

@pweil- @jupierce @smarterclayton i would really like to merge this otherwise this will be a rebase hell once the dcut opens. This is improving security of the controllers (well previously there was no security...). Also I would like QA to spend time on running on this to capture bugs associated with new controller privileges.

@openshift-bot openshift-bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 25, 2017
@mfojtik
Copy link
Contributor Author

mfojtik commented May 25, 2017

flake is: #14208

[test]

@mfojtik
Copy link
Contributor Author

mfojtik commented May 25, 2017

flake : #14353

@mfojtik
Copy link
Contributor Author

mfojtik commented May 25, 2017

[test]

@openshift-bot openshift-bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 25, 2017
@mfojtik
Copy link
Contributor Author

mfojtik commented May 30, 2017

@smarterclayton seems like this is not broken after I rebased against the shared informers stuff... the serviceaccount-token controller is not creating tokens (seems like the informer is stuck or not started).

@smarterclayton
Copy link
Contributor

Once the two controllers are started, we need to start the subset of Kube informers that control secrets and service accounts. See the old code, there's a massive comment right after the controller start

@openshift-bot openshift-bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 30, 2017
@mfojtik
Copy link
Contributor Author

mfojtik commented May 31, 2017

Once the two controllers are started, we need to start the subset of Kube informers that control secrets and service accounts. See the old code, there's a massive comment right after the controller start

@smarterclayton I saw that comment and I made sure we do start the kube informers right after the controller (serviceaccount-token) is started. That controller indeed starts and origin runs and I even see some tokens creates but there are no SA/secrets for new projects...

func RunServiceAccountPullSecretsController(ctx ControllerContext) (bool, error) {
kc := ctx.ClientBuilder.KubeInternalClientOrDie(bootstrappolicy.InfraServiceAccountPullSecretsControllerServiceAccountName)

serviceaccountcontrollers.NewDockercfgDeletedController(
Copy link
Contributor Author

@mfojtik mfojtik May 31, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@smarterclayton hrm... this has to be a goroutine now.... a cost I pay for rebasing this without coffe.

@openshift-bot
Copy link
Contributor

Evaluated for origin testextended up to f0d6e70

@mfojtik
Copy link
Contributor Author

mfojtik commented May 31, 2017

flake: #14122

[test]

@openshift-bot
Copy link
Contributor

continuous-integration/openshift-jenkins/testextended FAILURE (https://ci.openshift.redhat.com/jenkins/job/test_pull_request_origin_extended/528/) (Base Commit: 375c727) (Extended Tests: core(builds))

@mfojtik
Copy link
Contributor Author

mfojtik commented Jun 1, 2017

[test] again

@mfojtik
Copy link
Contributor Author

mfojtik commented Jun 1, 2017

dockerhub flake (pulling centos...)

[test]

@openshift-bot
Copy link
Contributor

Evaluated for origin test up to f0d6e70

@openshift-bot
Copy link
Contributor

continuous-integration/openshift-jenkins/test SUCCESS (https://ci.openshift.redhat.com/jenkins/job/test_pull_request_origin/1889/) (Base Commit: 1bf8a17)

@mfojtik
Copy link
Contributor Author

mfojtik commented Jun 5, 2017

[merge] (lets see if the merge is open now ;-)

@mfojtik
Copy link
Contributor Author

mfojtik commented Jun 5, 2017

re- [merge]

@openshift-bot
Copy link
Contributor

Evaluated for origin merge up to f0d6e70

@openshift-bot
Copy link
Contributor

openshift-bot commented Jun 5, 2017

continuous-integration/openshift-jenkins/merge SUCCESS (https://ci.openshift.redhat.com/jenkins/job/merge_pull_request_origin/892/) (Base Commit: 90592c5) (Image: devenv-rhel7_6300)

@openshift-bot openshift-bot merged commit 437dd3c into openshift:master Jun 5, 2017
@mfojtik mfojtik deleted the controller-init branch September 5, 2018 21:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants