Merge pull request #40698 from luxas/kubeadm_fix_authz_default
Automatic merge from submit-queue (batch tested with PRs 40707, 40698) kubeadm: Default to control plane v1.6.0-alpha.1 and using RBAC Also use constants for authz modes **What this PR does / why we need it**: Defaults to v1.6.0-alpha.1 (will be cut later today) because the certificates API group has been upgraded to beta, so `kubeadm join` at HEAD doesn't work on a `v1.5` cluster anyway. By defaulting to v1.6.0-alpha.1, we can focus totally on v1.6 for kubeadm at HEAD, we don't support other versions in the upcoming v1.6 kubeadm release because of the alpha -> beta upgrades. **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes # **Special notes for your reviewer**: **Release note**: ```release-note NONE ``` @mikedanese @pires
This commit is contained in:
		@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -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 != "" {
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -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",
 | 
			
		||||
 
 | 
			
		||||
@@ -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, ",")))
 | 
			
		||||
 
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user