Kubeadm requires manual version updates of its current supported k8s
control plane version and minimally supported k8s control plane and
kubelet versions every release cycle.
To avoid that, in constants.go:
- Add the helper function getSkewedKubernetesVersion() that can be
used to retrieve a MAJOR.(MINOR+n).0 version of k8s. It currently
uses the kubeadm version populated in "component-base/version" during
the kubeadm build process.
- Use the function to set existing version constants (variables).
Update util/config/common.go#NormalizeKubernetesVersion() to
tolerate the case where a k8s version in the ClusterConfiguration
is too old for the kubeadm binary to use during code freeze.
Include unit tests for the new utilities.
- scheme: switch to:
utilruntime.Must(scheme.SetVersionPriority(v1beta3.SchemeGroupVersion))
- change all imports in the code base from v1beta2 to v1beta3
- rename all import aliases for kubeadmapiv1beta2 to "kubeadmapiv".
this allows smaller diffs when changing the default public API.
MarshalClusterConfigurationToBytes has capabilities to output the component
configs, as separate YAML documents, besides the kubeadm ClusterConfiguration
kind. This is no longer necessary for the following reasons:
- All current use cases of this function require only the ClusterConfiguration.
- It will output component configs only if they are not the default ones. This
can produce undeterministic output and, thus, cause potential problems.
- There are only hacky ways to dump the ClusterConfiguration only (without the
component configs).
Hence, we simplify things by replacing the function with direct calls to the
underlaying MarshalToYamlForCodecs. Thus marshalling only ClusterConfiguration,
when needed.
Signed-off-by: Rostislav M. Georgiev <rostislavg@vmware.com>
Currently kubeadm supports a couple of configuration versions - v1alpha3 and
v1beta1. The former is deprecated, but still supported.
To discourage users from using it and to speedup conversion to newer versions,
we disable the loading of deprecated configurations by all kubeadm
sub-commands, but "kubeadm config migrate".
v1alpha3 is still present and supported at source level, but cannot be used
directly with kubeadm and some of its internal APIs.
The added benefit to this is, that users won't need to lookup for an old
kubeadm binary after upgrade, just because they were stuck with a deprecated
config version for too long.
To achieve this, the following was done:
- ValidateSupportedVersion now has an allowDeprecated boolean parameter, that
controls if the function should return an error upon detecting deprecated
config version. Currently the only deprecated version is v1alpha3.
- ValidateSupportedVersion is made package private, because it's not used
outside of the package anyway.
- BytesToInitConfiguration and LoadJoinConfigurationFromFile are modified to
disallow loading of deprecated kubeadm config versions. An error message,
that points users to kubeadm config migrate is returned.
- MigrateOldConfig is still allowed to load deprecated kubeadm config versions.
- A bunch of tests were fixed to not expect success if v1alpha3 config is
supplied.
Signed-off-by: Rostislav M. Georgiev <rostislavg@vmware.com>
MigrateOldConfigFromFile is a function, whose purpose is to migrate one config
into another. It is working OK for now, but it has some issues:
- It is incredibly inefficient. It can reload and re-parse a single config file
for up to 3 times.
- Because of the reloads, it has to take a file containing the configuration
(not a byte slice as most of the rest config functions). However, it returns
the migrated config in a byte slice (rather asymmetric from the input
method).
- Due to the above points it's difficult to implement a proper interface for
deprecated kubeadm config versions.
To fix the issues of MigrateOldConfigFromFile, the following is done:
- Re-implement the function by removing the calls to file loading package
public APIs and replacing them with newly extracted package private APIs that
do the job with pre-provided input data in the form of
map[GroupVersionKind][]byte.
- Take a byte slice of the input configuration as an argument. This makes the
function input symmetric to its output. Also, it's now renamed to
MigrateOldConfig to represent the change from config file path as an input
to byte slice.
- As a bonus (actually forgotten from a previous change) BytesToInternalConfig
is renamed to the more descriptive BytesToInitConfiguration.
Signed-off-by: Rostislav M. Georgiev <rostislavg@vmware.com>
Currently ConfigFileAndDefaultsToInternalConfig and
FetchConfigFromFileOrCluster are used to default and load InitConfiguration
from file or cluster. These two APIs do a couple of completely separate things
depending on how they were invoked. In the case of
ConfigFileAndDefaultsToInternalConfig, an InitConfiguration could be either
defaulted with external override parameters, or loaded from file.
With FetchConfigFromFileOrCluster an InitConfiguration is either loaded from
file or from the config map in the cluster.
The two share both some functionality, but not enough code. They are also quite
difficult to use and sometimes even error prone.
To solve the issues, the following steps were taken:
- Introduce DefaultedInitConfiguration which returns defaulted version agnostic
InitConfiguration. The function takes InitConfiguration for overriding the
defaults.
- Introduce LoadInitConfigurationFromFile, which loads, converts, validates and
defaults an InitConfiguration from file.
- Introduce FetchInitConfigurationFromCluster that fetches InitConfiguration
from the config map.
- Reduce, when possible, the usage of ConfigFileAndDefaultsToInternalConfig by
replacing it with DefaultedInitConfiguration or LoadInitConfigurationFromFile
invocations.
- Replace all usages of FetchConfigFromFileOrCluster with calls to
LoadInitConfigurationFromFile or FetchInitConfigurationFromCluster.
- Delete FetchConfigFromFileOrCluster as it's no longer used.
- Rename ConfigFileAndDefaultsToInternalConfig to
LoadOrDefaultInitConfiguration in order to better describe what the function
is actually doing.
Signed-off-by: Rostislav M. Georgiev <rostislavg@vmware.com>
Currently JoinConfigFileAndDefaultsToInternalConfig is doing a couple of
different things depending on its parameters. It:
- loads a versioned JoinConfiguration from an YAML file.
- returns defaulted JoinConfiguration allowing for some overrides.
In order to make code more manageable, the following steps are taken:
- Introduce LoadJoinConfigurationFromFile, which loads a versioned
JoinConfiguration from an YAML file, defaults it (both dynamically and
statically), converts it to internal JoinConfiguration and validates it.
- Introduce DefaultedJoinConfiguration, which returns defaulted (both
dynamically and statically) and verified internal JoinConfiguration.
The possibility of overwriting defaults via versioned JoinConfiguration is
retained.
- Re-implement JoinConfigFileAndDefaultsToInternalConfig to use
LoadJoinConfigurationFromFile and DefaultedJoinConfiguration.
- Replace some calls to JoinConfigFileAndDefaultsToInternalConfig with calls to
either LoadJoinConfigurationFromFile or DefaultedJoinConfiguration where
appropriate.
- Rename JoinConfigFileAndDefaultsToInternalConfig to the more appropriate name
LoadOrDefaultJoinConfiguration.
Signed-off-by: Rostislav M. Georgiev <rostislavg@vmware.com>
DetectUnsupportedVersion is somewhat uncomfortable, complex and inefficient
function to use. It takes an entire YAML document as bytes, splits it up to
byte slices of the different YAML sub-documents and group-version-kinds and
searches through those to detect an unsupported kubeadm config. If such config
is detected, the function returns an error, if it is not (i.e. the normal
function operation) everything done so far is discarded.
This could have been acceptable, if not the fact, that in all cases that this
function is called, the YAML document bytes are split up and an iteration on
GVK map is performed yet again. Hence, we don't need DetectUnsupportedVersion
in its current form as it's inefficient, complex and takes only YAML document
bytes.
This change replaces DetectUnsupportedVersion with ValidateSupportedVersion,
which takes a GroupVersion argument and checks if it is on the list of
unsupported config versions. In that case an error is returned.
ValidateSupportedVersion relies on the caller to read and split the YAML
document and then iterate on its GVK map checking if the particular
GroupVersion is supported or not.
Signed-off-by: Rostislav M. Georgiev <rostislavg@vmware.com>
kubeadm config migrate uses AnyConfigFileAndDefaultsToInternal, which can
unmarshal config from file only if InitConfiguration or JoinConfiguration are
present. Even with that in mind, it can only return a singlie config object,
with InitConfiguration taking precendence over JoinConfiguration. Thus, the
following cases were not handled properly, while they were perfectly valid for
kubeadm init/join:
- ClusterConfiguration only file caused kubeadm config migrate to exit with
error.
- Init + Join configurations in the same file caused Init + Cluster
configuration to be produced (ignoring JoinConfiguration). The same is valid
when the combo is Init + Cluster + Join configurations.
- Cluster + Join configuration ignores ClusterConfiguration and only
JoinConfiguration gets migrated.
To fix this, the following is done:
- Introduce MigrateOldConfigFromFile which migrates old config from a file,
while ensuring that all kubeadm originated input config kinds are taken care
of. Add comprehensive unit tests for this.
- Replace the use of AnyConfigFileAndDefaultsToInternal in
kubeadm config migrate with MigrateOldConfigFromFile.
- Remove the no longer used and error prone AnyConfigFileAndDefaultsToInternal.
Signed-off-by: Rostislav M. Georgiev <rostislavg@vmware.com>
ChooseAPIServerBindAddress is silently overriding the requested bind IP
address for the API server if that address is deemed unsuitable. This is
currently done only if the IP is a loopback one (127.0.0.0/8; ::1/128).
It's best to at least issue a warning if such override occurs, so that there
are no surprised users by this.
Signed-off-by: Rostislav M. Georgiev <rostislavg@vmware.com>
- Move from the old github.com/golang/glog to k8s.io/klog
- klog as explicit InitFlags() so we add them as necessary
- we update the other repositories that we vendor that made a similar
change from glog to klog
* github.com/kubernetes/repo-infra
* k8s.io/gengo/
* k8s.io/kube-openapi/
* github.com/google/cadvisor
- Entirely remove all references to glog
- Fix some tests by explicit InitFlags in their init() methods
Change-Id: I92db545ff36fcec83afe98f550c9e630098b3135
This change allows mixing InitConfiguration/ClusterConfiguration with
JoinConfiguration in a single YAML file, by performing the following changes:
- Replace the explicit error in `DetectUnsupportedVersion` with a warning.
- Modify `NodeConfigFileAndDefaultsToInternalConfig` to use only
`JoinConfiguration`.
Signed-off-by: Rostislav M. Georgiev <rostislavg@vmware.com>
1) Do not fail in case a bind address cannot be obtained
If netutil.ChooseBindAddress() fails looking up IP route tables
it will fail with an error in which case the kubeadm config
code will hard stop.
This scenario is possible if the Linux user intentionally disables
the WiFi from the distribution settings. In such a case the distro
could empty files such files as /proc/net/route and ChooseBindAddress()
will return an error.
For improved offline support, don't error on such scenarios but instead
show a warning. This is done by using the NoRoutesError type.
Also default the address to 0.0.0.0.
While doing that, prevent some commands like `init`, `join` and also
phases like `controlplane` and `certs` from using such an invalid
address.
Add unit tests for the new function for address verification.
2) Fallback to local client version
If there is no internet, label versions fail and this breaks
air-gapped setups unless the users pass an explicit version.
To work around that:
- Remain using 'release/stable-x.xx' as the default version.
- On timeout or any error different from status 404 return error
- On status 404 fallback to using the version of the client via
kubeadmVersion()
Add unit tests for kubeadmVersion().
Co-authored-by: Alexander Kanevskiy <alexander.kanevskiy@intel.com>