Skip to content

Commit cedcafd

Browse files
committed
simplify openshift controller manager startup
1 parent 73ea6cc commit cedcafd

File tree

5 files changed

+24
-141
lines changed

5 files changed

+24
-141
lines changed

pkg/cmd/server/origin/controller/config.go

-60
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,15 @@
11
package controller
22

33
import (
4-
"fmt"
5-
"io/ioutil"
64
"path"
75
"time"
86

97
"k8s.io/apimachinery/pkg/runtime/schema"
10-
"k8s.io/client-go/util/cert"
118
"k8s.io/kubernetes/pkg/api/legacyscheme"
129
kapi "k8s.io/kubernetes/pkg/apis/core"
13-
kcontroller "k8s.io/kubernetes/pkg/controller"
1410
serviceaccountadmission "k8s.io/kubernetes/plugin/pkg/admission/serviceaccount"
1511

1612
configapi "github.com/openshift/origin/pkg/cmd/server/apis/config"
17-
"github.com/openshift/origin/pkg/cmd/server/crypto"
1813
"github.com/openshift/origin/pkg/cmd/util/variable"
1914
)
2015

@@ -56,8 +51,6 @@ func getOpenShiftClientEnvVars(options configapi.MasterConfig) ([]kapi.EnvVar, e
5651
// OpenshiftControllerConfig is the runtime (non-serializable) config object used to
5752
// launch the set of openshift (not kube) controllers.
5853
type OpenshiftControllerConfig struct {
59-
ServiceAccountTokenControllerOptions ServiceAccountTokenControllerOptions
60-
6154
ServiceAccountControllerOptions ServiceAccountControllerOptions
6255

6356
BuildControllerConfig BuildControllerConfig
@@ -115,63 +108,10 @@ func (c *OpenshiftControllerConfig) GetControllerInitializers() (map[string]Init
115108
return ret, nil
116109
}
117110

118-
// NewOpenShiftControllerPreStartInitializers returns list of initializers for controllers
119-
// that needed to be run before any other controller is started.
120-
// Typically this has to done for the serviceaccount-token controller as it provides
121-
// tokens to other controllers.
122-
func (c *OpenshiftControllerConfig) ServiceAccountContentControllerInit() InitFunc {
123-
return c.ServiceAccountTokenControllerOptions.RunController
124-
}
125-
126111
func BuildOpenshiftControllerConfig(options configapi.MasterConfig) (*OpenshiftControllerConfig, error) {
127112
var err error
128113
ret := &OpenshiftControllerConfig{}
129114

130-
_, loopbackClientConfig, err := configapi.GetInternalKubeClient(options.MasterClients.OpenShiftLoopbackKubeConfig, options.MasterClients.OpenShiftLoopbackClientConnectionOverrides)
131-
if err != nil {
132-
return nil, err
133-
}
134-
135-
ret.ServiceAccountTokenControllerOptions = ServiceAccountTokenControllerOptions{
136-
RootClientBuilder: kcontroller.SimpleControllerClientBuilder{
137-
ClientConfig: loopbackClientConfig,
138-
},
139-
}
140-
if len(options.ServiceAccountConfig.PrivateKeyFile) > 0 {
141-
ret.ServiceAccountTokenControllerOptions.PrivateKey, err = cert.PrivateKeyFromFile(options.ServiceAccountConfig.PrivateKeyFile)
142-
if err != nil {
143-
return nil, fmt.Errorf("error reading signing key for Service Account Token Manager: %v", err)
144-
}
145-
}
146-
if len(options.ServiceAccountConfig.MasterCA) > 0 {
147-
ret.ServiceAccountTokenControllerOptions.RootCA, err = ioutil.ReadFile(options.ServiceAccountConfig.MasterCA)
148-
if err != nil {
149-
return nil, fmt.Errorf("error reading master ca file for Service Account Token Manager: %s: %v", options.ServiceAccountConfig.MasterCA, err)
150-
}
151-
if _, err := cert.ParseCertsPEM(ret.ServiceAccountTokenControllerOptions.RootCA); err != nil {
152-
return nil, fmt.Errorf("error parsing master ca file for Service Account Token Manager: %s: %v", options.ServiceAccountConfig.MasterCA, err)
153-
}
154-
}
155-
if options.ControllerConfig.ServiceServingCert.Signer != nil && len(options.ControllerConfig.ServiceServingCert.Signer.CertFile) > 0 {
156-
certFile := options.ControllerConfig.ServiceServingCert.Signer.CertFile
157-
serviceServingCA, err := ioutil.ReadFile(certFile)
158-
if err != nil {
159-
return nil, fmt.Errorf("error reading ca file for Service Serving Certificate Signer: %s: %v", certFile, err)
160-
}
161-
if _, err := crypto.CertsFromPEM(serviceServingCA); err != nil {
162-
return nil, fmt.Errorf("error parsing ca file for Service Serving Certificate Signer: %s: %v", certFile, err)
163-
}
164-
165-
// if we have a rootCA bundle add that too. The rootCA will be used when hitting the default master service, since those are signed
166-
// using a different CA by default. The rootCA's key is more closely guarded than ours and if it is compromised, that power could
167-
// be used to change the trusted signers for every pod anyway, so we're already effectively trusting it.
168-
if len(ret.ServiceAccountTokenControllerOptions.RootCA) > 0 {
169-
ret.ServiceAccountTokenControllerOptions.ServiceServingCA = append(ret.ServiceAccountTokenControllerOptions.ServiceServingCA, ret.ServiceAccountTokenControllerOptions.RootCA...)
170-
ret.ServiceAccountTokenControllerOptions.ServiceServingCA = append(ret.ServiceAccountTokenControllerOptions.ServiceServingCA, []byte("\n")...)
171-
}
172-
ret.ServiceAccountTokenControllerOptions.ServiceServingCA = append(ret.ServiceAccountTokenControllerOptions.ServiceServingCA, serviceServingCA...)
173-
}
174-
175115
ret.ServiceAccountControllerOptions = ServiceAccountControllerOptions{
176116
ManagedNames: options.ServiceAccountConfig.ManagedNames,
177117
}

pkg/cmd/server/origin/controller/serviceaccount.go

-33
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ import (
44
"github.com/golang/glog"
55

66
kapiv1 "k8s.io/api/core/v1"
7-
"k8s.io/kubernetes/pkg/controller"
87
sacontroller "k8s.io/kubernetes/pkg/controller/serviceaccount"
9-
"k8s.io/kubernetes/pkg/serviceaccount"
108

119
"github.com/openshift/origin/pkg/cmd/server/bootstrappolicy"
1210
serviceaccountcontrollers "github.com/openshift/origin/pkg/serviceaccounts/controllers"
@@ -49,37 +47,6 @@ func (c *ServiceAccountControllerOptions) RunController(ctx ControllerContext) (
4947
return true, nil
5048
}
5149

52-
type ServiceAccountTokenControllerOptions struct {
53-
RootCA []byte
54-
ServiceServingCA []byte
55-
PrivateKey interface{}
56-
57-
RootClientBuilder controller.SimpleControllerClientBuilder
58-
}
59-
60-
func (c *ServiceAccountTokenControllerOptions) RunController(ctx ControllerContext) (bool, error) {
61-
if c.PrivateKey == nil {
62-
glog.Infof("Skipped starting Service Account Token Manager, no private key specified")
63-
return false, nil
64-
}
65-
66-
controller, err := sacontroller.NewTokensController(
67-
ctx.ExternalKubeInformers.Core().V1().ServiceAccounts(),
68-
ctx.ExternalKubeInformers.Core().V1().Secrets(),
69-
c.RootClientBuilder.ClientOrDie(bootstrappolicy.InfraServiceAccountTokensControllerServiceAccountName),
70-
sacontroller.TokensControllerOptions{
71-
TokenGenerator: serviceaccount.JWTTokenGenerator(c.PrivateKey),
72-
RootCA: c.RootCA,
73-
ServiceServingCA: c.ServiceServingCA,
74-
},
75-
)
76-
if err != nil {
77-
return true, nil
78-
}
79-
go controller.Run(int(ctx.OpenshiftControllerOptions.ServiceAccountTokenOptions.ConcurrentSyncs), ctx.Stop)
80-
return true, nil
81-
}
82-
8350
func RunServiceAccountPullSecretsController(ctx ControllerContext) (bool, error) {
8451
kc := ctx.ClientBuilder.ClientOrDie(bootstrappolicy.InfraServiceAccountPullSecretsControllerServiceAccountName)
8552

pkg/cmd/server/start/start_kube_controller_manager.go

-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ func computeKubeControllerManagerArgs(kubeconfigFile, saPrivateKeyFile, saRootCA
2121
"-tokencleaner",
2222
// we have to configure this separately until it is generic
2323
"-horizontalpodautoscaling",
24-
// we carry patches on this. For now....
25-
"-serviceaccount-token",
2624
}
2725
}
2826
if _, ok := cmdLineArgs["service-account-private-key-file"]; !ok {

pkg/cmd/server/start/start_master.go

+23-45
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@ import (
66
"io"
77
"io/ioutil"
88
"net"
9-
"net/http"
109
"os"
1110
"path"
1211
"path/filepath"
1312
"strings"
14-
"time"
1513

1614
"github.com/coreos/go-systemd/daemon"
1715
"github.com/golang/glog"
@@ -21,7 +19,6 @@ import (
2119

2220
kerrors "k8s.io/apimachinery/pkg/api/errors"
2321
"k8s.io/apimachinery/pkg/util/sets"
24-
"k8s.io/apimachinery/pkg/util/wait"
2522
utilwait "k8s.io/apimachinery/pkg/util/wait"
2623
clientgoclientset "k8s.io/client-go/kubernetes"
2724
v1core "k8s.io/client-go/kubernetes/typed/core/v1"
@@ -431,19 +428,34 @@ func (m *Master) Start() error {
431428
go runEmbeddedScheduler(m.config.MasterClients.OpenShiftLoopbackKubeConfig, m.config.KubernetesMasterConfig.SchedulerConfigFile, m.config.KubernetesMasterConfig.SchedulerArguments)
432429

433430
go func() {
434-
kubeControllerConfigBytes, err := configapilatest.WriteYAML(m.config)
431+
kubeControllerConfigShallowCopy := *m.config
432+
// this creates using 0700
433+
kubeControllerConfigDir, err := ioutil.TempDir("", "openshift-kube-controller-manager-config-")
435434
if err != nil {
436435
glog.Fatal(err)
437436
}
438-
// this creates using 0600
439-
kubeControllerConfigFile, err := ioutil.TempFile("", "openshift-kube-controler-manager-config.yaml")
437+
defer func() {
438+
os.RemoveAll(kubeControllerConfigDir)
439+
}()
440+
if m.config.ControllerConfig.ServiceServingCert.Signer != nil && len(m.config.ControllerConfig.ServiceServingCert.Signer.CertFile) > 0 {
441+
caBytes, err := ioutil.ReadFile(m.config.ControllerConfig.ServiceServingCert.Signer.CertFile)
442+
if err != nil {
443+
glog.Fatal(err)
444+
}
445+
serviceServingCertSignerCAFile := path.Join(kubeControllerConfigDir, "service-signer.crt")
446+
if err := ioutil.WriteFile(serviceServingCertSignerCAFile, caBytes, 0644); err != nil {
447+
glog.Fatal(err)
448+
}
449+
450+
// we need to tweak the master config file with a relative ref, but to do that we need to copy it
451+
kubeControllerConfigShallowCopy.ControllerConfig.ServiceServingCert.Signer = &configapi.CertInfo{CertFile: "service-signer.crt"}
452+
}
453+
kubeControllerConfigBytes, err := configapilatest.WriteYAML(&kubeControllerConfigShallowCopy)
440454
if err != nil {
441455
glog.Fatal(err)
442456
}
443-
defer func() {
444-
os.Remove(kubeControllerConfigFile.Name())
445-
}()
446-
if err := ioutil.WriteFile(kubeControllerConfigFile.Name(), kubeControllerConfigBytes, 0644); err != nil {
457+
masterConfigFile := path.Join(kubeControllerConfigDir, "master-config.yaml")
458+
if err := ioutil.WriteFile(masterConfigFile, kubeControllerConfigBytes, 0644); err != nil {
447459
glog.Fatal(err)
448460
}
449461

@@ -452,7 +464,7 @@ func (m *Master) Start() error {
452464
m.config.ServiceAccountConfig.PrivateKeyFile,
453465
m.config.ServiceAccountConfig.MasterCA,
454466
m.config.KubernetesMasterConfig.PodEvictionTimeout,
455-
kubeControllerConfigFile.Name(),
467+
masterConfigFile,
456468
m.config.VolumeConfig.DynamicProvisioningEnabled,
457469
)
458470
}()
@@ -602,40 +614,6 @@ func startControllers(options configapi.MasterConfig, allocationController origi
602614
return err
603615
}
604616

605-
// We need to start the serviceaccount-tokens controller first as it provides token
606-
// generation for other controllers.
607-
startSATokenController := openshiftControllerConfig.ServiceAccountContentControllerInit()
608-
if enabled, err := startSATokenController(controllerContext); err != nil {
609-
return fmt.Errorf("Error starting serviceaccount-token controller: %v", err)
610-
} else if !enabled {
611-
glog.Warningf("Skipping serviceaccount-token controller")
612-
} else {
613-
glog.Infof("Started serviceaccount-token controller")
614-
}
615-
616-
// The service account controllers require informers in order to create service account tokens
617-
// for other controllers, which means we need to start their informers (which use the privileged
618-
// loopback client) before the other controllers will run.
619-
controllerContext.ExternalKubeInformers.Start(controllerContext.Stop)
620-
621-
// right now we have controllers which are relying on the ability to make requests before the bootstrap policy is in place
622-
// In 3.7, we will be fixed by the post start hook that prevents readiness unless policy is in place
623-
// for 3.6, just make sure we don't proceed until the garbage collector can hit discovery
624-
// wait for bootstrap permissions to be established. This check isn't perfect, but it ensures that at least the controllers checking discovery can succeed
625-
gcClientset := controllerContext.ClientBuilder.ClientOrDie("generic-garbage-collector")
626-
err = wait.PollImmediate(500*time.Millisecond, 30*time.Second, func() (bool, error) {
627-
result := gcClientset.Discovery().RESTClient().Get().AbsPath("/apis").Do()
628-
var statusCode int
629-
result.StatusCode(&statusCode)
630-
if statusCode >= http.StatusOK && statusCode < http.StatusMultipleChoices {
631-
return true, nil
632-
}
633-
return false, nil
634-
})
635-
if err != nil {
636-
return err
637-
}
638-
639617
// the service account passed for the recyclable volume plugins needs to exist. We want to do this via the init function, but its a kube init function
640618
// for the rebase, create that service account here
641619
// TODO make this a lot cleaner

test/util/server/server.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ func StartConfiguredMasterAPI(masterConfig *configapi.MasterConfig) (string, err
424424
if masterConfig.KubernetesMasterConfig.ControllerArguments == nil {
425425
masterConfig.KubernetesMasterConfig.ControllerArguments = map[string][]string{}
426426
}
427-
masterConfig.KubernetesMasterConfig.ControllerArguments["controllers"] = append(masterConfig.KubernetesMasterConfig.ControllerArguments["controllers"], "clusterrole-aggregation")
427+
masterConfig.KubernetesMasterConfig.ControllerArguments["controllers"] = append(masterConfig.KubernetesMasterConfig.ControllerArguments["controllers"], "serviceaccount-token", "clusterrole-aggregation")
428428

429429
return StartConfiguredMasterWithOptions(masterConfig)
430430
}

0 commit comments

Comments
 (0)