Update kubeadm config generation to be compatible with v1.14.0-beta.1

pull/3810/head
Thomas Stromberg 2019-03-06 13:32:33 -08:00
parent 79c1e7d955
commit 327fdd8d4b
5 changed files with 163 additions and 25 deletions

View File

@ -510,11 +510,15 @@ func generateConfig(k8s config.KubernetesConfig, r cruntime.Manager) (string, er
}
b := bytes.Buffer{}
kubeadmConfigTemplate := kubeadmConfigTemplateV1Alpha1
configTmpl := configTmplV1Alpha1
if version.GTE(semver.MustParse("1.12.0")) {
kubeadmConfigTemplate = kubeadmConfigTemplateV1Alpha3
configTmpl = configTmplV1Alpha3
}
if err := kubeadmConfigTemplate.Execute(&b, opts); err != nil {
// v1beta1 works in v1.13, but isn't required until v1.14.
if version.GTE(semver.MustParse("1.14.0-alpha.0")) {
configTmpl = configTmplV1Beta1
}
if err := configTmpl.Execute(&b, opts); err != nil {
return "", err
}

View File

@ -17,8 +17,10 @@ limitations under the License.
package kubeadm
import (
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/cruntime"
"k8s.io/minikube/pkg/util"
@ -104,6 +106,72 @@ schedulerExtraArgs:
`,
},
{
description: "extra args, v1.14.0",
cfg: config.KubernetesConfig{
NodeIP: "192.168.1.101",
KubernetesVersion: "v1.14.0-beta1",
NodeName: "extra-args-minikube-114",
ExtraOptions: util.ExtraOptionSlice{
util.ExtraOption{
Component: Apiserver,
Key: "fail-no-swap",
Value: "true",
},
util.ExtraOption{
Component: ControllerManager,
Key: "kube-api-burst",
Value: "32",
},
},
},
expectedCfg: `apiVersion: kubeadm.k8s.io/v1beta1
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 192.168.1.101
bindPort: 8443
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
ttl: 24h0m0s
usages:
- signing
- authentication
nodeRegistration:
criSocket: /var/run/dockershim.sock
name: extra-args-minikube-114
taints: []
---
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
apiServer:
extraArgs:
enable-admission-plugins: "Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota"fail-no-swap: "true"
controllerManager:
extraArgs:
kube-api-burst: "32"
certificatesDir: /var/lib/minikube/certs/
clusterName: kubernetes
controlPlaneEndpoint: localhost:8443
dns:
type: CoreDNS
etcd:
local:
dataDir: /data/minikube
kubernetesVersion: v1.14.0-beta1
networking:
dnsDomain: cluster.local
podSubnet: ""
serviceSubnet: 10.96.0.0/12
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
imageGCHighThresholdPercent: 100
evictionHard:
nodefs.available: "0%"
nodefs.inodesFree: "0%"
imagefs.available: "0%"
`,
}, {
description: "two extra args for one component",
cfg: config.KubernetesConfig{
NodeIP: "192.168.1.101",
@ -264,18 +332,21 @@ apiServerExtraArgs:
}
t.Run(test.description, func(t *testing.T) {
actualCfg, err := generateConfig(test.cfg, runtime)
got, err := generateConfig(test.cfg, runtime)
if err != nil && !test.shouldErr {
t.Errorf("got unexpected error generating config: %v", err)
return
}
if err == nil && test.shouldErr {
t.Errorf("expected error but got none, config: %s", actualCfg)
t.Errorf("expected error but got none, config: %s", got)
return
}
if actualCfg != test.expectedCfg {
t.Errorf("actual config does not match expected. actual:\n%sexpected:\n%s", actualCfg, test.expectedCfg)
return
// cmp.Diff doesn't present diffs of multi-line text well
gotSplit := strings.Split(got, "\n")
wantSplit := strings.Split(test.expectedCfg, "\n")
if diff := cmp.Diff(gotSplit, wantSplit); diff != "" {
t.Errorf("unexpected diff: (-want +got)\n%s\ngot: %s\n", diff, got)
}
})
}

View File

@ -22,7 +22,8 @@ import (
"text/template"
)
var kubeadmConfigTemplateV1Alpha1 = template.Must(template.New("kubeadmConfigTemplate-v1alpha1").Funcs(template.FuncMap{
// configTmplV1Alpha1 is for Kubernetes v1.11
var configTmplV1Alpha1 = template.Must(template.New("configTmpl-v1alpha1").Funcs(template.FuncMap{
"printMapInOrder": printMapInOrder,
}).Parse(`apiVersion: kubeadm.k8s.io/v1alpha1
kind: MasterConfiguration
@ -39,16 +40,16 @@ etcd:
dataDir: {{.EtcdDataDir}}
nodeName: {{.NodeName}}
{{if .CRISocket}}criSocket: {{.CRISocket}}
{{end}}{{range .ExtraArgs}}{{.Component}}:{{range $i, $val := printMapInOrder .Options ": " }}
{{end}}{{range .ExtraArgs}}{{.Component}}ExtraArgs:{{range $i, $val := printMapInOrder .Options ": " }}
{{$val}}{{end}}
{{end}}{{if .FeatureArgs}}featureGates: {{range $i, $val := .FeatureArgs}}
{{$i}}: {{$val}}{{end}}
{{end}}`))
var kubeadmConfigTemplateV1Alpha3 = template.Must(template.New("kubeadmConfigTemplate-v1alpha3").Funcs(template.FuncMap{
// configTmplV1Alpha3 is for Kubernetes v1.12
var configTmplV1Alpha3 = template.Must(template.New("configTmpl-v1alpha3").Funcs(template.FuncMap{
"printMapInOrder": printMapInOrder,
}).Parse(`
apiVersion: kubeadm.k8s.io/v1alpha3
}).Parse(`apiVersion: kubeadm.k8s.io/v1alpha3
kind: InitConfiguration
apiEndpoint:
advertiseAddress: {{.AdvertiseAddress}}
@ -67,7 +68,7 @@ nodeRegistration:
---
apiVersion: kubeadm.k8s.io/v1alpha3
kind: ClusterConfiguration
{{range .ExtraArgs}}{{.Component}}:{{range $i, $val := printMapInOrder .Options ": " }}
{{range .ExtraArgs}}{{.Component}}ExtraArgs:{{range $i, $val := printMapInOrder .Options ": " }}
{{$val}}{{end}}
{{end}}{{if .FeatureArgs}}featureGates: {{range $i, $val := .FeatureArgs}}
{{$i}}: {{$val}}{{end}}
@ -86,14 +87,62 @@ networking:
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
# disable disk resource management by default, as it doesn't work well within the minikube environment.
imageGCHighThresholdPercent: 100
# Don't evict jobs, as we only have a single node to run on.
evictionHard:
nodefs.available: "0%"
nodefs.inodesFree: "0%"
imagefs.available: "0%"
`))
`))
// configTmplV1Beta1 is for Kubernetes v1.13+
var configTmplV1Beta1 = template.Must(template.New("configTmpl-v1beta1").Funcs(template.FuncMap{
"printMapInOrder": printMapInOrder,
}).Parse(`apiVersion: kubeadm.k8s.io/v1beta1
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: {{.AdvertiseAddress}}
bindPort: {{.APIServerPort}}
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
ttl: 24h0m0s
usages:
- signing
- authentication
nodeRegistration:
criSocket: {{if .CRISocket}}{{.CRISocket}}{{else}}/var/run/dockershim.sock{{end}}
name: {{.NodeName}}
taints: []
---
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
{{range .ExtraArgs}}{{.Component}}:
extraArgs:
{{range $i, $val := printMapInOrder .Options ": " }}{{$val}}{{end}}
{{end}}{{if .FeatureArgs}}featureGates: {{range $i, $val := .FeatureArgs}}
{{$i}}: {{$val}}{{end}}
{{end -}}
certificatesDir: {{.CertDir}}
clusterName: kubernetes
controlPlaneEndpoint: localhost:{{.APIServerPort}}
dns:
type: CoreDNS
etcd:
local:
dataDir: {{.EtcdDataDir}}
kubernetesVersion: {{.KubernetesVersion}}
networking:
dnsDomain: cluster.local
podSubnet: ""
serviceSubnet: {{.ServiceCIDR}}
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
imageGCHighThresholdPercent: 100
evictionHard:
nodefs.available: "0%"
nodefs.inodesFree: "0%"
imagefs.available: "0%"
`))
var kubeletSystemdTemplate = template.Must(template.New("kubeletSystemdTemplate").Parse(`
[Unit]

View File

@ -65,10 +65,11 @@ type ComponentExtraArgs struct {
Options map[string]string
}
// mapping of component to the section name in kubeadm.
var componentToKubeadmConfigKey = map[string]string{
Apiserver: "apiServerExtraArgs",
ControllerManager: "controllerManagerExtraArgs",
Scheduler: "schedulerExtraArgs",
Apiserver: "apiServer",
ControllerManager: "controllerManager",
Scheduler: "scheduler",
// The Kubelet is not configured in kubeadm, only in systemd.
Kubelet: "",
}
@ -246,7 +247,7 @@ var versionSpecificOpts = []VersionedExtraOption{
Option: util.ExtraOption{
Component: Apiserver,
Key: "admission-control",
Value: strings.Join(util.DefaultAdmissionControllers, ","),
Value: strings.Join(util.DefaultLegacyAdmissionControllers, ","),
},
LessThanOrEqual: semver.MustParse("1.10.1000"), // Semver doesn't support wildcards.
GreaterThanOrEqual: semver.MustParse("1.9.0-alpha.0"),
@ -255,10 +256,20 @@ var versionSpecificOpts = []VersionedExtraOption{
Option: util.ExtraOption{
Component: Apiserver,
Key: "enable-admission-plugins",
Value: strings.Join(util.DefaultAdmissionControllers, ","),
Value: strings.Join(util.DefaultLegacyAdmissionControllers, ","),
},
GreaterThanOrEqual: semver.MustParse("1.11.0-alpha.0"),
LessThanOrEqual: semver.MustParse("1.13.1000"),
},
{
Option: util.ExtraOption{
Component: Apiserver,
Key: "enable-admission-plugins",
Value: strings.Join(util.DefaultV114AdmissionControllers, ","),
},
GreaterThanOrEqual: semver.MustParse("1.14.0-alpha.0"),
},
{
Option: util.ExtraOption{
Component: Kubelet,

View File

@ -32,8 +32,8 @@ const (
DefaultServiceCIDR = "10.96.0.0/12"
)
var DefaultAdmissionControllers = []string{
"Initializers",
// DefaultV114AdmissionControllers are admission controllers we default to in v1.14.x
var DefaultV114AdmissionControllers = []string{
"NamespaceLifecycle",
"LimitRanger",
"ServiceAccount",
@ -45,6 +45,9 @@ var DefaultAdmissionControllers = []string{
"ResourceQuota",
}
// DefaultLegacyAdmissionControllers are admission controllers we default to in order Kubernetes releases
var DefaultLegacyAdmissionControllers = append(DefaultV114AdmissionControllers, "Initializers")
// GetServiceClusterIP returns the first IP of the ServiceCIDR
func GetServiceClusterIP(serviceCIDR string) (net.IP, error) {
ip, _, err := net.ParseCIDR(serviceCIDR)