// TODO(phase1+): kube-proxy should be a daemonset, three different daemonsets should not be here func createKubeProxyPodSpec(s *kubeadmapi.MasterConfiguration, architecture string) api.PodSpec { envParams := kubeadmapi.GetEnvParams() privilegedTrue := true return api.PodSpec{ SecurityContext: &api.PodSecurityContext{HostNetwork: true}, NodeSelector: map[string]string{ "beta.kubernetes.io/arch": architecture, }, Containers: []api.Container{{ Name: kubeProxy, Image: images.GetCoreImage(images.KubeProxyImage, s, envParams["hyperkube_image"]), Command: append(getComponentCommand("proxy", s), "--kubeconfig=/run/kubeconfig"), SecurityContext: &api.SecurityContext{Privileged: &privilegedTrue}, VolumeMounts: []api.VolumeMount{ { Name: "dbus", MountPath: "/var/run/dbus", ReadOnly: false, }, { // TODO there are handful of clever options to get around this, but it's // easier to just mount kubelet's config here; we should probably just // make sure that proxy reads the token and CA cert from /run/secrets // and accepts `--master` at the same time // // clever options include: // - do CSR dance and create kubeconfig and mount it as a secret // - create a service account with a second secret encoding kubeconfig // - use init container to convert known information to kubeconfig // - ...whatever Name: "kubeconfig", MountPath: "/run/kubeconfig", ReadOnly: false, }, }, }}, Volumes: []api.Volume{ { Name: "kubeconfig", VolumeSource: api.VolumeSource{ HostPath: &api.HostPathVolumeSource{Path: path.Join(envParams["kubernetes_dir"], "kubelet.conf")}, }, }, { Name: "dbus", VolumeSource: api.VolumeSource{ HostPath: &api.HostPathVolumeSource{Path: "/var/run/dbus"}, }, }, }, } }
func createKubeProxyPodSpec(cfg *kubeadmapi.MasterConfiguration) v1.PodSpec { privilegedTrue := true return v1.PodSpec{ HostNetwork: true, SecurityContext: &v1.PodSecurityContext{}, Containers: []v1.Container{{ Name: kubeProxy, Image: images.GetCoreImage(images.KubeProxyImage, cfg, kubeadmapi.GlobalEnvParams.HyperkubeImage), Command: append(getProxyCommand(cfg), "--kubeconfig=/run/kubeconfig"), SecurityContext: &v1.SecurityContext{Privileged: &privilegedTrue}, VolumeMounts: []v1.VolumeMount{ { Name: "dbus", MountPath: "/var/run/dbus", ReadOnly: false, }, { // TODO there are handful of clever options to get around this, but it's // easier to just mount kubelet's config here; we should probably just // make sure that proxy reads the token and CA cert from /run/secrets // and accepts `--master` at the same time // // clever options include: // - do CSR dance and create kubeconfig and mount it as a secret // - create a service account with a second secret encoding kubeconfig // - use init container to convert known information to kubeconfig // - ...whatever Name: "kubeconfig", MountPath: "/run/kubeconfig", ReadOnly: false, }, }, }}, Volumes: []v1.Volume{ { Name: "kubeconfig", VolumeSource: v1.VolumeSource{ HostPath: &v1.HostPathVolumeSource{Path: path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeconfig.KubeletKubeConfigFileName)}, }, }, { Name: "dbus", VolumeSource: v1.VolumeSource{ HostPath: &v1.HostPathVolumeSource{Path: "/var/run/dbus"}, }, }, }, } }
// WriteStaticPodManifests builds manifest objects based on user provided configuration and then dumps it to disk // where kubelet will pick and schedule them. func WriteStaticPodManifests(cfg *kubeadmapi.MasterConfiguration) error { volumes := []api.Volume{k8sVolume(cfg)} volumeMounts := []api.VolumeMount{k8sVolumeMount()} if isCertsVolumeMountNeeded() { volumes = append(volumes, certsVolume(cfg)) volumeMounts = append(volumeMounts, certsVolumeMount()) } if isPkiVolumeMountNeeded() { volumes = append(volumes, pkiVolume(cfg)) volumeMounts = append(volumeMounts, pkiVolumeMount()) } // Prepare static pod specs staticPodSpecs := map[string]api.Pod{ kubeAPIServer: componentPod(api.Container{ Name: kubeAPIServer, Image: images.GetCoreImage(images.KubeAPIServerImage, cfg, kubeadmapi.GlobalEnvParams.HyperkubeImage), Command: getAPIServerCommand(cfg), VolumeMounts: volumeMounts, LivenessProbe: componentProbe(8080, "/healthz"), Resources: componentResources("250m"), Env: getProxyEnvVars(), }, volumes...), kubeControllerManager: componentPod(api.Container{ Name: kubeControllerManager, Image: images.GetCoreImage(images.KubeControllerManagerImage, cfg, kubeadmapi.GlobalEnvParams.HyperkubeImage), Command: getControllerManagerCommand(cfg), 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), Command: getSchedulerCommand(cfg), LivenessProbe: componentProbe(10251, "/healthz"), Resources: componentResources("100m"), Env: getProxyEnvVars(), }), } // Add etcd static pod spec only if external etcd is not configured if len(cfg.Etcd.Endpoints) == 0 { staticPodSpecs[etcd] = componentPod(api.Container{ Name: etcd, Command: []string{ "etcd", "--listen-client-urls=http://127.0.0.1:2379", "--advertise-client-urls=http://127.0.0.1:2379", "--data-dir=/var/etcd/data", }, VolumeMounts: []api.VolumeMount{certsVolumeMount(), etcdVolumeMount(), k8sVolumeMount()}, Image: images.GetCoreImage(images.KubeEtcdImage, cfg, kubeadmapi.GlobalEnvParams.EtcdImage), LivenessProbe: componentProbe(2379, "/health"), Resources: componentResources("200m"), SecurityContext: &api.SecurityContext{ SELinuxOptions: &api.SELinuxOptions{ // TODO: This implies our etcd container is not being restricted by // SELinux. This is not optimal and would be nice to adjust in future // so it can create and write /var/lib/etcd, but for now this avoids // recommending setenforce 0 system-wide. Type: "spc_t", }, }, }, certsVolume(cfg), etcdVolume(cfg), k8sVolume(cfg)) } manifestsPath := path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "manifests") if err := os.MkdirAll(manifestsPath, 0700); err != nil { return fmt.Errorf("failed to create directory %q [%v]", manifestsPath, err) } for name, spec := range staticPodSpecs { filename := path.Join(manifestsPath, name+".json") serialized, err := json.MarshalIndent(spec, "", " ") if err != nil { return fmt.Errorf("failed to marshal manifest for %q to JSON [%v]", name, err) } if err := cmdutil.DumpReaderToFile(bytes.NewReader(serialized), filename); err != nil { return fmt.Errorf("failed to create static pod manifest file for %q (%q) [%v]", name, filename, err) } } return nil }