mirror of https://github.com/k3s-io/k3s
kubeadm: refactor config
1) break object into substructures 2) seperate a config object for master and nodepull/6/head
parent
3933ddbc9a
commit
56ea178e7c
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
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 api
|
||||
|
||||
const (
|
||||
DefaultServiceDNSDomain = "cluster.local"
|
||||
DefaultServicesSubnet = "10.12.0.0/12"
|
||||
DefaultKubernetesVersion = "v1.4.0"
|
||||
)
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
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 api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// TODO(phase2) use componentconfig
|
||||
// we need some params for testing etc, let's keep these hidden for now
|
||||
func GetEnvParams() map[string]string {
|
||||
|
||||
envParams := map[string]string{
|
||||
// TODO(phase1+): Mode prefix and host_pki_path to another place as constants, and use them everywhere
|
||||
// Right now they're used here and there, but not consequently
|
||||
"kubernetes_dir": "/etc/kubernetes",
|
||||
"host_pki_path": "/etc/kubernetes/pki",
|
||||
"host_etcd_path": "/var/lib/etcd",
|
||||
"hyperkube_image": "",
|
||||
"discovery_image": fmt.Sprintf("gcr.io/google_containers/kube-discovery-%s:%s", runtime.GOARCH, "1.0"),
|
||||
"etcd_image": "",
|
||||
"component_loglevel": "--v=4",
|
||||
}
|
||||
|
||||
for k := range envParams {
|
||||
if v := os.Getenv(fmt.Sprintf("KUBE_%s", strings.ToUpper(k))); v != "" {
|
||||
envParams[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return envParams
|
||||
}
|
|
@ -16,89 +16,54 @@ limitations under the License.
|
|||
|
||||
package api
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
import "k8s.io/kubernetes/pkg/api/unversioned"
|
||||
|
||||
// KubeadmConfig TODO add description
|
||||
// TODO(phase1+) @krousey: Please don't embed structs. It obfuscates the source of the fields and doesn't really buy you anything.
|
||||
type KubeadmConfig struct {
|
||||
InitFlags
|
||||
JoinFlags
|
||||
Secrets struct {
|
||||
GivenToken string // dot-separated `<TokenID>.<Token>` set by the user
|
||||
TokenID string // optional on master side, will be generated if not specified
|
||||
Token []byte // optional on master side, will be generated if not specified
|
||||
BearerToken string // set based on Token
|
||||
}
|
||||
EnvParams map[string]string // TODO(phase2) this is likely to be come componentconfig
|
||||
type MasterConfiguration struct {
|
||||
unversioned.TypeMeta
|
||||
|
||||
Secrets Secrets
|
||||
API API
|
||||
Etcd Etcd
|
||||
Networking Networking
|
||||
KubernetesVersion string
|
||||
CloudProvider string
|
||||
}
|
||||
|
||||
// TODO(phase2) should we add validation functions for these structs?
|
||||
|
||||
// TODO(phase1+) refactor token handling
|
||||
// - https://github.com/kubernetes/kubernetes/pull/33262/files#r80333662
|
||||
// - https://github.com/kubernetes/kubernetes/pull/33262/files#r80336374
|
||||
// - https://github.com/kubernetes/kubernetes/pull/33262/files#r80333982
|
||||
|
||||
// InitFlags holds values for "kubeadm init" command flags.
|
||||
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
|
||||
DNSDomain string
|
||||
}
|
||||
PodNetwork struct {
|
||||
CIDR net.IPNet
|
||||
}
|
||||
Versions struct {
|
||||
Kubernetes string
|
||||
}
|
||||
CloudProvider string
|
||||
type API struct {
|
||||
AdvertiseAddresses []string
|
||||
ExternalDNSNames []string
|
||||
}
|
||||
|
||||
const (
|
||||
DefaultServiceDNSDomain = "cluster.local"
|
||||
DefaultServicesCIDRString = "10.12.0.0/12"
|
||||
DefaultKubernetesVersion = "v1.4.0"
|
||||
)
|
||||
|
||||
var (
|
||||
DefaultServicesCIDR *net.IPNet
|
||||
ListOfCloudProviders = []string{
|
||||
"aws",
|
||||
"azure",
|
||||
"cloudstack",
|
||||
"gce",
|
||||
"mesos",
|
||||
"openstack",
|
||||
"ovirt",
|
||||
"rackspace",
|
||||
"vsphere",
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
_, DefaultServicesCIDR, _ = net.ParseCIDR(DefaultServicesCIDRString)
|
||||
type Networking struct {
|
||||
ServiceSubnet string
|
||||
PodSubnet string
|
||||
DNSDomain string
|
||||
}
|
||||
|
||||
// JoinFlags holds values for "kubeadm join" command flags.
|
||||
type JoinFlags struct {
|
||||
MasterAddrs []net.IP
|
||||
// TODO(phase1+) add manual mode flags here, e.g. RootCACertPath
|
||||
type Etcd struct {
|
||||
Endpoints []string
|
||||
CAFile string
|
||||
CertFile string
|
||||
KeyFile string
|
||||
}
|
||||
|
||||
type Secrets struct {
|
||||
GivenToken string // dot-separated `<TokenID>.<Token>` set by the user
|
||||
TokenID string // optional on master side, will be generated if not specified
|
||||
Token []byte // optional on master side, will be generated if not specified
|
||||
BearerToken string // set based on Token
|
||||
}
|
||||
|
||||
type NodeConfiguration struct {
|
||||
unversioned.TypeMeta
|
||||
|
||||
MasterAddresses []string
|
||||
Secrets Secrets
|
||||
}
|
||||
|
||||
// ClusterInfo TODO add description
|
||||
type ClusterInfo struct {
|
||||
unversioned.TypeMeta
|
||||
// TODO(phase1+) this may become simply `api.Config`
|
||||
CertificateAuthorities []string `json:"certificateAuthorities"`
|
||||
Endpoints []string `json:"endpoints"`
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
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 api
|
||||
|
||||
func ValidateMasterConfiguration(o *MasterConfiguration) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func ValidateNodeConfiguration(o *MasterConfiguration) error {
|
||||
return nil
|
||||
}
|
|
@ -22,12 +22,11 @@ import (
|
|||
"github.com/renstrom/dedent"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/api"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/util/flag"
|
||||
)
|
||||
|
||||
func NewKubeadmCommand(f *cmdutil.Factory, in io.Reader, out, err io.Writer, envParams map[string]string) *cobra.Command {
|
||||
func NewKubeadmCommand(f *cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Command {
|
||||
cmds := &cobra.Command{
|
||||
Use: "kubeadm",
|
||||
Short: "kubeadm: easily bootstrap a secure Kubernetes cluster.",
|
||||
|
@ -76,14 +75,11 @@ func NewKubeadmCommand(f *cmdutil.Factory, in io.Reader, out, err io.Writer, env
|
|||
// would then be able to look at files users has given an diff or validate if those are sane, we could also warn
|
||||
// if any of the files had been deprecated
|
||||
|
||||
s := new(kubeadmapi.KubeadmConfig)
|
||||
s.EnvParams = envParams
|
||||
|
||||
cmds.ResetFlags()
|
||||
cmds.SetGlobalNormalizationFunc(flag.WarnWordSepNormalizeFunc)
|
||||
|
||||
cmds.AddCommand(NewCmdInit(out, s))
|
||||
cmds.AddCommand(NewCmdJoin(out, s))
|
||||
cmds.AddCommand(NewCmdInit(out))
|
||||
cmds.AddCommand(NewCmdJoin(out))
|
||||
cmds.AddCommand(NewCmdVersion(out))
|
||||
|
||||
return cmds
|
||||
|
|
|
@ -19,8 +19,6 @@ package cmd
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/renstrom/dedent"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -28,6 +26,7 @@ import (
|
|||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/api"
|
||||
kubemaster "k8s.io/kubernetes/cmd/kubeadm/app/master"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
netutil "k8s.io/kubernetes/pkg/util/net"
|
||||
)
|
||||
|
@ -43,66 +42,66 @@ var (
|
|||
)
|
||||
|
||||
// NewCmdInit returns "kubeadm init" command.
|
||||
func NewCmdInit(out io.Writer, s *kubeadmapi.KubeadmConfig) *cobra.Command {
|
||||
advertiseAddrs := &[]string{} // TODO(pahse1+) make it work somehow else, custom flag or whatever
|
||||
func NewCmdInit(out io.Writer) *cobra.Command {
|
||||
cfg := &kubeadmapi.MasterConfiguration{}
|
||||
cmd := &cobra.Command{
|
||||
Use: "init",
|
||||
Short: "Run this in order to set up the Kubernetes master.",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunInit(out, cmd, args, s, advertiseAddrs)
|
||||
err := RunInit(out, cmd, args, cfg)
|
||||
cmdutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&s.Secrets.GivenToken, "token", "",
|
||||
&cfg.Secrets.GivenToken, "token", "",
|
||||
"Shared secret used to secure cluster bootstrap; if none is provided, one will be generated for you",
|
||||
)
|
||||
cmd.PersistentFlags().StringSliceVar(
|
||||
advertiseAddrs, "api-advertise-addresses", []string{},
|
||||
&cfg.API.AdvertiseAddresses, "api-advertise-addresses", []string{},
|
||||
"The IP addresses to advertise, in case autodetection fails",
|
||||
)
|
||||
cmd.PersistentFlags().StringSliceVar(
|
||||
&s.InitFlags.API.ExternalDNSNames, "api-external-dns-names", []string{},
|
||||
&cfg.API.ExternalDNSNames, "api-external-dns-names", []string{},
|
||||
"The DNS names to advertise, in case you have configured them yourself",
|
||||
)
|
||||
cmd.PersistentFlags().IPNetVar(
|
||||
&s.InitFlags.Services.CIDR, "service-cidr", *kubeadmapi.DefaultServicesCIDR,
|
||||
`Use alterantive range of IP address for service VIPs, defaults to `+
|
||||
kubeadmapi.DefaultServicesCIDRString,
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&cfg.Networking.ServiceSubnet, "service-cidr", kubeadmapi.DefaultServicesSubnet,
|
||||
"Use alterantive range of IP address for service VIPs",
|
||||
)
|
||||
cmd.PersistentFlags().IPNetVar(
|
||||
&s.InitFlags.PodNetwork.CIDR, "pod-network-cidr", net.IPNet{},
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&cfg.Networking.PodSubnet, "pod-network-cidr", "",
|
||||
"Specify range of IP addresses for the pod network; if set, the control plane will automatically allocate CIDRs for every node",
|
||||
)
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&s.InitFlags.Services.DNSDomain, "service-dns-domain", kubeadmapi.DefaultServiceDNSDomain,
|
||||
&cfg.Networking.DNSDomain, "service-dns-domain", kubeadmapi.DefaultServiceDNSDomain,
|
||||
`Use alternative domain for services, e.g. "myorg.internal"`,
|
||||
)
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&s.InitFlags.CloudProvider, "cloud-provider", "",
|
||||
&cfg.CloudProvider, "cloud-provider", "",
|
||||
`Enable cloud provider features (external load-balancers, storage, etc), e.g. "gce"`,
|
||||
)
|
||||
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&s.InitFlags.Versions.Kubernetes, "use-kubernetes-version", kubeadmapi.DefaultKubernetesVersion,
|
||||
&cfg.KubernetesVersion, "use-kubernetes-version", kubeadmapi.DefaultKubernetesVersion,
|
||||
`Choose a specific Kubernetes version for the control plane`,
|
||||
)
|
||||
|
||||
// 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{},
|
||||
&cfg.Etcd.Endpoints, "external-etcd-endpoints", []string{},
|
||||
"etcd endpoints to use, in case you have an external cluster",
|
||||
)
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&s.InitFlags.API.Etcd.ExternalCAFile, "external-etcd-cafile", "",
|
||||
&cfg.Etcd.CAFile, "external-etcd-cafile", "",
|
||||
"etcd certificate authority certificate file. Note: The path must be in /etc/ssl/certs",
|
||||
)
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&s.InitFlags.API.Etcd.ExternalCertFile, "external-etcd-certfile", "",
|
||||
&cfg.Etcd.CertFile, "external-etcd-certfile", "",
|
||||
"etcd client certificate file. Note: The path must be in /etc/ssl/certs",
|
||||
)
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&s.InitFlags.API.Etcd.ExternalKeyFile, "external-etcd-keyfile", "",
|
||||
&cfg.Etcd.KeyFile, "external-etcd-keyfile", "",
|
||||
"etcd client key file. Note: The path must be in /etc/ssl/certs",
|
||||
)
|
||||
|
||||
|
@ -110,57 +109,40 @@ func NewCmdInit(out io.Writer, s *kubeadmapi.KubeadmConfig) *cobra.Command {
|
|||
}
|
||||
|
||||
// RunInit executes master node provisioning, including certificates, needed static pod manifests, etc.
|
||||
func RunInit(out io.Writer, cmd *cobra.Command, args []string, s *kubeadmapi.KubeadmConfig, advertiseAddrs *[]string) error {
|
||||
func RunInit(out io.Writer, cmd *cobra.Command, args []string, cfg *kubeadmapi.MasterConfiguration) error {
|
||||
// Auto-detect the IP
|
||||
if len(*advertiseAddrs) == 0 {
|
||||
if len(cfg.API.AdvertiseAddresses) == 0 {
|
||||
// TODO(phase1+) perhaps we could actually grab eth0 and eth1
|
||||
ip, err := netutil.ChooseHostInterface()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.InitFlags.API.AdvertiseAddrs = []net.IP{ip}
|
||||
} else {
|
||||
for _, i := range *advertiseAddrs {
|
||||
addr := net.ParseIP(i)
|
||||
if addr == nil {
|
||||
// TODO(phase1+) custom flag will help to get this error message into a better place
|
||||
return fmt.Errorf("<cmd/init> failed to parse %q (in %q) as an IP address", i, "--api-advertise-addresses="+strings.Join(*advertiseAddrs, ","))
|
||||
}
|
||||
s.InitFlags.API.AdvertiseAddrs = append(s.InitFlags.API.AdvertiseAddrs, addr)
|
||||
}
|
||||
cfg.API.AdvertiseAddresses = []string{ip.String()}
|
||||
}
|
||||
|
||||
// TODO(phase1+) create a custom flag
|
||||
if s.InitFlags.CloudProvider != "" {
|
||||
found := false
|
||||
for _, provider := range kubeadmapi.ListOfCloudProviders {
|
||||
if provider == s.InitFlags.CloudProvider {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if found {
|
||||
fmt.Printf("<cmd/init> cloud provider %q initialized for the control plane. Remember to set the same cloud provider flag on the kubelet.\n", s.InitFlags.CloudProvider)
|
||||
if cfg.CloudProvider != "" {
|
||||
if cloudprovider.IsCloudProvider(cfg.CloudProvider) {
|
||||
fmt.Printf("<cmd/init> cloud provider %q initialized for the control plane. Remember to set the same cloud provider flag on the kubelet.\n", cfg.CloudProvider)
|
||||
} else {
|
||||
return fmt.Errorf("<cmd/init> cloud provider %q is not supported, you can use any of %v, or leave it unset.\n", s.InitFlags.CloudProvider, kubeadmapi.ListOfCloudProviders)
|
||||
return fmt.Errorf("<cmd/init> cloud provider %q is not supported, you can use any of %v, or leave it unset.\n", cfg.CloudProvider, cloudprovider.CloudProviders())
|
||||
}
|
||||
}
|
||||
|
||||
if err := kubemaster.CreateTokenAuthFile(s); err != nil {
|
||||
if err := kubemaster.CreateTokenAuthFile(&cfg.Secrets); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := kubemaster.WriteStaticPodManifests(s); err != nil {
|
||||
if err := kubemaster.WriteStaticPodManifests(cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
caKey, caCert, err := kubemaster.CreatePKIAssets(s)
|
||||
caKey, caCert, err := kubemaster.CreatePKIAssets(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
kubeconfigs, err := kubemaster.CreateCertsAndConfigForClients(s, []string{"kubelet", "admin"}, caKey, caCert)
|
||||
kubeconfigs, err := kubemaster.CreateCertsAndConfigForClients(cfg.API.AdvertiseAddresses, []string{"kubelet", "admin"}, caKey, caCert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -175,7 +157,7 @@ func RunInit(out io.Writer, cmd *cobra.Command, args []string, s *kubeadmapi.Kub
|
|||
// importing existing files, may be we could even make our command idempotant,
|
||||
// or at least allow for external PKI and stuff)
|
||||
for name, kubeconfig := range kubeconfigs {
|
||||
if err := kubeadmutil.WriteKubeconfigIfNotExists(s, name, kubeconfig); err != nil {
|
||||
if err := kubeadmutil.WriteKubeconfigIfNotExists(name, kubeconfig); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -190,18 +172,18 @@ func RunInit(out io.Writer, cmd *cobra.Command, args []string, s *kubeadmapi.Kub
|
|||
return err
|
||||
}
|
||||
|
||||
if err := kubemaster.CreateDiscoveryDeploymentAndSecret(s, client, caCert); err != nil {
|
||||
if err := kubemaster.CreateDiscoveryDeploymentAndSecret(cfg, client, caCert); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := kubemaster.CreateEssentialAddons(s, client); err != nil {
|
||||
if err := kubemaster.CreateEssentialAddons(cfg, client); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO(phase1+) use templates to reference struct fields directly as order of args is fragile
|
||||
fmt.Fprintf(out, initDoneMsgf,
|
||||
s.Secrets.GivenToken,
|
||||
s.InitFlags.API.AdvertiseAddrs[0].String(),
|
||||
cfg.Secrets.GivenToken,
|
||||
cfg.API.AdvertiseAddresses[0],
|
||||
)
|
||||
|
||||
return nil
|
||||
|
|
|
@ -19,7 +19,6 @@ package cmd
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
|
||||
"github.com/renstrom/dedent"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -42,18 +41,19 @@ var (
|
|||
)
|
||||
|
||||
// NewCmdJoin returns "kubeadm join" command.
|
||||
func NewCmdJoin(out io.Writer, s *kubeadmapi.KubeadmConfig) *cobra.Command {
|
||||
func NewCmdJoin(out io.Writer) *cobra.Command {
|
||||
cfg := &kubeadmapi.NodeConfiguration{}
|
||||
cmd := &cobra.Command{
|
||||
Use: "join",
|
||||
Short: "Run this on any machine you wish to join an existing cluster.",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunJoin(out, cmd, args, s)
|
||||
err := RunJoin(out, cmd, args, cfg)
|
||||
cmdutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&s.Secrets.GivenToken, "token", "",
|
||||
&cfg.Secrets.GivenToken, "token", "",
|
||||
"(required) Shared secret used to secure bootstrap. Must match the output of 'kubeadm init'",
|
||||
)
|
||||
|
||||
|
@ -61,20 +61,14 @@ func NewCmdJoin(out io.Writer, s *kubeadmapi.KubeadmConfig) *cobra.Command {
|
|||
}
|
||||
|
||||
// RunJoin executes worked node provisioning and tries to join an existing cluster.
|
||||
func RunJoin(out io.Writer, cmd *cobra.Command, args []string, s *kubeadmapi.KubeadmConfig) error {
|
||||
func RunJoin(out io.Writer, cmd *cobra.Command, args []string, s *kubeadmapi.NodeConfiguration) error {
|
||||
// TODO(phase1+) this we are missing args from the help text, there should be a way to tell cobra about it
|
||||
if len(args) == 0 {
|
||||
return fmt.Errorf("<cmd/join> must specify master IP address (see --help)")
|
||||
}
|
||||
for _, i := range args {
|
||||
addr := net.ParseIP(i) // TODO(phase1+) should allow resolvable names too
|
||||
if addr == nil {
|
||||
return fmt.Errorf("<cmd/join> failed to parse argument (%q) as an IP address", i)
|
||||
}
|
||||
s.JoinFlags.MasterAddrs = append(s.JoinFlags.MasterAddrs, addr)
|
||||
}
|
||||
s.MasterAddresses = append(s.MasterAddresses, args...)
|
||||
|
||||
ok, err := kubeadmutil.UseGivenTokenIfValid(s)
|
||||
ok, err := kubeadmutil.UseGivenTokenIfValid(&s.Secrets)
|
||||
if !ok {
|
||||
if err != nil {
|
||||
return fmt.Errorf("<cmd/join> %v (see --help)\n", err)
|
||||
|
@ -87,7 +81,7 @@ func RunJoin(out io.Writer, cmd *cobra.Command, args []string, s *kubeadmapi.Kub
|
|||
return err
|
||||
}
|
||||
|
||||
err = kubeadmutil.WriteKubeconfigIfNotExists(s, "kubelet", kubeconfig)
|
||||
err = kubeadmutil.WriteKubeconfigIfNotExists("kubelet", kubeconfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -43,17 +43,17 @@ const (
|
|||
exechealthzVersion = "1.1"
|
||||
)
|
||||
|
||||
func GetCoreImage(image string, cfg *kubeadmapi.KubeadmConfig, overrideImage string) string {
|
||||
func GetCoreImage(image string, cfg *kubeadmapi.MasterConfiguration, overrideImage string) string {
|
||||
if overrideImage != "" {
|
||||
return overrideImage
|
||||
}
|
||||
|
||||
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, cfg.Versions.Kubernetes),
|
||||
KubeControllerManagerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-controller-manager", runtime.GOARCH, cfg.Versions.Kubernetes),
|
||||
KubeSchedulerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-scheduler", runtime.GOARCH, cfg.Versions.Kubernetes),
|
||||
KubeProxyImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-proxy", runtime.GOARCH, cfg.Versions.Kubernetes),
|
||||
KubeAPIServerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-apiserver", runtime.GOARCH, cfg.KubernetesVersion),
|
||||
KubeControllerManagerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-controller-manager", runtime.GOARCH, cfg.KubernetesVersion),
|
||||
KubeSchedulerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-scheduler", runtime.GOARCH, cfg.KubernetesVersion),
|
||||
KubeProxyImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-proxy", runtime.GOARCH, cfg.KubernetesVersion),
|
||||
}[image]
|
||||
}
|
||||
|
||||
|
|
|
@ -17,10 +17,7 @@ limitations under the License.
|
|||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/renstrom/dedent"
|
||||
"github.com/spf13/pflag"
|
||||
|
@ -36,31 +33,6 @@ var AlphaWarningOnExit = dedent.Dedent(`
|
|||
kubeadm: and make sure to mention @kubernetes/sig-cluster-lifecycle. Thank you!
|
||||
`)
|
||||
|
||||
// TODO(phase2) use componentconfig
|
||||
// we need some params for testing etc, let's keep these hidden for now
|
||||
func getEnvParams() map[string]string {
|
||||
|
||||
envParams := map[string]string{
|
||||
// TODO(phase1+): Mode prefix and host_pki_path to another place as constants, and use them everywhere
|
||||
// Right now they're used here and there, but not consequently
|
||||
"kubernetes_dir": "/etc/kubernetes",
|
||||
"host_pki_path": "/etc/kubernetes/pki",
|
||||
"host_etcd_path": "/var/lib/etcd",
|
||||
"hyperkube_image": "",
|
||||
"discovery_image": fmt.Sprintf("gcr.io/google_containers/kube-discovery-%s:%s", runtime.GOARCH, "1.0"),
|
||||
"etcd_image": "",
|
||||
"component_loglevel": "--v=4",
|
||||
}
|
||||
|
||||
for k := range envParams {
|
||||
if v := os.Getenv(fmt.Sprintf("KUBE_%s", strings.ToUpper(k))); v != "" {
|
||||
envParams[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return envParams
|
||||
}
|
||||
|
||||
func Run() error {
|
||||
logs.InitLogs()
|
||||
defer logs.FlushLogs()
|
||||
|
@ -69,6 +41,6 @@ func Run() error {
|
|||
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())
|
||||
cmd := cmd.NewKubeadmCommand(cmdutil.NewFactory(nil), os.Stdin, os.Stdout, os.Stderr)
|
||||
return cmd.Execute()
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package master
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"path"
|
||||
"runtime"
|
||||
|
||||
|
@ -31,7 +32,8 @@ import (
|
|||
)
|
||||
|
||||
// TODO(phase1+): kube-proxy should be a daemonset, three different daemonsets should not be here
|
||||
func createKubeProxyPodSpec(s *kubeadmapi.KubeadmConfig, architecture string) api.PodSpec {
|
||||
func createKubeProxyPodSpec(s *kubeadmapi.MasterConfiguration, architecture string) api.PodSpec {
|
||||
envParams := kubeadmapi.GetEnvParams()
|
||||
privilegedTrue := true
|
||||
return api.PodSpec{
|
||||
SecurityContext: &api.PodSecurityContext{HostNetwork: true},
|
||||
|
@ -40,7 +42,7 @@ func createKubeProxyPodSpec(s *kubeadmapi.KubeadmConfig, architecture string) ap
|
|||
},
|
||||
Containers: []api.Container{{
|
||||
Name: kubeProxy,
|
||||
Image: images.GetCoreImage(images.KubeProxyImage, s, s.EnvParams["hyperkube_image"]),
|
||||
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{
|
||||
|
@ -70,7 +72,7 @@ func createKubeProxyPodSpec(s *kubeadmapi.KubeadmConfig, architecture string) ap
|
|||
{
|
||||
Name: "kubeconfig",
|
||||
VolumeSource: api.VolumeSource{
|
||||
HostPath: &api.HostPathVolumeSource{Path: path.Join(s.EnvParams["kubernetes_dir"], "kubelet.conf")},
|
||||
HostPath: &api.HostPathVolumeSource{Path: path.Join(envParams["kubernetes_dir"], "kubelet.conf")},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -83,7 +85,7 @@ func createKubeProxyPodSpec(s *kubeadmapi.KubeadmConfig, architecture string) ap
|
|||
}
|
||||
}
|
||||
|
||||
func createKubeDNSPodSpec(s *kubeadmapi.KubeadmConfig) api.PodSpec {
|
||||
func createKubeDNSPodSpec(s *kubeadmapi.MasterConfiguration) api.PodSpec {
|
||||
|
||||
dnsPodResources := api.ResourceList{
|
||||
api.ResourceName(api.ResourceCPU): resource.MustParse("100m"),
|
||||
|
@ -98,7 +100,7 @@ func createKubeDNSPodSpec(s *kubeadmapi.KubeadmConfig) api.PodSpec {
|
|||
kubeDNSPort := int32(10053)
|
||||
dnsmasqPort := int32(53)
|
||||
|
||||
nslookup := fmt.Sprintf("nslookup kubernetes.default.svc.%s 127.0.0.1", s.InitFlags.Services.DNSDomain)
|
||||
nslookup := fmt.Sprintf("nslookup kubernetes.default.svc.%s 127.0.0.1", s.Networking.DNSDomain)
|
||||
|
||||
nslookup = fmt.Sprintf("-cmd=%s:%d >/dev/null && %s:%d >/dev/null",
|
||||
nslookup, dnsmasqPort,
|
||||
|
@ -119,7 +121,7 @@ func createKubeDNSPodSpec(s *kubeadmapi.KubeadmConfig) api.PodSpec {
|
|||
Requests: dnsPodResources,
|
||||
},
|
||||
Args: []string{
|
||||
fmt.Sprintf("--domain=%s", s.InitFlags.Services.DNSDomain),
|
||||
fmt.Sprintf("--domain=%s", s.Networking.DNSDomain),
|
||||
fmt.Sprintf("--dns-port=%d", kubeDNSPort),
|
||||
// TODO __PILLAR__FEDERATIONS__DOMAIN__MAP__
|
||||
},
|
||||
|
@ -212,10 +214,14 @@ func createKubeDNSPodSpec(s *kubeadmapi.KubeadmConfig) api.PodSpec {
|
|||
|
||||
}
|
||||
|
||||
func createKubeDNSServiceSpec(s *kubeadmapi.KubeadmConfig) (*api.ServiceSpec, error) {
|
||||
ip, err := ipallocator.GetIndexedIP(&s.InitFlags.Services.CIDR, 10)
|
||||
func createKubeDNSServiceSpec(s *kubeadmapi.MasterConfiguration) (*api.ServiceSpec, error) {
|
||||
_, n, err := net.ParseCIDR(s.Networking.ServiceSubnet)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to allocate IP address for kube-dns addon from the given CIDR (%q) [%v]", s.InitFlags.Services.CIDR, err)
|
||||
return nil, fmt.Errorf("could not parse %q: %v", s.Networking.ServiceSubnet, err)
|
||||
}
|
||||
ip, err := ipallocator.GetIndexedIP(n, 10)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to allocate IP address for kube-dns addon from the given CIDR (%q) [%v]", s.Networking.ServiceSubnet, err)
|
||||
}
|
||||
|
||||
svc := &api.ServiceSpec{
|
||||
|
@ -230,7 +236,7 @@ func createKubeDNSServiceSpec(s *kubeadmapi.KubeadmConfig) (*api.ServiceSpec, er
|
|||
return svc, nil
|
||||
}
|
||||
|
||||
func CreateEssentialAddons(s *kubeadmapi.KubeadmConfig, client *clientset.Clientset) error {
|
||||
func CreateEssentialAddons(s *kubeadmapi.MasterConfiguration, client *clientset.Clientset) error {
|
||||
arches := [3]string{"amd64", "arm", "arm64"}
|
||||
|
||||
for _, arch := range arches {
|
||||
|
|
|
@ -40,15 +40,15 @@ const (
|
|||
kubeDiscoverySecretName = "clusterinfo"
|
||||
)
|
||||
|
||||
func encodeKubeDiscoverySecretData(s *kubeadmapi.KubeadmConfig, caCert *x509.Certificate) map[string][]byte {
|
||||
func encodeKubeDiscoverySecretData(s *kubeadmapi.MasterConfiguration, caCert *x509.Certificate) map[string][]byte {
|
||||
var (
|
||||
data = map[string][]byte{}
|
||||
endpointList = []string{}
|
||||
tokenMap = map[string]string{}
|
||||
)
|
||||
|
||||
for _, addr := range s.InitFlags.API.AdvertiseAddrs {
|
||||
endpointList = append(endpointList, fmt.Sprintf("https://%s:443", addr.String()))
|
||||
for _, addr := range s.API.AdvertiseAddresses {
|
||||
endpointList = append(endpointList, fmt.Sprintf("https://%s:443", addr))
|
||||
}
|
||||
|
||||
tokenMap[s.Secrets.TokenID] = s.Secrets.BearerToken
|
||||
|
@ -60,7 +60,8 @@ func encodeKubeDiscoverySecretData(s *kubeadmapi.KubeadmConfig, caCert *x509.Cer
|
|||
return data
|
||||
}
|
||||
|
||||
func newKubeDiscoveryPodSpec(s *kubeadmapi.KubeadmConfig) api.PodSpec {
|
||||
func newKubeDiscoveryPodSpec() api.PodSpec {
|
||||
envParams := kubeadmapi.GetEnvParams()
|
||||
return api.PodSpec{
|
||||
// We have to use host network namespace, as `HostPort`/`HostIP` are Docker's
|
||||
// buisness and CNI support isn't quite there yet (except for kubenet)
|
||||
|
@ -69,7 +70,7 @@ func newKubeDiscoveryPodSpec(s *kubeadmapi.KubeadmConfig) api.PodSpec {
|
|||
SecurityContext: &api.PodSecurityContext{HostNetwork: true},
|
||||
Containers: []api.Container{{
|
||||
Name: kubeDiscoveryName,
|
||||
Image: s.EnvParams["discovery_image"],
|
||||
Image: envParams["discovery_image"],
|
||||
Command: []string{"/usr/local/bin/kube-discovery"},
|
||||
VolumeMounts: []api.VolumeMount{{
|
||||
Name: kubeDiscoverySecretName,
|
||||
|
@ -100,9 +101,9 @@ func newKubeDiscoveryPodSpec(s *kubeadmapi.KubeadmConfig) api.PodSpec {
|
|||
}
|
||||
}
|
||||
|
||||
func newKubeDiscovery(s *kubeadmapi.KubeadmConfig, caCert *x509.Certificate) kubeDiscovery {
|
||||
func newKubeDiscovery(s *kubeadmapi.MasterConfiguration, caCert *x509.Certificate) kubeDiscovery {
|
||||
kd := kubeDiscovery{
|
||||
Deployment: NewDeployment(kubeDiscoveryName, 1, newKubeDiscoveryPodSpec(s)),
|
||||
Deployment: NewDeployment(kubeDiscoveryName, 1, newKubeDiscoveryPodSpec()),
|
||||
Secret: &api.Secret{
|
||||
ObjectMeta: api.ObjectMeta{Name: kubeDiscoverySecretName},
|
||||
Type: api.SecretTypeOpaque,
|
||||
|
@ -116,7 +117,7 @@ func newKubeDiscovery(s *kubeadmapi.KubeadmConfig, caCert *x509.Certificate) kub
|
|||
return kd
|
||||
}
|
||||
|
||||
func CreateDiscoveryDeploymentAndSecret(s *kubeadmapi.KubeadmConfig, client *clientset.Clientset, caCert *x509.Certificate) error {
|
||||
func CreateDiscoveryDeploymentAndSecret(s *kubeadmapi.MasterConfiguration, client *clientset.Clientset, caCert *x509.Certificate) error {
|
||||
kd := newKubeDiscovery(s, caCert)
|
||||
|
||||
if _, err := client.Extensions().Deployments(api.NamespaceSystem).Create(kd.Deployment); err != nil {
|
||||
|
|
|
@ -22,20 +22,19 @@ import (
|
|||
"fmt"
|
||||
|
||||
// TODO: "k8s.io/client-go/client/tools/clientcmd/api"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/api"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
|
||||
certutil "k8s.io/kubernetes/pkg/util/cert"
|
||||
)
|
||||
|
||||
func CreateCertsAndConfigForClients(s *kubeadmapi.KubeadmConfig, clientNames []string, caKey *rsa.PrivateKey, caCert *x509.Certificate) (map[string]*clientcmdapi.Config, error) {
|
||||
func CreateCertsAndConfigForClients(advertiseAddresses, clientNames []string, caKey *rsa.PrivateKey, caCert *x509.Certificate) (map[string]*clientcmdapi.Config, error) {
|
||||
|
||||
basicClientConfig := kubeadmutil.CreateBasicClientConfig(
|
||||
"kubernetes",
|
||||
// TODO this is not great, but there is only one address we can use here
|
||||
// so we'll pick the first one, there is much of chance to have an empty
|
||||
// slice by the time this gets called
|
||||
fmt.Sprintf("https://%s:443", s.InitFlags.API.AdvertiseAddrs[0]),
|
||||
fmt.Sprintf("https://%s:443", advertiseAddresses[0]),
|
||||
certutil.EncodeCertPEM(caCert),
|
||||
)
|
||||
|
||||
|
|
|
@ -53,12 +53,13 @@ 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 {
|
||||
func WriteStaticPodManifests(s *kubeadmapi.MasterConfiguration) error {
|
||||
envParams := kubeadmapi.GetEnvParams()
|
||||
// Prepare static pod specs
|
||||
staticPodSpecs := map[string]api.Pod{
|
||||
kubeAPIServer: componentPod(api.Container{
|
||||
Name: kubeAPIServer,
|
||||
Image: images.GetCoreImage(images.KubeAPIServerImage, s, s.EnvParams["hyperkube_image"]),
|
||||
Image: images.GetCoreImage(images.KubeAPIServerImage, s, envParams["hyperkube_image"]),
|
||||
Command: getComponentCommand(apiServer, s),
|
||||
VolumeMounts: []api.VolumeMount{certsVolumeMount(), k8sVolumeMount()},
|
||||
LivenessProbe: componentProbe(8080, "/healthz"),
|
||||
|
@ -66,7 +67,7 @@ func WriteStaticPodManifests(s *kubeadmapi.KubeadmConfig) error {
|
|||
}, certsVolume(s), k8sVolume(s)),
|
||||
kubeControllerManager: componentPod(api.Container{
|
||||
Name: kubeControllerManager,
|
||||
Image: images.GetCoreImage(images.KubeControllerManagerImage, s, s.EnvParams["hyperkube_image"]),
|
||||
Image: images.GetCoreImage(images.KubeControllerManagerImage, s, envParams["hyperkube_image"]),
|
||||
Command: getComponentCommand(controllerManager, s),
|
||||
VolumeMounts: []api.VolumeMount{certsVolumeMount(), k8sVolumeMount()},
|
||||
LivenessProbe: componentProbe(10252, "/healthz"),
|
||||
|
@ -74,7 +75,7 @@ func WriteStaticPodManifests(s *kubeadmapi.KubeadmConfig) error {
|
|||
}, certsVolume(s), k8sVolume(s)),
|
||||
kubeScheduler: componentPod(api.Container{
|
||||
Name: kubeScheduler,
|
||||
Image: images.GetCoreImage(images.KubeSchedulerImage, s, s.EnvParams["hyperkube_image"]),
|
||||
Image: images.GetCoreImage(images.KubeSchedulerImage, s, envParams["hyperkube_image"]),
|
||||
Command: getComponentCommand(scheduler, s),
|
||||
LivenessProbe: componentProbe(10251, "/healthz"),
|
||||
Resources: componentResources("100m"),
|
||||
|
@ -82,7 +83,7 @@ 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 {
|
||||
if len(s.Etcd.Endpoints) == 0 {
|
||||
staticPodSpecs[etcd] = componentPod(api.Container{
|
||||
Name: etcd,
|
||||
Command: []string{
|
||||
|
@ -92,7 +93,7 @@ func WriteStaticPodManifests(s *kubeadmapi.KubeadmConfig) error {
|
|||
"--data-dir=/var/etcd/data",
|
||||
},
|
||||
VolumeMounts: []api.VolumeMount{certsVolumeMount(), etcdVolumeMount(), k8sVolumeMount()},
|
||||
Image: images.GetCoreImage(images.KubeEtcdImage, s, s.EnvParams["etcd_image"]),
|
||||
Image: images.GetCoreImage(images.KubeEtcdImage, s, envParams["etcd_image"]),
|
||||
LivenessProbe: componentProbe(2379, "/health"),
|
||||
Resources: componentResources("200m"),
|
||||
SecurityContext: &api.SecurityContext{
|
||||
|
@ -107,7 +108,7 @@ func WriteStaticPodManifests(s *kubeadmapi.KubeadmConfig) error {
|
|||
}, certsVolume(s), etcdVolume(s), k8sVolume(s))
|
||||
}
|
||||
|
||||
manifestsPath := path.Join(s.EnvParams["kubernetes_dir"], "manifests")
|
||||
manifestsPath := path.Join(envParams["kubernetes_dir"], "manifests")
|
||||
if err := os.MkdirAll(manifestsPath, 0700); err != nil {
|
||||
return fmt.Errorf("<master/manifests> failed to create directory %q [%v]", manifestsPath, err)
|
||||
}
|
||||
|
@ -125,11 +126,12 @@ func WriteStaticPodManifests(s *kubeadmapi.KubeadmConfig) error {
|
|||
}
|
||||
|
||||
// etcdVolume exposes a path on the host in order to guarantee data survival during reboot.
|
||||
func etcdVolume(s *kubeadmapi.KubeadmConfig) api.Volume {
|
||||
func etcdVolume(s *kubeadmapi.MasterConfiguration) api.Volume {
|
||||
envParams := kubeadmapi.GetEnvParams()
|
||||
return api.Volume{
|
||||
Name: "etcd",
|
||||
VolumeSource: api.VolumeSource{
|
||||
HostPath: &api.HostPathVolumeSource{Path: s.EnvParams["host_etcd_path"]},
|
||||
HostPath: &api.HostPathVolumeSource{Path: envParams["host_etcd_path"]},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -142,7 +144,7 @@ func etcdVolumeMount() api.VolumeMount {
|
|||
}
|
||||
|
||||
// certsVolume exposes host SSL certificates to pod containers.
|
||||
func certsVolume(s *kubeadmapi.KubeadmConfig) api.Volume {
|
||||
func certsVolume(s *kubeadmapi.MasterConfiguration) api.Volume {
|
||||
return api.Volume{
|
||||
Name: "certs",
|
||||
VolumeSource: api.VolumeSource{
|
||||
|
@ -159,11 +161,12 @@ func certsVolumeMount() api.VolumeMount {
|
|||
}
|
||||
}
|
||||
|
||||
func k8sVolume(s *kubeadmapi.KubeadmConfig) api.Volume {
|
||||
func k8sVolume(s *kubeadmapi.MasterConfiguration) api.Volume {
|
||||
envParams := kubeadmapi.GetEnvParams()
|
||||
return api.Volume{
|
||||
Name: "pki",
|
||||
VolumeSource: api.VolumeSource{
|
||||
HostPath: &api.HostPathVolumeSource{Path: s.EnvParams["kubernetes_dir"]},
|
||||
HostPath: &api.HostPathVolumeSource{Path: envParams["kubernetes_dir"]},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -218,13 +221,13 @@ func componentPod(container api.Container, volumes ...api.Volume) api.Pod {
|
|||
}
|
||||
}
|
||||
|
||||
func getComponentCommand(component string, s *kubeadmapi.KubeadmConfig) (command []string) {
|
||||
func getComponentCommand(component string, s *kubeadmapi.MasterConfiguration) (command []string) {
|
||||
baseFlags := map[string][]string{
|
||||
apiServer: {
|
||||
"--insecure-bind-address=127.0.0.1",
|
||||
"--etcd-servers=http://127.0.0.1:2379",
|
||||
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota",
|
||||
"--service-cluster-ip-range=" + s.InitFlags.Services.CIDR.String(),
|
||||
"--service-cluster-ip-range=" + s.Networking.ServiceSubnet,
|
||||
"--service-account-key-file=" + pkiDir + "/apiserver-key.pem",
|
||||
"--client-ca-file=" + pkiDir + "/ca.pem",
|
||||
"--tls-cert-file=" + pkiDir + "/apiserver.pem",
|
||||
|
@ -252,37 +255,38 @@ func getComponentCommand(component string, s *kubeadmapi.KubeadmConfig) (command
|
|||
proxy: {},
|
||||
}
|
||||
|
||||
if s.EnvParams["hyperkube_image"] != "" {
|
||||
envParams := kubeadmapi.GetEnvParams()
|
||||
if envParams["hyperkube_image"] != "" {
|
||||
command = []string{"/hyperkube", component}
|
||||
} else {
|
||||
command = []string{"/usr/local/bin/kube-" + component}
|
||||
}
|
||||
|
||||
command = append(command, s.EnvParams["component_loglevel"])
|
||||
command = append(command, envParams["component_loglevel"])
|
||||
command = append(command, baseFlags[component]...)
|
||||
|
||||
if component == apiServer {
|
||||
// Check if the user decided to use an external etcd cluster
|
||||
if len(s.InitFlags.API.Etcd.ExternalEndpoints) > 0 {
|
||||
command = append(command, fmt.Sprintf("--etcd-servers=%s", strings.Join(s.InitFlags.API.Etcd.ExternalEndpoints, ",")))
|
||||
if len(s.Etcd.Endpoints) > 0 {
|
||||
command = append(command, fmt.Sprintf("--etcd-servers=%s", strings.Join(s.Etcd.Endpoints, ",")))
|
||||
} else {
|
||||
command = append(command, "--etcd-servers=http://127.0.0.1:2379")
|
||||
}
|
||||
|
||||
// Is etcd secured?
|
||||
if s.InitFlags.API.Etcd.ExternalCAFile != "" {
|
||||
command = append(command, fmt.Sprintf("--etcd-cafile=%s", s.InitFlags.API.Etcd.ExternalCAFile))
|
||||
if s.Etcd.CAFile != "" {
|
||||
command = append(command, fmt.Sprintf("--etcd-cafile=%s", s.Etcd.CAFile))
|
||||
}
|
||||
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)
|
||||
if s.Etcd.CertFile != "" && s.Etcd.KeyFile != "" {
|
||||
etcdClientFileArg := fmt.Sprintf("--etcd-certfile=%s", s.Etcd.CertFile)
|
||||
etcdKeyFileArg := fmt.Sprintf("--etcd-keyfile=%s", s.Etcd.KeyFile)
|
||||
command = append(command, etcdClientFileArg, etcdKeyFileArg)
|
||||
}
|
||||
}
|
||||
|
||||
if component == controllerManager {
|
||||
if s.InitFlags.CloudProvider != "" {
|
||||
command = append(command, "--cloud-provider="+s.InitFlags.CloudProvider)
|
||||
if s.CloudProvider != "" {
|
||||
command = append(command, "--cloud-provider="+s.CloudProvider)
|
||||
|
||||
// Only append the --cloud-config option if there's a such file
|
||||
// TODO(phase1+) this won't work unless it's in one of the few directories we bind-mount
|
||||
|
@ -290,12 +294,9 @@ func getComponentCommand(component string, s *kubeadmapi.KubeadmConfig) (command
|
|||
command = append(command, "--cloud-config="+DefaultCloudConfigPath)
|
||||
}
|
||||
}
|
||||
|
||||
if s.InitFlags.PodNetwork.CIDR.IP != nil {
|
||||
// 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.
|
||||
command = append(command, "--allocate-node-cidrs=true", "--cluster-cidr="+s.InitFlags.PodNetwork.CIDR.String())
|
||||
}
|
||||
// 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.
|
||||
command = append(command, "--allocate-node-cidrs=true", "--cluster-cidr="+s.Networking.PodSubnet)
|
||||
}
|
||||
|
||||
return
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"net"
|
||||
"path"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/api"
|
||||
|
@ -45,7 +46,7 @@ func newCertificateAuthority() (*rsa.PrivateKey, *x509.Certificate, error) {
|
|||
return key, cert, nil
|
||||
}
|
||||
|
||||
func newServerKeyAndCert(s *kubeadmapi.KubeadmConfig, caCert *x509.Certificate, caKey *rsa.PrivateKey, altNames certutil.AltNames) (*rsa.PrivateKey, *x509.Certificate, error) {
|
||||
func newServerKeyAndCert(s *kubeadmapi.MasterConfiguration, caCert *x509.Certificate, caKey *rsa.PrivateKey, altNames certutil.AltNames) (*rsa.PrivateKey, *x509.Certificate, error) {
|
||||
key, err := certutil.NewPrivateKey()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unabel to create private key [%v]", err)
|
||||
|
@ -55,12 +56,16 @@ func newServerKeyAndCert(s *kubeadmapi.KubeadmConfig, caCert *x509.Certificate,
|
|||
"kubernetes",
|
||||
"kubernetes.default",
|
||||
"kubernetes.default.svc",
|
||||
fmt.Sprintf("kubernetes.default.svc.%s", s.InitFlags.Services.DNSDomain),
|
||||
fmt.Sprintf("kubernetes.default.svc.%s", s.Networking.DNSDomain),
|
||||
}
|
||||
|
||||
internalAPIServerVirtualIP, err := ipallocator.GetIndexedIP(&s.InitFlags.Services.CIDR, 1)
|
||||
_, n, err := net.ParseCIDR(s.Networking.ServiceSubnet)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to allocate IP address for the API server from the given CIDR (%q) [%v]", &s.InitFlags.Services.CIDR, err)
|
||||
return nil, nil, fmt.Errorf("error parsing CIDR %q: %v", s.Networking.ServiceSubnet, err)
|
||||
}
|
||||
internalAPIServerVirtualIP, err := ipallocator.GetIndexedIP(n, 1)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to allocate IP address for the API server from the given CIDR (%q) [%v]", &s.Networking.ServiceSubnet, err)
|
||||
}
|
||||
|
||||
altNames.IPs = append(altNames.IPs, internalAPIServerVirtualIP)
|
||||
|
@ -138,16 +143,22 @@ func newServiceAccountKey() (*rsa.PrivateKey, error) {
|
|||
// It first generates a self-signed CA certificate, a server certificate (signed by the CA) and a key for
|
||||
// signing service account tokens. It returns CA key and certificate, which is convenient for use with
|
||||
// client config funcs.
|
||||
func CreatePKIAssets(s *kubeadmapi.KubeadmConfig) (*rsa.PrivateKey, *x509.Certificate, error) {
|
||||
func CreatePKIAssets(s *kubeadmapi.MasterConfiguration) (*rsa.PrivateKey, *x509.Certificate, error) {
|
||||
var (
|
||||
err error
|
||||
altNames certutil.AltNames
|
||||
)
|
||||
|
||||
altNames.IPs = append(altNames.IPs, s.InitFlags.API.AdvertiseAddrs...)
|
||||
altNames.DNSNames = append(altNames.DNSNames, s.InitFlags.API.ExternalDNSNames...)
|
||||
for _, a := range s.API.AdvertiseAddresses {
|
||||
if ip := net.ParseIP(a); ip != nil {
|
||||
altNames.IPs = append(altNames.IPs, ip)
|
||||
} else {
|
||||
return nil, nil, fmt.Errorf("could not parse ip %q", a)
|
||||
}
|
||||
}
|
||||
altNames.DNSNames = append(altNames.DNSNames, s.API.ExternalDNSNames...)
|
||||
|
||||
pkiPath := path.Join(s.EnvParams["host_pki_path"])
|
||||
pkiPath := path.Join(kubeadmapi.GetEnvParams()["host_pki_path"])
|
||||
|
||||
caKey, caCert, err := newCertificateAuthority()
|
||||
if err != nil {
|
||||
|
|
|
@ -28,7 +28,7 @@ import (
|
|||
"k8s.io/kubernetes/pkg/util/uuid"
|
||||
)
|
||||
|
||||
func generateTokenIfNeeded(s *kubeadmapi.KubeadmConfig) error {
|
||||
func generateTokenIfNeeded(s *kubeadmapi.Secrets) error {
|
||||
ok, err := kubeadmutil.UseGivenTokenIfValid(s)
|
||||
// TODO(phase1+) @krousey: I know it won't happen with the way it is currently implemented, but this doesn't handle case where ok is true and err is non-nil.
|
||||
if !ok {
|
||||
|
@ -39,7 +39,7 @@ func generateTokenIfNeeded(s *kubeadmapi.KubeadmConfig) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("<master/tokens> generated token: %q\n", s.Secrets.GivenToken)
|
||||
fmt.Printf("<master/tokens> generated token: %q\n", s.GivenToken)
|
||||
} else {
|
||||
fmt.Println("<master/tokens> accepted provided token")
|
||||
}
|
||||
|
@ -47,15 +47,15 @@ func generateTokenIfNeeded(s *kubeadmapi.KubeadmConfig) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func CreateTokenAuthFile(s *kubeadmapi.KubeadmConfig) error {
|
||||
tokenAuthFilePath := path.Join(s.EnvParams["host_pki_path"], "tokens.csv")
|
||||
func CreateTokenAuthFile(s *kubeadmapi.Secrets) error {
|
||||
tokenAuthFilePath := path.Join(kubeadmapi.GetEnvParams()["host_pki_path"], "tokens.csv")
|
||||
if err := generateTokenIfNeeded(s); err != nil {
|
||||
return fmt.Errorf("<master/tokens> failed to generate token(s) [%v]", err)
|
||||
}
|
||||
if err := os.MkdirAll(s.EnvParams["host_pki_path"], 0700); err != nil {
|
||||
return fmt.Errorf("<master/tokens> failed to create directory %q [%v]", s.EnvParams["host_pki_path"], err)
|
||||
if err := os.MkdirAll(kubeadmapi.GetEnvParams()["host_pki_path"], 0700); err != nil {
|
||||
return fmt.Errorf("<master/tokens> failed to create directory %q [%v]", kubeadmapi.GetEnvParams()["host_pki_path"], err)
|
||||
}
|
||||
serialized := []byte(fmt.Sprintf("%s,kubeadm-node-csr,%s,system:kubelet-bootstrap\n", s.Secrets.BearerToken, uuid.NewUUID()))
|
||||
serialized := []byte(fmt.Sprintf("%s,kubeadm-node-csr,%s,system:kubelet-bootstrap\n", s.BearerToken, uuid.NewUUID()))
|
||||
// DumpReaderToFile create a file with mode 0600
|
||||
if err := cmdutil.DumpReaderToFile(bytes.NewReader(serialized), tokenAuthFilePath); err != nil {
|
||||
return fmt.Errorf("<master/tokens> failed to save token auth file (%q) [%v]", tokenAuthFilePath, err)
|
||||
|
|
|
@ -34,8 +34,8 @@ import (
|
|||
)
|
||||
|
||||
// PerformTLSBootstrap creates a RESTful client in order to execute certificate signing request.
|
||||
func PerformTLSBootstrap(s *kubeadmapi.KubeadmConfig, apiEndpoint string, caCert []byte) (*clientcmdapi.Config, error) {
|
||||
// TODO(phase2) try all the api servers until we find one that works
|
||||
func PerformTLSBootstrap(s *kubeadmapi.NodeConfiguration, apiEndpoint string, caCert []byte) (*clientcmdapi.Config, error) {
|
||||
// TODO(phase1+) try all the api servers until we find one that works
|
||||
bareClientConfig := kubeadmutil.CreateBasicClientConfig("kubernetes", apiEndpoint, caCert)
|
||||
|
||||
hostName, err := os.Hostname()
|
||||
|
|
|
@ -28,8 +28,8 @@ import (
|
|||
clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
|
||||
)
|
||||
|
||||
func RetrieveTrustedClusterInfo(s *kubeadmapi.KubeadmConfig) (*clientcmdapi.Config, error) {
|
||||
host, port := s.JoinFlags.MasterAddrs[0].String(), 9898
|
||||
func RetrieveTrustedClusterInfo(s *kubeadmapi.NodeConfiguration) (*clientcmdapi.Config, error) {
|
||||
host, port := s.MasterAddresses[0], 9898
|
||||
requestURL := fmt.Sprintf("http://%s:%d/cluster-info/v1/?token-id=%s", host, port, s.Secrets.TokenID)
|
||||
req, err := http.NewRequest("GET", requestURL, nil)
|
||||
if err != nil {
|
||||
|
|
|
@ -75,12 +75,13 @@ func MakeClientConfigWithToken(config *clientcmdapi.Config, clusterName string,
|
|||
return newConfig
|
||||
}
|
||||
|
||||
func WriteKubeconfigIfNotExists(s *kubeadmapi.KubeadmConfig, name string, kubeconfig *clientcmdapi.Config) error {
|
||||
if err := os.MkdirAll(s.EnvParams["kubernetes_dir"], 0700); err != nil {
|
||||
return fmt.Errorf("<util/kubeconfig> failed to create directory %q [%v]", s.EnvParams["kubernetes_dir"], err)
|
||||
func WriteKubeconfigIfNotExists(name string, kubeconfig *clientcmdapi.Config) error {
|
||||
envParams := kubeadmapi.GetEnvParams()
|
||||
if err := os.MkdirAll(envParams["kubernetes_dir"], 0700); err != nil {
|
||||
return fmt.Errorf("<util/kubeconfig> failed to create directory %q [%v]", envParams["kubernetes_dir"], err)
|
||||
}
|
||||
|
||||
filename := path.Join(s.EnvParams["kubernetes_dir"], fmt.Sprintf("%s.conf", name))
|
||||
filename := path.Join(envParams["kubernetes_dir"], fmt.Sprintf("%s.conf", name))
|
||||
// Create and open the file, only if it does not already exist.
|
||||
f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_EXCL, 0600)
|
||||
if err != nil {
|
||||
|
|
|
@ -42,7 +42,7 @@ func RandBytes(length int) ([]byte, string, error) {
|
|||
return b, hex.EncodeToString(b), nil
|
||||
}
|
||||
|
||||
func GenerateToken(s *kubeadmapi.KubeadmConfig) error {
|
||||
func GenerateToken(s *kubeadmapi.Secrets) error {
|
||||
_, tokenID, err := RandBytes(TokenIDLen / 2)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -53,19 +53,19 @@ func GenerateToken(s *kubeadmapi.KubeadmConfig) error {
|
|||
return err
|
||||
}
|
||||
|
||||
s.Secrets.TokenID = tokenID
|
||||
s.Secrets.BearerToken = token
|
||||
s.Secrets.Token = tokenBytes
|
||||
s.Secrets.GivenToken = fmt.Sprintf("%s.%s", tokenID, token)
|
||||
s.TokenID = tokenID
|
||||
s.BearerToken = token
|
||||
s.Token = tokenBytes
|
||||
s.GivenToken = fmt.Sprintf("%s.%s", tokenID, token)
|
||||
return nil
|
||||
}
|
||||
|
||||
func UseGivenTokenIfValid(s *kubeadmapi.KubeadmConfig) (bool, error) {
|
||||
if s.Secrets.GivenToken == "" {
|
||||
func UseGivenTokenIfValid(s *kubeadmapi.Secrets) (bool, error) {
|
||||
if s.GivenToken == "" {
|
||||
return false, nil // not given
|
||||
}
|
||||
fmt.Println("<util/tokens> validating provided token")
|
||||
givenToken := strings.Split(strings.ToLower(s.Secrets.GivenToken), ".")
|
||||
givenToken := strings.Split(strings.ToLower(s.GivenToken), ".")
|
||||
// TODO(phase1+) print desired format
|
||||
// TODO(phase1+) could also print more specific messages in each case
|
||||
invalidErr := "<util/tokens> provided token is invalid - %s"
|
||||
|
@ -78,8 +78,8 @@ func UseGivenTokenIfValid(s *kubeadmapi.KubeadmConfig) (bool, error) {
|
|||
len(givenToken[0]), TokenIDLen))
|
||||
}
|
||||
tokenBytes := []byte(givenToken[1])
|
||||
s.Secrets.TokenID = givenToken[0]
|
||||
s.Secrets.BearerToken = givenToken[1]
|
||||
s.Secrets.Token = tokenBytes
|
||||
s.TokenID = givenToken[0]
|
||||
s.BearerToken = givenToken[1]
|
||||
s.Token = tokenBytes
|
||||
return true, nil // given and valid
|
||||
}
|
||||
|
|
|
@ -32,8 +32,10 @@ import (
|
|||
type Factory func(config io.Reader) (Interface, error)
|
||||
|
||||
// All registered cloud providers.
|
||||
var providersMutex sync.Mutex
|
||||
var providers = make(map[string]Factory)
|
||||
var (
|
||||
providersMutex sync.Mutex
|
||||
providers = make(map[string]Factory)
|
||||
)
|
||||
|
||||
// RegisterCloudProvider registers a cloudprovider.Factory by name. This
|
||||
// is expected to happen during app startup.
|
||||
|
@ -47,6 +49,27 @@ func RegisterCloudProvider(name string, cloud Factory) {
|
|||
providers[name] = cloud
|
||||
}
|
||||
|
||||
// IsCloudProvider returns true if name corresponds to an already registered
|
||||
// cloud provider.
|
||||
func IsCloudProvider(name string) bool {
|
||||
providersMutex.Lock()
|
||||
defer providersMutex.Unlock()
|
||||
_, found := providers[name]
|
||||
return found
|
||||
}
|
||||
|
||||
// CloudProviders returns the name of all registered cloud providers in a
|
||||
// string slice
|
||||
func CloudProviders() []string {
|
||||
names := []string{}
|
||||
providersMutex.Lock()
|
||||
defer providersMutex.Unlock()
|
||||
for name := range providers {
|
||||
names = append(names, name)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
// GetCloudProvider creates an instance of the named cloud provider, or nil if
|
||||
// the name is not known. The error return is only used if the named provider
|
||||
// was known but failed to initialize. The config parameter specifies the
|
||||
|
|
Loading…
Reference in New Issue