Skip to content

Commit

Permalink
Merge pull request kubernetes#7 from pires/kubeadm-external-etcd
Browse files Browse the repository at this point in the history
Add support for external and optionally secured etcd cluster.
  • Loading branch information
errordeveloper committed Sep 20, 2016
2 parents c90f22b + 52127c8 commit b4fc62d
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 20 deletions.
6 changes: 6 additions & 0 deletions cmd/kubeadm/app/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ type InitFlags struct {
API struct {
AdvertiseAddrs []net.IP
ExternalDNSNames []string
Etcd struct {
ExternalEndpoints []string
ExternalCAFile string
ExternalCertFile string
ExternalKeyFile string
}
}
Services struct {
CIDR net.IPNet
Expand Down
19 changes: 19 additions & 0 deletions cmd/kubeadm/app/cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,25 @@ func NewCmdInit(out io.Writer, s *kubeadmapi.KubeadmConfig) *cobra.Command {
`(optional) allow to schedule workload to the node`,
)

// TODO (phase1+) @errordeveloper make the flags below not show up in --help but rather on --advanced-help

cmd.PersistentFlags().StringSliceVar(
&s.InitFlags.API.Etcd.ExternalEndpoints, "external-etcd-endpoints", []string{},
`(optional) etcd endpoints to use, in case you have an external cluster.`,
)
cmd.PersistentFlags().StringVar(
&s.InitFlags.API.Etcd.ExternalCAFile, "external-etcd-cafile", "",
`(optional) etcd certificate authority certificate file."`,
)
cmd.PersistentFlags().StringVar(
&s.InitFlags.API.Etcd.ExternalCertFile, "external-etcd-certfile", "",
`(optional) etcd client certificate file."`,
)
cmd.PersistentFlags().StringVar(
&s.InitFlags.API.Etcd.ExternalKeyFile, "external-etcd-keyfile", "",
`(optional) etcd client key file."`,
)

return cmd
}

Expand Down
83 changes: 63 additions & 20 deletions cmd/kubeadm/app/master/manifests.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"fmt"
"os"
"path"
"strings"

kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/api"
"k8s.io/kubernetes/cmd/kubeadm/app/images"
Expand Down Expand Up @@ -57,30 +58,38 @@ const (
// WriteStaticPodManifests builds manifest objects based on user provided configuration and then dumps it to disk
// where kubelet will pick and schedule them.
func WriteStaticPodManifests(s *kubeadmapi.KubeadmConfig) error {
// Placeholder for kube-apiserver pod spec command
apiServerCommand := getComponentCommand(apiServer, s)

// Check if the user decided to use an external etcd cluster
if len(s.InitFlags.API.Etcd.ExternalEndpoints) > 0 {
arg := fmt.Sprintf("--etcd-servers=%s", strings.Join(s.InitFlags.API.Etcd.ExternalEndpoints, ","))
apiServerCommand = append(apiServerCommand, arg)
} else {
apiServerCommand = append(apiServerCommand, "--etcd-servers=http://127.0.0.1:2379")
}

// Is etcd secured?
if s.InitFlags.API.Etcd.ExternalCAFile != "" {
etcdCAFileArg := fmt.Sprintf("--etcd-cafile=%s", s.InitFlags.API.Etcd.ExternalCAFile)
apiServerCommand = append(apiServerCommand, etcdCAFileArg)
}
if s.InitFlags.API.Etcd.ExternalCertFile != "" && s.InitFlags.API.Etcd.ExternalKeyFile != "" {
etcdClientFileArg := fmt.Sprintf("--etcd-certfile=%s", s.InitFlags.API.Etcd.ExternalCertFile)
etcdKeyFileArg := fmt.Sprintf("--etcd-keyfile=%s", s.InitFlags.API.Etcd.ExternalKeyFile)
apiServerCommand = append(apiServerCommand, etcdClientFileArg, etcdKeyFileArg)
}

// Prepare static pod specs
staticPodSpecs := map[string]api.Pod{
// TODO this needs a volume
etcd: componentPod(api.Container{
Command: []string{
"/usr/local/bin/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{etcdVolumeMount()},
Image: images.GetCoreImage(images.KubeEtcdImage, s.EnvParams["etcd_image"]),
LivenessProbe: componentProbe(2379, "/health"),
Name: etcd,
Resources: componentResources("200m"),
}, etcdVolume(s)),
// TODO bind-mount certs in
kubeAPIServer: componentPod(api.Container{
Name: kubeAPIServer,
Image: images.GetCoreImage(images.KubeAPIServerImage, s.EnvParams["hyperkube_image"]),
Command: getComponentCommand(apiServer, s),
VolumeMounts: []api.VolumeMount{k8sVolumeMount()},
Command: apiServerCommand,
VolumeMounts: []api.VolumeMount{certsVolumeMount(), k8sVolumeMount()},
LivenessProbe: componentProbe(8080, "/healthz"),
Resources: componentResources("250m"),
}, k8sVolume(s)),
}, certsVolume(s), k8sVolume(s)),
kubeControllerManager: componentPod(api.Container{
Name: kubeControllerManager,
Image: images.GetCoreImage(images.KubeControllerManagerImage, s.EnvParams["hyperkube_image"]),
Expand All @@ -98,6 +107,23 @@ func WriteStaticPodManifests(s *kubeadmapi.KubeadmConfig) error {
}),
}

// Add etcd static pod spec only if external etcd is not configured
if len(s.InitFlags.API.Etcd.ExternalEndpoints) == 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, s.EnvParams["etcd_image"]),
LivenessProbe: componentProbe(2379, "/health"),
Resources: componentResources("200m"),
}, certsVolume(s), etcdVolume(s), k8sVolume(s))
}

manifestsPath := path.Join(s.EnvParams["kubernetes_dir"], "manifests")
if err := os.MkdirAll(manifestsPath, 0700); err != nil {
return fmt.Errorf("<master/manifests> failed to create directory %q [%s]", manifestsPath, err)
Expand All @@ -115,8 +141,7 @@ func WriteStaticPodManifests(s *kubeadmapi.KubeadmConfig) error {
return nil
}

// etcdVolume returns an host-path volume for storing etcd data.
// By using a host-path, the data will survive pod restart.
// etcdVolume exposes a path on the host in order to guarantee data survival during reboot.
func etcdVolume(s *kubeadmapi.KubeadmConfig) api.Volume {
return api.Volume{
Name: "etcd",
Expand All @@ -133,6 +158,24 @@ func etcdVolumeMount() api.VolumeMount {
}
}

// certsVolume exposes host SSL certificates to pod containers.
func certsVolume(s *kubeadmapi.KubeadmConfig) api.Volume {
return api.Volume{
Name: "certs",
VolumeSource: api.VolumeSource{
// TODO make path configurable
HostPath: &api.HostPathVolumeSource{Path: "/etc/ssl/certs"},
},
}
}

func certsVolumeMount() api.VolumeMount {
return api.VolumeMount{
Name: "certs",
MountPath: "/etc/ssl/certs",
}
}

func k8sVolume(s *kubeadmapi.KubeadmConfig) api.Volume {
return api.Volume{
Name: "pki",
Expand Down

0 comments on commit b4fc62d

Please sign in to comment.