2016-08-18 12:38:18 +00:00
|
|
|
/*
|
|
|
|
Copyright 2016 The Kubernetes Authors.
|
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
2016-09-07 12:53:11 +00:00
|
|
|
package master
|
2016-08-18 12:38:18 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"path"
|
2016-09-20 10:37:02 +00:00
|
|
|
"strings"
|
2016-08-18 12:38:18 +00:00
|
|
|
|
2017-01-25 13:13:07 +00:00
|
|
|
"k8s.io/apimachinery/pkg/api/resource"
|
2017-01-11 14:09:48 +00:00
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
2017-01-27 20:42:17 +00:00
|
|
|
"k8s.io/apimachinery/pkg/util/intstr"
|
2016-09-29 06:36:18 +00:00
|
|
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
2017-01-20 22:33:06 +00:00
|
|
|
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
2016-09-19 15:11:05 +00:00
|
|
|
"k8s.io/kubernetes/cmd/kubeadm/app/images"
|
2016-08-18 12:38:18 +00:00
|
|
|
api "k8s.io/kubernetes/pkg/api/v1"
|
|
|
|
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
|
|
|
)
|
|
|
|
|
2016-09-24 13:40:10 +00:00
|
|
|
// Static pod definitions in golang form are included below so that `kubeadm init` can get going.
|
2016-08-18 12:38:18 +00:00
|
|
|
const (
|
2016-09-19 15:11:05 +00:00
|
|
|
DefaultClusterName = "kubernetes"
|
2016-12-07 14:24:02 +00:00
|
|
|
DefaultCloudConfigPath = "/etc/kubernetes/cloud-config"
|
2016-09-07 16:37:02 +00:00
|
|
|
|
2017-01-17 00:41:56 +00:00
|
|
|
etcd = "etcd"
|
|
|
|
apiServer = "apiserver"
|
|
|
|
controllerManager = "controller-manager"
|
|
|
|
scheduler = "scheduler"
|
|
|
|
proxy = "proxy"
|
|
|
|
kubeAPIServer = "kube-apiserver"
|
|
|
|
kubeControllerManager = "kube-controller-manager"
|
|
|
|
kubeScheduler = "kube-scheduler"
|
|
|
|
kubeProxy = "kube-proxy"
|
|
|
|
authorizationPolicyFile = "abac_policy.json"
|
|
|
|
authorizationWebhookConfigFile = "webhook_authz.conf"
|
2016-08-18 12:38:18 +00:00
|
|
|
)
|
|
|
|
|
2016-09-19 15:11:05 +00:00
|
|
|
// WriteStaticPodManifests builds manifest objects based on user provided configuration and then dumps it to disk
|
|
|
|
// where kubelet will pick and schedule them.
|
2016-10-17 08:00:22 +00:00
|
|
|
func WriteStaticPodManifests(cfg *kubeadmapi.MasterConfiguration) error {
|
2016-11-07 17:18:33 +00:00
|
|
|
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())
|
|
|
|
}
|
|
|
|
|
2016-09-20 10:37:02 +00:00
|
|
|
// Prepare static pod specs
|
2016-08-18 12:38:18 +00:00
|
|
|
staticPodSpecs := map[string]api.Pod{
|
2016-09-07 16:37:02 +00:00
|
|
|
kubeAPIServer: componentPod(api.Container{
|
|
|
|
Name: kubeAPIServer,
|
2016-10-29 01:24:59 +00:00
|
|
|
Image: images.GetCoreImage(images.KubeAPIServerImage, cfg, kubeadmapi.GlobalEnvParams.HyperkubeImage),
|
2017-01-20 16:26:48 +00:00
|
|
|
Command: getAPIServerCommand(cfg, false),
|
2016-11-07 17:18:33 +00:00
|
|
|
VolumeMounts: volumeMounts,
|
2016-08-18 12:38:18 +00:00
|
|
|
LivenessProbe: componentProbe(8080, "/healthz"),
|
|
|
|
Resources: componentResources("250m"),
|
2016-11-25 16:56:38 +00:00
|
|
|
Env: getProxyEnvVars(),
|
2016-11-07 17:18:33 +00:00
|
|
|
}, volumes...),
|
2016-09-07 16:37:02 +00:00
|
|
|
kubeControllerManager: componentPod(api.Container{
|
|
|
|
Name: kubeControllerManager,
|
2016-10-29 01:24:59 +00:00
|
|
|
Image: images.GetCoreImage(images.KubeControllerManagerImage, cfg, kubeadmapi.GlobalEnvParams.HyperkubeImage),
|
2017-01-20 16:26:48 +00:00
|
|
|
Command: getControllerManagerCommand(cfg, false),
|
2016-11-07 17:18:33 +00:00
|
|
|
VolumeMounts: volumeMounts,
|
2016-08-18 12:38:18 +00:00
|
|
|
LivenessProbe: componentProbe(10252, "/healthz"),
|
|
|
|
Resources: componentResources("200m"),
|
2016-11-25 16:56:38 +00:00
|
|
|
Env: getProxyEnvVars(),
|
2016-11-07 17:18:33 +00:00
|
|
|
}, volumes...),
|
2016-09-07 16:37:02 +00:00
|
|
|
kubeScheduler: componentPod(api.Container{
|
2017-01-20 16:26:48 +00:00
|
|
|
Name: kubeScheduler,
|
|
|
|
Image: images.GetCoreImage(images.KubeSchedulerImage, cfg, kubeadmapi.GlobalEnvParams.HyperkubeImage),
|
|
|
|
Command: getSchedulerCommand(cfg, false),
|
|
|
|
LivenessProbe: componentProbe(10251, "/healthz"),
|
2016-08-18 12:38:18 +00:00
|
|
|
Resources: componentResources("100m"),
|
2016-11-25 16:56:38 +00:00
|
|
|
Env: getProxyEnvVars(),
|
2016-08-18 12:38:18 +00:00
|
|
|
}),
|
|
|
|
}
|
|
|
|
|
2016-09-20 10:37:02 +00:00
|
|
|
// Add etcd static pod spec only if external etcd is not configured
|
2016-10-17 08:00:22 +00:00
|
|
|
if len(cfg.Etcd.Endpoints) == 0 {
|
2017-01-30 14:16:22 +00:00
|
|
|
etcdPod := componentPod(api.Container{
|
2016-09-20 10:37:02 +00:00
|
|
|
Name: etcd,
|
|
|
|
Command: []string{
|
|
|
|
"etcd",
|
|
|
|
"--listen-client-urls=http://127.0.0.1:2379",
|
|
|
|
"--advertise-client-urls=http://127.0.0.1:2379",
|
2017-01-04 16:43:12 +00:00
|
|
|
"--data-dir=/var/lib/etcd",
|
2016-09-20 10:37:02 +00:00
|
|
|
},
|
|
|
|
VolumeMounts: []api.VolumeMount{certsVolumeMount(), etcdVolumeMount(), k8sVolumeMount()},
|
2016-10-29 01:24:59 +00:00
|
|
|
Image: images.GetCoreImage(images.KubeEtcdImage, cfg, kubeadmapi.GlobalEnvParams.EtcdImage),
|
2016-09-20 10:37:02 +00:00
|
|
|
LivenessProbe: componentProbe(2379, "/health"),
|
|
|
|
Resources: componentResources("200m"),
|
2016-10-17 08:00:22 +00:00
|
|
|
}, certsVolume(cfg), etcdVolume(cfg), k8sVolume(cfg))
|
2017-01-30 14:16:22 +00:00
|
|
|
|
|
|
|
etcdPod.Spec.SecurityContext = &api.PodSecurityContext{
|
|
|
|
SELinuxOptions: &api.SELinuxOptions{
|
|
|
|
// Unconfine the etcd container so it can write to /var/lib/etcd with SELinux enforcing:
|
|
|
|
Type: "spc_t",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
staticPodSpecs[etcd] = etcdPod
|
2016-09-20 10:37:02 +00:00
|
|
|
}
|
|
|
|
|
2016-10-29 01:24:59 +00:00
|
|
|
manifestsPath := path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "manifests")
|
2016-08-18 12:38:18 +00:00
|
|
|
if err := os.MkdirAll(manifestsPath, 0700); err != nil {
|
2016-12-07 07:21:28 +00:00
|
|
|
return fmt.Errorf("failed to create directory %q [%v]", manifestsPath, err)
|
2016-08-18 12:38:18 +00:00
|
|
|
}
|
|
|
|
for name, spec := range staticPodSpecs {
|
|
|
|
filename := path.Join(manifestsPath, name+".json")
|
|
|
|
serialized, err := json.MarshalIndent(spec, "", " ")
|
|
|
|
if err != nil {
|
2016-12-07 07:21:28 +00:00
|
|
|
return fmt.Errorf("failed to marshal manifest for %q to JSON [%v]", name, err)
|
2016-08-18 12:38:18 +00:00
|
|
|
}
|
|
|
|
if err := cmdutil.DumpReaderToFile(bytes.NewReader(serialized), filename); err != nil {
|
2016-12-07 07:21:28 +00:00
|
|
|
return fmt.Errorf("failed to create static pod manifest file for %q (%q) [%v]", name, filename, err)
|
2016-08-18 12:38:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-09-20 10:37:02 +00:00
|
|
|
// etcdVolume exposes a path on the host in order to guarantee data survival during reboot.
|
2016-10-17 08:00:22 +00:00
|
|
|
func etcdVolume(cfg *kubeadmapi.MasterConfiguration) api.Volume {
|
2016-09-11 13:39:35 +00:00
|
|
|
return api.Volume{
|
|
|
|
Name: "etcd",
|
|
|
|
VolumeSource: api.VolumeSource{
|
2016-10-29 01:24:59 +00:00
|
|
|
HostPath: &api.HostPathVolumeSource{Path: kubeadmapi.GlobalEnvParams.HostEtcdPath},
|
2016-09-11 13:39:35 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func etcdVolumeMount() api.VolumeMount {
|
|
|
|
return api.VolumeMount{
|
|
|
|
Name: "etcd",
|
2017-01-04 16:43:12 +00:00
|
|
|
MountPath: "/var/lib/etcd",
|
2016-09-11 13:39:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-07 17:18:33 +00:00
|
|
|
func isCertsVolumeMountNeeded() bool {
|
|
|
|
// Always return true for now. We may add conditional logic here for images which do not require host mounting /etc/ssl
|
|
|
|
// hyperkube for example already has valid ca-certificates installed
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2016-09-20 10:37:02 +00:00
|
|
|
// certsVolume exposes host SSL certificates to pod containers.
|
2016-10-17 08:00:22 +00:00
|
|
|
func certsVolume(cfg *kubeadmapi.MasterConfiguration) api.Volume {
|
2016-09-20 10:37:02 +00:00
|
|
|
return api.Volume{
|
|
|
|
Name: "certs",
|
|
|
|
VolumeSource: api.VolumeSource{
|
2016-09-19 19:05:14 +00:00
|
|
|
// TODO(phase1+) make path configurable
|
2016-09-20 10:37:02 +00:00
|
|
|
HostPath: &api.HostPathVolumeSource{Path: "/etc/ssl/certs"},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func certsVolumeMount() api.VolumeMount {
|
|
|
|
return api.VolumeMount{
|
|
|
|
Name: "certs",
|
|
|
|
MountPath: "/etc/ssl/certs",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-07 17:18:33 +00:00
|
|
|
func isPkiVolumeMountNeeded() bool {
|
|
|
|
// On some systems were we host-mount /etc/ssl/certs, it is also required to mount /etc/pki. This is needed
|
|
|
|
// due to symlinks pointing from files in /etc/ssl/certs into /etc/pki/
|
|
|
|
if _, err := os.Stat("/etc/pki"); err == nil {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func pkiVolume(cfg *kubeadmapi.MasterConfiguration) api.Volume {
|
2016-08-18 12:38:18 +00:00
|
|
|
return api.Volume{
|
2016-12-09 20:16:37 +00:00
|
|
|
Name: "pki",
|
2016-11-07 17:18:33 +00:00
|
|
|
VolumeSource: api.VolumeSource{
|
|
|
|
// TODO(phase1+) make path configurable
|
|
|
|
HostPath: &api.HostPathVolumeSource{Path: "/etc/pki"},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func pkiVolumeMount() api.VolumeMount {
|
|
|
|
return api.VolumeMount{
|
|
|
|
Name: "pki",
|
|
|
|
MountPath: "/etc/pki",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-20 16:26:48 +00:00
|
|
|
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,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-07 17:18:33 +00:00
|
|
|
func k8sVolume(cfg *kubeadmapi.MasterConfiguration) api.Volume {
|
|
|
|
return api.Volume{
|
|
|
|
Name: "k8s",
|
2016-08-18 12:38:18 +00:00
|
|
|
VolumeSource: api.VolumeSource{
|
2016-10-29 01:24:59 +00:00
|
|
|
HostPath: &api.HostPathVolumeSource{Path: kubeadmapi.GlobalEnvParams.KubernetesDir},
|
2016-08-18 12:38:18 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-15 14:40:42 +00:00
|
|
|
func k8sVolumeMount() api.VolumeMount {
|
2016-08-18 12:38:18 +00:00
|
|
|
return api.VolumeMount{
|
2016-11-07 17:18:33 +00:00
|
|
|
Name: "k8s",
|
2016-09-15 14:40:42 +00:00
|
|
|
MountPath: "/etc/kubernetes/",
|
2016-08-18 12:38:18 +00:00
|
|
|
ReadOnly: true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func componentResources(cpu string) api.ResourceRequirements {
|
|
|
|
return api.ResourceRequirements{
|
|
|
|
Requests: api.ResourceList{
|
|
|
|
api.ResourceName(api.ResourceCPU): resource.MustParse(cpu),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func componentProbe(port int, path string) *api.Probe {
|
|
|
|
return &api.Probe{
|
|
|
|
Handler: api.Handler{
|
|
|
|
HTTPGet: &api.HTTPGetAction{
|
|
|
|
Host: "127.0.0.1",
|
|
|
|
Path: path,
|
|
|
|
Port: intstr.FromInt(port),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
InitialDelaySeconds: 15,
|
|
|
|
TimeoutSeconds: 15,
|
2016-10-01 13:25:27 +00:00
|
|
|
FailureThreshold: 8,
|
2016-08-18 12:38:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func componentPod(container api.Container, volumes ...api.Volume) api.Pod {
|
|
|
|
return api.Pod{
|
2016-12-03 18:57:26 +00:00
|
|
|
TypeMeta: metav1.TypeMeta{
|
2016-08-18 12:38:18 +00:00
|
|
|
APIVersion: "v1",
|
|
|
|
Kind: "Pod",
|
|
|
|
},
|
2017-01-17 03:38:19 +00:00
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
2016-08-18 12:38:18 +00:00
|
|
|
Name: container.Name,
|
|
|
|
Namespace: "kube-system",
|
|
|
|
Labels: map[string]string{"component": container.Name, "tier": "control-plane"},
|
|
|
|
},
|
|
|
|
Spec: api.PodSpec{
|
|
|
|
Containers: []api.Container{container},
|
|
|
|
HostNetwork: true,
|
|
|
|
Volumes: volumes,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2016-09-07 12:53:11 +00:00
|
|
|
|
2016-12-07 07:21:28 +00:00
|
|
|
func getComponentBaseCommand(component string) []string {
|
2016-10-29 01:24:59 +00:00
|
|
|
if kubeadmapi.GlobalEnvParams.HyperkubeImage != "" {
|
2016-12-07 07:21:28 +00:00
|
|
|
return []string{"/hyperkube", component}
|
2016-09-07 16:37:02 +00:00
|
|
|
}
|
2016-12-07 07:21:28 +00:00
|
|
|
|
|
|
|
return []string{"kube-" + component}
|
2016-10-19 12:30:03 +00:00
|
|
|
}
|
2016-09-07 16:37:02 +00:00
|
|
|
|
2017-01-20 22:33:06 +00:00
|
|
|
func getCertFilePath(certName string) string {
|
|
|
|
return path.Join(kubeadmapi.GlobalEnvParams.HostPKIPath, certName)
|
|
|
|
}
|
|
|
|
|
2017-01-20 16:26:48 +00:00
|
|
|
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),
|
2016-10-19 12:30:03 +00:00
|
|
|
"--insecure-bind-address=127.0.0.1",
|
|
|
|
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota",
|
|
|
|
"--service-cluster-ip-range="+cfg.Networking.ServiceSubnet,
|
2017-01-20 22:33:06 +00:00
|
|
|
"--service-account-key-file="+getCertFilePath(kubeadmconstants.APIServerKeyName),
|
|
|
|
"--client-ca-file="+getCertFilePath(kubeadmconstants.CACertName),
|
|
|
|
"--tls-cert-file="+getCertFilePath(kubeadmconstants.APIServerCertName),
|
|
|
|
"--tls-private-key-file="+getCertFilePath(kubeadmconstants.APIServerKeyName),
|
2017-01-23 19:45:48 +00:00
|
|
|
"--kubelet-client-certificate="+getCertFilePath(kubeadmconstants.APIServerKubeletClientCertName),
|
|
|
|
"--kubelet-client-key="+getCertFilePath(kubeadmconstants.APIServerKubeletClientKeyName),
|
2016-12-07 07:21:28 +00:00
|
|
|
"--token-auth-file="+kubeadmapi.GlobalEnvParams.HostPKIPath+"/tokens.csv",
|
2016-11-08 19:27:16 +00:00
|
|
|
fmt.Sprintf("--secure-port=%d", cfg.API.Port),
|
2016-10-19 12:30:03 +00:00
|
|
|
"--allow-privileged",
|
2017-01-23 10:08:01 +00:00
|
|
|
"--storage-backend=etcd3",
|
2017-01-31 07:24:15 +00:00
|
|
|
"--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname",
|
2016-10-19 12:30:03 +00:00
|
|
|
)
|
2016-09-19 19:05:14 +00:00
|
|
|
|
2017-01-17 00:41:56 +00:00
|
|
|
if cfg.AuthorizationMode != "" {
|
|
|
|
command = append(command, "--authorization-mode="+cfg.AuthorizationMode)
|
|
|
|
switch cfg.AuthorizationMode {
|
2017-01-31 07:24:15 +00:00
|
|
|
case kubeadmconstants.AuthzModeABAC:
|
2017-01-17 00:41:56 +00:00
|
|
|
command = append(command, "--authorization-policy-file="+path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, authorizationPolicyFile))
|
2017-01-31 07:24:15 +00:00
|
|
|
case kubeadmconstants.AuthzModeWebhook:
|
2017-01-17 00:41:56 +00:00
|
|
|
command = append(command, "--authorization-webhook-config-file="+path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, authorizationWebhookConfigFile))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-19 12:30:03 +00:00
|
|
|
// Use first address we are given
|
|
|
|
if len(cfg.API.AdvertiseAddresses) > 0 {
|
2017-01-20 16:26:48 +00:00
|
|
|
if selfHosted {
|
|
|
|
command = append(command, "--advertise-address=$(POD_IP)")
|
|
|
|
} else {
|
|
|
|
command = append(command, fmt.Sprintf("--advertise-address=%s", cfg.API.AdvertiseAddresses[0]))
|
|
|
|
}
|
2016-09-19 19:05:14 +00:00
|
|
|
}
|
|
|
|
|
2016-10-19 12:30:03 +00:00
|
|
|
// Check if the user decided to use an external etcd cluster
|
|
|
|
if len(cfg.Etcd.Endpoints) > 0 {
|
|
|
|
command = append(command, fmt.Sprintf("--etcd-servers=%s", strings.Join(cfg.Etcd.Endpoints, ",")))
|
|
|
|
} else {
|
|
|
|
command = append(command, "--etcd-servers=http://127.0.0.1:2379")
|
|
|
|
}
|
2016-09-15 14:40:42 +00:00
|
|
|
|
2016-10-19 12:30:03 +00:00
|
|
|
// Is etcd secured?
|
|
|
|
if cfg.Etcd.CAFile != "" {
|
|
|
|
command = append(command, fmt.Sprintf("--etcd-cafile=%s", cfg.Etcd.CAFile))
|
|
|
|
}
|
|
|
|
if cfg.Etcd.CertFile != "" && cfg.Etcd.KeyFile != "" {
|
|
|
|
etcdClientFileArg := fmt.Sprintf("--etcd-certfile=%s", cfg.Etcd.CertFile)
|
|
|
|
etcdKeyFileArg := fmt.Sprintf("--etcd-keyfile=%s", cfg.Etcd.KeyFile)
|
|
|
|
command = append(command, etcdClientFileArg, etcdKeyFileArg)
|
|
|
|
}
|
|
|
|
|
2016-12-07 14:24:02 +00:00
|
|
|
if cfg.CloudProvider != "" {
|
|
|
|
command = append(command, "--cloud-provider="+cfg.CloudProvider)
|
|
|
|
|
|
|
|
// Only append the --cloud-config option if there's a such file
|
|
|
|
if _, err := os.Stat(DefaultCloudConfigPath); err == nil {
|
|
|
|
command = append(command, "--cloud-config="+DefaultCloudConfigPath)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-07 07:21:28 +00:00
|
|
|
return command
|
2016-10-19 12:30:03 +00:00
|
|
|
}
|
|
|
|
|
2017-01-20 16:26:48 +00:00
|
|
|
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),
|
2016-10-19 12:30:03 +00:00
|
|
|
"--address=127.0.0.1",
|
|
|
|
"--leader-elect",
|
|
|
|
"--master=127.0.0.1:8080",
|
|
|
|
"--cluster-name="+DefaultClusterName,
|
2017-01-20 22:33:06 +00:00
|
|
|
"--root-ca-file="+getCertFilePath(kubeadmconstants.CACertName),
|
|
|
|
"--service-account-private-key-file="+getCertFilePath(kubeadmconstants.APIServerKeyName),
|
|
|
|
"--cluster-signing-cert-file="+getCertFilePath(kubeadmconstants.CACertName),
|
|
|
|
"--cluster-signing-key-file="+getCertFilePath(kubeadmconstants.CAKeyName),
|
2017-01-19 15:59:32 +00:00
|
|
|
"--insecure-experimental-approve-all-kubelet-csrs-for-group="+KubeletBootstrapGroup,
|
2016-10-19 12:30:03 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
if cfg.CloudProvider != "" {
|
|
|
|
command = append(command, "--cloud-provider="+cfg.CloudProvider)
|
|
|
|
|
|
|
|
// Only append the --cloud-config option if there's a such file
|
|
|
|
if _, err := os.Stat(DefaultCloudConfigPath); err == nil {
|
|
|
|
command = append(command, "--cloud-config="+DefaultCloudConfigPath)
|
2016-10-07 19:27:03 +00:00
|
|
|
}
|
2016-09-07 12:53:11 +00:00
|
|
|
}
|
|
|
|
|
2016-10-19 12:30:03 +00:00
|
|
|
// Let the controller-manager allocate Node CIDRs for the Pod network.
|
|
|
|
// Each node will get a subspace of the address CIDR provided with --pod-network-cidr.
|
|
|
|
if cfg.Networking.PodSubnet != "" {
|
|
|
|
command = append(command, "--allocate-node-cidrs=true", "--cluster-cidr="+cfg.Networking.PodSubnet)
|
|
|
|
}
|
2017-01-20 16:26:48 +00:00
|
|
|
|
2016-12-07 07:21:28 +00:00
|
|
|
return command
|
2016-10-19 12:30:03 +00:00
|
|
|
}
|
|
|
|
|
2017-01-20 16:26:48 +00:00
|
|
|
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),
|
2016-10-19 12:30:03 +00:00
|
|
|
"--address=127.0.0.1",
|
|
|
|
"--leader-elect",
|
|
|
|
"--master=127.0.0.1:8080",
|
|
|
|
)
|
2017-01-20 16:26:48 +00:00
|
|
|
|
|
|
|
return command
|
2016-10-19 12:30:03 +00:00
|
|
|
}
|
|
|
|
|
2016-11-25 16:56:38 +00:00
|
|
|
func getProxyEnvVars() []api.EnvVar {
|
|
|
|
envs := []api.EnvVar{}
|
|
|
|
for _, env := range os.Environ() {
|
|
|
|
pos := strings.Index(env, "=")
|
|
|
|
if pos == -1 {
|
|
|
|
// malformed environment variable, skip it.
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
name := env[:pos]
|
|
|
|
value := env[pos+1:]
|
|
|
|
if strings.HasSuffix(strings.ToLower(name), "_proxy") && value != "" {
|
|
|
|
envVar := api.EnvVar{Name: name, Value: value}
|
|
|
|
envs = append(envs, envVar)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return envs
|
|
|
|
}
|
2017-01-20 16:26:48 +00:00
|
|
|
|
|
|
|
func getSelfHostedAPIServerEnv() []api.EnvVar {
|
|
|
|
podIPEnvVar := api.EnvVar{
|
|
|
|
Name: "POD_IP",
|
|
|
|
ValueFrom: &api.EnvVarSource{
|
|
|
|
FieldRef: &api.ObjectFieldSelector{
|
|
|
|
FieldPath: "status.podIP",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
return append(getProxyEnvVars(), podIPEnvVar)
|
|
|
|
}
|