Merge pull request #63866 from luxas/kubeadm_remove_cloudprovider

Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

 kubeadm: Remove the `.CloudProvider` and `.PrivilegedPods` configuration option

**What this PR does / why we need it**:
Removes the `.CloudProvider` option, it has been experimental for a long time. People should now use external cloud providers, which is beta in v1.11. Most importantly, you can get the exact same behavior in the API by utilizing the `.*ExtraArgs` and `.*ExtraVolumes` fields.
Removes `.PrivilegedPods` as that serves a super small edge case with the legacy cloud provider, and only for openstack.

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Part of https://github.com/kubernetes/community/pull/2131

**Special notes for your reviewer**:
Depends on PRs:
 - [x] #63799
 - [x] #63788

**Release note**:

```release-note
[action required] In the new v1alpha2 kubeadm Configuration API, the `.CloudProvider` and `.PrivilegedPods` fields don't exist anymore.
Instead, you should use the out-of-tree cloud provider implementations which are beta in v1.11.
If you have to use the legacy in-tree cloud providers, you can rearrange your config like the example below.
If you need to use the `.PrivilegedPods` functionality, you can still edit the manifests in
`/etc/kubernetes/manifests/`, and set `.SecurityContext.Privileged=true` for the apiserver
and controller manager.
---
kind: MasterConfiguration
apiVersion: kubeadm.k8s.io/v1alpha2
apiServerExtraArgs:
  cloud-provider: "{cloud}"
  cloud-config: "{path}"
apiServerExtraVolumes:
- name: cloud
  hostPath: "{path}"
  mountPath: "{path}"
controllerManagerExtraArgs:
  cloud-provider: "{cloud}"
  cloud-config: "{path}"
controllerManagerExtraVolumes:
- name: cloud
  hostPath: "{path}"
  mountPath: "{path}"
---
```
@kubernetes/sig-cluster-lifecycle-pr-reviews @dims @liztio
This commit is contained in:
Kubernetes Submit Queue 2018-05-16 12:23:16 -07:00 committed by GitHub
commit bef2ab3c20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 70 additions and 306 deletions

View File

@ -42,8 +42,6 @@ type MasterConfiguration struct {
Networking Networking
// KubernetesVersion is the target version of the control plane.
KubernetesVersion string
// CloudProvider is the name of the cloud provider.
CloudProvider string
// NodeName is the name of the node that will host the k8s control plane.
// Defaults to the hostname if not provided.
NodeName string
@ -56,11 +54,6 @@ type MasterConfiguration struct {
// single node configurations).
NoTaintMaster bool
// Mark the controller and api server pods as privileged as some cloud
// controllers like openstack need escalated privileges under some conditions
// example - loading a config drive to fetch node information.
PrivilegedPods bool
// Token is used for establishing bidirectional trust between nodes and masters.
// Used for joining nodes in the cluster.
Token string

View File

@ -3,6 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"conversion.go",
"defaults.go",
"doc.go",
"register.go",

View File

@ -0,0 +1,61 @@
/*
Copyright 2018 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 v1alpha1
import (
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
)
func addConversionFuncs(scheme *runtime.Scheme) error {
// Add non-generated conversion functions
err := scheme.AddConversionFuncs(
Convert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration,
)
if err != nil {
return err
}
return nil
}
func Convert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in *MasterConfiguration, out *kubeadm.MasterConfiguration, s conversion.Scope) error {
if err := autoConvert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in, out, s); err != nil {
return err
}
UpgradeCloudProvider(in, out)
// We don't support migrating information from the .PrivilegedPods field which was removed in v1alpha2
return nil
}
// UpgradeCloudProvider handles the removal of .CloudProvider as smoothly as possible
func UpgradeCloudProvider(in *MasterConfiguration, out *kubeadm.MasterConfiguration) {
if len(in.CloudProvider) != 0 {
if out.APIServerExtraArgs == nil {
out.APIServerExtraArgs = map[string]string{}
}
if out.ControllerManagerExtraArgs == nil {
out.ControllerManagerExtraArgs = map[string]string{}
}
out.APIServerExtraArgs["cloud-provider"] = in.CloudProvider
out.ControllerManagerExtraArgs["cloud-provider"] = in.CloudProvider
}
}

View File

@ -43,7 +43,7 @@ func init() {
// We only register manually written functions here. The registration of the
// generated functions takes place in the generated files. The separation
// makes the code compile even when the generated files are missing.
localSchemeBuilder.Register(addKnownTypes, addDefaultingFuncs)
localSchemeBuilder.Register(addKnownTypes, addDefaultingFuncs, addConversionFuncs)
}
// Kind takes an unqualified kind and returns a Group qualified GroupKind

View File

@ -236,11 +236,11 @@ func autoConvert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in
return err
}
out.KubernetesVersion = in.KubernetesVersion
out.CloudProvider = in.CloudProvider
// WARNING: in.CloudProvider requires manual conversion: does not exist in peer-type
out.NodeName = in.NodeName
out.AuthorizationModes = *(*[]string)(unsafe.Pointer(&in.AuthorizationModes))
out.NoTaintMaster = in.NoTaintMaster
out.PrivilegedPods = in.PrivilegedPods
// WARNING: in.PrivilegedPods requires manual conversion: does not exist in peer-type
out.Token = in.Token
out.TokenTTL = (*meta_v1.Duration)(unsafe.Pointer(in.TokenTTL))
out.TokenUsages = *(*[]string)(unsafe.Pointer(&in.TokenUsages))
@ -265,11 +265,6 @@ func autoConvert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in
return nil
}
// Convert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration is an autogenerated conversion function.
func Convert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in *MasterConfiguration, out *kubeadm.MasterConfiguration, s conversion.Scope) error {
return autoConvert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in, out, s)
}
func autoConvert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in *kubeadm.MasterConfiguration, out *MasterConfiguration, s conversion.Scope) error {
if err := Convert_kubeadm_API_To_v1alpha1_API(&in.API, &out.API, s); err != nil {
return err
@ -287,11 +282,9 @@ func autoConvert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in
return err
}
out.KubernetesVersion = in.KubernetesVersion
out.CloudProvider = in.CloudProvider
out.NodeName = in.NodeName
out.AuthorizationModes = *(*[]string)(unsafe.Pointer(&in.AuthorizationModes))
out.NoTaintMaster = in.NoTaintMaster
out.PrivilegedPods = in.PrivilegedPods
out.Token = in.Token
out.TokenTTL = (*meta_v1.Duration)(unsafe.Pointer(in.TokenTTL))
out.TokenUsages = *(*[]string)(unsafe.Pointer(&in.TokenUsages))

View File

@ -42,8 +42,6 @@ type MasterConfiguration struct {
Networking Networking `json:"networking"`
// KubernetesVersion is the target version of the control plane.
KubernetesVersion string `json:"kubernetesVersion"`
// CloudProvider is the name of the cloud provider.
CloudProvider string `json:"cloudProvider"`
// NodeName is the name of the node that will host the k8s control plane.
// Defaults to the hostname if not provided.
NodeName string `json:"nodeName"`
@ -56,11 +54,6 @@ type MasterConfiguration struct {
// single node configurations).
NoTaintMaster bool `json:"noTaintMaster,omitempty"`
// Mark the controller and api server pods as privileged as some cloud
// controllers like openstack need escalated privileges under some conditions
// example - loading a config drive to fetch node information
PrivilegedPods bool `json:"privilegedPods"`
// Token is used for establishing bidirectional trust between nodes and masters.
// Used for joining nodes in the cluster.
Token string `json:"token"`

View File

@ -236,11 +236,9 @@ func autoConvert_v1alpha2_MasterConfiguration_To_kubeadm_MasterConfiguration(in
return err
}
out.KubernetesVersion = in.KubernetesVersion
out.CloudProvider = in.CloudProvider
out.NodeName = in.NodeName
out.AuthorizationModes = *(*[]string)(unsafe.Pointer(&in.AuthorizationModes))
out.NoTaintMaster = in.NoTaintMaster
out.PrivilegedPods = in.PrivilegedPods
out.Token = in.Token
out.TokenTTL = (*meta_v1.Duration)(unsafe.Pointer(in.TokenTTL))
out.TokenUsages = *(*[]string)(unsafe.Pointer(&in.TokenUsages))
@ -287,11 +285,9 @@ func autoConvert_kubeadm_MasterConfiguration_To_v1alpha2_MasterConfiguration(in
return err
}
out.KubernetesVersion = in.KubernetesVersion
out.CloudProvider = in.CloudProvider
out.NodeName = in.NodeName
out.AuthorizationModes = *(*[]string)(unsafe.Pointer(&in.AuthorizationModes))
out.NoTaintMaster = in.NoTaintMaster
out.PrivilegedPods = in.PrivilegedPods
out.Token = in.Token
out.TokenTTL = (*meta_v1.Duration)(unsafe.Pointer(in.TokenTTL))
out.TokenUsages = *(*[]string)(unsafe.Pointer(&in.TokenUsages))

View File

@ -49,20 +49,6 @@ import (
"k8s.io/kubernetes/pkg/util/node"
)
// TODO: Break out the cloudprovider functionality out of core and only support the new flow
// described in https://github.com/kubernetes/community/pull/128
var cloudproviders = []string{
"aws",
"azure",
"cloudstack",
"gce",
"external", // Support for out-of-tree cloud providers
"openstack",
"ovirt",
"photon",
"vsphere",
}
// Describes the authorization modes that are enforced by kubeadm
var requiredAuthzModes = []string{
authzmodes.ModeRBAC,
@ -72,7 +58,6 @@ var requiredAuthzModes = []string{
// ValidateMasterConfiguration validates master configuration and collects all encountered errors
func ValidateMasterConfiguration(c *kubeadm.MasterConfiguration) field.ErrorList {
allErrs := field.ErrorList{}
allErrs = append(allErrs, ValidateCloudProvider(c.CloudProvider, field.NewPath("cloudProvider"))...)
allErrs = append(allErrs, ValidateAuthorizationModes(c.AuthorizationModes, field.NewPath("authorizationModes"))...)
allErrs = append(allErrs, ValidateNetworking(&c.Networking, field.NewPath("networking"))...)
allErrs = append(allErrs, ValidateCertSANs(c.APIServerCertSANs, field.NewPath("apiServerCertSANs"))...)
@ -332,21 +317,6 @@ func ValidateNodeName(nodename string, fldPath *field.Path) field.ErrorList {
return allErrs
}
// ValidateCloudProvider validates if cloud provider is supported
func ValidateCloudProvider(provider string, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if len(provider) == 0 {
return allErrs
}
for _, supported := range cloudproviders {
if provider == supported {
return allErrs
}
}
allErrs = append(allErrs, field.Invalid(fldPath, provider, "cloudprovider not supported"))
return allErrs
}
// ValidateMixedArguments validates passed arguments
func ValidateMixedArguments(flag *pflag.FlagSet) error {
// If --config isn't set, we have nothing to validate

View File

@ -155,30 +155,6 @@ func TestValidateNodeName(t *testing.T) {
}
}
func TestValidateCloudProvider(t *testing.T) {
var tests = []struct {
s string
f *field.Path
expected bool
}{
{"", nil, true}, // if not provided, ok, it's optional
{"1234", nil, false}, // not supported
{"awws", nil, false}, // not supported
{"aws", nil, true}, // supported
{"gce", nil, true}, // supported
}
for _, rt := range tests {
actual := ValidateCloudProvider(rt.s, rt.f)
if (len(actual) == 0) != rt.expected {
t.Errorf(
"failed ValidateCloudProvider:\n\texpected: %t\n\t actual: %t",
rt.expected,
(len(actual) == 0),
)
}
}
}
func TestValidateCertSANs(t *testing.T) {
var tests = []struct {
sans []string

View File

@ -254,12 +254,6 @@ func NewInit(cfgPath string, externalcfg *kubeadmapiv1alpha2.MasterConfiguration
glog.Infof("[init] using Kubernetes version: %s\n", cfg.KubernetesVersion)
glog.Infof("[init] using Authorization modes: %v\n", cfg.AuthorizationModes)
// Warn about the limitations with the current cloudprovider solution.
if cfg.CloudProvider != "" {
glog.Warningln("[init] for cloudprovider integrations to work --cloud-provider must be set for all kubelets in the cluster")
glog.Infoln("\t(/etc/systemd/system/kubelet.service.d/10-kubeadm.conf should be edited for this purpose)")
}
glog.Infoln("[preflight] running pre-flight checks")
if err := preflight.RunInitMasterChecks(utilsexec.New(), cfg, ignorePreflightErrors); err != nil {

View File

@ -127,7 +127,7 @@ func TestConfigDirCleaner(t *testing.T) {
"manifests",
},
},
"preserve cloud-config": {
"preserve unrelated file foo": {
setupDirs: []string{
"manifests",
"pki",
@ -138,12 +138,12 @@ func TestConfigDirCleaner(t *testing.T) {
"pki/ca.pem",
kubeadmconstants.AdminKubeConfigFileName,
kubeadmconstants.KubeletKubeConfigFileName,
"cloud-config",
"foo",
},
verifyExists: []string{
"manifests",
"pki",
"cloud-config",
"foo",
},
},
"preserve hidden files and directories": {
@ -158,13 +158,11 @@ func TestConfigDirCleaner(t *testing.T) {
"pki/ca.pem",
kubeadmconstants.AdminKubeConfigFileName,
kubeadmconstants.KubeletKubeConfigFileName,
".cloud-config",
".mydir/.myfile",
},
verifyExists: []string{
"manifests",
"pki",
".cloud-config",
".mydir",
".mydir/.myfile",
},

View File

@ -47,7 +47,6 @@ func TestPrintConfiguration(t *testing.T) {
logDir: ""
path: ""
certificatesDir: ""
cloudProvider: ""
etcd:
caFile: ""
certFile: ""
@ -65,7 +64,6 @@ func TestPrintConfiguration(t *testing.T) {
podSubnet: ""
serviceSubnet: ""
nodeName: ""
privilegedPods: false
token: ""
unifiedControlPlaneImage: ""
`),
@ -87,7 +85,6 @@ func TestPrintConfiguration(t *testing.T) {
logDir: ""
path: ""
certificatesDir: ""
cloudProvider: ""
etcd:
caFile: ""
certFile: ""
@ -105,7 +102,6 @@ func TestPrintConfiguration(t *testing.T) {
podSubnet: ""
serviceSubnet: 10.96.0.1/12
nodeName: ""
privilegedPods: false
token: ""
unifiedControlPlaneImage: ""
`),
@ -132,7 +128,6 @@ func TestPrintConfiguration(t *testing.T) {
logDir: ""
path: ""
certificatesDir: ""
cloudProvider: ""
etcd:
caFile: ""
certFile: ""
@ -155,7 +150,6 @@ func TestPrintConfiguration(t *testing.T) {
podSubnet: ""
serviceSubnet: ""
nodeName: ""
privilegedPods: false
token: ""
unifiedControlPlaneImage: ""
`),

View File

@ -44,7 +44,6 @@ go_library(
"//cmd/kubeadm/app/util/staticpod:go_default_library",
"//pkg/kubeapiserver/authorizer/modes:go_default_library",
"//pkg/master/reconcilers:go_default_library",
"//pkg/util/pointer:go_default_library",
"//pkg/util/version:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",

View File

@ -38,17 +38,10 @@ import (
staticpodutil "k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod"
authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
"k8s.io/kubernetes/pkg/master/reconcilers"
utilpointer "k8s.io/kubernetes/pkg/util/pointer"
"k8s.io/kubernetes/pkg/util/version"
)
// Static pod definitions in golang form are included below so that `kubeadm init` can get going.
const (
DefaultCloudConfigPath = "/etc/kubernetes/cloud-config"
deprecatedV19AdmissionControl = "NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota"
defaultV19AdmissionControl = "NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota"
)
const defaultAdmissionControl = "NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota"
// CreateInitStaticPodManifestFiles will write all static pod manifest files needed to bring up the control plane.
func CreateInitStaticPodManifestFiles(manifestDir string, cfg *kubeadmapi.MasterConfiguration) error {
@ -113,19 +106,6 @@ func GetStaticPodSpecs(cfg *kubeadmapi.MasterConfiguration, k8sVersion *version.
Env: getProxyEnvVars(),
}, mounts.GetVolumes(kubeadmconstants.KubeScheduler)),
}
// Some cloud providers need extra privileges for example to load node information from a config drive
// TODO: when we fully to external cloud providers and the api server and controller manager do not need
// to call out to cloud provider code, we can remove the support for the PrivilegedPods
if cfg.PrivilegedPods {
staticPodSpecs[kubeadmconstants.KubeAPIServer].Spec.Containers[0].SecurityContext = &v1.SecurityContext{
Privileged: utilpointer.BoolPtr(true),
}
staticPodSpecs[kubeadmconstants.KubeControllerManager].Spec.Containers[0].SecurityContext = &v1.SecurityContext{
Privileged: utilpointer.BoolPtr(true),
}
}
return staticPodSpecs
}
@ -165,7 +145,7 @@ func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration) []string {
defaultArguments := map[string]string{
"advertise-address": cfg.API.AdvertiseAddress,
"insecure-port": "0",
"admission-control": defaultV19AdmissionControl,
"admission-control": defaultAdmissionControl,
"service-cluster-ip-range": cfg.Networking.ServiceSubnet,
"service-account-key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.ServiceAccountPublicKeyName),
"client-ca-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.CACertName),
@ -190,10 +170,6 @@ func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration) []string {
command := []string{"kube-apiserver"}
if cfg.CloudProvider == "aws" || cfg.CloudProvider == "gce" {
defaultArguments["admission-control"] = deprecatedV19AdmissionControl
}
// If the user set endpoints for an external etcd cluster
if len(cfg.Etcd.Endpoints) > 0 {
defaultArguments["etcd-servers"] = strings.Join(cfg.Etcd.Endpoints, ",")
@ -225,15 +201,6 @@ func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration) []string {
}
}
if cfg.CloudProvider != "" {
defaultArguments["cloud-provider"] = cfg.CloudProvider
// Only append the --cloud-config option if there's a such file
if _, err := os.Stat(DefaultCloudConfigPath); err == nil {
defaultArguments["cloud-config"] = DefaultCloudConfigPath
}
}
if features.Enabled(cfg.FeatureGates, features.HighAvailability) {
defaultArguments["endpoint-reconciler-type"] = reconcilers.LeaseEndpointReconcilerType
}
@ -323,15 +290,6 @@ func getControllerManagerCommand(cfg *kubeadmapi.MasterConfiguration, k8sVersion
defaultArguments["cluster-signing-cert-file"] = ""
}
if cfg.CloudProvider != "" {
defaultArguments["cloud-provider"] = cfg.CloudProvider
// Only append the --cloud-config option if there's a such file
if _, err := os.Stat(DefaultCloudConfigPath); err == nil {
defaultArguments["cloud-config"] = DefaultCloudConfigPath
}
}
// 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.
if cfg.Networking.PodSubnet != "" {

View File

@ -136,58 +136,6 @@ func TestCreateStaticPodFilesAndWrappers(t *testing.T) {
}
}
func TestCreatePrivilegedContainerForOpenStack(t *testing.T) {
// Creates a Master Configuration with OpenStack cloud provider
var staticPodNames = []string{
kubeadmconstants.KubeAPIServer,
kubeadmconstants.KubeControllerManager,
}
var assertions = []struct {
cloudProvider string
privilegedPods bool
expectedPrivilege bool
}{
{
cloudProvider: "",
expectedPrivilege: false,
},
{
cloudProvider: "aws",
expectedPrivilege: false,
},
{
cloudProvider: "openstack",
privilegedPods: true,
expectedPrivilege: true,
},
}
for _, assertion := range assertions {
cfg := &kubeadmapi.MasterConfiguration{
KubernetesVersion: "v1.9.0",
CloudProvider: assertion.cloudProvider,
PrivilegedPods: assertion.privilegedPods,
}
k8sVersion, _ := version.ParseSemantic(cfg.KubernetesVersion)
specs := GetStaticPodSpecs(cfg, k8sVersion)
for _, podname := range staticPodNames {
spec, _ := specs[podname]
sc := spec.Spec.Containers[0].SecurityContext
if assertion.expectedPrivilege == true {
if sc == nil || sc.Privileged == nil || *sc.Privileged == false {
t.Errorf("GetStaticPodSpecs did not enable privileged containers in %s pod for provider %s", podname, assertion.cloudProvider)
}
} else {
if sc != nil && sc.Privileged != nil && *sc.Privileged == true {
t.Errorf("GetStaticPodSpecs enabled privileged containers in %s pod for provider %s", podname, assertion.cloudProvider)
}
}
}
}
}
func TestGetAPIServerCommand(t *testing.T) {
var tests = []struct {
name string
@ -470,84 +418,6 @@ func TestGetAPIServerCommand(t *testing.T) {
"--audit-log-maxage=0",
},
},
{
name: "ensure gce cloud provider gets passed through",
cfg: &kubeadmapi.MasterConfiguration{
API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"},
Networking: kubeadmapi.Networking{ServiceSubnet: "bar"},
CertificatesDir: testCertsDir,
CloudProvider: "gce",
},
expected: []string{
"kube-apiserver",
"--insecure-port=0",
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota",
"--service-cluster-ip-range=bar",
"--service-account-key-file=" + testCertsDir + "/sa.pub",
"--client-ca-file=" + testCertsDir + "/ca.crt",
"--tls-cert-file=" + testCertsDir + "/apiserver.crt",
"--tls-private-key-file=" + testCertsDir + "/apiserver.key",
"--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt",
"--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key",
"--enable-bootstrap-token-auth=true",
"--secure-port=123",
"--allow-privileged=true",
"--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname",
"--proxy-client-cert-file=/var/lib/certs/front-proxy-client.crt",
"--proxy-client-key-file=/var/lib/certs/front-proxy-client.key",
"--requestheader-username-headers=X-Remote-User",
"--requestheader-group-headers=X-Remote-Group",
"--requestheader-extra-headers-prefix=X-Remote-Extra-",
"--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt",
"--requestheader-allowed-names=front-proxy-client",
"--authorization-mode=Node,RBAC",
"--advertise-address=1.2.3.4",
"--etcd-servers=https://127.0.0.1:2379",
"--etcd-cafile=" + testCertsDir + "/etcd/ca.crt",
"--etcd-certfile=" + testCertsDir + "/apiserver-etcd-client.crt",
"--etcd-keyfile=" + testCertsDir + "/apiserver-etcd-client.key",
"--cloud-provider=gce",
},
},
{
name: "ensure aws cloud provider gets passed through",
cfg: &kubeadmapi.MasterConfiguration{
API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"},
Networking: kubeadmapi.Networking{ServiceSubnet: "bar"},
CertificatesDir: testCertsDir,
CloudProvider: "aws",
},
expected: []string{
"kube-apiserver",
"--insecure-port=0",
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota",
"--service-cluster-ip-range=bar",
"--service-account-key-file=" + testCertsDir + "/sa.pub",
"--client-ca-file=" + testCertsDir + "/ca.crt",
"--tls-cert-file=" + testCertsDir + "/apiserver.crt",
"--tls-private-key-file=" + testCertsDir + "/apiserver.key",
"--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt",
"--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key",
"--enable-bootstrap-token-auth=true",
"--secure-port=123",
"--allow-privileged=true",
"--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname",
"--proxy-client-cert-file=/var/lib/certs/front-proxy-client.crt",
"--proxy-client-key-file=/var/lib/certs/front-proxy-client.key",
"--requestheader-username-headers=X-Remote-User",
"--requestheader-group-headers=X-Remote-Group",
"--requestheader-extra-headers-prefix=X-Remote-Extra-",
"--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt",
"--requestheader-allowed-names=front-proxy-client",
"--authorization-mode=Node,RBAC",
"--advertise-address=1.2.3.4",
"--etcd-servers=https://127.0.0.1:2379",
"--etcd-cafile=" + testCertsDir + "/etcd/ca.crt",
"--etcd-certfile=" + testCertsDir + "/apiserver-etcd-client.crt",
"--etcd-keyfile=" + testCertsDir + "/apiserver-etcd-client.key",
"--cloud-provider=aws",
},
},
{
name: "ensure the DynamicKubelet flag gets passed through",
cfg: &kubeadmapi.MasterConfiguration{
@ -672,26 +542,6 @@ func TestGetControllerManagerCommand(t *testing.T) {
"--controllers=*,bootstrapsigner,tokencleaner",
},
},
{
cfg: &kubeadmapi.MasterConfiguration{
CloudProvider: "foo",
CertificatesDir: testCertsDir,
KubernetesVersion: "v1.7.0",
},
expected: []string{
"kube-controller-manager",
"--address=127.0.0.1",
"--leader-elect=true",
"--kubeconfig=" + kubeadmconstants.KubernetesDir + "/controller-manager.conf",
"--root-ca-file=" + testCertsDir + "/ca.crt",
"--service-account-private-key-file=" + testCertsDir + "/sa.key",
"--cluster-signing-cert-file=" + testCertsDir + "/ca.crt",
"--cluster-signing-key-file=" + testCertsDir + "/ca.key",
"--use-service-account-credentials=true",
"--controllers=*,bootstrapsigner,tokencleaner",
"--cloud-provider=foo",
},
},
{
cfg: &kubeadmapi.MasterConfiguration{
Networking: kubeadmapi.Networking{PodSubnet: "10.0.1.15/16"},

View File

@ -34,7 +34,6 @@ const (
caCertsVolumeName = "ca-certs"
caCertsVolumePath = "/etc/ssl/certs"
flexvolumeDirVolumeName = "flexvolume-dir"
cloudConfigVolumeName = "cloud-config"
flexvolumeDirVolumePath = "/usr/libexec/kubernetes/kubelet-plugins/volume/exec"
)
@ -77,13 +76,6 @@ func getHostPathVolumesForTheControlPlane(cfg *kubeadmapi.MasterConfiguration) c
// Read-only mount for the controller manager kubeconfig file
controllerManagerKubeConfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ControllerManagerKubeConfigFileName)
mounts.NewHostPathMount(kubeadmconstants.KubeControllerManager, kubeadmconstants.KubeConfigVolumeName, controllerManagerKubeConfigFile, controllerManagerKubeConfigFile, true, &hostPathFileOrCreate)
// Read-only mount of the cloud config file if present
if cfg.CloudProvider != "" {
if _, err := os.Stat(DefaultCloudConfigPath); err == nil {
mounts.NewHostPathMount(kubeadmconstants.KubeAPIServer, cloudConfigVolumeName, DefaultCloudConfigPath, DefaultCloudConfigPath, true, &hostPathFileOrCreate)
mounts.NewHostPathMount(kubeadmconstants.KubeControllerManager, cloudConfigVolumeName, DefaultCloudConfigPath, DefaultCloudConfigPath, true, &hostPathFileOrCreate)
}
}
// Mount for the flexvolume directory (/usr/libexec/kubernetes/kubelet-plugins/volume/exec) directory
// Flexvolume dir must NOT be readonly as it is used for third-party plugins to integrate with their storage backends via unix domain socket.
if stat, err := os.Stat(flexvolumeDirVolumePath); err == nil && stat.IsDir() {

View File

@ -556,9 +556,6 @@ func TestGetHostPathVolumesForTheControlPlane(t *testing.T) {
if _, ok := mounts.volumeMounts[kubeadmconstants.KubeControllerManager][flexvolumeDirVolumeName]; ok {
delete(mounts.volumeMounts[kubeadmconstants.KubeControllerManager], flexvolumeDirVolumeName)
}
if _, ok := mounts.volumeMounts[kubeadmconstants.KubeControllerManager][cloudConfigVolumeName]; ok {
delete(mounts.volumeMounts[kubeadmconstants.KubeControllerManager], cloudConfigVolumeName)
}
if !reflect.DeepEqual(mounts.volumes, rt.vol) {
t.Errorf(
"failed getHostPathVolumesForTheControlPlane:\n\texpected: %v\n\t actual: %v",

View File

@ -55,7 +55,6 @@ authorizationModes:
- Node
- RBAC
certificatesDir: %s
cloudProvider: ""
controllerManagerExtraArgs: null
etcd:
caFile: ""