diff --git a/cmd/kubeadm/app/cmd/init.go b/cmd/kubeadm/app/cmd/init.go index cdb7a391aaf..8a25cef156b 100644 --- a/cmd/kubeadm/app/cmd/init.go +++ b/cmd/kubeadm/app/cmd/init.go @@ -173,18 +173,6 @@ func NewInit(cfgPath string, cfg *kubeadmapi.MasterConfiguration, skipPreFlight // Try to start the kubelet service in case it's inactive preflight.TryStartKubelet() - // validate version argument - ver, err := kubeadmutil.KubernetesReleaseVersion(cfg.KubernetesVersion) - if err != nil { - if cfg.KubernetesVersion != kubeadmapiext.DefaultKubernetesVersion { - return nil, err - } else { - ver = kubeadmapiext.DefaultKubernetesFallbackVersion - } - } - cfg.KubernetesVersion = ver - fmt.Println("[init] Using Kubernetes version:", ver) - fmt.Println("[init] Using Authorization mode:", cfg.AuthorizationMode) // Warn about the limitations with the current cloudprovider solution. if cfg.CloudProvider != "" { diff --git a/cmd/kubeadm/app/master/apiclient.go b/cmd/kubeadm/app/master/apiclient.go index cdbadd168bc..b72f948d85c 100644 --- a/cmd/kubeadm/app/master/apiclient.go +++ b/cmd/kubeadm/app/master/apiclient.go @@ -109,11 +109,11 @@ func WaitForAPI(client *clientset.Clientset) { cs, err := client.ComponentStatuses().List(v1.ListOptions{}) if err != nil { if apierrs.IsForbidden(err) { - fmt.Print("\r[apiclient] Waiting for the API server to create RBAC policies") + fmt.Println("[apiclient] Waiting for API server authorization") } return false, nil } - fmt.Println("\n[apiclient] RBAC policies created") + // TODO(phase2) must revisit this when we implement HA if len(cs.Items) < 3 { return false, nil diff --git a/cmd/kubeadm/app/master/manifests.go b/cmd/kubeadm/app/master/manifests.go index e5dc2e83c11..65e9dbd1409 100644 --- a/cmd/kubeadm/app/master/manifests.go +++ b/cmd/kubeadm/app/master/manifests.go @@ -82,7 +82,7 @@ func WriteStaticPodManifests(cfg *kubeadmapi.MasterConfiguration) error { kubeAPIServer: componentPod(api.Container{ Name: kubeAPIServer, Image: images.GetCoreImage(images.KubeAPIServerImage, cfg, kubeadmapi.GlobalEnvParams.HyperkubeImage), - Command: getAPIServerCommand(cfg), + Command: getAPIServerCommand(cfg, false), VolumeMounts: volumeMounts, LivenessProbe: componentProbe(8080, "/healthz"), Resources: componentResources("250m"), @@ -91,19 +91,17 @@ func WriteStaticPodManifests(cfg *kubeadmapi.MasterConfiguration) error { kubeControllerManager: componentPod(api.Container{ Name: kubeControllerManager, Image: images.GetCoreImage(images.KubeControllerManagerImage, cfg, kubeadmapi.GlobalEnvParams.HyperkubeImage), - Command: getControllerManagerCommand(cfg), + Command: getControllerManagerCommand(cfg, false), VolumeMounts: volumeMounts, LivenessProbe: componentProbe(10252, "/healthz"), Resources: componentResources("200m"), Env: getProxyEnvVars(), }, volumes...), kubeScheduler: componentPod(api.Container{ - Name: kubeScheduler, - Image: images.GetCoreImage(images.KubeSchedulerImage, cfg, kubeadmapi.GlobalEnvParams.HyperkubeImage), - // TODO: Using non-standard port here so self-hosted scheduler can come up: - // Use the regular port if this is not going to be a self-hosted deployment. - Command: getSchedulerCommand(cfg, 10260), - LivenessProbe: componentProbe(10260, "/healthz"), + Name: kubeScheduler, + Image: images.GetCoreImage(images.KubeSchedulerImage, cfg, kubeadmapi.GlobalEnvParams.HyperkubeImage), + Command: getSchedulerCommand(cfg, false), + LivenessProbe: componentProbe(10251, "/healthz"), Resources: componentResources("100m"), Env: getProxyEnvVars(), }), @@ -219,6 +217,23 @@ func pkiVolumeMount() api.VolumeMount { } } +func flockVolume() api.Volume { + return api.Volume{ + Name: "var-lock", + VolumeSource: api.VolumeSource{ + HostPath: &api.HostPathVolumeSource{Path: "/var/lock"}, + }, + } +} + +func flockVolumeMount() api.VolumeMount { + return api.VolumeMount{ + Name: "var-lock", + MountPath: "/var/lock", + ReadOnly: false, + } +} + func k8sVolume(cfg *kubeadmapi.MasterConfiguration) api.Volume { return api.Volume{ Name: "k8s", @@ -286,8 +301,15 @@ func getComponentBaseCommand(component string) []string { return []string{"kube-" + component} } -func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration) []string { - command := append(getComponentBaseCommand(apiServer), +func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration, selfHosted bool) []string { + var command []string + + // self-hosted apiserver needs to wait on a lock + if selfHosted { + command = []string{"/usr/bin/flock", "--exclusive", "--timeout=30", "/var/lock/api-server.lock"} + } + + command = append(getComponentBaseCommand(apiServer), "--insecure-bind-address=127.0.0.1", "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota", "--service-cluster-ip-range="+cfg.Networking.ServiceSubnet, @@ -312,7 +334,11 @@ func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration) []string { // Use first address we are given if len(cfg.API.AdvertiseAddresses) > 0 { - command = append(command, fmt.Sprintf("--advertise-address=%s", cfg.API.AdvertiseAddresses[0])) + if selfHosted { + command = append(command, "--advertise-address=$(POD_IP)") + } else { + command = append(command, fmt.Sprintf("--advertise-address=%s", cfg.API.AdvertiseAddresses[0])) + } } if len(cfg.KubernetesVersion) != 0 { @@ -361,8 +387,15 @@ func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration) []string { return command } -func getControllerManagerCommand(cfg *kubeadmapi.MasterConfiguration) []string { - command := append(getComponentBaseCommand(controllerManager), +func getControllerManagerCommand(cfg *kubeadmapi.MasterConfiguration, selfHosted bool) []string { + var command []string + + // self-hosted controller-manager needs to wait on a lock + if selfHosted { + command = []string{"/usr/bin/flock", "--exclusive", "--timeout=30", "/var/lock/controller-manager.lock"} + } + + command = append(getComponentBaseCommand(controllerManager), "--address=127.0.0.1", "--leader-elect", "--master=127.0.0.1:8080", @@ -388,16 +421,25 @@ func getControllerManagerCommand(cfg *kubeadmapi.MasterConfiguration) []string { if cfg.Networking.PodSubnet != "" { command = append(command, "--allocate-node-cidrs=true", "--cluster-cidr="+cfg.Networking.PodSubnet) } + return command } -func getSchedulerCommand(cfg *kubeadmapi.MasterConfiguration, schedulerPort int) []string { - return append(getComponentBaseCommand(scheduler), +func getSchedulerCommand(cfg *kubeadmapi.MasterConfiguration, selfHosted bool) []string { + var command []string + + // self-hosted apiserver needs to wait on a lock + if selfHosted { + command = []string{"/usr/bin/flock", "--exclusive", "--timeout=30", "/var/lock/api-server.lock"} + } + + command = append(getComponentBaseCommand(scheduler), "--address=127.0.0.1", "--leader-elect", "--master=127.0.0.1:8080", - fmt.Sprintf("--port=%d", schedulerPort), ) + + return command } func getProxyCommand(cfg *kubeadmapi.MasterConfiguration) []string { @@ -421,3 +463,16 @@ func getProxyEnvVars() []api.EnvVar { } return envs } + +func getSelfHostedAPIServerEnv() []api.EnvVar { + podIPEnvVar := api.EnvVar{ + Name: "POD_IP", + ValueFrom: &api.EnvVarSource{ + FieldRef: &api.ObjectFieldSelector{ + FieldPath: "status.podIP", + }, + }, + } + + return append(getProxyEnvVars(), podIPEnvVar) +} diff --git a/cmd/kubeadm/app/master/manifests_test.go b/cmd/kubeadm/app/master/manifests_test.go index 214bf0424c3..11d028d6678 100644 --- a/cmd/kubeadm/app/master/manifests_test.go +++ b/cmd/kubeadm/app/master/manifests_test.go @@ -454,7 +454,7 @@ func TestGetAPIServerCommand(t *testing.T) { } for _, rt := range tests { - actual := getAPIServerCommand(rt.cfg) + actual := getAPIServerCommand(rt.cfg, false) for i := range actual { if actual[i] != rt.expected[i] { t.Errorf( @@ -523,7 +523,7 @@ func TestGetControllerManagerCommand(t *testing.T) { } for _, rt := range tests { - actual := getControllerManagerCommand(rt.cfg) + actual := getControllerManagerCommand(rt.cfg, false) for i := range actual { if actual[i] != rt.expected[i] { t.Errorf( @@ -553,7 +553,7 @@ func TestGetSchedulerCommand(t *testing.T) { } for _, rt := range tests { - actual := getSchedulerCommand(rt.cfg) + actual := getSchedulerCommand(rt.cfg, false) for i := range actual { if actual[i] != rt.expected[i] { t.Errorf( diff --git a/cmd/kubeadm/app/master/selfhosted.go b/cmd/kubeadm/app/master/selfhosted.go index 6a30aae7baa..b0c54e48c36 100644 --- a/cmd/kubeadm/app/master/selfhosted.go +++ b/cmd/kubeadm/app/master/selfhosted.go @@ -46,21 +46,26 @@ func CreateSelfHostedControlPlane(cfg *kubeadmapi.MasterConfiguration, client *c volumeMounts = append(volumeMounts, pkiVolumeMount()) } - if err := LaunchSelfHostedAPIServer(cfg, client, volumes, volumeMounts); err != nil { + // Need lock for self-hosted + volumes = append(volumes, flockVolume()) + volumeMounts = append(volumeMounts, flockVolumeMount()) + + if err := launchSelfHostedAPIServer(cfg, client, volumes, volumeMounts); err != nil { return err } - if err := LaunchSelfHostedScheduler(cfg, client, volumes, volumeMounts); err != nil { + if err := launchSelfHostedScheduler(cfg, client, volumes, volumeMounts); err != nil { return err } - if err := LaunchSelfHostedControllerManager(cfg, client, volumes, volumeMounts); err != nil { + if err := launchSelfHostedControllerManager(cfg, client, volumes, volumeMounts); err != nil { return err } + return nil } -func LaunchSelfHostedAPIServer(cfg *kubeadmapi.MasterConfiguration, client *clientset.Clientset, volumes []v1.Volume, volumeMounts []v1.VolumeMount) error { +func launchSelfHostedAPIServer(cfg *kubeadmapi.MasterConfiguration, client *clientset.Clientset, volumes []v1.Volume, volumeMounts []v1.VolumeMount) error { start := time.Now() apiServer := getAPIServerDS(cfg, volumes, volumeMounts) @@ -72,13 +77,13 @@ func LaunchSelfHostedAPIServer(cfg *kubeadmapi.MasterConfiguration, client *clie // TODO: This might be pointless, checking the pods is probably enough. // It does however get us a count of how many there should be which may be useful // with HA. - apiDS, err := client.DaemonSets(api.NamespaceSystem).Get(kubeAPIServer, + apiDS, err := client.DaemonSets(api.NamespaceSystem).Get("self-hosted-"+kubeAPIServer, metav1.GetOptions{}) if err != nil { - fmt.Println("[debug] error getting apiserver DaemonSet:", err) + fmt.Println("[self-hosted] error getting apiserver DaemonSet:", err) return false, nil } - fmt.Printf("[debug] %s DaemonSet current=%d, desired=%d\n", + fmt.Printf("[self-hosted] %s DaemonSet current=%d, desired=%d\n", kubeAPIServer, apiDS.Status.CurrentNumberScheduled, apiDS.Status.DesiredNumberScheduled) @@ -90,25 +95,22 @@ func LaunchSelfHostedAPIServer(cfg *kubeadmapi.MasterConfiguration, client *clie return true, nil }) - waitForPodsWithLabel(client, kubeAPIServer) + // Wait for self-hosted API server to take ownership + waitForPodsWithLabel(client, "self-hosted-"+kubeAPIServer, true) - apiServerStaticManifestPath := path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, - "manifests", kubeAPIServer+".json") - if err := os.Remove(apiServerStaticManifestPath); err != nil { + // Remove temporary API server + apiServerStaticManifestPath := buildStaticManifestFilepath(kubeAPIServer) + if err := os.RemoveAll(apiServerStaticManifestPath); err != nil { return fmt.Errorf("unable to delete temporary API server manifest [%v]", err) } - // Wait until kubernetes detects the static pod removal and our newly created - // API server comes online: - // TODO: Should we verify that either the API is down, or the static apiserver pod is gone before - // waiting? WaitForAPI(client) - fmt.Printf("[debug] self-hosted kube-apiserver ready after %f seconds\n", time.Since(start).Seconds()) + fmt.Printf("[self-hosted] self-hosted kube-apiserver ready after %f seconds\n", time.Since(start).Seconds()) return nil } -func LaunchSelfHostedControllerManager(cfg *kubeadmapi.MasterConfiguration, client *clientset.Clientset, volumes []v1.Volume, volumeMounts []v1.VolumeMount) error { +func launchSelfHostedControllerManager(cfg *kubeadmapi.MasterConfiguration, client *clientset.Clientset, volumes []v1.Volume, volumeMounts []v1.VolumeMount) error { start := time.Now() ctrlMgr := getControllerManagerDeployment(cfg, volumes, volumeMounts) @@ -116,105 +118,98 @@ func LaunchSelfHostedControllerManager(cfg *kubeadmapi.MasterConfiguration, clie return fmt.Errorf("failed to create self-hosted %q deployment [%v]", kubeControllerManager, err) } - waitForPodsWithLabel(client, kubeControllerManager) + waitForPodsWithLabel(client, "self-hosted-"+kubeControllerManager, false) - ctrlMgrStaticManifestPath := path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, - "manifests", kubeControllerManager+".json") - if err := os.Remove(ctrlMgrStaticManifestPath); err != nil { + ctrlMgrStaticManifestPath := buildStaticManifestFilepath(kubeControllerManager) + if err := os.RemoveAll(ctrlMgrStaticManifestPath); err != nil { return fmt.Errorf("unable to delete temporary controller manager manifest [%v]", err) } - fmt.Printf("[debug] self-hosted kube-controller-manager ready after %f seconds\n", time.Since(start).Seconds()) + fmt.Printf("[self-hosted] self-hosted kube-controller-manager ready after %f seconds\n", time.Since(start).Seconds()) return nil } -func LaunchSelfHostedScheduler(cfg *kubeadmapi.MasterConfiguration, client *clientset.Clientset, volumes []v1.Volume, volumeMounts []v1.VolumeMount) error { - +func launchSelfHostedScheduler(cfg *kubeadmapi.MasterConfiguration, client *clientset.Clientset, volumes []v1.Volume, volumeMounts []v1.VolumeMount) error { start := time.Now() scheduler := getSchedulerDeployment(cfg) if _, err := client.Extensions().Deployments(api.NamespaceSystem).Create(&scheduler); err != nil { return fmt.Errorf("failed to create self-hosted %q deployment [%v]", kubeScheduler, err) } - waitForPodsWithLabel(client, kubeScheduler) + waitForPodsWithLabel(client, "self-hosted-"+kubeScheduler, false) - schedulerStaticManifestPath := path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, - "manifests", kubeScheduler+".json") - if err := os.Remove(schedulerStaticManifestPath); err != nil { + schedulerStaticManifestPath := buildStaticManifestFilepath(kubeScheduler) + if err := os.RemoveAll(schedulerStaticManifestPath); err != nil { return fmt.Errorf("unable to delete temporary scheduler manifest [%v]", err) } - fmt.Printf("[debug] self-hosted kube-scheduler ready after %f seconds\n", time.Since(start).Seconds()) + fmt.Printf("[self-hosted] self-hosted kube-scheduler ready after %f seconds\n", time.Since(start).Seconds()) return nil } // waitForPodsWithLabel will lookup pods with the given label and wait until they are all // reporting status as running. -func waitForPodsWithLabel(client *clientset.Clientset, appLabel string) { +func waitForPodsWithLabel(client *clientset.Clientset, appLabel string, mustBeRunning bool) { wait.PollInfinite(apiCallRetryInterval, func() (bool, error) { // TODO: Do we need a stronger label link than this? listOpts := v1.ListOptions{LabelSelector: fmt.Sprintf("k8s-app=%s", appLabel)} apiPods, err := client.Pods(api.NamespaceSystem).List(listOpts) if err != nil { - fmt.Printf("[debug] error getting %s pods [%v]\n", appLabel, err) + fmt.Printf("[self-hosted] error getting %s pods [%v]\n", appLabel, err) return false, nil } - fmt.Printf("[debug] Found %d %s pods\n", len(apiPods.Items), appLabel) + fmt.Printf("[self-hosted] Found %d %s pods\n", len(apiPods.Items), appLabel) // TODO: HA if int32(len(apiPods.Items)) != 1 { return false, nil } for _, pod := range apiPods.Items { - fmt.Printf("[debug] Pod %s status: %s\n", pod.Name, pod.Status.Phase) - if pod.Status.Phase != "Running" { + fmt.Printf("[self-hosted] Pod %s status: %s\n", pod.Name, pod.Status.Phase) + if mustBeRunning && pod.Status.Phase != "Running" { return false, nil } } return true, nil }) - - return } // Sources from bootkube templates.go -func getAPIServerDS(cfg *kubeadmapi.MasterConfiguration, - volumes []v1.Volume, volumeMounts []v1.VolumeMount) ext.DaemonSet { - +func getAPIServerDS(cfg *kubeadmapi.MasterConfiguration, volumes []v1.Volume, volumeMounts []v1.VolumeMount) ext.DaemonSet { ds := ext.DaemonSet{ TypeMeta: metav1.TypeMeta{ APIVersion: "extensions/v1beta1", Kind: "DaemonSet", }, ObjectMeta: metav1.ObjectMeta{ - Name: kubeAPIServer, + Name: "self-hosted-" + kubeAPIServer, Namespace: "kube-system", - //Labels: map[string]string{"k8s-app": "kube-apiserver"}, + Labels: map[string]string{"k8s-app": "self-hosted-" + kubeAPIServer}, }, Spec: ext.DaemonSetSpec{ Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{ - // TODO: taken from bootkube, appears to be essential, without this - // we don't get an apiserver pod... - "k8s-app": kubeAPIServer, + "k8s-app": "self-hosted-" + kubeAPIServer, "component": kubeAPIServer, "tier": "control-plane", }, + Annotations: map[string]string{ + v1.TolerationsAnnotationKey: getMasterToleration(), + }, }, Spec: v1.PodSpec{ - // TODO: Make sure masters get this label NodeSelector: map[string]string{metav1.NodeLabelKubeadmAlphaRole: metav1.NodeLabelRoleMaster}, HostNetwork: true, Volumes: volumes, Containers: []v1.Container{ { - Name: kubeAPIServer, + Name: "self-hosted-" + kubeAPIServer, Image: images.GetCoreImage(images.KubeAPIServerImage, cfg, kubeadmapi.GlobalEnvParams.HyperkubeImage), - Command: getAPIServerCommand(cfg), - Env: getProxyEnvVars(), + Command: getAPIServerCommand(cfg, true), + Env: getSelfHostedAPIServerEnv(), VolumeMounts: volumeMounts, LivenessProbe: componentProbe(8080, "/healthz"), Resources: componentResources("250m"), @@ -227,24 +222,23 @@ func getAPIServerDS(cfg *kubeadmapi.MasterConfiguration, return ds } -func getControllerManagerDeployment(cfg *kubeadmapi.MasterConfiguration, - volumes []v1.Volume, volumeMounts []v1.VolumeMount) ext.Deployment { - - cmDep := ext.Deployment{ +func getControllerManagerDeployment(cfg *kubeadmapi.MasterConfiguration, volumes []v1.Volume, volumeMounts []v1.VolumeMount) ext.Deployment { + d := ext.Deployment{ TypeMeta: metav1.TypeMeta{ APIVersion: "extensions/v1beta1", Kind: "Deployment", }, ObjectMeta: metav1.ObjectMeta{ - Name: kubeControllerManager, + Name: "self-hosted-" + kubeControllerManager, Namespace: "kube-system", + Labels: map[string]string{"k8s-app": "self-hosted-" + kubeControllerManager}, }, Spec: ext.DeploymentSpec{ + // TODO bootkube uses 2 replicas Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{ - // TODO: taken from bootkube, appears to be essential - "k8s-app": kubeControllerManager, + "k8s-app": "self-hosted-" + kubeControllerManager, "component": kubeControllerManager, "tier": "control-plane", }, @@ -253,27 +247,74 @@ func getControllerManagerDeployment(cfg *kubeadmapi.MasterConfiguration, }, }, Spec: v1.PodSpec{ - // TODO: Make sure masters get this label NodeSelector: map[string]string{metav1.NodeLabelKubeadmAlphaRole: metav1.NodeLabelRoleMaster}, HostNetwork: true, Volumes: volumes, - Containers: []v1.Container{ { - Name: kubeControllerManager, + Name: "self-hosted-" + kubeControllerManager, Image: images.GetCoreImage(images.KubeControllerManagerImage, cfg, kubeadmapi.GlobalEnvParams.HyperkubeImage), - Command: getControllerManagerCommand(cfg), + Command: getControllerManagerCommand(cfg, true), VolumeMounts: volumeMounts, LivenessProbe: componentProbe(10252, "/healthz"), Resources: componentResources("200m"), Env: getProxyEnvVars(), }, }, + DNSPolicy: v1.DNSDefault, + }, + }, + }, + } + return d +} + +func getSchedulerDeployment(cfg *kubeadmapi.MasterConfiguration) ext.Deployment { + d := ext.Deployment{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "extensions/v1beta1", + Kind: "Deployment", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "self-hosted-" + kubeScheduler, + Namespace: "kube-system", + Labels: map[string]string{"k8s-app": "self-hosted-" + kubeScheduler}, + }, + Spec: ext.DeploymentSpec{ + // TODO bootkube uses 2 replicas + Template: v1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "k8s-app": "self-hosted-" + kubeScheduler, + "component": kubeScheduler, + "tier": "control-plane", + }, + Annotations: map[string]string{ + v1.TolerationsAnnotationKey: getMasterToleration(), + }, + }, + Spec: v1.PodSpec{ + NodeSelector: map[string]string{metav1.NodeLabelKubeadmAlphaRole: metav1.NodeLabelRoleMaster}, + HostNetwork: true, + Containers: []v1.Container{ + { + Name: "self-hosted-" + kubeScheduler, + Image: images.GetCoreImage(images.KubeSchedulerImage, cfg, kubeadmapi.GlobalEnvParams.HyperkubeImage), + Command: getSchedulerCommand(cfg, true), + LivenessProbe: componentProbe(10251, "/healthz"), + Resources: componentResources("100m"), + Env: getProxyEnvVars(), + }, + }, }, }, }, } - return cmDep + return d +} + +func buildStaticManifestFilepath(name string) string { + return path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "manifests", name+".json") } func getMasterToleration() string { @@ -288,47 +329,3 @@ func getMasterToleration() string { }}) return string(masterToleration) } - -func getSchedulerDeployment(cfg *kubeadmapi.MasterConfiguration) ext.Deployment { - - cmDep := ext.Deployment{ - TypeMeta: metav1.TypeMeta{ - APIVersion: "extensions/v1beta1", - Kind: "Deployment", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: kubeScheduler, - Namespace: "kube-system", - }, - Spec: ext.DeploymentSpec{ - Template: v1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "k8s-app": kubeScheduler, - "component": kubeScheduler, - "tier": "control-plane", - }, - Annotations: map[string]string{ - v1.TolerationsAnnotationKey: getMasterToleration(), - }, - }, - Spec: v1.PodSpec{ - NodeSelector: map[string]string{metav1.NodeLabelKubeadmAlphaRole: metav1.NodeLabelRoleMaster}, - HostNetwork: true, - - Containers: []v1.Container{ - { - Name: kubeScheduler, - Image: images.GetCoreImage(images.KubeSchedulerImage, cfg, kubeadmapi.GlobalEnvParams.HyperkubeImage), - Command: getSchedulerCommand(cfg, 10251), - LivenessProbe: componentProbe(10251, "/healthz"), - Resources: componentResources("100m"), - Env: getProxyEnvVars(), - }, - }, - }, - }, - }, - } - return cmDep -}