diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.go index 23785f3abc7..42fcf65caef 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.go @@ -21,13 +21,12 @@ import "k8s.io/apimachinery/pkg/runtime" const ( DefaultServiceDNSDomain = "cluster.local" DefaultServicesSubnet = "10.96.0.0/12" - DefaultKubernetesVersion = "stable" + DefaultKubernetesVersion = "latest" // This is only for clusters without internet, were the latest stable version can't be determined - DefaultKubernetesFallbackVersion = "v1.5.2" + DefaultKubernetesFallbackVersion = "v1.6.0-alpha.1" DefaultAPIBindPort = 6443 DefaultDiscoveryBindPort = 9898 - // TODO: Default this to RBAC when DefaultKubernetesFallbackVersion is v1.6-something - DefaultAuthorizationMode = "AlwaysAllow" + DefaultAuthorizationMode = "RBAC" ) func addDefaultingFuncs(scheme *runtime.Scheme) error { diff --git a/cmd/kubeadm/app/cmd/defaults.go b/cmd/kubeadm/app/cmd/defaults.go index c834f05cab9..c29bd63db1a 100644 --- a/cmd/kubeadm/app/cmd/defaults.go +++ b/cmd/kubeadm/app/cmd/defaults.go @@ -23,14 +23,14 @@ import ( netutil "k8s.io/apimachinery/pkg/util/net" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" + kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" "github.com/blang/semver" ) var ( - // Maximum version when using AllowAll as the default authz mode. Everything above this will use RBAC by default. - allowAllMaxVersion = semver.MustParse("1.6.0-alpha.0") + minK8sVersion = semver.MustParse(kubeadmconstants.MinimumControlPlaneVersion) ) func setInitDynamicDefaults(cfg *kubeadmapi.MasterConfiguration) error { @@ -53,16 +53,18 @@ func setInitDynamicDefaults(cfg *kubeadmapi.MasterConfiguration) error { } } cfg.KubernetesVersion = ver - fmt.Println("[init] Using Kubernetes version:", ver) // Omit the "v" in the beginning, otherwise semver will fail - // If the version is newer than the specified version, RBAC v1beta1 support is enabled in the apiserver so we can default to RBAC k8sVersion, err := semver.Parse(cfg.KubernetesVersion[1:]) - if k8sVersion.GT(allowAllMaxVersion) { - cfg.AuthorizationMode = "RBAC" + if err != nil { + return fmt.Errorf("couldn't parse kubernetes version %q: %v", cfg.KubernetesVersion, err) + } + if k8sVersion.LT(minK8sVersion) { + return fmt.Errorf("this version of kubeadm only supports deploying clusters with the control plane version >= v1.6.0-alpha.1. Current version: %s", cfg.KubernetesVersion) } - fmt.Println("[init] Using Authorization mode:", cfg.AuthorizationMode) + fmt.Printf("[init] Using Kubernetes version: %s\n", cfg.KubernetesVersion) + fmt.Printf("[init] Using Authorization mode: %s\n", cfg.AuthorizationMode) // Warn about the limitations with the current cloudprovider solution. if cfg.CloudProvider != "" { diff --git a/cmd/kubeadm/app/cmd/init.go b/cmd/kubeadm/app/cmd/init.go index 3a447bae6f4..270211a47a2 100644 --- a/cmd/kubeadm/app/cmd/init.go +++ b/cmd/kubeadm/app/cmd/init.go @@ -30,6 +30,7 @@ import ( kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/flags" + kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/discovery" kubemaster "k8s.io/kubernetes/cmd/kubeadm/app/master" "k8s.io/kubernetes/cmd/kubeadm/app/phases/apiconfig" @@ -219,7 +220,7 @@ func (i *Init) Run(out io.Writer) error { return err } - if i.cfg.AuthorizationMode == "RBAC" { + if i.cfg.AuthorizationMode == kubeadmconstants.AuthzModeRBAC { err = apiconfig.CreateBootstrapRBACClusterRole(client) if err != nil { return err diff --git a/cmd/kubeadm/app/constants/constants.go b/cmd/kubeadm/app/constants/constants.go index c25ee19014f..386b1653f13 100644 --- a/cmd/kubeadm/app/constants/constants.go +++ b/cmd/kubeadm/app/constants/constants.go @@ -28,4 +28,15 @@ const ( APIServerKubeletClientCertAndKeyBaseName = "apiserver-kubelet-client" APIServerKubeletClientCertName = "apiserver-kubelet-client.crt" APIServerKubeletClientKeyName = "apiserver-kubelet-client.key" + + // TODO: These constants should actually come from pkg/kubeapiserver/authorizer, but we can't vendor that package in now + // because of all the other sub-packages that would get vendored. To fix this, a pkg/kubeapiserver/authorizer/modes package + // or similar should exist that only has these constants; then we can vendor it. + AuthzModeAlwaysAllow = "AlwaysAllow" + AuthzModeABAC = "ABAC" + AuthzModeRBAC = "RBAC" + AuthzModeWebhook = "Webhook" + + // Important: a "v"-prefix shouldn't exist here; semver doesn't allow that + MinimumControlPlaneVersion = "1.6.0-alpha.1" ) diff --git a/cmd/kubeadm/app/master/BUILD b/cmd/kubeadm/app/master/BUILD index 4dc4cacb315..a0e7cbd4b5e 100644 --- a/cmd/kubeadm/app/master/BUILD +++ b/cmd/kubeadm/app/master/BUILD @@ -31,7 +31,6 @@ go_library( "//pkg/client/clientset_generated/clientset:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", "//pkg/registry/core/service/ipallocator:go_default_library", - "//vendor:github.com/blang/semver", "//vendor:k8s.io/apimachinery/pkg/api/errors", "//vendor:k8s.io/apimachinery/pkg/api/resource", "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", diff --git a/cmd/kubeadm/app/master/manifests.go b/cmd/kubeadm/app/master/manifests.go index 40836a2d0cb..9f2c343ca3f 100644 --- a/cmd/kubeadm/app/master/manifests.go +++ b/cmd/kubeadm/app/master/manifests.go @@ -32,8 +32,6 @@ import ( "k8s.io/kubernetes/cmd/kubeadm/app/images" api "k8s.io/kubernetes/pkg/api/v1" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - - "github.com/blang/semver" ) // Static pod definitions in golang form are included below so that `kubeadm init` can get going. @@ -54,14 +52,6 @@ const ( authorizationWebhookConfigFile = "webhook_authz.conf" ) -var ( - // Minimum version of kube-apiserver that supports --kubelet-preferred-address-types - preferredAddressAPIServerMinVersion = semver.MustParse("1.5.0") - - // Minimum version of kube-apiserver that has to have --anonymous-auth=false set - anonAuthDisableAPIServerMinVersion = semver.MustParse("1.5.0") -) - // WriteStaticPodManifests builds manifest objects based on user provided configuration and then dumps it to disk // where kubelet will pick and schedule them. func WriteStaticPodManifests(cfg *kubeadmapi.MasterConfiguration) error { @@ -328,14 +318,15 @@ func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration, selfHosted bool) [ fmt.Sprintf("--secure-port=%d", cfg.API.Port), "--allow-privileged", "--storage-backend=etcd3", + "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", ) if cfg.AuthorizationMode != "" { command = append(command, "--authorization-mode="+cfg.AuthorizationMode) switch cfg.AuthorizationMode { - case "ABAC": + case kubeadmconstants.AuthzModeABAC: command = append(command, "--authorization-policy-file="+path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, authorizationPolicyFile)) - case "Webhook": + case kubeadmconstants.AuthzModeWebhook: command = append(command, "--authorization-webhook-config-file="+path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, authorizationWebhookConfigFile)) } } @@ -349,23 +340,6 @@ func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration, selfHosted bool) [ } } - if len(cfg.KubernetesVersion) != 0 { - // If the k8s version is v1.5-something, this argument is set and makes `kubectl logs` and `kubectl exec` - // work on bare-metal where hostnames aren't usually resolvable - // Omit the "v" in the beginning, otherwise semver will fail - k8sVersion, err := semver.Parse(cfg.KubernetesVersion[1:]) - - // If the k8s version is greater than this version, it supports telling it which way it should contact kubelets - if err == nil && k8sVersion.GTE(preferredAddressAPIServerMinVersion) { - command = append(command, "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname") - } - - // This is a critical "bugfix". Any version above this is vulnerable unless a RBAC/ABAC-authorizer is provided (which kubeadm doesn't for the time being) - if err == nil && k8sVersion.GTE(anonAuthDisableAPIServerMinVersion) { - command = append(command, "--anonymous-auth=false") - } - } - // 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, ","))) diff --git a/cmd/kubeadm/app/master/manifests_test.go b/cmd/kubeadm/app/master/manifests_test.go index 81cd42a1634..b8de56b7fc2 100644 --- a/cmd/kubeadm/app/master/manifests_test.go +++ b/cmd/kubeadm/app/master/manifests_test.go @@ -382,6 +382,7 @@ func TestGetAPIServerCommand(t *testing.T) { fmt.Sprintf("--secure-port=%d", 123), "--allow-privileged", "--storage-backend=etcd3", + "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", "--etcd-servers=http://127.0.0.1:2379", }, }, @@ -405,6 +406,7 @@ func TestGetAPIServerCommand(t *testing.T) { fmt.Sprintf("--secure-port=%d", 123), "--allow-privileged", "--storage-backend=etcd3", + "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", "--advertise-address=foo", "--etcd-servers=http://127.0.0.1:2379", }, @@ -430,39 +432,12 @@ func TestGetAPIServerCommand(t *testing.T) { fmt.Sprintf("--secure-port=%d", 123), "--allow-privileged", "--storage-backend=etcd3", + "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", "--etcd-servers=http://127.0.0.1:2379", "--etcd-certfile=fiz", "--etcd-keyfile=faz", }, }, - // Make sure --kubelet-preferred-address-types - { - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadm.API{Port: 123, AdvertiseAddresses: []string{"foo"}}, - Networking: kubeadm.Networking{ServiceSubnet: "bar"}, - KubernetesVersion: "v1.5.3", - }, - expected: []string{ - "kube-apiserver", - "--insecure-bind-address=127.0.0.1", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota", - "--service-cluster-ip-range=bar", - "--service-account-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.key", - "--client-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.crt", - "--tls-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.crt", - "--tls-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.key", - "--kubelet-client-certificate=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-kubelet-client.crt", - "--kubelet-client-key=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-kubelet-client.key", - "--token-auth-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/tokens.csv", - fmt.Sprintf("--secure-port=%d", 123), - "--allow-privileged", - "--storage-backend=etcd3", - "--advertise-address=foo", - "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", - "--anonymous-auth=false", - "--etcd-servers=http://127.0.0.1:2379", - }, - }, } for _, rt := range tests {