2015-01-30 23:31:36 +00:00
/ *
2016-06-03 00:25:58 +00:00
Copyright 2014 The Kubernetes Authors .
2015-01-30 23:31:36 +00:00
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 .
* /
2015-02-08 04:07:00 +00:00
// Package app implements a server that runs a set of active
2015-01-30 23:31:36 +00:00
// components. This includes replication controllers, service endpoints and
// nodes.
2015-06-11 13:13:19 +00:00
//
2015-02-08 04:07:00 +00:00
package app
2015-01-30 23:31:36 +00:00
import (
2015-06-23 22:43:59 +00:00
"fmt"
"io/ioutil"
2015-10-06 09:12:00 +00:00
"math/rand"
2015-01-30 23:31:36 +00:00
"net"
"net/http"
2015-03-13 15:44:11 +00:00
"net/http/pprof"
2015-11-04 23:22:11 +00:00
"os"
2015-01-30 23:31:36 +00:00
"strconv"
"time"
2015-12-24 23:59:05 +00:00
"k8s.io/kubernetes/cmd/kube-controller-manager/app/options"
2015-11-04 23:22:11 +00:00
"k8s.io/kubernetes/pkg/api"
2016-11-18 20:50:17 +00:00
"k8s.io/kubernetes/pkg/api/v1"
2016-09-13 03:28:49 +00:00
"k8s.io/kubernetes/pkg/apimachinery/registered"
2016-08-10 00:43:38 +00:00
"k8s.io/kubernetes/pkg/apis/batch"
2016-11-18 20:50:17 +00:00
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
v1core "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5/typed/core/v1"
2015-11-04 23:22:11 +00:00
"k8s.io/kubernetes/pkg/client/leaderelection"
2016-09-15 19:17:18 +00:00
"k8s.io/kubernetes/pkg/client/leaderelection/resourcelock"
2015-11-04 23:22:11 +00:00
"k8s.io/kubernetes/pkg/client/record"
2016-02-12 18:58:43 +00:00
"k8s.io/kubernetes/pkg/client/restclient"
2016-11-21 20:00:20 +00:00
"k8s.io/kubernetes/pkg/client/typed/discovery"
2016-03-03 04:34:18 +00:00
"k8s.io/kubernetes/pkg/client/typed/dynamic"
2015-08-13 19:01:50 +00:00
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/cloudprovider"
2015-11-11 21:19:39 +00:00
"k8s.io/kubernetes/pkg/controller"
2016-05-16 02:18:18 +00:00
certcontroller "k8s.io/kubernetes/pkg/controller/certificates"
2016-11-01 22:46:23 +00:00
"k8s.io/kubernetes/pkg/controller/cronjob"
2015-08-27 17:18:01 +00:00
"k8s.io/kubernetes/pkg/controller/daemon"
2015-09-03 00:02:22 +00:00
"k8s.io/kubernetes/pkg/controller/deployment"
2016-05-13 22:51:05 +00:00
"k8s.io/kubernetes/pkg/controller/disruption"
2015-10-10 03:58:57 +00:00
endpointcontroller "k8s.io/kubernetes/pkg/controller/endpoint"
2016-05-26 06:05:50 +00:00
"k8s.io/kubernetes/pkg/controller/garbagecollector"
2016-07-02 06:46:00 +00:00
"k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly"
2016-09-14 18:35:38 +00:00
"k8s.io/kubernetes/pkg/controller/informers"
2015-08-27 12:19:35 +00:00
"k8s.io/kubernetes/pkg/controller/job"
2015-10-10 03:58:57 +00:00
namespacecontroller "k8s.io/kubernetes/pkg/controller/namespace"
nodecontroller "k8s.io/kubernetes/pkg/controller/node"
2016-04-25 19:24:40 +00:00
petset "k8s.io/kubernetes/pkg/controller/petset"
2015-09-10 13:10:07 +00:00
"k8s.io/kubernetes/pkg/controller/podautoscaler"
"k8s.io/kubernetes/pkg/controller/podautoscaler/metrics"
2016-06-06 22:43:57 +00:00
"k8s.io/kubernetes/pkg/controller/podgc"
2016-01-19 00:06:57 +00:00
replicaset "k8s.io/kubernetes/pkg/controller/replicaset"
2015-10-10 03:58:57 +00:00
replicationcontroller "k8s.io/kubernetes/pkg/controller/replication"
resourcequotacontroller "k8s.io/kubernetes/pkg/controller/resourcequota"
routecontroller "k8s.io/kubernetes/pkg/controller/route"
servicecontroller "k8s.io/kubernetes/pkg/controller/service"
2015-12-24 21:54:40 +00:00
serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount"
2016-07-02 01:50:25 +00:00
"k8s.io/kubernetes/pkg/controller/volume/attachdetach"
persistentvolumecontroller "k8s.io/kubernetes/pkg/controller/volume/persistentvolume"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/healthz"
2016-02-22 16:15:09 +00:00
quotainstall "k8s.io/kubernetes/pkg/quota/install"
2016-11-21 02:55:31 +00:00
"k8s.io/kubernetes/pkg/runtime/schema"
2016-07-02 06:46:00 +00:00
"k8s.io/kubernetes/pkg/runtime/serializer"
2015-12-24 21:54:40 +00:00
"k8s.io/kubernetes/pkg/serviceaccount"
2016-09-16 15:52:29 +00:00
certutil "k8s.io/kubernetes/pkg/util/cert"
2016-02-02 02:09:02 +00:00
"k8s.io/kubernetes/pkg/util/configz"
2015-10-28 06:46:44 +00:00
"k8s.io/kubernetes/pkg/util/wait"
2015-04-18 13:31:24 +00:00
2015-01-30 23:31:36 +00:00
"github.com/golang/glog"
2015-04-22 14:46:03 +00:00
"github.com/prometheus/client_golang/prometheus"
2015-10-12 14:33:39 +00:00
"github.com/spf13/cobra"
2015-01-30 23:31:36 +00:00
"github.com/spf13/pflag"
)
2016-03-30 14:07:30 +00:00
const (
// Jitter used when starting controller managers
ControllerStartJitter = 1.0
)
2015-10-12 14:33:39 +00:00
// NewControllerManagerCommand creates a *cobra.Command object with default parameters
func NewControllerManagerCommand ( ) * cobra . Command {
2015-12-24 23:59:05 +00:00
s := options . NewCMServer ( )
2015-10-12 14:33:39 +00:00
s . AddFlags ( pflag . CommandLine )
cmd := & cobra . Command {
Use : "kube-controller-manager" ,
Long : ` The Kubernetes controller manager is a daemon that embeds
the core control loops shipped with Kubernetes . In applications of robotics and
automation , a control loop is a non - terminating loop that regulates the state of
the system . In Kubernetes , a controller is a control loop that watches the shared
state of the cluster through the apiserver and makes changes attempting to move the
current state towards the desired state . Examples of controllers that ship with
Kubernetes today are the replication controller , endpoints controller , namespace
controller , and serviceaccounts controller . ` ,
Run : func ( cmd * cobra . Command , args [ ] string ) {
} ,
}
return cmd
}
2015-12-24 23:59:05 +00:00
func ResyncPeriod ( s * options . CMServer ) func ( ) time . Duration {
return func ( ) time . Duration {
factor := rand . Float64 ( ) + 1
return time . Duration ( float64 ( s . MinResyncPeriod . Nanoseconds ( ) ) * factor )
}
2015-10-06 09:12:00 +00:00
}
2015-01-30 23:31:36 +00:00
// Run runs the CMServer. This should never exit.
2015-12-24 23:59:05 +00:00
func Run ( s * options . CMServer ) error {
2016-02-02 02:09:02 +00:00
if c , err := configz . New ( "componentconfig" ) ; err == nil {
c . Set ( s . KubeControllerManagerConfiguration )
} else {
glog . Errorf ( "unable to register configz: %s" , err )
}
2015-11-06 18:34:49 +00:00
kubeconfig , err := clientcmd . BuildConfigFromFlags ( s . Master , s . Kubeconfig )
2015-04-17 07:18:07 +00:00
if err != nil {
return err
}
2016-04-19 07:35:32 +00:00
kubeconfig . ContentConfig . ContentType = s . ContentType
2015-10-12 15:56:15 +00:00
// Override kubeconfig qps/burst settings from flags
2015-10-20 12:33:48 +00:00
kubeconfig . QPS = s . KubeAPIQPS
2016-04-27 04:35:14 +00:00
kubeconfig . Burst = int ( s . KubeAPIBurst )
2016-09-20 13:43:11 +00:00
kubeClient , err := clientset . NewForConfig ( restclient . AddUserAgent ( kubeconfig , "controller-manager" ) )
2015-01-30 23:31:36 +00:00
if err != nil {
glog . Fatalf ( "Invalid API configuration: %v" , err )
}
2016-09-26 07:46:59 +00:00
leaderElectionClient := clientset . NewForConfigOrDie ( restclient . AddUserAgent ( kubeconfig , "leader-election" ) )
2015-01-30 23:31:36 +00:00
2015-03-13 15:44:11 +00:00
go func ( ) {
2015-04-22 14:46:03 +00:00
mux := http . NewServeMux ( )
healthz . InstallHandler ( mux )
2015-03-13 15:44:11 +00:00
if s . EnableProfiling {
mux . HandleFunc ( "/debug/pprof/" , pprof . Index )
mux . HandleFunc ( "/debug/pprof/profile" , pprof . Profile )
mux . HandleFunc ( "/debug/pprof/symbol" , pprof . Symbol )
}
2016-07-21 11:27:09 +00:00
configz . InstallHandler ( mux )
2015-04-22 14:46:03 +00:00
mux . Handle ( "/metrics" , prometheus . Handler ( ) )
server := & http . Server {
2016-04-27 04:35:14 +00:00
Addr : net . JoinHostPort ( s . Address , strconv . Itoa ( int ( s . Port ) ) ) ,
2015-04-22 14:46:03 +00:00
Handler : mux ,
}
glog . Fatal ( server . ListenAndServe ( ) )
2015-03-13 15:44:11 +00:00
} ( )
2015-01-30 23:31:36 +00:00
2016-06-21 16:13:23 +00:00
eventBroadcaster := record . NewBroadcaster ( )
eventBroadcaster . StartLogging ( glog . Infof )
2016-11-18 20:50:17 +00:00
eventBroadcaster . StartRecordingToSink ( & v1core . EventSinkImpl { Interface : kubeClient . Core ( ) . Events ( "" ) } )
recorder := eventBroadcaster . NewRecorder ( v1 . EventSource { Component : "controller-manager" } )
2016-06-21 16:13:23 +00:00
2015-11-04 23:22:11 +00:00
run := func ( stop <- chan struct { } ) {
2016-09-22 19:53:08 +00:00
rootClientBuilder := controller . SimpleControllerClientBuilder {
ClientConfig : kubeconfig ,
}
var clientBuilder controller . ControllerClientBuilder
2016-11-01 13:27:35 +00:00
if len ( s . ServiceAccountKeyFile ) > 0 && s . UseServiceAccountCredentials {
2016-09-22 19:53:08 +00:00
clientBuilder = controller . SAControllerClientBuilder {
ClientConfig : restclient . AnonymousClientConfig ( kubeconfig ) ,
CoreClient : kubeClient . Core ( ) ,
Namespace : "kube-system" ,
}
} else {
clientBuilder = rootClientBuilder
}
2016-11-21 20:09:12 +00:00
err := StartControllers ( s , rootClientBuilder , clientBuilder , stop )
2015-11-04 23:22:11 +00:00
glog . Fatalf ( "error running controllers: %v" , err )
panic ( "unreachable" )
}
if ! s . LeaderElection . LeaderElect {
run ( nil )
panic ( "unreachable" )
}
id , err := os . Hostname ( )
if err != nil {
return err
}
2016-09-15 19:17:18 +00:00
// TODO: enable other lock types
rl := resourcelock . EndpointsLock {
2016-11-18 20:50:17 +00:00
EndpointsMeta : v1 . ObjectMeta {
2015-11-04 23:22:11 +00:00
Namespace : "kube-system" ,
Name : "kube-controller-manager" ,
} ,
2016-09-15 19:17:18 +00:00
Client : leaderElectionClient ,
LockConfig : resourcelock . ResourceLockConfig {
Identity : id ,
EventRecorder : recorder ,
} ,
}
leaderelection . RunOrDie ( leaderelection . LeaderElectionConfig {
Lock : & rl ,
2016-09-26 07:46:59 +00:00
LeaseDuration : s . LeaderElection . LeaseDuration . Duration ,
RenewDeadline : s . LeaderElection . RenewDeadline . Duration ,
RetryPeriod : s . LeaderElection . RetryPeriod . Duration ,
2015-11-04 23:22:11 +00:00
Callbacks : leaderelection . LeaderCallbacks {
OnStartedLeading : run ,
OnStoppedLeading : func ( ) {
glog . Fatalf ( "leaderelection lost" )
} ,
} ,
} )
panic ( "unreachable" )
}
2016-11-21 20:00:20 +00:00
// TODO: In general, any controller checking this needs to be dynamic so
// users don't have to restart their controller manager if they change the apiserver.
func getAvailableResources ( clientBuilder controller . ControllerClientBuilder ) ( map [ schema . GroupVersionResource ] bool , error ) {
var discoveryClient discovery . DiscoveryInterface
// If apiserver is not running we should wait for some time and fail only then. This is particularly
// important when we start apiserver and controller manager at the same time.
err := wait . PollImmediate ( time . Second , 10 * time . Second , func ( ) ( bool , error ) {
client , err := clientBuilder . Client ( "controller-discovery" )
if err != nil {
glog . Errorf ( "Failed to get api versions from server: %v" , err )
return false , nil
}
discoveryClient = client . Discovery ( )
return true , nil
} )
if err != nil {
2016-11-21 20:10:59 +00:00
return nil , fmt . Errorf ( "failed to get api versions from server: %v" , err )
2016-11-21 20:00:20 +00:00
}
resourceMap , err := discoveryClient . ServerResources ( )
if err != nil {
2016-11-21 20:10:59 +00:00
return nil , fmt . Errorf ( "failed to get supported resources from server: %v" , err )
2016-11-21 20:00:20 +00:00
}
allResources := map [ schema . GroupVersionResource ] bool { }
for _ , apiResourceList := range resourceMap {
version , err := schema . ParseGroupVersion ( apiResourceList . GroupVersion )
if err != nil {
return nil , err
}
for _ , apiResource := range apiResourceList . APIResources {
allResources [ version . WithResource ( apiResource . Name ) ] = true
}
}
return allResources , nil
}
2016-11-21 20:09:12 +00:00
func StartControllers ( s * options . CMServer , rootClientBuilder , clientBuilder controller . ControllerClientBuilder , stop <- chan struct { } ) error {
2016-11-21 20:13:22 +00:00
sharedInformers := informers . NewSharedInformerFactory ( rootClientBuilder . ClientOrDie ( "shared-informers" ) , nil , ResyncPeriod ( s ) ( ) )
2016-08-04 07:06:29 +00:00
2016-09-22 19:53:08 +00:00
// always start the SA token controller first using a full-power client, since it needs to mint tokens for the rest
if len ( s . ServiceAccountKeyFile ) > 0 {
privateKey , err := serviceaccount . ReadPrivateKey ( s . ServiceAccountKeyFile )
if err != nil {
2016-11-21 20:10:59 +00:00
return fmt . Errorf ( "error reading key for service account token controller: %v" , err )
2016-09-22 19:53:08 +00:00
} else {
var rootCA [ ] byte
if s . RootCAFile != "" {
rootCA , err = ioutil . ReadFile ( s . RootCAFile )
if err != nil {
return fmt . Errorf ( "error reading root-ca-file at %s: %v" , s . RootCAFile , err )
}
if _ , err := certutil . ParseCertsPEM ( rootCA ) ; err != nil {
return fmt . Errorf ( "error parsing root-ca-file at %s: %v" , s . RootCAFile , err )
}
} else {
2016-11-21 20:09:12 +00:00
rootCA = rootClientBuilder . ConfigOrDie ( "tokens-controller" ) . CAData
2016-09-22 19:53:08 +00:00
}
go serviceaccountcontroller . NewTokensController (
rootClientBuilder . ClientOrDie ( "tokens-controller" ) ,
serviceaccountcontroller . TokensControllerOptions {
TokenGenerator : serviceaccount . JWTTokenGenerator ( privateKey ) ,
RootCA : rootCA ,
} ,
2016-11-21 19:51:14 +00:00
) . Run ( int ( s . ConcurrentSATokenSyncs ) , stop )
2016-09-22 19:53:08 +00:00
time . Sleep ( wait . Jitter ( s . ControllerStartInterval . Duration , ControllerStartJitter ) )
}
}
2016-11-21 20:00:20 +00:00
availableResources , err := getAvailableResources ( clientBuilder )
if err != nil {
return err
}
2016-11-21 20:13:22 +00:00
go endpointcontroller . NewEndpointController ( sharedInformers . Pods ( ) . Informer ( ) , clientBuilder . ClientOrDie ( "endpoint-controller" ) ) .
2016-11-21 19:51:14 +00:00
Run ( int ( s . ConcurrentEndpointSyncs ) , stop )
2016-03-30 14:07:30 +00:00
time . Sleep ( wait . Jitter ( s . ControllerStartInterval . Duration , ControllerStartJitter ) )
2015-01-30 23:31:36 +00:00
2015-12-02 12:12:31 +00:00
go replicationcontroller . NewReplicationManager (
2016-08-04 07:06:29 +00:00
sharedInformers . Pods ( ) . Informer ( ) ,
2016-09-22 19:53:08 +00:00
clientBuilder . ClientOrDie ( "replication-controller" ) ,
2015-12-24 23:59:05 +00:00
ResyncPeriod ( s ) ,
2015-12-02 12:12:31 +00:00
replicationcontroller . BurstReplicas ,
2016-04-27 04:35:14 +00:00
int ( s . LookupCacheSizeForRC ) ,
2016-06-10 23:28:42 +00:00
s . EnableGarbageCollector ,
2016-11-21 19:51:14 +00:00
) . Run ( int ( s . ConcurrentRCSyncs ) , stop )
2016-03-30 14:07:30 +00:00
time . Sleep ( wait . Jitter ( s . ControllerStartInterval . Duration , ControllerStartJitter ) )
2015-01-30 23:31:36 +00:00
2016-11-21 20:13:22 +00:00
go podgc . NewPodGC ( clientBuilder . ClientOrDie ( "pod-garbage-collector" ) , sharedInformers . Pods ( ) . Informer ( ) ,
2016-11-21 19:51:14 +00:00
int ( s . TerminatedPodGCThreshold ) ) . Run ( stop )
2016-10-25 00:15:39 +00:00
time . Sleep ( wait . Jitter ( s . ControllerStartInterval . Duration , ControllerStartJitter ) )
2015-09-21 22:51:27 +00:00
2015-07-01 18:41:49 +00:00
cloud , err := cloudprovider . InitCloudProvider ( s . CloudProvider , s . CloudConfigFile )
if err != nil {
2016-11-21 20:10:59 +00:00
return fmt . Errorf ( "cloud provider could not be initialized: %v" , err )
2015-07-01 18:41:49 +00:00
}
2015-02-07 19:53:42 +00:00
2016-05-23 07:37:22 +00:00
_ , clusterCIDR , err := net . ParseCIDR ( s . ClusterCIDR )
if err != nil {
glog . Warningf ( "Unsuccessful parsing of cluster CIDR %v: %v" , s . ClusterCIDR , err )
}
_ , serviceCIDR , err := net . ParseCIDR ( s . ServiceCIDR )
if err != nil {
glog . Warningf ( "Unsuccessful parsing of service CIDR %v: %v" , s . ServiceCIDR , err )
}
2016-09-23 16:01:58 +00:00
nodeController , err := nodecontroller . NewNodeController (
sharedInformers . Pods ( ) , sharedInformers . Nodes ( ) , sharedInformers . DaemonSets ( ) ,
2016-11-21 20:13:22 +00:00
cloud , clientBuilder . ClientOrDie ( "node-controller" ) ,
2016-08-05 12:50:19 +00:00
s . PodEvictionTimeout . Duration , s . NodeEvictionRate , s . SecondaryNodeEvictionRate , s . LargeClusterSizeThreshold , s . UnhealthyZoneThreshold , s . NodeMonitorGracePeriod . Duration ,
2016-07-13 08:40:22 +00:00
s . NodeStartupGracePeriod . Duration , s . NodeMonitorPeriod . Duration , clusterCIDR , serviceCIDR ,
int ( s . NodeCIDRMaskSize ) , s . AllocateNodeCIDRs )
2016-07-16 18:52:51 +00:00
if err != nil {
2016-11-21 20:10:59 +00:00
return fmt . Errorf ( "failed to initialize nodecontroller: %v" , err )
2016-07-16 18:52:51 +00:00
}
2016-08-30 12:24:56 +00:00
nodeController . Run ( )
2016-03-30 14:07:30 +00:00
time . Sleep ( wait . Jitter ( s . ControllerStartInterval . Duration , ControllerStartJitter ) )
2015-01-30 23:31:36 +00:00
2016-11-21 20:13:22 +00:00
serviceController , err := servicecontroller . New ( cloud , clientBuilder . ClientOrDie ( "service-controller" ) , s . ClusterName )
2016-07-26 05:35:40 +00:00
if err != nil {
2015-03-24 17:32:43 +00:00
glog . Errorf ( "Failed to start service controller: %v" , err )
2016-07-26 05:35:40 +00:00
} else {
serviceController . Run ( int ( s . ConcurrentServiceSyncs ) )
2015-03-24 17:32:43 +00:00
}
2016-03-30 14:07:30 +00:00
time . Sleep ( wait . Jitter ( s . ControllerStartInterval . Duration , ControllerStartJitter ) )
2015-03-24 17:32:43 +00:00
2016-05-14 13:50:17 +00:00
if s . AllocateNodeCIDRs && s . ConfigureCloudRoutes {
2015-11-24 02:11:51 +00:00
if cloud == nil {
2016-05-14 13:50:17 +00:00
glog . Warning ( "configure-cloud-routes is set, but no cloud provider specified. Will not configure cloud provider routes." )
2015-07-26 00:02:23 +00:00
} else if routes , ok := cloud . Routes ( ) ; ! ok {
2016-05-14 13:50:17 +00:00
glog . Warning ( "configure-cloud-routes is set, but cloud provider does not support routes. Will not configure cloud provider routes." )
2015-07-26 00:02:23 +00:00
} else {
2016-11-21 20:13:22 +00:00
routeController := routecontroller . New ( routes , clientBuilder . ClientOrDie ( "route-controller" ) , s . ClusterName , clusterCIDR )
2016-08-31 08:19:53 +00:00
routeController . Run ( s . RouteReconciliationPeriod . Duration )
2016-03-30 14:07:30 +00:00
time . Sleep ( wait . Jitter ( s . ControllerStartInterval . Duration , ControllerStartJitter ) )
2015-05-15 21:49:26 +00:00
}
2016-07-21 10:31:28 +00:00
} else {
glog . Infof ( "Will not configure cloud provider routes for allocate-node-cidrs: %v, configure-cloud-routes: %v." , s . AllocateNodeCIDRs , s . ConfigureCloudRoutes )
2015-05-15 21:49:26 +00:00
}
2016-11-21 20:13:22 +00:00
resourceQuotaControllerClient := clientBuilder . ClientOrDie ( "resourcequota-controller" )
2016-10-14 17:44:20 +00:00
resourceQuotaRegistry := quotainstall . NewRegistry ( resourceQuotaControllerClient , sharedInformers )
2016-11-21 02:55:31 +00:00
groupKindsToReplenish := [ ] schema . GroupKind {
2016-02-22 16:15:09 +00:00
api . Kind ( "Pod" ) ,
api . Kind ( "Service" ) ,
api . Kind ( "ReplicationController" ) ,
api . Kind ( "PersistentVolumeClaim" ) ,
api . Kind ( "Secret" ) ,
2016-02-29 17:02:05 +00:00
api . Kind ( "ConfigMap" ) ,
2016-02-22 16:15:09 +00:00
}
resourceQuotaControllerOptions := & resourcequotacontroller . ResourceQuotaControllerOptions {
2016-03-07 07:20:32 +00:00
KubeClient : resourceQuotaControllerClient ,
ResyncPeriod : controller . StaticResyncPeriodFunc ( s . ResourceQuotaSyncPeriod . Duration ) ,
Registry : resourceQuotaRegistry ,
2016-10-14 17:44:20 +00:00
ControllerFactory : resourcequotacontroller . NewReplenishmentControllerFactory ( sharedInformers , resourceQuotaControllerClient ) ,
2016-03-07 07:20:32 +00:00
ReplenishmentResyncPeriod : ResyncPeriod ( s ) ,
GroupKindsToReplenish : groupKindsToReplenish ,
2016-02-22 16:15:09 +00:00
}
2016-11-21 19:51:14 +00:00
go resourcequotacontroller . NewResourceQuotaController ( resourceQuotaControllerOptions ) . Run ( int ( s . ConcurrentResourceQuotaSyncs ) , stop )
2016-03-30 14:07:30 +00:00
time . Sleep ( wait . Jitter ( s . ControllerStartInterval . Duration , ControllerStartJitter ) )
2015-01-30 23:31:36 +00:00
2016-09-13 03:28:49 +00:00
// TODO: should use a dynamic RESTMapper built from the discovery results.
restMapper := registered . RESTMapper ( )
2016-03-03 04:34:18 +00:00
// Find the list of namespaced resources via discovery that the namespace controller must manage
2016-11-21 20:13:22 +00:00
namespaceKubeClient := clientBuilder . ClientOrDie ( "namespace-controller" )
2016-11-21 20:09:12 +00:00
namespaceClientPool := dynamic . NewClientPool ( rootClientBuilder . ConfigOrDie ( "namespace-controller" ) , restMapper , dynamic . LegacyAPIPathResolverFunc )
2016-11-01 05:55:28 +00:00
// TODO: consider using a list-watch + cache here rather than polling
2016-11-17 13:19:03 +00:00
gvrFn := func ( ) ( map [ schema . GroupVersionResource ] struct { } , error ) {
resources , err := namespaceKubeClient . Discovery ( ) . ServerPreferredNamespacedResources ( )
if err != nil {
// best effort extraction
gvrs , _ := discovery . GroupVersionResources ( resources )
return gvrs , fmt . Errorf ( "failed to get supported namespaced resources: %v" , err )
}
gvrs , err := discovery . GroupVersionResources ( resources )
if err != nil {
return gvrs , fmt . Errorf ( "failed to parse supported namespaced resources: %v" , err )
}
return gvrs , nil
}
2016-11-01 05:55:28 +00:00
rsrcs , err := namespaceKubeClient . Discovery ( ) . ServerResources ( )
2016-03-03 04:34:18 +00:00
if err != nil {
2016-11-21 20:10:59 +00:00
return fmt . Errorf ( "failed to get group version resources: %v" , err )
2016-11-01 05:55:28 +00:00
}
2016-11-17 13:19:03 +00:00
tprFound := false
searchThirdPartyResource :
2016-11-01 05:55:28 +00:00
for _ , rsrcList := range rsrcs {
for ix := range rsrcList . APIResources {
rsrc := & rsrcList . APIResources [ ix ]
if rsrc . Kind == "ThirdPartyResource" {
2016-11-17 13:19:03 +00:00
tprFound = true
break searchThirdPartyResource
2016-11-01 05:55:28 +00:00
}
}
}
2016-11-17 13:19:03 +00:00
if ! tprFound {
gvr , err := gvrFn ( )
2016-11-01 05:55:28 +00:00
if err != nil {
2016-11-21 20:10:59 +00:00
return fmt . Errorf ( "failed to get resources: %v" , err )
2016-11-01 05:55:28 +00:00
}
2016-11-17 13:19:03 +00:00
gvrFn = func ( ) ( map [ schema . GroupVersionResource ] struct { } , error ) {
2016-11-01 05:55:28 +00:00
return gvr , nil
}
2016-03-03 04:34:18 +00:00
}
2016-11-18 20:50:17 +00:00
namespaceController := namespacecontroller . NewNamespaceController ( namespaceKubeClient , namespaceClientPool , gvrFn , s . NamespaceSyncPeriod . Duration , v1 . FinalizerKubernetes )
2016-11-21 19:51:14 +00:00
go namespaceController . Run ( int ( s . ConcurrentNamespaceSyncs ) , stop )
2016-03-30 14:07:30 +00:00
time . Sleep ( wait . Jitter ( s . ControllerStartInterval . Duration , ControllerStartJitter ) )
2015-10-12 21:23:50 +00:00
2016-11-21 20:00:20 +00:00
if availableResources [ schema . GroupVersionResource { Group : "extensions" , Version : "v1beta1" , Resource : "daemonsets" } ] {
2016-11-21 20:13:22 +00:00
go daemon . NewDaemonSetsController ( sharedInformers . DaemonSets ( ) , sharedInformers . Pods ( ) , sharedInformers . Nodes ( ) , clientBuilder . ClientOrDie ( "daemon-set-controller" ) , int ( s . LookupCacheSizeForDaemonSet ) ) .
2016-11-21 20:00:20 +00:00
Run ( int ( s . ConcurrentDaemonSetSyncs ) , stop )
time . Sleep ( wait . Jitter ( s . ControllerStartInterval . Duration , ControllerStartJitter ) )
}
2015-10-12 21:23:50 +00:00
2016-11-21 20:00:20 +00:00
if availableResources [ schema . GroupVersionResource { Group : "extensions" , Version : "v1beta1" , Resource : "jobs" } ] {
glog . Infof ( "Starting job controller" )
2016-11-21 20:13:22 +00:00
go job . NewJobController ( sharedInformers . Pods ( ) . Informer ( ) , sharedInformers . Jobs ( ) , clientBuilder . ClientOrDie ( "job-controller" ) ) .
2016-11-21 20:00:20 +00:00
Run ( int ( s . ConcurrentJobSyncs ) , stop )
time . Sleep ( wait . Jitter ( s . ControllerStartInterval . Duration , ControllerStartJitter ) )
}
2015-10-02 21:42:18 +00:00
2016-11-21 20:00:20 +00:00
if availableResources [ schema . GroupVersionResource { Group : "extensions" , Version : "v1beta1" , Resource : "deployments" } ] {
glog . Infof ( "Starting deployment controller" )
2016-11-21 20:13:22 +00:00
go deployment . NewDeploymentController ( sharedInformers . Deployments ( ) , sharedInformers . ReplicaSets ( ) , sharedInformers . Pods ( ) , clientBuilder . ClientOrDie ( "deployment-controller" ) ) .
2016-11-21 20:00:20 +00:00
Run ( int ( s . ConcurrentDeploymentSyncs ) , stop )
time . Sleep ( wait . Jitter ( s . ControllerStartInterval . Duration , ControllerStartJitter ) )
}
2016-01-19 00:06:57 +00:00
2016-11-21 20:00:20 +00:00
if availableResources [ schema . GroupVersionResource { Group : "extensions" , Version : "v1beta1" , Resource : "replicasets" } ] {
glog . Infof ( "Starting ReplicaSet controller" )
2016-11-21 20:13:22 +00:00
go replicaset . NewReplicaSetController ( sharedInformers . ReplicaSets ( ) , sharedInformers . Pods ( ) , clientBuilder . ClientOrDie ( "replicaset-controller" ) , replicaset . BurstReplicas , int ( s . LookupCacheSizeForRS ) , s . EnableGarbageCollector ) .
2016-11-21 20:00:20 +00:00
Run ( int ( s . ConcurrentRSSyncs ) , stop )
time . Sleep ( wait . Jitter ( s . ControllerStartInterval . Duration , ControllerStartJitter ) )
2015-09-03 00:02:22 +00:00
}
2015-09-03 14:50:53 +00:00
2016-11-21 20:00:20 +00:00
if availableResources [ schema . GroupVersionResource { Group : "autoscaling" , Version : "v1" , Resource : "horizontalpodautoscalers" } ] {
glog . Infof ( "Starting horizontal pod autoscaler controller." )
2016-11-21 20:13:22 +00:00
hpaClient := clientBuilder . ClientOrDie ( "horizontal-pod-autoscaler" )
2016-11-21 20:00:20 +00:00
metricsClient := metrics . NewHeapsterMetricsClient (
hpaClient ,
metrics . DefaultHeapsterNamespace ,
metrics . DefaultHeapsterScheme ,
metrics . DefaultHeapsterService ,
metrics . DefaultHeapsterPort ,
)
replicaCalc := podautoscaler . NewReplicaCalculator ( metricsClient , hpaClient . Core ( ) )
go podautoscaler . NewHorizontalController ( hpaClient . Core ( ) , hpaClient . Extensions ( ) , hpaClient . Autoscaling ( ) , replicaCalc , s . HorizontalPodAutoscalerSyncPeriod . Duration ) .
Run ( stop )
time . Sleep ( wait . Jitter ( s . ControllerStartInterval . Duration , ControllerStartJitter ) )
2016-11-04 09:00:56 +00:00
}
2016-11-21 20:00:20 +00:00
if availableResources [ schema . GroupVersionResource { Group : "policy" , Version : "v1beta1" , Resource : "poddisruptionbudgets" } ] {
glog . Infof ( "Starting disruption controller" )
2016-11-21 20:13:22 +00:00
go disruption . NewDisruptionController ( sharedInformers . Pods ( ) . Informer ( ) , clientBuilder . ClientOrDie ( "disruption-controller" ) ) . Run ( stop )
2016-11-21 20:00:20 +00:00
time . Sleep ( wait . Jitter ( s . ControllerStartInterval . Duration , ControllerStartJitter ) )
2016-05-13 22:51:05 +00:00
}
2016-11-21 20:00:20 +00:00
if availableResources [ schema . GroupVersionResource { Group : "apps" , Version : "v1beta1" , Resource : "statefulsets" } ] {
glog . Infof ( "Starting StatefulSet controller" )
resyncPeriod := ResyncPeriod ( s ) ( )
go petset . NewStatefulSetController (
sharedInformers . Pods ( ) . Informer ( ) ,
2016-11-21 20:13:22 +00:00
clientBuilder . ClientOrDie ( "statefulset-controller" ) ,
2016-11-21 20:00:20 +00:00
resyncPeriod ,
) . Run ( 1 , stop )
time . Sleep ( wait . Jitter ( s . ControllerStartInterval . Duration , ControllerStartJitter ) )
2016-04-25 19:24:40 +00:00
}
2016-11-21 20:00:20 +00:00
if availableResources [ schema . GroupVersionResource { Group : "batch" , Version : "v2alpha1" , Resource : "cronjobs" } ] {
glog . Infof ( "Starting cronjob controller" )
// TODO: this is a temp fix for allowing kubeClient list v2alpha1 sj, should switch to using clientset
2016-11-21 20:09:12 +00:00
cronjobConfig := rootClientBuilder . ConfigOrDie ( "cronjob-controller" )
cronjobConfig . ContentConfig . GroupVersion = & schema . GroupVersion { Group : batch . GroupName , Version : "v2alpha1" }
go cronjob . NewCronJobController ( clientset . NewForConfigOrDie ( cronjobConfig ) ) . Run ( stop )
2016-11-21 20:00:20 +00:00
time . Sleep ( wait . Jitter ( s . ControllerStartInterval . Duration , ControllerStartJitter ) )
2016-05-20 07:53:39 +00:00
}
2016-08-18 08:36:50 +00:00
alphaProvisioner , err := NewAlphaVolumeProvisioner ( cloud , s . VolumeConfiguration )
if err != nil {
2016-11-21 20:10:59 +00:00
return fmt . Errorf ( "an backward-compatible provisioner could not be created: %v, but one was expected. Provisioning will not work. This functionality is considered an early Alpha version." , err )
2016-08-18 08:36:50 +00:00
}
2016-09-26 12:15:25 +00:00
params := persistentvolumecontroller . ControllerParameters {
2016-11-21 20:13:22 +00:00
KubeClient : clientBuilder . ClientOrDie ( "persistent-volume-binder" ) ,
2016-09-26 12:15:25 +00:00
SyncPeriod : s . PVClaimBinderSyncPeriod . Duration ,
AlphaProvisioner : alphaProvisioner ,
VolumePlugins : ProbeControllerVolumePlugins ( cloud , s . VolumeConfiguration ) ,
Cloud : cloud ,
ClusterName : s . ClusterName ,
EnableDynamicProvisioning : s . VolumeConfiguration . EnableDynamicProvisioning ,
}
volumeController := persistentvolumecontroller . NewController ( params )
2016-11-21 19:51:14 +00:00
volumeController . Run ( stop )
2016-03-30 14:07:30 +00:00
time . Sleep ( wait . Jitter ( s . ControllerStartInterval . Duration , ControllerStartJitter ) )
2015-04-16 17:26:08 +00:00
2016-04-30 06:36:27 +00:00
attachDetachController , attachDetachControllerErr :=
2016-07-02 01:50:25 +00:00
attachdetach . NewAttachDetachController (
2016-11-21 20:13:22 +00:00
clientBuilder . ClientOrDie ( "attachdetach-controller" ) ,
2016-08-04 07:06:29 +00:00
sharedInformers . Pods ( ) . Informer ( ) ,
sharedInformers . Nodes ( ) . Informer ( ) ,
sharedInformers . PersistentVolumeClaims ( ) . Informer ( ) ,
sharedInformers . PersistentVolumes ( ) . Informer ( ) ,
2016-04-30 06:36:27 +00:00
cloud ,
2016-11-21 19:51:14 +00:00
ProbeAttachableVolumePlugins ( s . VolumeConfiguration ) )
2016-04-30 06:36:27 +00:00
if attachDetachControllerErr != nil {
2016-11-21 20:10:59 +00:00
return fmt . Errorf ( "failed to start attach/detach controller: %v" , attachDetachControllerErr )
2016-04-30 06:36:27 +00:00
}
2016-11-21 19:51:14 +00:00
go attachDetachController . Run ( stop )
2016-07-21 10:31:28 +00:00
time . Sleep ( wait . Jitter ( s . ControllerStartInterval . Duration , ControllerStartJitter ) )
2016-04-30 06:36:27 +00:00
2016-11-21 20:00:20 +00:00
if availableResources [ schema . GroupVersionResource { Group : "certificates.k8s.io" , Version : "v1alpha1" , Resource : "certificatesigningrequests" } ] {
glog . Infof ( "Starting certificate request controller" )
resyncPeriod := ResyncPeriod ( s ) ( )
2016-11-19 23:58:46 +00:00
c := clientBuilder . ClientOrDie ( "certificate-controller" )
2016-11-21 20:00:20 +00:00
certController , err := certcontroller . NewCertificateController (
2016-11-19 23:58:46 +00:00
c ,
2016-11-21 20:00:20 +00:00
resyncPeriod ,
s . ClusterSigningCertFile ,
s . ClusterSigningKeyFile ,
2016-11-19 23:58:46 +00:00
certcontroller . NewGroupApprover ( c . Certificates ( ) . CertificateSigningRequests ( ) , s . ApproveAllKubeletCSRsForGroup ) ,
2016-11-21 20:00:20 +00:00
)
if err != nil {
glog . Errorf ( "Failed to start certificate controller: %v" , err )
} else {
go certController . Run ( 1 , stop )
2016-05-16 02:18:18 +00:00
}
2016-11-21 20:00:20 +00:00
time . Sleep ( wait . Jitter ( s . ControllerStartInterval . Duration , ControllerStartJitter ) )
2016-05-16 02:18:18 +00:00
}
2016-10-20 19:08:49 +00:00
go serviceaccountcontroller . NewServiceAccountsController (
sharedInformers . ServiceAccounts ( ) , sharedInformers . Namespaces ( ) ,
2016-11-21 20:13:22 +00:00
clientBuilder . ClientOrDie ( "service-account-controller" ) ,
2015-12-24 21:54:40 +00:00
serviceaccountcontroller . DefaultServiceAccountsControllerOptions ( ) ,
2016-10-20 19:08:49 +00:00
) . Run ( 1 , stop )
2016-03-30 14:07:30 +00:00
time . Sleep ( wait . Jitter ( s . ControllerStartInterval . Duration , ControllerStartJitter ) )
2015-04-21 03:25:56 +00:00
2016-05-26 06:05:50 +00:00
if s . EnableGarbageCollector {
2016-11-21 20:13:22 +00:00
gcClientset := clientBuilder . ClientOrDie ( "generic-garbage-collector" )
2016-11-17 13:19:03 +00:00
preferredResources , err := gcClientset . Discovery ( ) . ServerPreferredResources ( )
2016-05-26 06:05:50 +00:00
if err != nil {
2016-11-21 20:10:59 +00:00
return fmt . Errorf ( "failed to get supported resources from server: %v" , err )
2016-05-26 06:05:50 +00:00
}
2016-11-17 13:19:03 +00:00
groupVersionResources , err := discovery . GroupVersionResources ( preferredResources )
if err != nil {
glog . Fatalf ( "Failed to parse supported resources from server: %v" , err )
}
2016-09-13 03:28:49 +00:00
2016-11-21 20:09:12 +00:00
config := rootClientBuilder . ConfigOrDie ( "generic-garbage-collector" )
2016-07-02 06:46:00 +00:00
config . ContentConfig . NegotiatedSerializer = serializer . DirectCodecFactory { CodecFactory : metaonly . NewMetadataCodecFactory ( ) }
2016-09-13 03:28:49 +00:00
metaOnlyClientPool := dynamic . NewClientPool ( config , restMapper , dynamic . LegacyAPIPathResolverFunc )
2016-10-12 20:55:28 +00:00
config . ContentConfig = dynamic . ContentConfig ( )
2016-09-13 03:28:49 +00:00
clientPool := dynamic . NewClientPool ( config , restMapper , dynamic . LegacyAPIPathResolverFunc )
garbageCollector , err := garbagecollector . NewGarbageCollector ( metaOnlyClientPool , clientPool , restMapper , groupVersionResources )
2016-05-26 06:05:50 +00:00
if err != nil {
2016-07-21 11:36:07 +00:00
glog . Errorf ( "Failed to start the generic garbage collector: %v" , err )
2016-05-26 06:05:50 +00:00
} else {
2016-07-01 07:26:35 +00:00
workers := int ( s . ConcurrentGCSyncs )
2016-11-21 19:51:14 +00:00
go garbageCollector . Run ( workers , stop )
2016-05-26 06:05:50 +00:00
}
}
2016-08-04 07:06:29 +00:00
sharedInformers . Start ( stop )
2016-04-14 18:00:52 +00:00
2015-01-30 23:31:36 +00:00
select { }
}