mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-31 07:20:13 +00:00
Merge pull request #65776 from luxas/kubeadm_stop_using_v1alpha1
Automatic merge from submit-queue (batch tested with PRs 65776, 64896). 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: Stop using/supporting the v1alpha1 Config API **What this PR does / why we need it**: In v1.10 and earlier, kubeadm only had the v1alpha1 API. In v1.11, kubeadm could read v1alpha1 configs, but only write v1alpha2 configs In v1.12, kubeadm can read v1alpha2 configs, but only write v1alpha3 or v1beta1 configs. **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/kubernetes/pull/65628 ref: kubernetes/kubeadm#911 **Special notes for your reviewer**: **Release note**: ```release-note NONE ``` @kubernetes/sig-cluster-lifecycle-pr-reviews /assign @timothysc
This commit is contained in:
commit
28768f1d7e
@ -26,7 +26,6 @@ go_library(
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/bootstrap/token/api:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/bootstrap/token/util:go_default_library",
|
||||
"//vendor/github.com/google/gofuzz:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -7,7 +7,6 @@ go_library(
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
|
@ -23,7 +23,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
|
||||
)
|
||||
|
||||
@ -38,10 +37,9 @@ func init() {
|
||||
AddToScheme(Scheme)
|
||||
}
|
||||
|
||||
// AddToScheme builds the Kubeadm scheme using all known versions of the kubeadm api.
|
||||
// AddToScheme builds the kubeadm scheme using all known versions of the kubeadm api.
|
||||
func AddToScheme(scheme *runtime.Scheme) {
|
||||
utilruntime.Must(kubeadm.AddToScheme(scheme))
|
||||
utilruntime.Must(v1alpha1.AddToScheme(scheme))
|
||||
utilruntime.Must(v1alpha2.AddToScheme(scheme))
|
||||
utilruntime.Must(scheme.SetVersionPriority(v1alpha1.SchemeGroupVersion))
|
||||
utilruntime.Must(scheme.SetVersionPriority(v1alpha2.SchemeGroupVersion))
|
||||
}
|
||||
|
@ -17,8 +17,6 @@ limitations under the License.
|
||||
package kubeadm
|
||||
|
||||
import (
|
||||
fuzz "github.com/google/gofuzz"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1"
|
||||
@ -201,14 +199,6 @@ type Etcd struct {
|
||||
External *ExternalEtcd
|
||||
}
|
||||
|
||||
// Fuzz is a dummy function here to get the roundtrip tests working in cmd/kubeadm/app/apis/kubeadm/fuzzer working.
|
||||
// As we split the monolith-etcd struct into two smaller pieces with pointers and they are mutually exclusive, roundtrip
|
||||
// tests that randomize all values in this struct isn't feasible. Instead, we override the fuzzing function for .Etcd with
|
||||
// this func by letting Etcd implement the fuzz.Interface interface. As this func does nothing, we rely on the values given
|
||||
// in fuzzer/fuzzer.go for the roundtrip tests, which is exactly what we want.
|
||||
// TODO: Remove this function when we remove the v1alpha1 API
|
||||
func (e Etcd) Fuzz(c fuzz.Continue) {}
|
||||
|
||||
// LocalEtcd describes that kubeadm should run an etcd cluster locally
|
||||
type LocalEtcd struct {
|
||||
|
||||
|
@ -22,7 +22,6 @@ go_library(
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd/options:go_default_library",
|
||||
|
@ -31,7 +31,6 @@ import (
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
||||
kubeadmapiv1alpha1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
@ -161,7 +160,7 @@ func NewCmdConfigMigrate(out io.Writer) *cobra.Command {
|
||||
locally in the CLI tool without ever touching anything in the cluster.
|
||||
In this version of kubeadm, the following API versions are supported:
|
||||
- %s
|
||||
- %s
|
||||
- TODO: kubeadm.k8s.io/v1beta1
|
||||
|
||||
Further, kubeadm can only write out config of version %q, but read both types.
|
||||
So regardless of what version you pass to the --old-config parameter here, the API object will be
|
||||
@ -170,7 +169,7 @@ func NewCmdConfigMigrate(out io.Writer) *cobra.Command {
|
||||
|
||||
In other words, the output of this command is what kubeadm actually would read internally if you
|
||||
submitted this file to "kubeadm init"
|
||||
`), kubeadmapiv1alpha2.SchemeGroupVersion.String(), kubeadmapiv1alpha1.SchemeGroupVersion.String(), kubeadmapiv1alpha2.SchemeGroupVersion.String()),
|
||||
`), kubeadmapiv1alpha2.SchemeGroupVersion.String(), kubeadmapiv1alpha2.SchemeGroupVersion.String()),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(oldCfgPath) == 0 {
|
||||
kubeadmutil.CheckErr(fmt.Errorf("The --old-config flag is mandatory"))
|
||||
|
@ -1,3 +1,3 @@
|
||||
apiVersion: kubeadm.k8s.io/v1alpha1
|
||||
apiVersion: kubeadm.k8s.io/v1alpha2
|
||||
kind: MasterConfiguration
|
||||
kubernetesVersion: 1.11.0
|
||||
|
@ -17,7 +17,7 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/preflight",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library",
|
||||
"//cmd/kubeadm/app/constants:go_default_library",
|
||||
"//cmd/kubeadm/app/images:go_default_library",
|
||||
"//pkg/registry/core/service/ipallocator:go_default_library",
|
||||
|
@ -42,7 +42,7 @@ import (
|
||||
netutil "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmdefaults "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/images"
|
||||
"k8s.io/kubernetes/pkg/registry/core/service/ipallocator"
|
||||
@ -533,7 +533,7 @@ func (sysver SystemVerificationCheck) Check() (warnings, errors []error) {
|
||||
&system.KernelValidator{Reporter: reporter}}
|
||||
|
||||
// run the docker validator only with dockershim
|
||||
if sysver.CRISocket == kubeadmdefaults.DefaultCRISocket {
|
||||
if sysver.CRISocket == kubeadmapiv1alpha2.DefaultCRISocket {
|
||||
// https://github.com/kubernetes/kubeadm/issues/533
|
||||
validators = append(validators, &system.DockerValidator{Reporter: reporter})
|
||||
}
|
||||
@ -958,7 +958,7 @@ func RunJoinNodeChecks(execer utilsexec.Interface, cfg *kubeadmapi.NodeConfigura
|
||||
// kubeadm init and join commands
|
||||
func addCommonChecks(execer utilsexec.Interface, cfg kubeadmapi.CommonConfiguration, checks []Checker) []Checker {
|
||||
// Check whether or not the CRI socket defined is the default
|
||||
if cfg.GetCRISocket() != kubeadmdefaults.DefaultCRISocket {
|
||||
if cfg.GetCRISocket() != kubeadmapiv1alpha2.DefaultCRISocket {
|
||||
checks = append(checks, CRICheck{socket: cfg.GetCRISocket(), exec: execer})
|
||||
} else {
|
||||
checks = append(checks, ServiceCheck{Service: "docker", CheckIfActive: true})
|
||||
|
@ -21,7 +21,6 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/util",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||
@ -49,7 +48,7 @@ go_test(
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
],
|
||||
|
@ -17,7 +17,6 @@ go_library(
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library",
|
||||
"//cmd/kubeadm/app/constants:go_default_library",
|
||||
@ -46,14 +45,10 @@ go_test(
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library",
|
||||
"//cmd/kubeadm/app/util:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||
"//vendor/github.com/pmezard/go-difflib/difflib:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/require:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -30,7 +30,6 @@ import (
|
||||
bootstraputil "k8s.io/client-go/tools/bootstrap/token/util"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
||||
kubeadmapiv1alpha1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
@ -131,51 +130,12 @@ func ConfigFileAndDefaultsToInternalConfig(cfgPath string, defaultversionedcfg *
|
||||
func BytesToInternalConfig(b []byte) (*kubeadmapi.MasterConfiguration, error) {
|
||||
internalcfg := &kubeadmapi.MasterConfiguration{}
|
||||
|
||||
decoded, err := kubeadmutil.LoadYAML(b)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to decode config from bytes: %v", err)
|
||||
if err := DetectUnsupportedVersion(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// As there was a bug in kubeadm v1.10 and earlier that made the YAML uploaded to the cluster configmap NOT have metav1.TypeMeta information
|
||||
// we need to populate this here manually. If kind or apiVersion is empty, we know the apiVersion is v1alpha1, as by the time kubeadm had this bug,
|
||||
// it could only write
|
||||
// TODO: Remove this "hack" in v1.12 when we know the ConfigMap always contains v1alpha2 content written by kubeadm v1.11. Also, we will drop support for
|
||||
// v1alpha1 in v1.12
|
||||
kind := decoded["kind"]
|
||||
apiVersion := decoded["apiVersion"]
|
||||
if kind == nil || len(kind.(string)) == 0 {
|
||||
decoded["kind"] = "MasterConfiguration"
|
||||
}
|
||||
if apiVersion == nil || len(apiVersion.(string)) == 0 {
|
||||
decoded["apiVersion"] = kubeadmapiv1alpha1.SchemeGroupVersion.String()
|
||||
}
|
||||
|
||||
// Between v1.9 and v1.10 the proxy componentconfig in the v1alpha1 MasterConfiguration changed unexpectedly, which broke unmarshalling out-of-the-box
|
||||
// Hence, we need to workaround this bug in the v1alpha1 API
|
||||
if decoded["apiVersion"] == kubeadmapiv1alpha1.SchemeGroupVersion.String() {
|
||||
v1alpha1cfg := &kubeadmapiv1alpha1.MasterConfiguration{}
|
||||
if err := kubeadmapiv1alpha1.Migrate(decoded, v1alpha1cfg, kubeadmscheme.Codecs); err != nil {
|
||||
return nil, fmt.Errorf("unable to migrate config from previous version: %v", err)
|
||||
}
|
||||
|
||||
// Default and convert to the internal version
|
||||
kubeadmscheme.Scheme.Default(v1alpha1cfg)
|
||||
kubeadmscheme.Scheme.Convert(v1alpha1cfg, internalcfg, nil)
|
||||
} else if decoded["apiVersion"] == kubeadmapiv1alpha2.SchemeGroupVersion.String() {
|
||||
v1alpha2cfg := &kubeadmapiv1alpha2.MasterConfiguration{}
|
||||
if err := runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(), b, v1alpha2cfg); err != nil {
|
||||
return nil, fmt.Errorf("unable to decode config: %v", err)
|
||||
}
|
||||
|
||||
// Default and convert to the internal version
|
||||
kubeadmscheme.Scheme.Default(v1alpha2cfg)
|
||||
kubeadmscheme.Scheme.Convert(v1alpha2cfg, internalcfg, nil)
|
||||
} else {
|
||||
// TODO: Add support for an upcoming v1alpha2 API
|
||||
// TODO: In the future, we can unmarshal any two or more external types into the internal object directly using the following syntax.
|
||||
// Long-term we don't need this if/else clause. In the future this will do
|
||||
// runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(kubeadmapiv1alpha2.SchemeGroupVersion, kubeadmapiv2alpha3.SchemeGroupVersion), b, internalcfg)
|
||||
return nil, fmt.Errorf("unknown API version for kubeadm configuration")
|
||||
if err := runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(kubeadmapiv1alpha2.SchemeGroupVersion), b, internalcfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return defaultAndValidate(internalcfg)
|
||||
@ -193,6 +153,29 @@ func defaultAndValidate(cfg *kubeadmapi.MasterConfiguration) (*kubeadmapi.Master
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
// DetectUnsupportedVersion reads YAML bytes, extracts the TypeMeta information and errors out with an user-friendly message if the API spec is too old for this kubeadm version
|
||||
func DetectUnsupportedVersion(b []byte) error {
|
||||
apiVersionStr, _, err := kubeadmutil.ExtractAPIVersionAndKindFromYAML(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: On our way to making the kubeadm API beta and higher, give good user output in case they use an old config file with a new kubeadm version, and
|
||||
// tell them how to upgrade. The support matrix will look something like this now and in the future:
|
||||
// v1.10 and earlier: v1alpha1
|
||||
// v1.11: v1alpha1 read-only, writes only v1alpha2 config
|
||||
// v1.12: v1alpha2 read-only, writes only v1beta1 config. Warns if the user tries to use v1alpha1
|
||||
// v1.13 and v1.14: v1beta1 read-only, writes only v1 config. Warns if the user tries to use v1alpha1 or v1alpha2.
|
||||
// v1.15: v1 is the only supported format.
|
||||
oldKnownAPIVersions := map[string]string{
|
||||
"kubeadm.k8s.io/v1alpha1": "v1.11",
|
||||
}
|
||||
if useKubeadmVersion := oldKnownAPIVersions[apiVersionStr]; len(useKubeadmVersion) != 0 {
|
||||
return fmt.Errorf("your configuration file seem to use an old API spec. Please use kubeadm %s instead and run 'kubeadm config migrate --old-config old.yaml --new-config new.yaml', which will write the new, similar spec using a newer API version.", useKubeadmVersion)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NormalizeKubernetesVersion resolves version labels, sets alternative
|
||||
// image registry if requested for CI builds, and validates minimal
|
||||
// version that kubeadm supports.
|
||||
|
@ -22,28 +22,20 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
)
|
||||
|
||||
const (
|
||||
master_v1alpha1YAML = "testdata/conversion/master/v1alpha1.yaml"
|
||||
master_v1alpha1WithoutTypeMetaYAML = "testdata/conversion/master/v1alpha1_without_TypeMeta.yaml"
|
||||
master_v1alpha2YAML = "testdata/conversion/master/v1alpha2.yaml"
|
||||
master_internalYAML = "testdata/conversion/master/internal.yaml"
|
||||
master_incompleteYAML = "testdata/defaulting/master/incomplete.yaml"
|
||||
master_defaultedYAML = "testdata/defaulting/master/defaulted.yaml"
|
||||
master_invalidYAML = "testdata/validation/invalid_mastercfg.yaml"
|
||||
master_beforeUpgradeYAML = "testdata/v1alpha1_upgrade/before.yaml"
|
||||
master_afterUpgradeYAML = "testdata/v1alpha1_upgrade/after.yaml"
|
||||
master_v1alpha2YAML = "testdata/conversion/master/v1alpha2.yaml"
|
||||
master_internalYAML = "testdata/conversion/master/internal.yaml"
|
||||
master_incompleteYAML = "testdata/defaulting/master/incomplete.yaml"
|
||||
master_defaultedYAML = "testdata/defaulting/master/defaulted.yaml"
|
||||
master_invalidYAML = "testdata/validation/invalid_mastercfg.yaml"
|
||||
)
|
||||
|
||||
func diff(expected, actual []byte) string {
|
||||
@ -67,45 +59,27 @@ func TestConfigFileAndDefaultsToInternalConfig(t *testing.T) {
|
||||
}{
|
||||
// These tests are reading one file, loading it using ConfigFileAndDefaultsToInternalConfig that all of kubeadm is using for unmarshal of our API types,
|
||||
// and then marshals the internal object to the expected groupVersion
|
||||
{ // v1alpha1 (faulty) -> internal
|
||||
name: "v1alpha1WithoutTypeMetaToInternal",
|
||||
in: master_v1alpha1WithoutTypeMetaYAML,
|
||||
out: master_internalYAML,
|
||||
groupVersion: kubeadm.SchemeGroupVersion,
|
||||
},
|
||||
{ // v1alpha1 -> internal
|
||||
name: "v1alpha1ToInternal",
|
||||
in: master_v1alpha1YAML,
|
||||
out: master_internalYAML,
|
||||
groupVersion: kubeadm.SchemeGroupVersion,
|
||||
},
|
||||
{ // v1alpha2 -> internal
|
||||
name: "v1alpha2ToInternal",
|
||||
in: master_v1alpha2YAML,
|
||||
out: master_internalYAML,
|
||||
groupVersion: kubeadm.SchemeGroupVersion,
|
||||
},
|
||||
{ // v1alpha1 (faulty) -> internal -> v1alpha2
|
||||
name: "v1alpha1WithoutTypeMetaTov1alpha2",
|
||||
in: master_v1alpha1WithoutTypeMetaYAML,
|
||||
out: master_v1alpha2YAML,
|
||||
groupVersion: v1alpha2.SchemeGroupVersion,
|
||||
},
|
||||
{ // v1alpha1 -> internal -> v1alpha2
|
||||
name: "v1alpha1Tov1alpha2",
|
||||
in: master_v1alpha1YAML,
|
||||
{ // v1alpha2 -> internal -> v1alpha2
|
||||
name: "v1alpha2Tov1alpha2",
|
||||
in: master_v1alpha2YAML,
|
||||
out: master_v1alpha2YAML,
|
||||
groupVersion: v1alpha2.SchemeGroupVersion,
|
||||
},
|
||||
// These tests are reading one file that has only a subset of the fields populated, loading it using ConfigFileAndDefaultsToInternalConfig,
|
||||
// and then marshals the internal object to the expected groupVersion
|
||||
{ // v1alpha1 (faulty) -> default -> validate -> internal -> v1alpha2
|
||||
{ // v1alpha2 -> default -> validate -> internal -> v1alpha2
|
||||
name: "incompleteYAMLToDefaultedv1alpha2",
|
||||
in: master_incompleteYAML,
|
||||
out: master_defaultedYAML,
|
||||
groupVersion: v1alpha2.SchemeGroupVersion,
|
||||
},
|
||||
{ // v1alpha1 (faulty) -> validation should fail
|
||||
{ // v1alpha2 -> validation should fail
|
||||
name: "invalidYAMLShouldFail",
|
||||
in: master_invalidYAML,
|
||||
expectedErr: true,
|
||||
@ -141,43 +115,6 @@ func TestConfigFileAndDefaultsToInternalConfig(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestUpgrade tests reading a faulty YAML representation of the MasterConfiguration object (as found in kubeadm clusters <= v1.9.x),
|
||||
// fixes the problems internally and verifies the marshalled output is the expected output
|
||||
func TestUpgrade(t *testing.T) {
|
||||
before, err := ioutil.ReadFile(master_beforeUpgradeYAML)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't read test data: %v", err)
|
||||
}
|
||||
|
||||
afterExpected, err := ioutil.ReadFile(master_afterUpgradeYAML)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't read test data: %v", err)
|
||||
}
|
||||
|
||||
decoded, err := kubeadmutil.LoadYAML(before)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't unmarshal test yaml: %v", err)
|
||||
}
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
require.NoError(t, v1alpha1.AddToScheme(scheme))
|
||||
codecs := serializer.NewCodecFactory(scheme)
|
||||
|
||||
obj := &v1alpha1.MasterConfiguration{}
|
||||
if err := v1alpha1.Migrate(decoded, obj, codecs); err != nil {
|
||||
t.Fatalf("couldn't decode migrated object: %v", err)
|
||||
}
|
||||
|
||||
afterActual, err := kubeadmutil.MarshalToYamlForCodecs(obj, v1alpha1.SchemeGroupVersion, codecs)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't marshal object: %v", err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(afterExpected, afterActual) {
|
||||
t.Errorf("v1alpha1 object after unmarshal, conversion and marshal didn't match expected value.\n\tdiff: \n%s\n", diff(afterExpected, afterActual))
|
||||
}
|
||||
}
|
||||
|
||||
func TestLowercaseSANs(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -25,7 +25,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
||||
kubeadmapiv1alpha1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
"k8s.io/kubernetes/pkg/util/node"
|
||||
@ -43,14 +42,21 @@ func NodeConfigFileAndDefaultsToInternalConfig(cfgPath string, defaultversionedc
|
||||
|
||||
if cfgPath != "" {
|
||||
// Loads configuration from config file, if provided
|
||||
// Nb. --config overrides command line flags
|
||||
// Nb. --config overrides command line flags, TODO: fix this
|
||||
glog.V(1).Infoln("loading configuration from the given file")
|
||||
|
||||
b, err := ioutil.ReadFile(cfgPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to read config from %q [%v]", cfgPath, err)
|
||||
}
|
||||
runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(kubeadmapiv1alpha1.SchemeGroupVersion, kubeadmapiv1alpha2.SchemeGroupVersion), b, internalcfg)
|
||||
|
||||
if err := DetectUnsupportedVersion(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(kubeadmapiv1alpha2.SchemeGroupVersion), b, internalcfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// Takes passed flags into account; the defaulting is executed once again enforcing assignement of
|
||||
// static default values to cfg only for values not provided with flags
|
||||
|
@ -29,7 +29,6 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
node_v1alpha1YAML = "testdata/conversion/node/v1alpha1.yaml"
|
||||
node_v1alpha2YAML = "testdata/conversion/node/v1alpha2.yaml"
|
||||
node_internalYAML = "testdata/conversion/node/internal.yaml"
|
||||
node_incompleteYAML = "testdata/defaulting/node/incomplete.yaml"
|
||||
@ -45,21 +44,15 @@ func TestNodeConfigFileAndDefaultsToInternalConfig(t *testing.T) {
|
||||
}{
|
||||
// These tests are reading one file, loading it using NodeConfigFileAndDefaultsToInternalConfig that all of kubeadm is using for unmarshal of our API types,
|
||||
// and then marshals the internal object to the expected groupVersion
|
||||
{ // v1alpha1 -> internal
|
||||
name: "v1alpha1ToInternal",
|
||||
in: node_v1alpha1YAML,
|
||||
out: node_internalYAML,
|
||||
groupVersion: kubeadm.SchemeGroupVersion,
|
||||
},
|
||||
{ // v1alpha2 -> internal
|
||||
name: "v1alpha2ToInternal",
|
||||
in: node_v1alpha2YAML,
|
||||
out: node_internalYAML,
|
||||
groupVersion: kubeadm.SchemeGroupVersion,
|
||||
},
|
||||
{ // v1alpha1 -> internal -> v1alpha2
|
||||
name: "v1alpha1WithoutTypeMetaTov1alpha2",
|
||||
in: node_v1alpha1YAML,
|
||||
{ // v1alpha2 -> internal -> v1alpha2
|
||||
name: "v1alpha2Tov1alpha2",
|
||||
in: node_v1alpha2YAML,
|
||||
out: node_v1alpha2YAML,
|
||||
groupVersion: v1alpha2.SchemeGroupVersion,
|
||||
},
|
||||
|
@ -1,150 +0,0 @@
|
||||
api:
|
||||
advertiseAddress: 192.168.2.2
|
||||
bindPort: 6443
|
||||
controlPlaneEndpoint: ""
|
||||
apiVersion: kubeadm.k8s.io/v1alpha1
|
||||
auditPolicy:
|
||||
logDir: /var/log/kubernetes/audit
|
||||
logMaxAge: 2
|
||||
path: ""
|
||||
authorizationModes:
|
||||
- Node
|
||||
- RBAC
|
||||
- Webhook
|
||||
certificatesDir: /etc/kubernetes/pki
|
||||
cloudProvider: ""
|
||||
clusterName: kubernetes
|
||||
criSocket: /var/run/dockershim.sock
|
||||
etcd:
|
||||
caFile: ""
|
||||
certFile: ""
|
||||
dataDir: /var/lib/etcd
|
||||
endpoints: null
|
||||
image: ""
|
||||
keyFile: ""
|
||||
imageRepository: k8s.gcr.io
|
||||
kind: MasterConfiguration
|
||||
kubeProxy:
|
||||
config:
|
||||
bindAddress: 0.0.0.0
|
||||
clientConnection:
|
||||
acceptContentTypes: ""
|
||||
burst: 10
|
||||
contentType: application/vnd.kubernetes.protobuf
|
||||
kubeconfig: /var/lib/kube-proxy/kubeconfig.conf
|
||||
qps: 5
|
||||
clusterCIDR: ""
|
||||
configSyncPeriod: 15m0s
|
||||
conntrack:
|
||||
max: null
|
||||
maxPerCore: 32768
|
||||
min: 131072
|
||||
tcpCloseWaitTimeout: 1h0m0s
|
||||
tcpEstablishedTimeout: 24h0m0s
|
||||
enableProfiling: false
|
||||
featureGates:
|
||||
ServiceNodeExclusion: true
|
||||
SupportIPVSProxyMode: true
|
||||
healthzBindAddress: 0.0.0.0:10256
|
||||
hostnameOverride: ""
|
||||
iptables:
|
||||
masqueradeAll: false
|
||||
masqueradeBit: 14
|
||||
minSyncPeriod: 0s
|
||||
syncPeriod: 30s
|
||||
ipvs:
|
||||
excludeCIDRs: null
|
||||
minSyncPeriod: 0s
|
||||
scheduler: ""
|
||||
syncPeriod: 30s
|
||||
metricsBindAddress: 127.0.0.1:10249
|
||||
mode: ""
|
||||
nodePortAddresses: null
|
||||
oomScoreAdj: -999
|
||||
portRange: ""
|
||||
resourceContainer: /kube-proxy
|
||||
udpIdleTimeout: 250ms
|
||||
kubeletConfiguration:
|
||||
baseConfig:
|
||||
address: 0.0.0.0
|
||||
authentication:
|
||||
anonymous:
|
||||
enabled: false
|
||||
webhook:
|
||||
cacheTTL: 2m0s
|
||||
enabled: true
|
||||
x509:
|
||||
clientCAFile: /etc/kubernetes/pki/ca.crt
|
||||
authorization:
|
||||
mode: Webhook
|
||||
webhook:
|
||||
cacheAuthorizedTTL: 5m0s
|
||||
cacheUnauthorizedTTL: 30s
|
||||
cgroupDriver: cgroupfs
|
||||
cgroupsPerQOS: true
|
||||
clusterDNS:
|
||||
- 10.96.0.10
|
||||
clusterDomain: cluster.local
|
||||
configMapAndSecretChangeDetectionStrategy: Watch
|
||||
containerLogMaxFiles: 5
|
||||
containerLogMaxSize: 10Mi
|
||||
contentType: application/vnd.kubernetes.protobuf
|
||||
cpuCFSQuota: true
|
||||
cpuManagerPolicy: none
|
||||
cpuManagerReconcilePeriod: 10s
|
||||
enableControllerAttachDetach: true
|
||||
enableDebuggingHandlers: true
|
||||
enforceNodeAllocatable:
|
||||
- pods
|
||||
eventBurst: 10
|
||||
eventRecordQPS: 5
|
||||
evictionHard:
|
||||
imagefs.available: 15%
|
||||
memory.available: 100Mi
|
||||
nodefs.available: 10%
|
||||
nodefs.inodesFree: 5%
|
||||
evictionPressureTransitionPeriod: 5m0s
|
||||
failSwapOn: true
|
||||
fileCheckFrequency: 20s
|
||||
hairpinMode: promiscuous-bridge
|
||||
healthzBindAddress: 127.0.0.1
|
||||
healthzPort: 10248
|
||||
httpCheckFrequency: 20s
|
||||
imageGCHighThresholdPercent: 85
|
||||
imageGCLowThresholdPercent: 80
|
||||
imageMinimumGCAge: 2m0s
|
||||
iptablesDropBit: 15
|
||||
iptablesMasqueradeBit: 14
|
||||
kubeAPIBurst: 10
|
||||
kubeAPIQPS: 5
|
||||
makeIPTablesUtilChains: true
|
||||
maxOpenFiles: 1000000
|
||||
maxPods: 110
|
||||
nodeStatusUpdateFrequency: 10s
|
||||
oomScoreAdj: -999
|
||||
podPidsLimit: -1
|
||||
port: 10250
|
||||
registryBurst: 10
|
||||
registryPullQPS: 5
|
||||
resolvConf: /etc/resolv.conf
|
||||
runtimeRequestTimeout: 2m0s
|
||||
serializeImagePulls: true
|
||||
staticPodPath: /etc/kubernetes/manifests
|
||||
streamingConnectionIdleTimeout: 4h0m0s
|
||||
syncFrequency: 1m0s
|
||||
volumeStatsAggPeriod: 1m0s
|
||||
kubernetesVersion: v1.10.2
|
||||
networking:
|
||||
dnsDomain: cluster.local
|
||||
podSubnet: ""
|
||||
serviceSubnet: 10.96.0.0/12
|
||||
nodeName: master-1
|
||||
privilegedPods: false
|
||||
token: s73ybu.6tw6wnqgp5z0wb77
|
||||
tokenGroups:
|
||||
- system:bootstrappers:kubeadm:default-node-token
|
||||
tokenTTL: 24h0m0s
|
||||
tokenUsages:
|
||||
- signing
|
||||
- authentication
|
||||
unifiedControlPlaneImage: ""
|
@ -1,147 +0,0 @@
|
||||
# This file don't have TypeMeta set. kubeadm should then unmarshal it as a apiVersion=kubeadm.k8s.io/v1alpha1 and kind=MasterConfiguration
|
||||
api:
|
||||
advertiseAddress: 192.168.2.2
|
||||
bindPort: 6443
|
||||
controlPlaneEndpoint: ""
|
||||
auditPolicy:
|
||||
logDir: /var/log/kubernetes/audit
|
||||
logMaxAge: 2
|
||||
path: ""
|
||||
authorizationModes:
|
||||
- Node
|
||||
- RBAC
|
||||
- Webhook
|
||||
certificatesDir: /etc/kubernetes/pki
|
||||
cloudProvider: ""
|
||||
clusterName: kubernetes
|
||||
criSocket: /var/run/dockershim.sock
|
||||
etcd:
|
||||
caFile: ""
|
||||
certFile: ""
|
||||
dataDir: /var/lib/etcd
|
||||
endpoints: null
|
||||
image: ""
|
||||
keyFile: ""
|
||||
imageRepository: k8s.gcr.io
|
||||
kubeProxy:
|
||||
config:
|
||||
bindAddress: 0.0.0.0
|
||||
clientConnection:
|
||||
acceptContentTypes: ""
|
||||
burst: 10
|
||||
contentType: application/vnd.kubernetes.protobuf
|
||||
kubeconfig: /var/lib/kube-proxy/kubeconfig.conf
|
||||
qps: 5
|
||||
clusterCIDR: ""
|
||||
configSyncPeriod: 15m0s
|
||||
conntrack:
|
||||
max: null
|
||||
maxPerCore: 32768
|
||||
min: 131072
|
||||
tcpCloseWaitTimeout: 1h0m0s
|
||||
tcpEstablishedTimeout: 24h0m0s
|
||||
enableProfiling: false
|
||||
featureGates: "SupportIPVSProxyMode=true,ServiceNodeExclusion=true"
|
||||
healthzBindAddress: 0.0.0.0:10256
|
||||
hostnameOverride: ""
|
||||
iptables:
|
||||
masqueradeAll: false
|
||||
masqueradeBit: 14
|
||||
minSyncPeriod: 0s
|
||||
syncPeriod: 30s
|
||||
ipvs:
|
||||
excludeCIDRs: null
|
||||
minSyncPeriod: 0s
|
||||
scheduler: ""
|
||||
syncPeriod: 30s
|
||||
metricsBindAddress: 127.0.0.1:10249
|
||||
mode: ""
|
||||
nodePortAddresses: null
|
||||
oomScoreAdj: -999
|
||||
portRange: ""
|
||||
resourceContainer: /kube-proxy
|
||||
udpIdleTimeout: 250ms
|
||||
kubeletConfiguration:
|
||||
baseConfig:
|
||||
address: 0.0.0.0
|
||||
authentication:
|
||||
anonymous:
|
||||
enabled: false
|
||||
webhook:
|
||||
cacheTTL: 2m0s
|
||||
enabled: true
|
||||
x509:
|
||||
clientCAFile: /etc/kubernetes/pki/ca.crt
|
||||
authorization:
|
||||
mode: Webhook
|
||||
webhook:
|
||||
cacheAuthorizedTTL: 5m0s
|
||||
cacheUnauthorizedTTL: 30s
|
||||
cgroupDriver: cgroupfs
|
||||
cgroupsPerQOS: true
|
||||
clusterDNS:
|
||||
- 10.96.0.10
|
||||
clusterDomain: cluster.local
|
||||
configMapAndSecretChangeDetectionStrategy: Watch
|
||||
containerLogMaxFiles: 5
|
||||
containerLogMaxSize: 10Mi
|
||||
contentType: application/vnd.kubernetes.protobuf
|
||||
cpuCFSQuota: true
|
||||
cpuManagerPolicy: none
|
||||
cpuManagerReconcilePeriod: 10s
|
||||
enableControllerAttachDetach: true
|
||||
enableDebuggingHandlers: true
|
||||
enforceNodeAllocatable:
|
||||
- pods
|
||||
eventBurst: 10
|
||||
eventRecordQPS: 5
|
||||
evictionHard:
|
||||
imagefs.available: 15%
|
||||
memory.available: 100Mi
|
||||
nodefs.available: 10%
|
||||
nodefs.inodesFree: 5%
|
||||
evictionPressureTransitionPeriod: 5m0s
|
||||
failSwapOn: true
|
||||
fileCheckFrequency: 20s
|
||||
hairpinMode: promiscuous-bridge
|
||||
healthzBindAddress: 127.0.0.1
|
||||
healthzPort: 10248
|
||||
httpCheckFrequency: 20s
|
||||
imageGCHighThresholdPercent: 85
|
||||
imageGCLowThresholdPercent: 80
|
||||
imageMinimumGCAge: 2m0s
|
||||
iptablesDropBit: 15
|
||||
iptablesMasqueradeBit: 14
|
||||
kubeAPIBurst: 10
|
||||
kubeAPIQPS: 5
|
||||
makeIPTablesUtilChains: true
|
||||
maxOpenFiles: 1000000
|
||||
maxPods: 110
|
||||
nodeStatusUpdateFrequency: 10s
|
||||
oomScoreAdj: -999
|
||||
podPidsLimit: -1
|
||||
port: 10250
|
||||
registryBurst: 10
|
||||
registryPullQPS: 5
|
||||
resolvConf: /etc/resolv.conf
|
||||
runtimeRequestTimeout: 2m0s
|
||||
serializeImagePulls: true
|
||||
staticPodPath: /etc/kubernetes/manifests
|
||||
streamingConnectionIdleTimeout: 4h0m0s
|
||||
syncFrequency: 1m0s
|
||||
volumeStatsAggPeriod: 1m0s
|
||||
kubernetesVersion: v1.10.2
|
||||
networking:
|
||||
dnsDomain: cluster.local
|
||||
podSubnet: ""
|
||||
serviceSubnet: 10.96.0.0/12
|
||||
nodeName: master-1
|
||||
privilegedPods: false
|
||||
token: s73ybu.6tw6wnqgp5z0wb77
|
||||
tokenGroups:
|
||||
- system:bootstrappers:kubeadm:default-node-token
|
||||
tokenTTL: 24h0m0s
|
||||
tokenUsages:
|
||||
- signing
|
||||
- authentication
|
||||
unifiedControlPlaneImage: ""
|
@ -1,14 +0,0 @@
|
||||
apiVersion: kubeadm.k8s.io/v1alpha1
|
||||
kind: NodeConfiguration
|
||||
caCertPath: /etc/kubernetes/pki/ca.crt
|
||||
clusterName: kubernetes
|
||||
criSocket: /var/run/dockershim.sock
|
||||
discoveryFile: ""
|
||||
discoveryTimeout: 5m0s
|
||||
discoveryToken: abcdef.0123456789abcdef
|
||||
discoveryTokenAPIServers:
|
||||
- kube-apiserver:6443
|
||||
discoveryTokenUnsafeSkipCAVerification: true
|
||||
nodeName: master-1
|
||||
tlsBootstrapToken: abcdef.0123456789abcdef
|
||||
token: abcdef.0123456789abcdef
|
@ -1,15 +1,17 @@
|
||||
# This file _should_ set TypeMeta, but at some point earlier we supported deserializing MasterConfigurations without TypeMeta, so we need to support that as long as we
|
||||
# support the v1alpha1 API. In the meantime kubeadm will treat this as v1alpha1 automatically when unmarshalling.
|
||||
apiVersion: kubeadm.k8s.io/v1alpha2
|
||||
kind: MasterConfiguration
|
||||
api:
|
||||
advertiseAddress: 192.168.2.2
|
||||
bindPort: 6443
|
||||
bootstrapTokens:
|
||||
- token: s73ybu.6tw6wnqgp5z0wb77
|
||||
certificatesDir: /var/lib/kubernetes/pki
|
||||
clusterName: kubernetes
|
||||
criSocket: /var/run/criruntime.sock
|
||||
imageRepository: my-company.com
|
||||
kubernetesVersion: v1.10.2
|
||||
networking:
|
||||
dnsDomain: cluster.global
|
||||
serviceSubnet: 10.196.0.0/12
|
||||
nodeName: master-1
|
||||
token: s73ybu.6tw6wnqgp5z0wb77
|
||||
nodeRegistration:
|
||||
criSocket: /var/run/criruntime.sock
|
||||
name: master-1
|
||||
|
@ -1,7 +1,8 @@
|
||||
apiVersion: kubeadm.k8s.io/v1alpha1
|
||||
apiVersion: kubeadm.k8s.io/v1alpha2
|
||||
kind: NodeConfiguration
|
||||
discoveryTokenAPIServers:
|
||||
- kube-apiserver:6443
|
||||
discoveryTokenUnsafeSkipCAVerification: true
|
||||
nodeName: thegopher
|
||||
nodeRegistration:
|
||||
name: thegopher
|
||||
token: abcdef.0123456789abcdef
|
||||
|
@ -1,73 +0,0 @@
|
||||
api:
|
||||
advertiseAddress: 172.31.93.180
|
||||
bindPort: 6443
|
||||
controlPlaneEndpoint: ""
|
||||
apiVersion: kubeadm.k8s.io/v1alpha1
|
||||
auditPolicy:
|
||||
logDir: ""
|
||||
path: ""
|
||||
authorizationModes:
|
||||
- Node
|
||||
- RBAC
|
||||
certificatesDir: /etc/kubernetes/pki
|
||||
cloudProvider: aws
|
||||
etcd:
|
||||
caFile: ""
|
||||
certFile: ""
|
||||
dataDir: /var/lib/etcd
|
||||
endpoints: null
|
||||
image: ""
|
||||
keyFile: ""
|
||||
imageRepository: gcr.io/google_containers
|
||||
kind: MasterConfiguration
|
||||
kubeProxy:
|
||||
config:
|
||||
bindAddress: 0.0.0.0
|
||||
clientConnection:
|
||||
acceptContentTypes: ""
|
||||
burst: 10
|
||||
contentType: application/vnd.kubernetes.protobuf
|
||||
kubeconfig: /var/lib/kube-proxy/kubeconfig.conf
|
||||
qps: 5
|
||||
clusterCIDR: 192.168.0.0/16
|
||||
configSyncPeriod: 15m0s
|
||||
conntrack:
|
||||
max: null
|
||||
maxPerCore: 32768
|
||||
min: 131072
|
||||
tcpCloseWaitTimeout: 1h0m0s
|
||||
tcpEstablishedTimeout: 24h0m0s
|
||||
enableProfiling: false
|
||||
featureGates:
|
||||
ServiceNodeExclusion: true
|
||||
SupportIPVSProxyMode: true
|
||||
healthzBindAddress: 0.0.0.0:10256
|
||||
hostnameOverride: ""
|
||||
iptables:
|
||||
masqueradeAll: false
|
||||
masqueradeBit: 14
|
||||
minSyncPeriod: 0s
|
||||
syncPeriod: 30s
|
||||
ipvs:
|
||||
excludeCIDRs: null
|
||||
minSyncPeriod: 0s
|
||||
scheduler: ""
|
||||
syncPeriod: 30s
|
||||
metricsBindAddress: 127.0.0.1:10249
|
||||
mode: ""
|
||||
nodePortAddresses: null
|
||||
oomScoreAdj: -999
|
||||
portRange: ""
|
||||
resourceContainer: /kube-proxy
|
||||
udpIdleTimeout: 0s
|
||||
kubeletConfiguration: {}
|
||||
kubernetesVersion: v1.9.6
|
||||
networking:
|
||||
dnsDomain: cluster.local
|
||||
podSubnet: 192.168.0.0/16
|
||||
serviceSubnet: 10.96.0.0/12
|
||||
nodeName: ip-172-31-93-180.ec2.internal
|
||||
privilegedPods: false
|
||||
token: 8d69af.cd3e1c58f6228dfc
|
||||
tokenTTL: 24h0m0s
|
||||
unifiedControlPlaneImage: ""
|
@ -1,64 +0,0 @@
|
||||
# This MasterConfiguration object is wrong in two ways: it hasn't TypeMeta set, and .kubeProxy.config.featureGates is a string as it was in v1.9
|
||||
# In v1.10 however, it changed in an inbackwards-compatible way to a map[string]string, so we have to workaround that to unmarshal this object
|
||||
api:
|
||||
advertiseAddress: 172.31.93.180
|
||||
bindPort: 6443
|
||||
authorizationModes:
|
||||
- Node
|
||||
- RBAC
|
||||
certificatesDir: /etc/kubernetes/pki
|
||||
cloudProvider: aws
|
||||
etcd:
|
||||
caFile: ""
|
||||
certFile: ""
|
||||
dataDir: /var/lib/etcd
|
||||
endpoints: null
|
||||
image: ""
|
||||
keyFile: ""
|
||||
imageRepository: gcr.io/google_containers
|
||||
kubeProxy:
|
||||
config:
|
||||
bindAddress: 0.0.0.0
|
||||
clientConnection:
|
||||
acceptContentTypes: ""
|
||||
burst: 10
|
||||
contentType: application/vnd.kubernetes.protobuf
|
||||
kubeconfig: /var/lib/kube-proxy/kubeconfig.conf
|
||||
qps: 5
|
||||
clusterCIDR: 192.168.0.0/16
|
||||
configSyncPeriod: 15m0s
|
||||
conntrack:
|
||||
max: null
|
||||
maxPerCore: 32768
|
||||
min: 131072
|
||||
tcpCloseWaitTimeout: 1h0m0s
|
||||
tcpEstablishedTimeout: 24h0m0s
|
||||
enableProfiling: false
|
||||
featureGates: "SupportIPVSProxyMode=true,ServiceNodeExclusion=true"
|
||||
healthzBindAddress: 0.0.0.0:10256
|
||||
hostnameOverride: ""
|
||||
iptables:
|
||||
masqueradeAll: false
|
||||
masqueradeBit: 14
|
||||
minSyncPeriod: 0s
|
||||
syncPeriod: 30s
|
||||
ipvs:
|
||||
minSyncPeriod: 0s
|
||||
scheduler: ""
|
||||
syncPeriod: 30s
|
||||
metricsBindAddress: 127.0.0.1:10249
|
||||
mode: ""
|
||||
oomScoreAdj: -999
|
||||
portRange: ""
|
||||
resourceContainer: /kube-proxy
|
||||
udpTimeoutMilliseconds: 250ms
|
||||
kubeletConfiguration: {}
|
||||
kubernetesVersion: v1.9.6
|
||||
networking:
|
||||
dnsDomain: cluster.local
|
||||
podSubnet: 192.168.0.0/16
|
||||
serviceSubnet: 10.96.0.0/12
|
||||
nodeName: ip-172-31-93-180.ec2.internal
|
||||
token: 8d69af.cd3e1c58f6228dfc
|
||||
tokenTTL: 24h0m0s
|
||||
unifiedControlPlaneImage: ""
|
@ -1,12 +1,16 @@
|
||||
apiVersion: kubeadm.k8s.io/v1alpha2
|
||||
kind: MasterConfiguration
|
||||
api:
|
||||
bindPort: 0
|
||||
bootstrapTokens:
|
||||
- token: s7bu.6tw6wn
|
||||
certificatesDir: relativepath
|
||||
clusterName: kubernetes
|
||||
criSocket: relativepath
|
||||
imageRepository: my-company.com
|
||||
kubernetesVersion: v1.10.2
|
||||
networking:
|
||||
dnsDomain: cluster.GLOBAL
|
||||
serviceSubnet: 10.196.1000.0/100
|
||||
nodeName: MASTER
|
||||
token: s7bu.6tw6wn
|
||||
nodeRegistration:
|
||||
criSocket: relativepath
|
||||
name: MASTER
|
||||
|
@ -1,11 +1,12 @@
|
||||
apiVersion: kubeadm.k8s.io/v1alpha1
|
||||
apiVersion: kubeadm.k8s.io/v1alpha2
|
||||
kind: NodeConfiguration
|
||||
caCertPath: relativepath
|
||||
criSocket: relativepath
|
||||
discoveryFile: relativepath
|
||||
discoveryTimeout: not-a-time
|
||||
discoveryTokenAPIServers:
|
||||
- INVALID_URL
|
||||
discoveryTokenUnsafeSkipCAVerification: false
|
||||
nodeName: NODE-1
|
||||
nodeRegistration:
|
||||
criSocket: relativepath
|
||||
name: NODE-1
|
||||
token: invalidtoken
|
||||
|
@ -26,7 +26,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
kubeadmapiv1alpha1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
)
|
||||
|
||||
// MarshalToYaml marshals an object into yaml.
|
||||
@ -67,37 +66,36 @@ func UnmarshalFromYamlForCodecs(buffer []byte, gv schema.GroupVersion, codecs se
|
||||
return runtime.Decode(decoder, buffer)
|
||||
}
|
||||
|
||||
// GroupVersionKindFromBytes parses the bytes and returns the gvk
|
||||
func GroupVersionKindFromBytes(buffer []byte, codecs serializer.CodecFactory) (schema.GroupVersionKind, error) {
|
||||
|
||||
decoded, err := LoadYAML(buffer)
|
||||
// ExtractAPIVersionAndKindFromYAML extracts the APIVersion and Kind fields from YAML bytes
|
||||
func ExtractAPIVersionAndKindFromYAML(b []byte) (string, string, error) {
|
||||
decoded, err := LoadYAML(b)
|
||||
if err != nil {
|
||||
return schema.EmptyObjectKind.GroupVersionKind(), fmt.Errorf("unable to decode config from bytes: %v", err)
|
||||
return "", "", fmt.Errorf("unable to decode config from bytes: %v", err)
|
||||
}
|
||||
kindStr, apiVersionStr := "", ""
|
||||
|
||||
// As there was a bug in kubeadm v1.10 and earlier that made the YAML uploaded to the cluster configmap NOT have metav1.TypeMeta information
|
||||
// we need to populate this here manually. If kind or apiVersion is empty, we know the apiVersion is v1alpha1, as by the time kubeadm had this bug,
|
||||
// it could only write
|
||||
// TODO: Remove this "hack" in v1.12 when we know the ConfigMap always contains v1alpha2 content written by kubeadm v1.11. Also, we will drop support for
|
||||
// v1alpha1 in v1.12
|
||||
kind := decoded["kind"]
|
||||
apiVersion := decoded["apiVersion"]
|
||||
if kind == nil || len(kind.(string)) == 0 {
|
||||
kindStr = "MasterConfiguration"
|
||||
} else {
|
||||
kindStr = kind.(string)
|
||||
kindStr, ok := decoded["kind"].(string)
|
||||
if !ok || len(kindStr) == 0 {
|
||||
return "", "", fmt.Errorf("any config file must have the kind field set")
|
||||
}
|
||||
if apiVersion == nil || len(apiVersion.(string)) == 0 {
|
||||
apiVersionStr = kubeadmapiv1alpha1.SchemeGroupVersion.String()
|
||||
} else {
|
||||
apiVersionStr = apiVersion.(string)
|
||||
apiVersionStr, ok := decoded["apiVersion"].(string)
|
||||
if !ok || len(apiVersionStr) == 0 {
|
||||
return "", "", fmt.Errorf("any config file must have the apiVersion field set")
|
||||
}
|
||||
return apiVersionStr, kindStr, nil
|
||||
}
|
||||
|
||||
// GroupVersionKindFromBytes parses the bytes and returns the gvk
|
||||
// TODO: Find a better way to do this, invoking the API machinery directly without first loading the yaml manually
|
||||
func GroupVersionKindFromBytes(b []byte, codecs serializer.CodecFactory) (schema.GroupVersionKind, error) {
|
||||
apiVersionStr, kindStr, err := ExtractAPIVersionAndKindFromYAML(b)
|
||||
if err != nil {
|
||||
return schema.EmptyObjectKind.GroupVersionKind(), err
|
||||
}
|
||||
|
||||
gv, err := schema.ParseGroupVersion(apiVersionStr)
|
||||
if err != nil {
|
||||
return schema.EmptyObjectKind.GroupVersionKind(), fmt.Errorf("unable to parse apiVersion: %v", err)
|
||||
}
|
||||
|
||||
return gv.WithKind(kindStr), nil
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
|
||||
)
|
||||
|
||||
func TestMarshalUnmarshalYaml(t *testing.T) {
|
||||
@ -75,51 +75,42 @@ func TestMarshalUnmarshalYaml(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMarshalUnmarshalToYamlForCodecs(t *testing.T) {
|
||||
cfg := &kubeadmapiext.MasterConfiguration{
|
||||
API: kubeadmapiext.API{
|
||||
cfg := &kubeadmapiv1alpha2.MasterConfiguration{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "MasterConfiguration",
|
||||
APIVersion: kubeadmapiv1alpha2.SchemeGroupVersion.String(),
|
||||
},
|
||||
API: kubeadmapiv1alpha2.API{
|
||||
AdvertiseAddress: "10.100.0.1",
|
||||
BindPort: 4332,
|
||||
},
|
||||
NodeName: "testNode",
|
||||
NoTaintMaster: true,
|
||||
Networking: kubeadmapiext.Networking{
|
||||
NodeRegistration: kubeadmapiv1alpha2.NodeRegistrationOptions{
|
||||
Name: "testNode",
|
||||
CRISocket: "/var/run/cri.sock",
|
||||
},
|
||||
Networking: kubeadmapiv1alpha2.Networking{
|
||||
ServiceSubnet: "10.100.0.0/24",
|
||||
PodSubnet: "10.100.1.0/24",
|
||||
},
|
||||
}
|
||||
scheme.Scheme.Default(cfg)
|
||||
|
||||
bytes, err := MarshalToYamlForCodecs(cfg, kubeadmapiext.SchemeGroupVersion, scheme.Codecs)
|
||||
bytes, err := MarshalToYamlForCodecs(cfg, kubeadmapiv1alpha2.SchemeGroupVersion, scheme.Codecs)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error marshalling MasterConfiguration: %v", err)
|
||||
}
|
||||
t.Logf("\n%s", bytes)
|
||||
|
||||
obj, err := UnmarshalFromYamlForCodecs(bytes, kubeadmapiext.SchemeGroupVersion, scheme.Codecs)
|
||||
obj, err := UnmarshalFromYamlForCodecs(bytes, kubeadmapiv1alpha2.SchemeGroupVersion, scheme.Codecs)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error unmarshalling MasterConfiguration: %v", err)
|
||||
}
|
||||
|
||||
cfg2, ok := obj.(*kubeadmapiext.MasterConfiguration)
|
||||
if !ok {
|
||||
cfg2, ok := obj.(*kubeadmapiv1alpha2.MasterConfiguration)
|
||||
if !ok || cfg2 == nil {
|
||||
t.Fatal("did not get MasterConfiguration back")
|
||||
}
|
||||
|
||||
if cfg2.API.AdvertiseAddress != cfg.API.AdvertiseAddress {
|
||||
t.Errorf("expected %q, got %q", cfg.API.AdvertiseAddress, cfg2.API.AdvertiseAddress)
|
||||
}
|
||||
if cfg2.API.BindPort != cfg.API.BindPort {
|
||||
t.Errorf("expected %d, got %d", cfg.API.BindPort, cfg2.API.BindPort)
|
||||
}
|
||||
if cfg2.NodeName != cfg.NodeName {
|
||||
t.Errorf("expected %q, got %q", cfg.NodeName, cfg2.NodeName)
|
||||
}
|
||||
if cfg2.NoTaintMaster != cfg.NoTaintMaster {
|
||||
t.Errorf("expected %v, got %v", cfg.NoTaintMaster, cfg2.NoTaintMaster)
|
||||
}
|
||||
if cfg2.Networking.ServiceSubnet != cfg.Networking.ServiceSubnet {
|
||||
t.Errorf("expected %v, got %v", cfg.Networking.ServiceSubnet, cfg2.Networking.ServiceSubnet)
|
||||
}
|
||||
if cfg2.Networking.PodSubnet != cfg.Networking.PodSubnet {
|
||||
t.Errorf("expected %v, got %v", cfg.Networking.PodSubnet, cfg2.Networking.PodSubnet)
|
||||
if !reflect.DeepEqual(*cfg, *cfg2) {
|
||||
t.Errorf("expected %v, got %v", *cfg, *cfg2)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user