Cleanup/refactor some things, make it possible to use individual images, hide unused flags

pull/6/head
Lucas Käldström 2016-09-07 15:53:11 +03:00 committed by Ilya Dmitrichenko
parent b48df06aba
commit 26c4f593aa
No known key found for this signature in database
GPG Key ID: E7889175A6C0CEB9
17 changed files with 153 additions and 68 deletions

View File

@ -20,7 +20,6 @@ import (
"fmt"
"os"
"path"
"runtime"
"strings"
"github.com/spf13/pflag"
@ -43,12 +42,11 @@ func getEnvParams() map[string]string {
envParams := map[string]string{
"prefix": globalPrefix,
"host_pki_path": path.Join(globalPrefix, "pki"),
"hyperkube_image": fmt.Sprintf("gcr.io/google_containers/hyperkube-%s:%s", runtime.GOARCH, "v1.4.0-alpha.3"),
"discovery_image": "dgoodwin/kubediscovery:latest",
"etcd_image": fmt.Sprintf("gcr.io/google_containers/etcd-%s:%s", runtime.GOARCH, "2.2.5"),
"hyperkube_image": "",
"discovery_image": "dgoodwin/kubediscovery:latest", // TODO(phase1): fmt.Sprintf("gcr.io/google_containers/kube-discovery-%s:%s", runtime.GOARCH, "1.0"),
"etcd_image": "",
"component_loglevel": "--v=4",
"dns_domain": "cluster.local",
"dns_replicas": "1",
}
for k := range envParams {
@ -65,6 +63,10 @@ func Run() error {
logs.InitLogs()
defer logs.FlushLogs()
// We do not want these flags to show up in --help
pflag.CommandLine.MarkHidden("google-json-key")
pflag.CommandLine.MarkHidden("log-flush-frequency")
cmd := cmd.NewKubeadmCommand(cmdutil.NewFactory(nil), os.Stdin, os.Stdout, os.Stderr, getEnvParams())
return cmd.Execute()
}

View File

@ -22,6 +22,7 @@ import (
"k8s.io/kubernetes/cmd/kubeadm/app"
)
// TODO(phase1): check for root
func main() {
if err := app.Run(); err != nil {
os.Exit(1)

View File

@ -14,7 +14,11 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package kubeadmapi
package api
import (
"net"
)
type BootstrapParams struct {
// TODO this is mostly out of date and bloated now, let's revisit this soon
@ -32,7 +36,8 @@ type OutOfBandDiscovery struct {
BearerToken string // set based on Token
// 'init-master' side
ApiServerDNSName string // optional, used in master bootstrap
ListenIP string // optional IP for master to listen on, rather than autodetect
ListenIP net.IP // optional IP for master to listen on, rather than autodetect
UseHyperkubeImage bool
}
type ClusterInfo struct {

View File

@ -42,7 +42,7 @@ var (
func NewCmdInit(out io.Writer, params *kubeadmapi.BootstrapParams) *cobra.Command {
cmd := &cobra.Command{
Use: "init --token <secret> [--listen-ip <addr>]",
Use: "init",
Short: "Run this on the first server you deploy onto.",
Run: func(cmd *cobra.Command, args []string) {
err := RunInit(out, cmd, args, params)
@ -50,21 +50,25 @@ func NewCmdInit(out io.Writer, params *kubeadmapi.BootstrapParams) *cobra.Comman
},
}
cmd.PersistentFlags().StringVarP(&params.Discovery.ListenIP, "listen-ip", "", "",
cmd.PersistentFlags().IPVar(&params.Discovery.ListenIP, "listen-ip", nil,
`(optional) IP address to listen on, in case autodetection fails.`)
cmd.PersistentFlags().StringVarP(&params.Discovery.GivenToken, "token", "", "",
cmd.PersistentFlags().StringVar(&params.Discovery.GivenToken, "token", "",
`(optional) Shared secret used to secure bootstrap. Will be generated and displayed if not provided.`)
cmd.PersistentFlags().BoolVar(&params.Discovery.UseHyperkubeImage, "use-hyperkube", false,
`(optional) Use the hyperkube image for running the apiserver, controller-manager, scheduler and proxy.`)
return cmd
}
func RunInit(out io.Writer, cmd *cobra.Command, args []string, params *kubeadmapi.BootstrapParams) error {
if params.Discovery.ListenIP == "" {
// Auto-detect the IP
if params.Discovery.ListenIP == nil {
ip, err := netutil.ChooseHostInterface()
if err != nil {
return err
}
params.Discovery.ListenIP = ip.String()
params.Discovery.ListenIP = ip
}
if err := kubemaster.CreateTokenAuthFile(params); err != nil {
return err

View File

@ -107,25 +107,27 @@ func NewCmdManualBootstrapInitMaster(out io.Writer, params *kubeadmapi.Bootstrap
}
params.Discovery.ApiServerURLs = "http://127.0.0.1:8080/" // On the master, assume you can talk to the API server
cmd.PersistentFlags().StringVarP(&params.Discovery.ApiServerDNSName, "api-dns-name", "", "",
cmd.PersistentFlags().StringVar(&params.Discovery.ApiServerDNSName, "api-dns-name", "",
`(optional) DNS name for the API server, will be encoded into
subjectAltName in the resulting (generated) TLS certificates`)
cmd.PersistentFlags().StringVarP(&params.Discovery.ListenIP, "listen-ip", "", "",
cmd.PersistentFlags().IPVar(&params.Discovery.ListenIP, "listen-ip", nil,
`(optional) IP address to listen on, in case autodetection fails.`)
cmd.PersistentFlags().StringVarP(&params.Discovery.BearerToken, "token", "", "",
cmd.PersistentFlags().StringVar(&params.Discovery.BearerToken, "token", "",
`(optional) Shared secret used to secure bootstrap. Will be generated and displayed if not provided.`)
return cmd
}
func RunManualBootstrapInitMaster(out io.Writer, cmd *cobra.Command, args []string, params *kubeadmapi.BootstrapParams) error {
if params.Discovery.ListenIP == "" {
// Auto-detect the IP
if params.Discovery.ListenIP == nil {
ip, err := netutil.ChooseHostInterface()
if err != nil {
return fmt.Errorf("<cmd/join> unable to autodetect IP address [%s], please specify with --listen-ip", err)
return err
}
params.Discovery.ListenIP = ip.String()
params.Discovery.ListenIP = ip
}
if err := kubemaster.CreateTokenAuthFile(params); err != nil {
return err
}

View File

@ -0,0 +1,76 @@
/*
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.
*/
package images
import (
"fmt"
"runtime"
)
const (
KubeEtcdImage = "etcd"
KubeApiServerImage = "apiserver"
KubeControllerManagerImage = "controller-manager"
KubeSchedulerImage = "scheduler"
KubeProxyImage = "proxy"
KubeDnsImage = "kube-dns"
KubeDnsmasqImage = "dnsmasq"
KubeExechealthzImage = "exechealthz"
gcrPrefix = "gcr.io/google_containers"
etcdVersion = "2.2.5"
kubeVersion = "v1.4.0-alpha.3"
kubeDnsVersion = "1.7"
dnsmasqVersion = "1.3"
exechealthzVersion = "1.1"
)
func GetCoreImage(image string, overrideImage string, useHyperkube bool) string {
if overrideImage != "" {
return overrideImage
}
if useHyperkube {
return map[string]string{
KubeEtcdImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "etcd", runtime.GOARCH, etcdVersion),
KubeApiServerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "hyperkube", runtime.GOARCH, kubeVersion),
KubeControllerManagerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "hyperkube", runtime.GOARCH, kubeVersion),
KubeSchedulerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "hyperkube", runtime.GOARCH, kubeVersion),
KubeProxyImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "hyperkube", runtime.GOARCH, kubeVersion),
}[image]
}
return map[string]string{
KubeEtcdImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "etcd", runtime.GOARCH, etcdVersion),
KubeApiServerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-apiserver", runtime.GOARCH, kubeVersion),
KubeControllerManagerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-controller-manager", runtime.GOARCH, kubeVersion),
KubeSchedulerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-scheduler", runtime.GOARCH, kubeVersion),
KubeProxyImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-proxy", runtime.GOARCH, kubeVersion),
}[image]
}
func GetAddonImage(image string) string {
return map[string]string{
KubeDnsImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-dns", runtime.GOARCH, kubeDnsVersion),
KubeDnsmasqImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-dnsmasq", runtime.GOARCH, dnsmasqVersion),
KubeExechealthzImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "exechealthz", runtime.GOARCH, exechealthzVersion),
}[image]
}

View File

@ -14,18 +14,17 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package kubemaster
package master
import (
"fmt"
"path"
"runtime"
"strconv"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/resource"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
kubeadmapi "k8s.io/kubernetes/pkg/kubeadm/api"
"k8s.io/kubernetes/pkg/kubeadm/images"
"k8s.io/kubernetes/pkg/util/intstr"
)
@ -35,13 +34,11 @@ func createKubeProxyPodSpec(params *kubeadmapi.BootstrapParams) api.PodSpec {
SecurityContext: &api.PodSecurityContext{HostNetwork: true},
Containers: []api.Container{{
Name: "kube-proxy",
Image: params.EnvParams["hyperkube_image"],
Command: []string{
"/hyperkube",
"proxy",
Image: images.GetCoreImage(images.KubeProxyImage, params.EnvParams["hyperkube_image"], params.Discovery.UseHyperkubeImage),
Command: append(getImageEntrypoint("proxy", params.Discovery.UseHyperkubeImage), []string{
"--kubeconfig=/run/kubeconfig",
params.EnvParams["component_loglevel"],
},
}...),
SecurityContext: &api.SecurityContext{Privileged: &privilegedTrue},
VolumeMounts: []api.VolumeMount{
{
@ -83,6 +80,7 @@ func createKubeProxyPodSpec(params *kubeadmapi.BootstrapParams) api.PodSpec {
}
}
// TODO(phase1): Create the DNS service as well
func createKubeDNSPodSpec(params *kubeadmapi.BootstrapParams) api.PodSpec {
dnsPodResources := api.ResourceList{
@ -100,7 +98,7 @@ func createKubeDNSPodSpec(params *kubeadmapi.BootstrapParams) api.PodSpec {
// DNS server
{
Name: "kube-dns",
Image: "gcr.io/google_containers/kubedns-" + runtime.GOARCH + ":1.7",
Image: images.GetAddonImage(images.KubeDnsImage),
Resources: api.ResourceRequirements{
Limits: dnsPodResources,
Requests: dnsPodResources,
@ -152,7 +150,7 @@ func createKubeDNSPodSpec(params *kubeadmapi.BootstrapParams) api.PodSpec {
// dnsmasq
{
Name: "dnsmasq",
Image: "gcr.io/google_containers/kube-dnsmasq-" + runtime.GOARCH + ":1.3",
Image: images.GetAddonImage(images.KubeDnsmasqImage),
Resources: api.ResourceRequirements{
Limits: dnsPodResources,
Requests: dnsPodResources,
@ -178,7 +176,7 @@ func createKubeDNSPodSpec(params *kubeadmapi.BootstrapParams) api.PodSpec {
// healthz
{
Name: "healthz",
Image: "gcr.io/google_containers/exechealthz-" + runtime.GOARCH + ":1.1",
Image: images.GetAddonImage(images.KubeExechealthzImage),
Resources: api.ResourceRequirements{
Limits: healthzPodResources,
Requests: healthzPodResources,
@ -219,14 +217,7 @@ func CreateEssentialAddons(params *kubeadmapi.BootstrapParams, client *clientset
fmt.Println("<master/addons> created essential addon: kube-proxy")
// TODO should we wait for it to become ready at least on the master?
dnsReplicas, err := strconv.Atoi(params.EnvParams["dns_replicas"])
if err != nil {
dnsReplicas = 1
}
kubeDNSDeployment := NewDeployment("kube-dns", int32(dnsReplicas), createKubeDNSPodSpec(params))
kubeDNSDeployment := NewDeployment("kube-dns", 1, createKubeDNSPodSpec(params))
SetMasterTaintTolerations(&kubeDNSDeployment.Spec.Template.ObjectMeta)
if _, err := client.Extensions().Deployments(api.NamespaceSystem).Create(kubeDNSDeployment); err != nil {

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package kubemaster
package master
import (
"encoding/json"

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package kubemaster
package master
import (
"crypto/x509"

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package kubemaster
package master
import (
"crypto/rsa"

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package kubemaster
package master
import (
"bytes"
@ -27,6 +27,7 @@ import (
"k8s.io/kubernetes/pkg/api/unversioned"
api "k8s.io/kubernetes/pkg/api/v1"
kubeadmapi "k8s.io/kubernetes/pkg/kubeadm/api"
"k8s.io/kubernetes/pkg/kubeadm/images"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/util/intstr"
)
@ -50,11 +51,11 @@ func WriteStaticPodManifests(params *kubeadmapi.BootstrapParams) error {
"etcd": componentPod(api.Container{
Command: []string{
"/usr/local/bin/etcd",
"--listen-client-urls=http://127.0.0.1:2379,http://127.0.0.1:4001",
"--advertise-client-urls=http://127.0.0.1:2379,http://127.0.0.1:4001",
"--listen-client-urls=http://127.0.0.1:2379",
"--advertise-client-urls=http://127.0.0.1:2379",
"--data-dir=/var/etcd/data",
},
Image: params.EnvParams["etcd_image"],
Image: images.GetCoreImage(images.KubeEtcdImage, params.EnvParams["etcd_image"], params.Discovery.UseHyperkubeImage),
LivenessProbe: componentProbe(2379, "/health"),
Name: "etcd-server",
Resources: componentResources("200m"),
@ -62,10 +63,8 @@ func WriteStaticPodManifests(params *kubeadmapi.BootstrapParams) error {
// TODO bind-mount certs in
"kube-apiserver": componentPod(api.Container{
Name: "kube-apiserver",
Image: params.EnvParams["hyperkube_image"],
Command: []string{
"/hyperkube",
"apiserver",
Image: images.GetCoreImage(images.KubeApiServerImage, params.EnvParams["hyperkube_image"], params.Discovery.UseHyperkubeImage),
Command: append(getImageEntrypoint("apiserver", params.Discovery.UseHyperkubeImage), []string{
"--address=127.0.0.1",
"--etcd-servers=http://127.0.0.1:2379",
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota",
@ -78,17 +77,15 @@ func WriteStaticPodManifests(params *kubeadmapi.BootstrapParams) error {
"--allow-privileged",
params.EnvParams["component_loglevel"],
"--token-auth-file=/etc/kubernetes/pki/tokens.csv",
},
}...),
VolumeMounts: []api.VolumeMount{pkiVolumeMount()},
LivenessProbe: componentProbe(8080, "/healthz"),
Resources: componentResources("250m"),
}, pkiVolume(params)),
"kube-controller-manager": componentPod(api.Container{
Name: "kube-controller-manager",
Image: params.EnvParams["hyperkube_image"],
Command: []string{
"/hyperkube",
"controller-manager",
Image: images.GetCoreImage(images.KubeControllerManagerImage, params.EnvParams["hyperkube_image"], params.Discovery.UseHyperkubeImage),
Command: append(getImageEntrypoint("controller-manager", params.Discovery.UseHyperkubeImage), []string{
"--leader-elect",
MASTER,
CLUSTER_NAME,
@ -97,22 +94,21 @@ func WriteStaticPodManifests(params *kubeadmapi.BootstrapParams) error {
"--cluster-signing-cert-file=/etc/kubernetes/pki/ca.pem",
"--cluster-signing-key-file=/etc/kubernetes/pki/ca-key.pem",
"--insecure-experimental-approve-all-kubelet-csrs-for-group=system:kubelet-bootstrap",
"--cluster-cidr=10.2.0.0/16",
params.EnvParams["component_loglevel"],
},
}...),
VolumeMounts: []api.VolumeMount{pkiVolumeMount()},
LivenessProbe: componentProbe(10252, "/healthz"),
Resources: componentResources("200m"),
}, pkiVolume(params)),
"kube-scheduler": componentPod(api.Container{
Name: "kube-scheduler",
Image: params.EnvParams["hyperkube_image"],
Command: []string{
"/hyperkube",
"scheduler",
Image: images.GetCoreImage(images.KubeSchedulerImage, params.EnvParams["hyperkube_image"], params.Discovery.UseHyperkubeImage),
Command: append(getImageEntrypoint("scheduler", params.Discovery.UseHyperkubeImage), []string{
"--leader-elect",
MASTER,
params.EnvParams["component_loglevel"],
},
}...),
LivenessProbe: componentProbe(10251, "/healthz"),
Resources: componentResources("100m"),
}),
@ -192,3 +188,11 @@ func componentPod(container api.Container, volumes ...api.Volume) api.Pod {
},
}
}
func getImageEntrypoint(component string, useHyperkube bool) []string {
if useHyperkube {
return []string{"/hyperkube", component}
}
return []string{"/usr/local/bin/kube-" + component}
}

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package kubemaster
package master
import (
"crypto/rsa"
@ -137,8 +137,8 @@ func CreatePKIAssets(params *kubeadmapi.BootstrapParams) (*rsa.PrivateKey, *x509
altNames certutil.AltNames // TODO actual SANs
)
if params.Discovery.ListenIP != "" {
altNames.IPs = append(altNames.IPs, net.ParseIP(params.Discovery.ListenIP))
if params.Discovery.ListenIP != nil {
altNames.IPs = append(altNames.IPs, params.Discovery.ListenIP)
}
if params.Discovery.ApiServerDNSName != "" {

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package kubemaster
package master
import (
"bytes"

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package kubenode
package node
import (
"fmt"

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package kubenode
package node
import (
"bytes"
@ -25,7 +25,7 @@ import (
"net/url"
"strings"
"github.com/square/go-jose"
jose "github.com/square/go-jose"
clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
kubeadmapi "k8s.io/kubernetes/pkg/kubeadm/api"
)

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package kubeadmutil
package util
import (
"fmt"

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package kubeadmutil
package util
import (
"crypto/rand"