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
pull/6/head
Kubernetes Submit Queue 2017-01-31 03:29:44 -08:00 committed by GitHub
commit 8ffada6699
7 changed files with 31 additions and 70 deletions

View File

@ -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 {

View File

@ -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 != "" {

View File

@ -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

View File

@ -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"
)

View File

@ -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",

View File

@ -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, ",")))

View File

@ -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 {