Bumping k8s dependencies to 1.13
This commit is contained in:
37
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/BUILD
generated
vendored
37
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/BUILD
generated
vendored
@@ -10,6 +10,7 @@ go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"cluster.go",
|
||||
"common.go",
|
||||
"masterconfig.go",
|
||||
"nodeconfig.go",
|
||||
],
|
||||
@@ -17,27 +18,31 @@ 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/v1alpha3:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library",
|
||||
"//cmd/kubeadm/app/componentconfigs:go_default_library",
|
||||
"//cmd/kubeadm/app/constants:go_default_library",
|
||||
"//cmd/kubeadm/app/util:go_default_library",
|
||||
"//pkg/util/node:go_default_library",
|
||||
"//pkg/util/version: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",
|
||||
"//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/util/net:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/bootstrap/token/util:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/util/cert:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/bootstrap/token/util:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"cluster_test.go",
|
||||
"common_test.go",
|
||||
"masterconfig_test.go",
|
||||
"nodeconfig_test.go",
|
||||
],
|
||||
@@ -46,13 +51,17 @@ 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/apis/kubeadm/v1alpha3:go_default_library",
|
||||
"//cmd/kubeadm/app/constants:go_default_library",
|
||||
"//cmd/kubeadm/app/util:go_default_library",
|
||||
"//cmd/kubeadm/app/util/apiclient:go_default_library",
|
||||
"//pkg/util/version: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",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||
"//vendor/github.com/pmezard/go-difflib/difflib:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
231
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/cluster.go
generated
vendored
231
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/cluster.go
generated
vendored
@@ -17,49 +17,244 @@ limitations under the License.
|
||||
package config
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
certutil "k8s.io/client-go/util/cert"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/pkg/util/version"
|
||||
)
|
||||
|
||||
// TODO: Add unit tests for this file
|
||||
|
||||
// FetchConfigFromFileOrCluster fetches configuration required for upgrading your cluster from a file (which has precedence) or a ConfigMap in the cluster
|
||||
func FetchConfigFromFileOrCluster(client clientset.Interface, w io.Writer, logPrefix, cfgPath string) (*kubeadmapi.MasterConfiguration, error) {
|
||||
func FetchConfigFromFileOrCluster(client clientset.Interface, w io.Writer, logPrefix, cfgPath string, newControlPlane bool) (*kubeadmapi.InitConfiguration, error) {
|
||||
// Load the configuration from a file or the cluster
|
||||
configBytes, err := loadConfigurationBytes(client, w, logPrefix, cfgPath)
|
||||
initcfg, err := loadConfiguration(client, w, logPrefix, cfgPath, newControlPlane)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Take the versioned configuration populated from the file or ConfigMap, convert it to internal, default and validate
|
||||
return BytesToInternalConfig(configBytes)
|
||||
// Apply dynamic defaults
|
||||
if err := SetInitDynamicDefaults(initcfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return initcfg, err
|
||||
}
|
||||
|
||||
// loadConfigurationBytes loads the configuration byte slice from either a file or the cluster ConfigMap
|
||||
func loadConfigurationBytes(client clientset.Interface, w io.Writer, logPrefix, cfgPath string) ([]byte, error) {
|
||||
// loadConfiguration loads the configuration byte slice from either a file or the cluster ConfigMap
|
||||
func loadConfiguration(client clientset.Interface, w io.Writer, logPrefix, cfgPath string, newControlPlane bool) (*kubeadmapi.InitConfiguration, error) {
|
||||
// The config file has the highest priority
|
||||
if cfgPath != "" {
|
||||
fmt.Fprintf(w, "[%s] Reading configuration options from a file: %s\n", logPrefix, cfgPath)
|
||||
return ioutil.ReadFile(cfgPath)
|
||||
return loadInitConfigurationFromFile(cfgPath)
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "[%s] Reading configuration from the cluster...\n", logPrefix)
|
||||
fmt.Fprintf(w, "[%s] FYI: You can look at this config file with 'kubectl -n %s get cm %s -oyaml'\n", logPrefix, metav1.NamespaceSystem, constants.InitConfigurationConfigMap)
|
||||
return getInitConfigurationFromCluster(constants.KubernetesDir, client, newControlPlane)
|
||||
}
|
||||
|
||||
configMap, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(constants.MasterConfigurationConfigMap, metav1.GetOptions{})
|
||||
if apierrors.IsNotFound(err) {
|
||||
// Return the apierror directly so the caller of this function can know what type of error occurred and act based on that
|
||||
return []byte{}, err
|
||||
} else if err != nil {
|
||||
return []byte{}, fmt.Errorf("an unexpected error happened when trying to get the ConfigMap %q in the %s namespace: %v", constants.MasterConfigurationConfigMap, metav1.NamespaceSystem, err)
|
||||
func loadInitConfigurationFromFile(cfgPath string) (*kubeadmapi.InitConfiguration, error) {
|
||||
configBytes, err := ioutil.ReadFile(cfgPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "[%s] FYI: You can look at this config file with 'kubectl -n %s get cm %s -oyaml'\n", logPrefix, metav1.NamespaceSystem, constants.MasterConfigurationConfigMap)
|
||||
return []byte(configMap.Data[constants.MasterConfigurationConfigMapKey]), nil
|
||||
// Unmarshal the versioned configuration populated from the file,
|
||||
// convert it to the internal API types, then default and validate
|
||||
// NB the file can be one of
|
||||
// - a single YAML, with a v1alpha2.MasterConfiguration object (with embedded component configs)
|
||||
// - multiple YAML, with a combination of
|
||||
// - a YAML with a v1alpha3.InitConfiguration object
|
||||
// - a YAML with a v1alpha3.ClusterConfiguration object (without embedded component configs)
|
||||
// - separated YAML for components configs
|
||||
initcfg, err := BytesToInternalConfig(configBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return initcfg, nil
|
||||
}
|
||||
|
||||
func getInitConfigurationFromCluster(kubeconfigDir string, client clientset.Interface, newControlPlane bool) (*kubeadmapi.InitConfiguration, error) {
|
||||
// TODO: This code should support reading the MasterConfiguration key as well for backwards-compat
|
||||
// Also, the config map really should be KubeadmConfigConfigMap...
|
||||
configMap, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(constants.InitConfigurationConfigMap, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: remove in V1.13
|
||||
// If InitConfigurationConfigMapKey exist, the kubeadm-config was created with v1.11
|
||||
if _, ok := configMap.Data[constants.InitConfigurationConfigMapKey]; ok {
|
||||
return getInitConfigurationFromConfigMapV11(configMap.Data)
|
||||
}
|
||||
|
||||
return getInitConfigurationFromConfigMaps(kubeconfigDir, client, configMap.Data, newControlPlane)
|
||||
}
|
||||
|
||||
func getInitConfigurationFromConfigMapV11(data map[string]string) (*kubeadmapi.InitConfiguration, error) {
|
||||
configBytes := []byte(data[constants.InitConfigurationConfigMapKey])
|
||||
|
||||
// Unmarshal the versioned configuration populated from the file,
|
||||
// convert it to the internal API types, then default and validate
|
||||
// NB the config map created with v11 is a single YAML, with a v1alpha2.MasterConfiguration object (with embedded component configs)
|
||||
initcfg, err := BytesToInternalConfig(configBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return initcfg, nil
|
||||
}
|
||||
|
||||
func getInitConfigurationFromConfigMaps(kubeconfigDir string, client clientset.Interface, data map[string]string, newControlPlane bool) (*kubeadmapi.InitConfiguration, error) {
|
||||
// In case of cluster crated with v1.12 InitConfiguration is composed with data from different places
|
||||
initcfg := &kubeadmapi.InitConfiguration{}
|
||||
|
||||
// gets ClusterConfiguration from kubeadm-config
|
||||
clusterConfigurationData, ok := data[constants.ClusterConfigurationConfigMapKey]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected error when reading kubeadm-config ConfigMap: %s key value pair missing", constants.ClusterConfigurationConfigMapKey)
|
||||
}
|
||||
if err := runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(), []byte(clusterConfigurationData), &initcfg.ClusterConfiguration); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// gets the component configs from the corresponding config maps
|
||||
if err := getComponentConfigs(client, &initcfg.ClusterConfiguration); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// if this isn't a new controlplane instance (e.g. in case of kubeadm upgrades)
|
||||
// get nodes specific information as well
|
||||
if !newControlPlane {
|
||||
// gets the nodeRegistration for the current from the node object
|
||||
if err := getNodeRegistration(kubeconfigDir, client, &initcfg.NodeRegistration); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// gets the APIEndpoint for the current node from then ClusterStatus in the kubeadm-config ConfigMap
|
||||
if err := getAPIEndpoint(data, initcfg.NodeRegistration.Name, &initcfg.APIEndpoint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return initcfg, nil
|
||||
}
|
||||
|
||||
// getNodeRegistration returns the nodeRegistration for the current node
|
||||
func getNodeRegistration(kubeconfigDir string, client clientset.Interface, nodeRegistration *kubeadmapi.NodeRegistrationOptions) error {
|
||||
// gets the name of the current node
|
||||
nodeName, err := getNodeNameFromKubeletConfig(kubeconfigDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// gets the corresponding node and retrives attributes stored there.
|
||||
node, err := client.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
criSocket, ok := node.ObjectMeta.Annotations[constants.AnnotationKubeadmCRISocket]
|
||||
if !ok {
|
||||
return fmt.Errorf("Node %s doesn't have %s annotation", nodeName, constants.AnnotationKubeadmCRISocket)
|
||||
}
|
||||
|
||||
// returns the nodeRegistration attributes
|
||||
nodeRegistration.Name = nodeName
|
||||
nodeRegistration.CRISocket = criSocket
|
||||
nodeRegistration.Taints = node.Spec.Taints
|
||||
// NB. currently nodeRegistration.KubeletExtraArgs isn't stored at node level but only in the kubeadm-flags.env
|
||||
// that isn't modified during upgrades
|
||||
// in future we might reconsider this thus enabling changes to the kubeadm-flags.env during upgrades as well
|
||||
return nil
|
||||
}
|
||||
|
||||
// getNodeNameFromConfig gets the node name from a kubelet config file
|
||||
// TODO: in future we want to switch to a more canonical way for doing this e.g. by having this
|
||||
// information in the local kubelet config.yaml
|
||||
func getNodeNameFromKubeletConfig(kubeconfigDir string) (string, error) {
|
||||
// loads the kubelet.conf file
|
||||
fileName := filepath.Join(kubeconfigDir, constants.KubeletKubeConfigFileName)
|
||||
config, err := clientcmd.LoadFromFile(fileName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// gets the info about the current user
|
||||
authInfo := config.AuthInfos[config.Contexts[config.CurrentContext].AuthInfo]
|
||||
|
||||
// gets the X509 certificate with current user credentials
|
||||
var certs []*x509.Certificate
|
||||
if len(authInfo.ClientCertificateData) > 0 {
|
||||
// if the config file uses an embedded x509 certificate (e.g. kubelet.conf created by kubeadm), parse it
|
||||
if certs, err = certutil.ParseCertsPEM(authInfo.ClientCertificateData); err != nil {
|
||||
return "", err
|
||||
}
|
||||
} else if len(authInfo.ClientCertificate) > 0 {
|
||||
// if the config file links an external x509 certificate (e.g. kubelet.conf created by TLS bootstrap), load it
|
||||
if certs, err = certutil.CertsFromFile(authInfo.ClientCertificate); err != nil {
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
return "", errors.New("Invalid kubelet.conf. X509 certificate expected")
|
||||
}
|
||||
|
||||
// We are only putting one certificate in the certificate pem file, so it's safe to just pick the first one
|
||||
// TODO: Support multiple certs here in order to be able to rotate certs
|
||||
cert := certs[0]
|
||||
|
||||
// gets the node name from the certificate common name
|
||||
return strings.TrimPrefix(cert.Subject.CommonName, constants.NodesUserPrefix), nil
|
||||
}
|
||||
|
||||
// getAPIEndpoint returns the APIEndpoint for the current node
|
||||
func getAPIEndpoint(data map[string]string, nodeName string, apiEndpoint *kubeadmapi.APIEndpoint) error {
|
||||
// gets the ClusterStatus from kubeadm-config
|
||||
clusterStatusData, ok := data[constants.ClusterStatusConfigMapKey]
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected error when reading kubeadm-config ConfigMap: %s key value pair missing", constants.ClusterStatusConfigMapKey)
|
||||
}
|
||||
clusterStatus := &kubeadmapi.ClusterStatus{}
|
||||
if err := runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(), []byte(clusterStatusData), clusterStatus); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// gets the APIEndpoint for the current machine from the ClusterStatus
|
||||
e, ok := clusterStatus.APIEndpoints[nodeName]
|
||||
if !ok {
|
||||
return errors.New("failed to get APIEndpoint information for this node")
|
||||
}
|
||||
|
||||
apiEndpoint.AdvertiseAddress = e.AdvertiseAddress
|
||||
apiEndpoint.BindPort = e.BindPort
|
||||
return nil
|
||||
}
|
||||
|
||||
// getComponentConfigs gets the component configs from the corresponding config maps
|
||||
func getComponentConfigs(client clientset.Interface, clusterConfiguration *kubeadmapi.ClusterConfiguration) error {
|
||||
// some config maps is versioned, so we need the KubernetesVersion for getting the right config map
|
||||
k8sVersion := version.MustParseGeneric(clusterConfiguration.KubernetesVersion)
|
||||
for kind, registration := range componentconfigs.Known {
|
||||
obj, err := registration.GetFromConfigMap(client, k8sVersion)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ok := registration.SetToInternalConfig(obj, clusterConfiguration); !ok {
|
||||
return fmt.Errorf("couldn't save componentconfig value for kind %q", string(kind))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
684
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/cluster_test.go
generated
vendored
Normal file
684
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/cluster_test.go
generated
vendored
Normal file
@@ -0,0 +1,684 @@
|
||||
/*
|
||||
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 config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
clientsetfake "k8s.io/client-go/kubernetes/fake"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
||||
"k8s.io/kubernetes/pkg/util/version"
|
||||
)
|
||||
|
||||
var k8sVersionString = "v1.12.0"
|
||||
var k8sVersion = version.MustParseGeneric(k8sVersionString)
|
||||
var nodeName = "mynode"
|
||||
var cfgFiles = map[string][]byte{
|
||||
"MasterConfiguration_v1alpha2": []byte(`
|
||||
apiVersion: kubeadm.k8s.io/v1alpha2
|
||||
kind: MasterConfiguration
|
||||
kubernetesVersion: ` + k8sVersionString + `
|
||||
api:
|
||||
advertiseAddress: 1.2.3.4
|
||||
bindPort: 1234
|
||||
`),
|
||||
"InitConfiguration_v1alpha3": []byte(`
|
||||
apiVersion: kubeadm.k8s.io/v1alpha3
|
||||
kind: InitConfiguration
|
||||
`),
|
||||
"ClusterConfiguration_v1alpha3": []byte(`
|
||||
apiVersion: kubeadm.k8s.io/v1alpha3
|
||||
kind: ClusterConfiguration
|
||||
kubernetesVersion: ` + k8sVersionString + `
|
||||
`),
|
||||
"ClusterStatus_v1alpha3": []byte(`
|
||||
apiVersion: kubeadm.k8s.io/v1alpha3
|
||||
kind: ClusterStatus
|
||||
apiEndpoints:
|
||||
` + nodeName + `:
|
||||
advertiseAddress: 1.2.3.4
|
||||
bindPort: 1234
|
||||
`),
|
||||
"ClusterStatus_v1alpha3_Without_APIEndpoints": []byte(`
|
||||
apiVersion: kubeadm.k8s.io/v1alpha3
|
||||
kind: ClusterStatus
|
||||
`),
|
||||
"Kube-proxy_componentconfig": []byte(`
|
||||
apiVersion: kubeproxy.config.k8s.io/v1alpha1
|
||||
kind: KubeProxyConfiguration
|
||||
`),
|
||||
"Kubelet_componentconfig": []byte(`
|
||||
apiVersion: kubelet.config.k8s.io/v1beta1
|
||||
kind: KubeletConfiguration
|
||||
`),
|
||||
}
|
||||
|
||||
var kubeletConfFiles = map[string][]byte{
|
||||
"withoutX509Cert": []byte(`
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
server: https://10.0.2.15:6443
|
||||
name: kubernetes
|
||||
contexts:
|
||||
- context:
|
||||
cluster: kubernetes
|
||||
user: system:node:mynode
|
||||
name: system:node:mynode@kubernetes
|
||||
current-context: system:node:mynode@kubernetes
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: system:node:mynode
|
||||
user:
|
||||
`),
|
||||
"configWithEmbeddedCert": []byte(`
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
server: https://10.0.2.15:6443
|
||||
name: kubernetes
|
||||
contexts:
|
||||
- context:
|
||||
cluster: kubernetes
|
||||
user: system:node:mynode
|
||||
name: system:node:mynode@kubernetes
|
||||
current-context: system:node:mynode@kubernetes
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: system:node:mynode
|
||||
user:
|
||||
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM4akNDQWRxZ0F3SUJBZ0lJQWl3VURhYk5vZ1F3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB4T0RBNU1ERXhOVE14TWpaYUZ3MHhPVEE1TURFeE5qQXhOVGxhTURReApGVEFUQmdOVkJBb1RESE41YzNSbGJUcHViMlJsY3pFYk1Ca0dBMVVFQXhNU2MzbHpkR1Z0T201dlpHVTZiWGx1CmIyUmxNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQWs2UXUzeStyNEZYUzZ4VkoKWU1vNE9kSkt3R1d1MHY4TEJIUnhhOUhvVHo1RXZLQnB1OVJoemt5dStUaFczb0xta2ZTRmNJcitHa0M5MW0zOApFelRmVE5JY2dsL0V5YkpmR1QvdGdUazZYd1kxY1UrUUdmSEFNNTBCVzFXTFVHc25CSllJZjA5eENnZTVoTkxLCnREeUJOWWNQZzg1bUJpOU9CNFJ2UlgyQVFRMjJwZ0xrQUpJWklOU0FEdUFrODN2b051SXM2YVY2bHBkR2Vva3YKdDlpTFdNR3p3a3ZTZUZQTlNGeWZ3Q055eENjb1FDQUNtSnJRS3NoeUE2bWNzdVhORWVXdlRQdVVFSWZPVFl4dwpxdkszRVBOK0xUYlA2anhUMWtTcFJUOSt4Z29uSlFhU0RsbUNBd20zRGJkSVppWUt3R2ppMkxKL0kvYWc0cTlzCjNLb0J2UUlEQVFBQm95Y3dKVEFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFLcVVrU21jdW85OG5EK015b005VFdEV0pyTndySXpQTUNqRQpCSkdyREhVaHIwcEZlRjc0RHViODNzRXlaNjFxNUVQd2Y0enNLSzdzdDRUTzZhcE9pZWJYVmN3dnZoa09HQ2dFCmFVdGNOMjFhUGxtU0tOd0c4ai8yK3ZhbU80bGplK1NnZzRUUVB0eDZWejh5VXN2RFhxSUZycjNNd1gzSDA1RW4KWXAzN05JYkhKbGxHUW5LVHA5aTg5aXF4WXVhSERqZldiVHlEY3B5NldNVjdVaFYvY1plc3lGL0NBamNHd1V6YgowRlo5bW5tMnFONlBGWHZ4RmdMSGFWZzN2SVVCbkNmVVVyY1BDNE94VFNPK21aUmUxazh3eUFpVWovSk0rZllvCkcrMi9sbThUYVZqb1U3Rmk1S2E1RzVIWTJHTGFSN1ArSXhZY3JNSENsNjJZN1JxY3JuYz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
|
||||
`),
|
||||
"configWithLinkedCert": []byte(`
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
server: https://10.0.2.15:6443
|
||||
name: kubernetes
|
||||
contexts:
|
||||
- context:
|
||||
cluster: kubernetes
|
||||
user: system:node:mynode
|
||||
name: system:node:mynode@kubernetes
|
||||
current-context: system:node:mynode@kubernetes
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: system:node:mynode
|
||||
user:
|
||||
client-certificate: kubelet.pem
|
||||
`),
|
||||
}
|
||||
|
||||
var pemFiles = map[string][]byte{
|
||||
"mynode.pem": []byte(`
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIC8jCCAdqgAwIBAgIIAiwUDabNogQwDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE
|
||||
AxMKa3ViZXJuZXRlczAeFw0xODA5MDExNTMxMjZaFw0xOTA5MDExNjAxNTlaMDQx
|
||||
FTATBgNVBAoTDHN5c3RlbTpub2RlczEbMBkGA1UEAxMSc3lzdGVtOm5vZGU6bXlu
|
||||
b2RlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk6Qu3y+r4FXS6xVJ
|
||||
YMo4OdJKwGWu0v8LBHRxa9HoTz5EvKBpu9Rhzkyu+ThW3oLmkfSFcIr+GkC91m38
|
||||
EzTfTNIcgl/EybJfGT/tgTk6XwY1cU+QGfHAM50BW1WLUGsnBJYIf09xCge5hNLK
|
||||
tDyBNYcPg85mBi9OB4RvRX2AQQ22pgLkAJIZINSADuAk83voNuIs6aV6lpdGeokv
|
||||
t9iLWMGzwkvSeFPNSFyfwCNyxCcoQCACmJrQKshyA6mcsuXNEeWvTPuUEIfOTYxw
|
||||
qvK3EPN+LTbP6jxT1kSpRT9+xgonJQaSDlmCAwm3DbdIZiYKwGji2LJ/I/ag4q9s
|
||||
3KoBvQIDAQABoycwJTAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUH
|
||||
AwIwDQYJKoZIhvcNAQELBQADggEBAKqUkSmcuo98nD+MyoM9TWDWJrNwrIzPMCjE
|
||||
BJGrDHUhr0pFeF74Dub83sEyZ61q5EPwf4zsKK7st4TO6apOiebXVcwvvhkOGCgE
|
||||
aUtcN21aPlmSKNwG8j/2+vamO4lje+Sgg4TQPtx6Vz8yUsvDXqIFrr3MwX3H05En
|
||||
Yp37NIbHJllGQnKTp9i89iqxYuaHDjfWbTyDcpy6WMV7UhV/cZesyF/CAjcGwUzb
|
||||
0FZ9mnm2qN6PFXvxFgLHaVg3vIUBnCfUUrcPC4OxTSO+mZRe1k8wyAiUj/JM+fYo
|
||||
G+2/lm8TaVjoU7Fi5Ka5G5HY2GLaR7P+IxYcrMHCl62Y7Rqcrnc=
|
||||
-----END CERTIFICATE-----
|
||||
`),
|
||||
}
|
||||
|
||||
func TestLoadInitConfigurationFromFile(t *testing.T) {
|
||||
// Create temp folder for the test case
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatalf("Couldn't create tmpdir")
|
||||
}
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
fileContents []byte
|
||||
}{
|
||||
{
|
||||
name: "v1alpha2.MasterConfiguration",
|
||||
fileContents: cfgFiles["MasterConfiguration_v1alpha2"],
|
||||
},
|
||||
{
|
||||
name: "v1alpha3.partial1",
|
||||
fileContents: cfgFiles["InitConfiguration_v1alpha3"],
|
||||
},
|
||||
{
|
||||
name: "v1alpha3.partial2",
|
||||
fileContents: cfgFiles["ClusterConfiguration_v1alpha3"],
|
||||
},
|
||||
{
|
||||
name: "v1alpha3.full",
|
||||
fileContents: bytes.Join([][]byte{
|
||||
cfgFiles["InitConfiguration_v1alpha3"],
|
||||
cfgFiles["ClusterConfiguration_v1alpha3"],
|
||||
cfgFiles["Kube-proxy_componentconfig"],
|
||||
cfgFiles["Kubelet_componentconfig"],
|
||||
}, []byte(kubeadmconstants.YAMLDocumentSeparator)),
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.name, func(t2 *testing.T) {
|
||||
cfgPath := filepath.Join(tmpdir, rt.name)
|
||||
err := ioutil.WriteFile(cfgPath, rt.fileContents, 0644)
|
||||
if err != nil {
|
||||
t.Errorf("Couldn't create file")
|
||||
return
|
||||
}
|
||||
|
||||
obj, err := loadInitConfigurationFromFile(cfgPath)
|
||||
if err != nil {
|
||||
t.Errorf("Error reading file: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if obj == nil {
|
||||
t.Errorf("Unexpected nil return value")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetNodeNameFromKubeletConfig(t *testing.T) {
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatalf("Couldn't create tmpdir")
|
||||
}
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
kubeconfigContent []byte
|
||||
pemContent []byte
|
||||
expectedError bool
|
||||
}{
|
||||
{
|
||||
name: "valid - with embedded cert",
|
||||
kubeconfigContent: kubeletConfFiles["configWithEmbeddedCert"],
|
||||
},
|
||||
{
|
||||
name: "invalid - linked cert missing",
|
||||
kubeconfigContent: kubeletConfFiles["configWithLinkedCert"],
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "valid - with linked cert",
|
||||
kubeconfigContent: kubeletConfFiles["configWithLinkedCert"],
|
||||
pemContent: pemFiles["mynode.pem"],
|
||||
},
|
||||
{
|
||||
name: "invalid - without embedded or linked X509Cert",
|
||||
kubeconfigContent: kubeletConfFiles["withoutX509Cert"],
|
||||
expectedError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.name, func(t2 *testing.T) {
|
||||
if len(rt.pemContent) > 0 {
|
||||
pemPath := filepath.Join(tmpdir, "kubelet.pem")
|
||||
err := ioutil.WriteFile(pemPath, rt.pemContent, 0644)
|
||||
if err != nil {
|
||||
t.Errorf("Couldn't create pem file: %v", err)
|
||||
return
|
||||
}
|
||||
rt.kubeconfigContent = []byte(strings.Replace(string(rt.kubeconfigContent), "kubelet.pem", pemPath, -1))
|
||||
}
|
||||
|
||||
kubeconfigPath := filepath.Join(tmpdir, kubeadmconstants.KubeletKubeConfigFileName)
|
||||
err := ioutil.WriteFile(kubeconfigPath, rt.kubeconfigContent, 0644)
|
||||
if err != nil {
|
||||
t.Errorf("Couldn't create kubeconfig: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
name, err := getNodeNameFromKubeletConfig(tmpdir)
|
||||
if rt.expectedError != (err != nil) {
|
||||
t.Errorf("unexpected return err from getNodeRegistration: %v", err)
|
||||
return
|
||||
}
|
||||
if rt.expectedError {
|
||||
return
|
||||
}
|
||||
|
||||
if name != nodeName {
|
||||
t.Errorf("invalid name")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetNodeRegistration(t *testing.T) {
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatalf("Couldn't create tmpdir")
|
||||
}
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
fileContents []byte
|
||||
node *v1.Node
|
||||
expectedError bool
|
||||
}{
|
||||
{
|
||||
name: "invalid - no kubelet.conf",
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "valid",
|
||||
fileContents: kubeletConfFiles["configWithEmbeddedCert"],
|
||||
node: &v1.Node{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: nodeName,
|
||||
Annotations: map[string]string{
|
||||
kubeadmconstants.AnnotationKubeadmCRISocket: "myCRIsocket",
|
||||
},
|
||||
},
|
||||
Spec: v1.NodeSpec{
|
||||
Taints: []v1.Taint{kubeadmconstants.MasterTaint},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid - no node",
|
||||
fileContents: kubeletConfFiles["configWithEmbeddedCert"],
|
||||
expectedError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.name, func(t2 *testing.T) {
|
||||
cfgPath := filepath.Join(tmpdir, kubeadmconstants.KubeletKubeConfigFileName)
|
||||
if len(rt.fileContents) > 0 {
|
||||
err := ioutil.WriteFile(cfgPath, rt.fileContents, 0644)
|
||||
if err != nil {
|
||||
t.Errorf("Couldn't create file")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
client := clientsetfake.NewSimpleClientset()
|
||||
|
||||
if rt.node != nil {
|
||||
_, err := client.CoreV1().Nodes().Create(rt.node)
|
||||
if err != nil {
|
||||
t.Errorf("couldn't create Node")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
cfg := &kubeadmapi.InitConfiguration{}
|
||||
err = getNodeRegistration(tmpdir, client, &cfg.NodeRegistration)
|
||||
if rt.expectedError != (err != nil) {
|
||||
t.Errorf("unexpected return err from getNodeRegistration: %v", err)
|
||||
return
|
||||
}
|
||||
if rt.expectedError {
|
||||
return
|
||||
}
|
||||
|
||||
if cfg.NodeRegistration.Name != nodeName {
|
||||
t.Errorf("invalid cfg.NodeRegistration.Name")
|
||||
}
|
||||
if cfg.NodeRegistration.CRISocket != "myCRIsocket" {
|
||||
t.Errorf("invalid cfg.NodeRegistration.CRISocket")
|
||||
}
|
||||
if len(cfg.NodeRegistration.Taints) != 1 {
|
||||
t.Errorf("invalid cfg.NodeRegistration.Taints")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAPIEndpoint(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
configMap fakeConfigMap
|
||||
expectedError bool
|
||||
}{
|
||||
{
|
||||
name: "valid",
|
||||
configMap: fakeConfigMap{
|
||||
name: kubeadmconstants.InitConfigurationConfigMap, // ClusterConfiguration from kubeadm-config.
|
||||
data: map[string]string{
|
||||
kubeadmconstants.ClusterStatusConfigMapKey: string(cfgFiles["ClusterStatus_v1alpha3"]),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid - No CLusterStatus in kubeadm-config ConfigMap",
|
||||
configMap: fakeConfigMap{
|
||||
name: kubeadmconstants.InitConfigurationConfigMap, // ClusterConfiguration from kubeadm-config.
|
||||
data: map[string]string{},
|
||||
},
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid - CLusterStatus without APIEndopoints",
|
||||
configMap: fakeConfigMap{
|
||||
name: kubeadmconstants.InitConfigurationConfigMap, // ClusterConfiguration from kubeadm-config.
|
||||
data: map[string]string{
|
||||
kubeadmconstants.ClusterStatusConfigMapKey: string(cfgFiles["ClusterStatus_v1alpha3_Without_APIEndpoints"]),
|
||||
},
|
||||
},
|
||||
expectedError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.name, func(t *testing.T) {
|
||||
cfg := &kubeadmapi.InitConfiguration{}
|
||||
err := getAPIEndpoint(rt.configMap.data, nodeName, &cfg.APIEndpoint)
|
||||
if rt.expectedError != (err != nil) {
|
||||
t.Errorf("unexpected return err from getInitConfigurationFromCluster: %v", err)
|
||||
return
|
||||
}
|
||||
if rt.expectedError {
|
||||
return
|
||||
}
|
||||
|
||||
if cfg.APIEndpoint.AdvertiseAddress != "1.2.3.4" || cfg.APIEndpoint.BindPort != 1234 {
|
||||
t.Errorf("invalid cfg.APIEndpoint")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetComponentConfigs(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
configMaps []fakeConfigMap
|
||||
expectedError bool
|
||||
}{
|
||||
{
|
||||
name: "valid",
|
||||
configMaps: []fakeConfigMap{
|
||||
{
|
||||
name: kubeadmconstants.KubeProxyConfigMap, // Kube-proxy component config from corresponding ConfigMap.
|
||||
data: map[string]string{
|
||||
kubeadmconstants.KubeProxyConfigMapKey: string(cfgFiles["Kube-proxy_componentconfig"]),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: kubeadmconstants.GetKubeletConfigMapName(k8sVersion), // Kubelet component config from corresponding ConfigMap.
|
||||
data: map[string]string{
|
||||
kubeadmconstants.KubeletBaseConfigurationConfigMapKey: string(cfgFiles["Kubelet_componentconfig"]),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid - No kubelet component config ConfigMap",
|
||||
configMaps: []fakeConfigMap{
|
||||
{
|
||||
name: kubeadmconstants.KubeProxyConfigMap,
|
||||
data: map[string]string{
|
||||
kubeadmconstants.KubeProxyConfigMapKey: string(cfgFiles["Kube-proxy_componentconfig"]),
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid - No kube-proxy component config ConfigMap",
|
||||
configMaps: []fakeConfigMap{
|
||||
{
|
||||
name: kubeadmconstants.GetKubeletConfigMapName(k8sVersion),
|
||||
data: map[string]string{
|
||||
kubeadmconstants.KubeletBaseConfigurationConfigMapKey: string(cfgFiles["Kubelet_componentconfig"]),
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.name, func(t *testing.T) {
|
||||
client := clientsetfake.NewSimpleClientset()
|
||||
|
||||
for _, c := range rt.configMaps {
|
||||
err := c.create(client)
|
||||
if err != nil {
|
||||
t.Errorf("couldn't create ConfigMap %s", c.name)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
cfg := &kubeadmapi.InitConfiguration{
|
||||
ClusterConfiguration: kubeadmapi.ClusterConfiguration{
|
||||
KubernetesVersion: k8sVersionString,
|
||||
},
|
||||
}
|
||||
err := getComponentConfigs(client, &cfg.ClusterConfiguration)
|
||||
if rt.expectedError != (err != nil) {
|
||||
t.Errorf("unexpected return err from getInitConfigurationFromCluster: %v", err)
|
||||
return
|
||||
}
|
||||
if rt.expectedError {
|
||||
return
|
||||
}
|
||||
|
||||
// Test expected values in InitConfiguration
|
||||
if cfg.ComponentConfigs.Kubelet == nil {
|
||||
t.Errorf("invalid cfg.ComponentConfigs.Kubelet")
|
||||
}
|
||||
if cfg.ComponentConfigs.KubeProxy == nil {
|
||||
t.Errorf("invalid cfg.ComponentConfigs.KubeProxy")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInitConfigurationFromCluster(t *testing.T) {
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatalf("Couldn't create tmpdir")
|
||||
}
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
fileContents []byte
|
||||
node *v1.Node
|
||||
configMaps []fakeConfigMap
|
||||
newControlPlane bool
|
||||
expectedError bool
|
||||
}{
|
||||
{ //TODO: remove in V1.13
|
||||
name: "before v1.11", // single YAML, with a v1alpha2.MasterConfiguration object (with embedded component configs)
|
||||
configMaps: []fakeConfigMap{
|
||||
{
|
||||
name: kubeadmconstants.InitConfigurationConfigMap,
|
||||
data: map[string]string{
|
||||
kubeadmconstants.InitConfigurationConfigMapKey: string(cfgFiles["MasterConfiguration_v1alpha2"]),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid - No kubeadm-config ConfigMap",
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid - No CLusterConfiguration in kubeadm-config ConfigMap",
|
||||
configMaps: []fakeConfigMap{
|
||||
{
|
||||
name: kubeadmconstants.InitConfigurationConfigMap, // ClusterConfiguration from kubeadm-config.
|
||||
data: map[string]string{},
|
||||
},
|
||||
},
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "valid - new control plane == false", // InitConfiguration composed with data from different places, with also node specific information from ClusterStatus and node
|
||||
configMaps: []fakeConfigMap{
|
||||
{
|
||||
name: kubeadmconstants.InitConfigurationConfigMap, // ClusterConfiguration from kubeadm-config.
|
||||
data: map[string]string{
|
||||
kubeadmconstants.ClusterConfigurationConfigMapKey: string(cfgFiles["ClusterConfiguration_v1alpha3"]),
|
||||
kubeadmconstants.ClusterStatusConfigMapKey: string(cfgFiles["ClusterStatus_v1alpha3"]),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: kubeadmconstants.KubeProxyConfigMap, // Kube-proxy component config from corresponding ConfigMap.
|
||||
data: map[string]string{
|
||||
kubeadmconstants.KubeProxyConfigMapKey: string(cfgFiles["Kube-proxy_componentconfig"]),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: kubeadmconstants.GetKubeletConfigMapName(k8sVersion), // Kubelet component config from corresponding ConfigMap.
|
||||
data: map[string]string{
|
||||
kubeadmconstants.KubeletBaseConfigurationConfigMapKey: string(cfgFiles["Kubelet_componentconfig"]),
|
||||
},
|
||||
},
|
||||
},
|
||||
fileContents: kubeletConfFiles["configWithEmbeddedCert"],
|
||||
node: &v1.Node{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: nodeName,
|
||||
Annotations: map[string]string{
|
||||
kubeadmconstants.AnnotationKubeadmCRISocket: "myCRIsocket",
|
||||
},
|
||||
},
|
||||
Spec: v1.NodeSpec{
|
||||
Taints: []v1.Taint{kubeadmconstants.MasterTaint},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid - new control plane == true", // InitConfiguration composed with data from different places, without node specific information
|
||||
configMaps: []fakeConfigMap{
|
||||
{
|
||||
name: kubeadmconstants.InitConfigurationConfigMap, // ClusterConfiguration from kubeadm-config.
|
||||
data: map[string]string{
|
||||
kubeadmconstants.ClusterConfigurationConfigMapKey: string(cfgFiles["ClusterConfiguration_v1alpha3"]),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: kubeadmconstants.KubeProxyConfigMap, // Kube-proxy component config from corresponding ConfigMap.
|
||||
data: map[string]string{
|
||||
kubeadmconstants.KubeProxyConfigMapKey: string(cfgFiles["Kube-proxy_componentconfig"]),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: kubeadmconstants.GetKubeletConfigMapName(k8sVersion), // Kubelet component config from corresponding ConfigMap.
|
||||
data: map[string]string{
|
||||
kubeadmconstants.KubeletBaseConfigurationConfigMapKey: string(cfgFiles["Kubelet_componentconfig"]),
|
||||
},
|
||||
},
|
||||
},
|
||||
newControlPlane: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.name, func(t *testing.T) {
|
||||
cfgPath := filepath.Join(tmpdir, kubeadmconstants.KubeletKubeConfigFileName)
|
||||
if len(rt.fileContents) > 0 {
|
||||
err := ioutil.WriteFile(cfgPath, rt.fileContents, 0644)
|
||||
if err != nil {
|
||||
t.Errorf("Couldn't create file")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
client := clientsetfake.NewSimpleClientset()
|
||||
|
||||
if rt.node != nil {
|
||||
_, err := client.CoreV1().Nodes().Create(rt.node)
|
||||
if err != nil {
|
||||
t.Errorf("couldn't create Node")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for _, c := range rt.configMaps {
|
||||
err := c.create(client)
|
||||
if err != nil {
|
||||
t.Errorf("couldn't create ConfigMap %s", c.name)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
cfg, err := getInitConfigurationFromCluster(tmpdir, client, rt.newControlPlane)
|
||||
if rt.expectedError != (err != nil) {
|
||||
t.Errorf("unexpected return err from getInitConfigurationFromCluster: %v", err)
|
||||
return
|
||||
}
|
||||
if rt.expectedError {
|
||||
return
|
||||
}
|
||||
|
||||
// Test expected values in InitConfiguration
|
||||
if cfg == nil {
|
||||
t.Errorf("unexpected nil return value")
|
||||
}
|
||||
if cfg.ClusterConfiguration.KubernetesVersion != k8sVersionString {
|
||||
t.Errorf("invalid ClusterConfiguration.KubernetesVersion")
|
||||
}
|
||||
if !rt.newControlPlane && (cfg.APIEndpoint.AdvertiseAddress != "1.2.3.4" || cfg.APIEndpoint.BindPort != 1234) {
|
||||
t.Errorf("invalid cfg.APIEndpoint")
|
||||
}
|
||||
if cfg.ComponentConfigs.Kubelet == nil {
|
||||
t.Errorf("invalid cfg.ComponentConfigs.Kubelet")
|
||||
}
|
||||
if cfg.ComponentConfigs.KubeProxy == nil {
|
||||
t.Errorf("invalid cfg.ComponentConfigs.KubeProxy")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type fakeConfigMap struct {
|
||||
name string
|
||||
data map[string]string
|
||||
}
|
||||
|
||||
func (c *fakeConfigMap) create(client clientset.Interface) error {
|
||||
return apiclient.CreateOrUpdateConfigMap(client, &v1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: c.name,
|
||||
Namespace: metav1.NamespaceSystem,
|
||||
},
|
||||
Data: c.data,
|
||||
})
|
||||
}
|
178
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/common.go
generated
vendored
Normal file
178
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/common.go
generated
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
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 config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
netutil "k8s.io/apimachinery/pkg/util/net"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
|
||||
kubeadmapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/pkg/util/version"
|
||||
)
|
||||
|
||||
// AnyConfigFileAndDefaultsToInternal reads either a InitConfiguration or JoinConfiguration and unmarshals it
|
||||
func AnyConfigFileAndDefaultsToInternal(cfgPath string) (runtime.Object, error) {
|
||||
b, err := ioutil.ReadFile(cfgPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gvks, err := kubeadmutil.GroupVersionKindsFromBytes(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// First, check if the gvk list has InitConfiguration and in that case try to unmarshal it
|
||||
if kubeadmutil.GroupVersionKindsHasInitConfiguration(gvks...) {
|
||||
return ConfigFileAndDefaultsToInternalConfig(cfgPath, &kubeadmapiv1alpha3.InitConfiguration{})
|
||||
}
|
||||
if kubeadmutil.GroupVersionKindsHasJoinConfiguration(gvks...) {
|
||||
return NodeConfigFileAndDefaultsToInternalConfig(cfgPath, &kubeadmapiv1alpha3.JoinConfiguration{})
|
||||
}
|
||||
return nil, fmt.Errorf("didn't recognize types with GroupVersionKind: %v", gvks)
|
||||
}
|
||||
|
||||
// MarshalKubeadmConfigObject marshals an Object registered in the kubeadm scheme. If the object is a InitConfiguration or ClusterConfiguration, some extra logic is run
|
||||
func MarshalKubeadmConfigObject(obj runtime.Object) ([]byte, error) {
|
||||
switch internalcfg := obj.(type) {
|
||||
case *kubeadmapi.InitConfiguration:
|
||||
return MarshalInitConfigurationToBytes(internalcfg, kubeadmapiv1alpha3.SchemeGroupVersion)
|
||||
case *kubeadmapi.ClusterConfiguration:
|
||||
return MarshalClusterConfigurationToBytes(internalcfg, kubeadmapiv1alpha3.SchemeGroupVersion)
|
||||
default:
|
||||
return kubeadmutil.MarshalToYamlForCodecs(obj, kubeadmapiv1alpha3.SchemeGroupVersion, kubeadmscheme.Codecs)
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
gvks, err := kubeadmutil.GroupVersionKindsFromBytes(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 we find an old API version in this gvk list, error out and tell the user why this doesn't work
|
||||
knownKinds := map[string]bool{}
|
||||
for _, gvk := range gvks {
|
||||
if useKubeadmVersion := oldKnownAPIVersions[gvk.GroupVersion().String()]; len(useKubeadmVersion) != 0 {
|
||||
return fmt.Errorf("your configuration file uses an old API spec: %q. 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.", gvk.GroupVersion().String(), useKubeadmVersion)
|
||||
}
|
||||
knownKinds[gvk.Kind] = true
|
||||
}
|
||||
// InitConfiguration, MasterConfiguration and NodeConfiguration may not apply together, warn if more than one is specified
|
||||
mutuallyExclusive := []string{constants.InitConfigurationKind, constants.MasterConfigurationKind, constants.JoinConfigurationKind, constants.NodeConfigurationKind}
|
||||
mutuallyExclusiveCount := 0
|
||||
for _, kind := range mutuallyExclusive {
|
||||
if knownKinds[kind] {
|
||||
mutuallyExclusiveCount++
|
||||
}
|
||||
}
|
||||
if mutuallyExclusiveCount > 1 {
|
||||
glog.Warningf("WARNING: Detected resource kinds that may not apply: %v", mutuallyExclusive)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NormalizeKubernetesVersion resolves version labels, sets alternative
|
||||
// image registry if requested for CI builds, and validates minimal
|
||||
// version that kubeadm SetInitDynamicDefaultssupports.
|
||||
func NormalizeKubernetesVersion(cfg *kubeadmapi.ClusterConfiguration) error {
|
||||
// Requested version is automatic CI build, thus use KubernetesCI Image Repository for core images
|
||||
if kubeadmutil.KubernetesIsCIVersion(cfg.KubernetesVersion) {
|
||||
cfg.CIImageRepository = constants.DefaultCIImageRepository
|
||||
}
|
||||
|
||||
// Parse and validate the version argument and resolve possible CI version labels
|
||||
ver, err := kubeadmutil.KubernetesReleaseVersion(cfg.KubernetesVersion)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfg.KubernetesVersion = ver
|
||||
|
||||
// Parse the given kubernetes version and make sure it's higher than the lowest supported
|
||||
k8sVersion, err := version.ParseSemantic(cfg.KubernetesVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't parse kubernetes version %q: %v", cfg.KubernetesVersion, err)
|
||||
}
|
||||
if k8sVersion.LessThan(constants.MinimumControlPlaneVersion) {
|
||||
return fmt.Errorf("this version of kubeadm only supports deploying clusters with the control plane version >= %s. Current version: %s", constants.MinimumControlPlaneVersion.String(), cfg.KubernetesVersion)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LowercaseSANs can be used to force all SANs to be lowercase so it passes IsDNS1123Subdomain
|
||||
func LowercaseSANs(sans []string) {
|
||||
for i, san := range sans {
|
||||
lowercase := strings.ToLower(san)
|
||||
if lowercase != san {
|
||||
glog.V(1).Infof("lowercasing SAN %q to %q", san, lowercase)
|
||||
sans[i] = lowercase
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// VerifyAPIServerBindAddress can be used to verify if a bind address for the API Server is 0.0.0.0,
|
||||
// in which case this address is not valid and should not be used.
|
||||
func VerifyAPIServerBindAddress(address string) error {
|
||||
ip := net.ParseIP(address)
|
||||
if ip == nil {
|
||||
return fmt.Errorf("cannot parse IP address: %s", address)
|
||||
}
|
||||
if !ip.IsGlobalUnicast() {
|
||||
return fmt.Errorf("cannot use %q as the bind address for the API Server", address)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ChooseAPIServerBindAddress is a wrapper for netutil.ChooseBindAddress that also handles
|
||||
// the case where no default routes were found and an IP for the API server could not be obatained.
|
||||
func ChooseAPIServerBindAddress(bindAddress net.IP) (net.IP, error) {
|
||||
ip, err := netutil.ChooseBindAddress(bindAddress)
|
||||
if err != nil {
|
||||
if netutil.IsNoRoutesError(err) {
|
||||
glog.Warningf("WARNING: could not obtain a bind address for the API Server: %v; using: %s", err, constants.DefaultAPIServerBindAddress)
|
||||
defaultIP := net.ParseIP(constants.DefaultAPIServerBindAddress)
|
||||
if defaultIP == nil {
|
||||
return nil, fmt.Errorf("cannot parse default IP address: %s", constants.DefaultAPIServerBindAddress)
|
||||
}
|
||||
return defaultIP, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return ip, nil
|
||||
}
|
277
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/common_test.go
generated
vendored
Normal file
277
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/common_test.go
generated
vendored
Normal file
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
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 config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
kubeadmapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
)
|
||||
|
||||
var files = map[string][]byte{
|
||||
"Master_v1alpha1": []byte(`
|
||||
apiVersion: kubeadm.k8s.io/v1alpha1
|
||||
kind: InitConfiguration
|
||||
`),
|
||||
"Node_v1alpha1": []byte(`
|
||||
apiVersion: kubeadm.k8s.io/v1alpha1
|
||||
kind: NodeConfiguration
|
||||
`),
|
||||
"Master_v1alpha2": []byte(`
|
||||
apiVersion: kubeadm.k8s.io/v1alpha2
|
||||
kind: MasterConfiguration
|
||||
`),
|
||||
"Node_v1alpha2": []byte(`
|
||||
apiVersion: kubeadm.k8s.io/v1alpha2
|
||||
kind: NodeConfiguration
|
||||
`),
|
||||
"Init_v1alpha3": []byte(`
|
||||
apiVersion: kubeadm.k8s.io/v1alpha3
|
||||
kind: InitConfiguration
|
||||
`),
|
||||
"Join_v1alpha3": []byte(`
|
||||
apiVersion: kubeadm.k8s.io/v1alpha3
|
||||
kind: JoinConfiguration
|
||||
`),
|
||||
"NoKind": []byte(`
|
||||
apiVersion: baz.k8s.io/v1
|
||||
foo: foo
|
||||
bar: bar
|
||||
`),
|
||||
"NoAPIVersion": []byte(`
|
||||
kind: Bar
|
||||
foo: foo
|
||||
bar: bar
|
||||
`),
|
||||
"Foo": []byte(`
|
||||
apiVersion: foo.k8s.io/v1
|
||||
kind: Foo
|
||||
`),
|
||||
}
|
||||
|
||||
func TestDetectUnsupportedVersion(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
fileContents []byte
|
||||
expectedErr bool
|
||||
}{
|
||||
{
|
||||
name: "Master_v1alpha1",
|
||||
fileContents: files["Master_v1alpha1"],
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "Node_v1alpha1",
|
||||
fileContents: files["Node_v1alpha1"],
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "Master_v1alpha2",
|
||||
fileContents: files["Master_v1alpha2"],
|
||||
},
|
||||
{
|
||||
name: "Node_v1alpha2",
|
||||
fileContents: files["Node_v1alpha2"],
|
||||
},
|
||||
{
|
||||
name: "Init_v1alpha3",
|
||||
fileContents: files["Init_v1alpha3"],
|
||||
},
|
||||
{
|
||||
name: "Join_v1alpha3",
|
||||
fileContents: files["Join_v1alpha3"],
|
||||
},
|
||||
{
|
||||
name: "DuplicateMaster",
|
||||
fileContents: bytes.Join([][]byte{files["Master_v1alpha2"], files["Master_v1alpha2"]}, []byte(constants.YAMLDocumentSeparator)),
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "DuplicateNode",
|
||||
fileContents: bytes.Join([][]byte{files["Node_v1alpha2"], files["Node_v1alpha2"]}, []byte(constants.YAMLDocumentSeparator)),
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "DuplicateInit",
|
||||
fileContents: bytes.Join([][]byte{files["Init_v1alpha3"], files["Init_v1alpha3"]}, []byte(constants.YAMLDocumentSeparator)),
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "DuplicateJoin",
|
||||
fileContents: bytes.Join([][]byte{files["Join_v1alpha3"], files["Join_v1alpha3"]}, []byte(constants.YAMLDocumentSeparator)),
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "NoKind",
|
||||
fileContents: files["NoKind"],
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "NoAPIVersion",
|
||||
fileContents: files["NoAPIVersion"],
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "v1alpha1InMultiple",
|
||||
fileContents: bytes.Join([][]byte{files["Foo"], files["Master_v1alpha1"]}, []byte(constants.YAMLDocumentSeparator)),
|
||||
expectedErr: true,
|
||||
},
|
||||
// CanMix* cases used to be MustNotMix*, however due to UX issues DetectUnsupportedVersion had to tolerate that.
|
||||
// So the following tests actually verify, that previously conflicting configs can be mixed together with no error.
|
||||
{
|
||||
name: "CanMixMasterNode",
|
||||
fileContents: bytes.Join([][]byte{files["Master_v1alpha2"], files["Node_v1alpha2"]}, []byte(constants.YAMLDocumentSeparator)),
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "CanMixMasterJoin",
|
||||
fileContents: bytes.Join([][]byte{files["Master_v1alpha2"], files["Join_v1alpha3"]}, []byte(constants.YAMLDocumentSeparator)),
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "CanMixJoinNode",
|
||||
fileContents: bytes.Join([][]byte{files["Join_v1alpha3"], files["Node_v1alpha2"]}, []byte(constants.YAMLDocumentSeparator)),
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "CanMixInitMaster",
|
||||
fileContents: bytes.Join([][]byte{files["Init_v1alpha3"], files["Master_v1alpha2"]}, []byte(constants.YAMLDocumentSeparator)),
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "CanMixInitNode",
|
||||
fileContents: bytes.Join([][]byte{files["Init_v1alpha3"], files["Node_v1alpha2"]}, []byte(constants.YAMLDocumentSeparator)),
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "CanMixInitJoin",
|
||||
fileContents: bytes.Join([][]byte{files["Init_v1alpha3"], files["Join_v1alpha3"]}, []byte(constants.YAMLDocumentSeparator)),
|
||||
expectedErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.name, func(t2 *testing.T) {
|
||||
|
||||
err := DetectUnsupportedVersion(rt.fileContents)
|
||||
if (err != nil) != rt.expectedErr {
|
||||
t2.Errorf("expected error: %t, actual: %t", rt.expectedErr, err != nil)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLowercaseSANs(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
in []string
|
||||
out []string
|
||||
}{
|
||||
{
|
||||
name: "empty struct",
|
||||
},
|
||||
{
|
||||
name: "already lowercase",
|
||||
in: []string{"example.k8s.io"},
|
||||
out: []string{"example.k8s.io"},
|
||||
},
|
||||
{
|
||||
name: "ip addresses and uppercase",
|
||||
in: []string{"EXAMPLE.k8s.io", "10.100.0.1"},
|
||||
out: []string{"example.k8s.io", "10.100.0.1"},
|
||||
},
|
||||
{
|
||||
name: "punycode and uppercase",
|
||||
in: []string{"xn--7gq663byk9a.xn--fiqz9s", "ANOTHEREXAMPLE.k8s.io"},
|
||||
out: []string{"xn--7gq663byk9a.xn--fiqz9s", "anotherexample.k8s.io"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
cfg := &kubeadmapiv1alpha3.InitConfiguration{
|
||||
ClusterConfiguration: kubeadmapiv1alpha3.ClusterConfiguration{
|
||||
APIServerCertSANs: test.in,
|
||||
},
|
||||
}
|
||||
|
||||
LowercaseSANs(cfg.APIServerCertSANs)
|
||||
|
||||
if len(cfg.APIServerCertSANs) != len(test.out) {
|
||||
t.Fatalf("expected %d elements, got %d", len(test.out), len(cfg.APIServerCertSANs))
|
||||
}
|
||||
|
||||
for i, expected := range test.out {
|
||||
if cfg.APIServerCertSANs[i] != expected {
|
||||
t.Errorf("expected element %d to be %q, got %q", i, expected, cfg.APIServerCertSANs[i])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifyAPIServerBindAddress(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
address string
|
||||
expectedError bool
|
||||
}{
|
||||
{
|
||||
name: "valid address: IPV4",
|
||||
address: "192.168.0.1",
|
||||
},
|
||||
{
|
||||
name: "valid address: IPV6",
|
||||
address: "2001:db8:85a3::8a2e:370:7334",
|
||||
},
|
||||
{
|
||||
name: "invalid address: not a global unicast 0.0.0.0",
|
||||
address: "0.0.0.0",
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid address: not a global unicast 127.0.0.1",
|
||||
address: "127.0.0.1",
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid address: not a global unicast ::",
|
||||
address: "::",
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid address: cannot parse IPV4",
|
||||
address: "255.255.255.255.255",
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid address: cannot parse IPV6",
|
||||
address: "2a00:800::2a00:800:10102a00",
|
||||
expectedError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
if err := VerifyAPIServerBindAddress(test.address); (err != nil) != test.expectedError {
|
||||
t.Errorf("expected error: %v, got %v, error: %v", test.expectedError, (err != nil), err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
399
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/masterconfig.go
generated
vendored
399
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/masterconfig.go
generated
vendored
@@ -17,63 +17,55 @@ limitations under the License.
|
||||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"strings"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
netutil "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
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"
|
||||
kubeadmapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/pkg/util/node"
|
||||
"k8s.io/kubernetes/pkg/util/version"
|
||||
nodeutil "k8s.io/kubernetes/pkg/util/node"
|
||||
)
|
||||
|
||||
// SetInitDynamicDefaults checks and sets configuration values for the MasterConfiguration object
|
||||
func SetInitDynamicDefaults(cfg *kubeadmapi.MasterConfiguration) error {
|
||||
|
||||
// validate cfg.API.AdvertiseAddress.
|
||||
addressIP := net.ParseIP(cfg.API.AdvertiseAddress)
|
||||
if addressIP == nil && cfg.API.AdvertiseAddress != "" {
|
||||
return fmt.Errorf("couldn't use \"%s\" as \"apiserver-advertise-address\", must be ipv4 or ipv6 address", cfg.API.AdvertiseAddress)
|
||||
}
|
||||
// Choose the right address for the API Server to advertise. If the advertise address is localhost or 0.0.0.0, the default interface's IP address is used
|
||||
// This is the same logic as the API Server uses
|
||||
ip, err := netutil.ChooseBindAddress(addressIP)
|
||||
if err != nil {
|
||||
// SetInitDynamicDefaults checks and sets configuration values for the InitConfiguration object
|
||||
func SetInitDynamicDefaults(cfg *kubeadmapi.InitConfiguration) error {
|
||||
if err := SetBootstrapTokensDynamicDefaults(&cfg.BootstrapTokens); err != nil {
|
||||
return err
|
||||
}
|
||||
cfg.API.AdvertiseAddress = ip.String()
|
||||
ip = net.ParseIP(cfg.API.AdvertiseAddress)
|
||||
if ip.To4() != nil {
|
||||
cfg.KubeProxy.Config.BindAddress = kubeadmapiv1alpha2.DefaultProxyBindAddressv4
|
||||
} else {
|
||||
cfg.KubeProxy.Config.BindAddress = kubeadmapiv1alpha2.DefaultProxyBindAddressv6
|
||||
}
|
||||
// Resolve possible version labels and validate version string
|
||||
if err := NormalizeKubernetesVersion(cfg); err != nil {
|
||||
if err := SetNodeRegistrationDynamicDefaults(&cfg.NodeRegistration, true); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := SetAPIEndpointDynamicDefaults(&cfg.APIEndpoint); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := SetClusterDynamicDefaults(&cfg.ClusterConfiguration, cfg.APIEndpoint.AdvertiseAddress, cfg.APIEndpoint.BindPort); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Downcase SANs. Some domain names (like ELBs) have capitals in them.
|
||||
LowercaseSANs(cfg.APIServerCertSANs)
|
||||
|
||||
// SetBootstrapTokensDynamicDefaults checks and sets configuration values for the BootstrapTokens object
|
||||
func SetBootstrapTokensDynamicDefaults(cfg *[]kubeadmapi.BootstrapToken) error {
|
||||
// Populate the .Token field with a random value if unset
|
||||
// We do this at this layer, and not the API defaulting layer
|
||||
// because of possible security concerns, and more practically
|
||||
// because we can't return errors in the API object defaulting
|
||||
// process but here we can.
|
||||
for i, bt := range cfg.BootstrapTokens {
|
||||
for i, bt := range *cfg {
|
||||
if bt.Token != nil && len(bt.Token.String()) > 0 {
|
||||
continue
|
||||
}
|
||||
@@ -86,26 +78,88 @@ func SetInitDynamicDefaults(cfg *kubeadmapi.MasterConfiguration) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfg.BootstrapTokens[i].Token = token
|
||||
(*cfg)[i].Token = token
|
||||
}
|
||||
|
||||
cfg.NodeRegistration.Name = node.GetHostname(cfg.NodeRegistration.Name)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetNodeRegistrationDynamicDefaults checks and sets configuration values for the NodeRegistration object
|
||||
func SetNodeRegistrationDynamicDefaults(cfg *kubeadmapi.NodeRegistrationOptions, masterTaint bool) error {
|
||||
var err error
|
||||
cfg.Name, err = nodeutil.GetHostname(cfg.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Only if the slice is nil, we should append the master taint. This allows the user to specify an empty slice for no default master taint
|
||||
if cfg.NodeRegistration.Taints == nil {
|
||||
cfg.NodeRegistration.Taints = []v1.Taint{kubeadmconstants.MasterTaint}
|
||||
if masterTaint && cfg.Taints == nil {
|
||||
cfg.Taints = []v1.Taint{kubeadmconstants.MasterTaint}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetAPIEndpointDynamicDefaults checks and sets configuration values for the APIEndpoint object
|
||||
func SetAPIEndpointDynamicDefaults(cfg *kubeadmapi.APIEndpoint) error {
|
||||
// validate cfg.API.AdvertiseAddress.
|
||||
addressIP := net.ParseIP(cfg.AdvertiseAddress)
|
||||
if addressIP == nil && cfg.AdvertiseAddress != "" {
|
||||
return fmt.Errorf("couldn't use \"%s\" as \"apiserver-advertise-address\", must be ipv4 or ipv6 address", cfg.AdvertiseAddress)
|
||||
}
|
||||
// This is the same logic as the API Server uses, except that if no interface is found the address is set to 0.0.0.0, which is invalid and cannot be used
|
||||
// for bootstrapping a cluster.
|
||||
ip, err := ChooseAPIServerBindAddress(addressIP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfg.AdvertiseAddress = ip.String()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetClusterDynamicDefaults checks and sets configuration values for the InitConfiguration object
|
||||
func SetClusterDynamicDefaults(cfg *kubeadmapi.ClusterConfiguration, advertiseAddress string, bindPort int32) error {
|
||||
// Default all the embedded ComponentConfig structs
|
||||
componentconfigs.Known.Default(cfg)
|
||||
|
||||
ip := net.ParseIP(advertiseAddress)
|
||||
if ip.To4() != nil {
|
||||
cfg.ComponentConfigs.KubeProxy.BindAddress = kubeadmapiv1alpha3.DefaultProxyBindAddressv4
|
||||
} else {
|
||||
cfg.ComponentConfigs.KubeProxy.BindAddress = kubeadmapiv1alpha3.DefaultProxyBindAddressv6
|
||||
}
|
||||
|
||||
// Resolve possible version labels and validate version string
|
||||
if err := NormalizeKubernetesVersion(cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If ControlPlaneEndpoint is specified without a port number defaults it to
|
||||
// the bindPort number of the APIEndpoint.
|
||||
// This will allow join of additional control plane instances with different bindPort number
|
||||
if cfg.ControlPlaneEndpoint != "" {
|
||||
host, port, err := kubeadmutil.ParseHostPort(cfg.ControlPlaneEndpoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if port == "" {
|
||||
cfg.ControlPlaneEndpoint = net.JoinHostPort(host, strconv.FormatInt(int64(bindPort), 10))
|
||||
}
|
||||
}
|
||||
|
||||
// Downcase SANs. Some domain names (like ELBs) have capitals in them.
|
||||
LowercaseSANs(cfg.APIServerCertSANs)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ConfigFileAndDefaultsToInternalConfig takes a path to a config file and a versioned configuration that can serve as the default config
|
||||
// If cfgPath is specified, defaultversionedcfg will always get overridden. Otherwise, the default config (often populated by flags) will be used.
|
||||
// Then the external, versioned configuration is defaulted and converted to the internal type.
|
||||
// Right thereafter, the configuration is defaulted again with dynamic values (like IP addresses of a machine, etc)
|
||||
// Lastly, the internal config is validated and returned.
|
||||
func ConfigFileAndDefaultsToInternalConfig(cfgPath string, defaultversionedcfg *kubeadmapiv1alpha2.MasterConfiguration) (*kubeadmapi.MasterConfiguration, error) {
|
||||
internalcfg := &kubeadmapi.MasterConfiguration{}
|
||||
func ConfigFileAndDefaultsToInternalConfig(cfgPath string, defaultversionedcfg *kubeadmapiv1alpha3.InitConfiguration) (*kubeadmapi.InitConfiguration, error) {
|
||||
internalcfg := &kubeadmapi.InitConfiguration{}
|
||||
|
||||
if cfgPath != "" {
|
||||
// Loads configuration from config file, if provided
|
||||
@@ -116,117 +170,202 @@ func ConfigFileAndDefaultsToInternalConfig(cfgPath string, defaultversionedcfg *
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to read config from %q [%v]", cfgPath, err)
|
||||
}
|
||||
return BytesToInternalConfig(b)
|
||||
}
|
||||
|
||||
// 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
|
||||
kubeadmscheme.Scheme.Default(defaultversionedcfg)
|
||||
kubeadmscheme.Scheme.Convert(defaultversionedcfg, internalcfg, nil)
|
||||
|
||||
return defaultAndValidate(internalcfg)
|
||||
}
|
||||
|
||||
// BytesToInternalConfig converts a byte array to an internal, defaulted and validated configuration object
|
||||
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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
internalcfg, err = BytesToInternalConfig(b)
|
||||
if err != nil {
|
||||
return nil, 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")
|
||||
// Takes passed flags into account; the defaulting is executed once again enforcing assignment of
|
||||
// static default values to cfg only for values not provided with flags
|
||||
kubeadmscheme.Scheme.Default(defaultversionedcfg)
|
||||
kubeadmscheme.Scheme.Convert(defaultversionedcfg, internalcfg, nil)
|
||||
}
|
||||
|
||||
return defaultAndValidate(internalcfg)
|
||||
}
|
||||
|
||||
func defaultAndValidate(cfg *kubeadmapi.MasterConfiguration) (*kubeadmapi.MasterConfiguration, error) {
|
||||
// Applies dynamic defaults to settings not provided with flags
|
||||
if err := SetInitDynamicDefaults(cfg); err != nil {
|
||||
if err := SetInitDynamicDefaults(internalcfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Validates cfg (flags/configs + defaults + dynamic defaults)
|
||||
if err := validation.ValidateMasterConfiguration(cfg).ToAggregate(); err != nil {
|
||||
if err := validation.ValidateInitConfiguration(internalcfg).ToAggregate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cfg, nil
|
||||
return internalcfg, nil
|
||||
}
|
||||
|
||||
// NormalizeKubernetesVersion resolves version labels, sets alternative
|
||||
// image registry if requested for CI builds, and validates minimal
|
||||
// version that kubeadm supports.
|
||||
func NormalizeKubernetesVersion(cfg *kubeadmapi.MasterConfiguration) error {
|
||||
// Requested version is automatic CI build, thus use KubernetesCI Image Repository for core images
|
||||
if kubeadmutil.KubernetesIsCIVersion(cfg.KubernetesVersion) {
|
||||
cfg.CIImageRepository = kubeadmconstants.DefaultCIImageRepository
|
||||
// BytesToInternalConfig converts a byte slice to an internal, defaulted and validated configuration object.
|
||||
// The byte slice may contain one or many different YAML documents. These YAML documents are parsed one-by-one
|
||||
// and well-known ComponentConfig GroupVersionKinds are stored inside of the internal InitConfiguration struct
|
||||
func BytesToInternalConfig(b []byte) (*kubeadmapi.InitConfiguration, error) {
|
||||
var initcfg *kubeadmapi.InitConfiguration
|
||||
var clustercfg *kubeadmapi.ClusterConfiguration
|
||||
decodedComponentConfigObjects := map[componentconfigs.RegistrationKind]runtime.Object{}
|
||||
|
||||
if err := DetectUnsupportedVersion(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Parse and validate the version argument and resolve possible CI version labels
|
||||
ver, err := kubeadmutil.KubernetesReleaseVersion(cfg.KubernetesVersion)
|
||||
gvkmap, err := kubeadmutil.SplitYAMLDocuments(b)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
cfg.KubernetesVersion = ver
|
||||
|
||||
// Parse the given kubernetes version and make sure it's higher than the lowest supported
|
||||
k8sVersion, err := version.ParseSemantic(cfg.KubernetesVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't parse kubernetes version %q: %v", cfg.KubernetesVersion, err)
|
||||
}
|
||||
if k8sVersion.LessThan(kubeadmconstants.MinimumControlPlaneVersion) {
|
||||
return fmt.Errorf("this version of kubeadm only supports deploying clusters with the control plane version >= %s. Current version: %s", kubeadmconstants.MinimumControlPlaneVersion.String(), cfg.KubernetesVersion)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
for gvk, fileContent := range gvkmap {
|
||||
// Try to get the registration for the ComponentConfig based on the kind
|
||||
regKind := componentconfigs.RegistrationKind(gvk.Kind)
|
||||
registration, found := componentconfigs.Known[regKind]
|
||||
if found {
|
||||
// Unmarshal the bytes from the YAML document into a runtime.Object containing the ComponentConfiguration struct
|
||||
obj, err := registration.Unmarshal(fileContent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
decodedComponentConfigObjects[regKind] = obj
|
||||
continue
|
||||
}
|
||||
|
||||
// LowercaseSANs can be used to force all SANs to be lowercase so it passes IsDNS1123Subdomain
|
||||
func LowercaseSANs(sans []string) {
|
||||
for i, san := range sans {
|
||||
lowercase := strings.ToLower(san)
|
||||
if lowercase != san {
|
||||
glog.V(1).Infof("lowercasing SAN %q to %q", san, lowercase)
|
||||
sans[i] = lowercase
|
||||
if kubeadmutil.GroupVersionKindsHasInitConfiguration(gvk) {
|
||||
// Set initcfg to an empty struct value the deserializer will populate
|
||||
initcfg = &kubeadmapi.InitConfiguration{}
|
||||
// Decode the bytes into the internal struct. Under the hood, the bytes will be unmarshalled into the
|
||||
// right external version, defaulted, and converted into the internal version.
|
||||
if err := runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(), fileContent, initcfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
if kubeadmutil.GroupVersionKindsHasClusterConfiguration(gvk) {
|
||||
// Set clustercfg to an empty struct value the deserializer will populate
|
||||
clustercfg = &kubeadmapi.ClusterConfiguration{}
|
||||
// Decode the bytes into the internal struct. Under the hood, the bytes will be unmarshalled into the
|
||||
// right external version, defaulted, and converted into the internal version.
|
||||
if err := runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(), fileContent, clustercfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf("[config] WARNING: Ignored YAML document with GroupVersionKind %v\n", gvk)
|
||||
}
|
||||
|
||||
// Enforce that InitConfiguration and/or ClusterConfiguration has to exist among the YAML documents
|
||||
if initcfg == nil && clustercfg == nil {
|
||||
return nil, fmt.Errorf("no InitConfiguration or ClusterConfiguration kind was found in the YAML file")
|
||||
}
|
||||
|
||||
// If InitConfiguration wasn't given, default it by creating an external struct instance, default it and convert into the internal type
|
||||
if initcfg == nil {
|
||||
extinitcfg := &kubeadmapiv1alpha3.InitConfiguration{}
|
||||
kubeadmscheme.Scheme.Default(extinitcfg)
|
||||
// Set initcfg to an empty struct value the deserializer will populate
|
||||
initcfg = &kubeadmapi.InitConfiguration{}
|
||||
kubeadmscheme.Scheme.Convert(extinitcfg, initcfg, nil)
|
||||
}
|
||||
// If ClusterConfiguration was given, populate it in the InitConfiguration struct
|
||||
if clustercfg != nil {
|
||||
initcfg.ClusterConfiguration = *clustercfg
|
||||
}
|
||||
|
||||
// Save the loaded ComponentConfig objects in the initcfg object
|
||||
for kind, obj := range decodedComponentConfigObjects {
|
||||
registration, found := componentconfigs.Known[kind]
|
||||
if found {
|
||||
if ok := registration.SetToInternalConfig(obj, &initcfg.ClusterConfiguration); !ok {
|
||||
return nil, fmt.Errorf("couldn't save componentconfig value for kind %q", string(kind))
|
||||
}
|
||||
} else {
|
||||
// This should never happen in practice
|
||||
fmt.Printf("[config] WARNING: Decoded a kind that couldn't be saved to the internal configuration: %q\n", string(kind))
|
||||
}
|
||||
}
|
||||
return initcfg, nil
|
||||
}
|
||||
|
||||
func defaultedInternalConfig() *kubeadmapi.ClusterConfiguration {
|
||||
externalcfg := &kubeadmapiv1alpha3.ClusterConfiguration{}
|
||||
internalcfg := &kubeadmapi.ClusterConfiguration{}
|
||||
|
||||
kubeadmscheme.Scheme.Default(externalcfg)
|
||||
kubeadmscheme.Scheme.Convert(externalcfg, internalcfg, nil)
|
||||
|
||||
// Default the embedded ComponentConfig structs
|
||||
componentconfigs.Known.Default(internalcfg)
|
||||
return internalcfg
|
||||
}
|
||||
|
||||
// MarshalInitConfigurationToBytes marshals the internal InitConfiguration object to bytes. It writes the embedded
|
||||
// ClusterConfiguration object with ComponentConfigs out as separate YAML documents
|
||||
func MarshalInitConfigurationToBytes(cfg *kubeadmapi.InitConfiguration, gv schema.GroupVersion) ([]byte, error) {
|
||||
initbytes, err := kubeadmutil.MarshalToYamlForCodecs(cfg, gv, kubeadmscheme.Codecs)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
allFiles := [][]byte{initbytes}
|
||||
|
||||
// Exception: If the specified groupversion is targeting the internal type, don't print embedded ClusterConfiguration contents
|
||||
// This is mostly used for unit testing. In a real scenario the internal version of the API is never marshalled as-is.
|
||||
if gv.Version != runtime.APIVersionInternal {
|
||||
clusterbytes, err := MarshalClusterConfigurationToBytes(&cfg.ClusterConfiguration, gv)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
allFiles = append(allFiles, clusterbytes)
|
||||
}
|
||||
return bytes.Join(allFiles, []byte(kubeadmconstants.YAMLDocumentSeparator)), nil
|
||||
}
|
||||
|
||||
// MarshalClusterConfigurationToBytes marshals the internal ClusterConfiguration object to bytes. It writes the embedded
|
||||
// ComponentConfiguration objects out as separate YAML documents
|
||||
func MarshalClusterConfigurationToBytes(clustercfg *kubeadmapi.ClusterConfiguration, gv schema.GroupVersion) ([]byte, error) {
|
||||
clusterbytes, err := kubeadmutil.MarshalToYamlForCodecs(clustercfg, gv, kubeadmscheme.Codecs)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
allFiles := [][]byte{clusterbytes}
|
||||
componentConfigContent := map[string][]byte{}
|
||||
defaultedcfg := defaultedInternalConfig()
|
||||
|
||||
for kind, registration := range componentconfigs.Known {
|
||||
// If the ComponentConfig struct for the current registration is nil, skip it when marshalling
|
||||
realobj, ok := registration.GetFromInternalConfig(clustercfg)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
defaultedobj, ok := registration.GetFromInternalConfig(defaultedcfg)
|
||||
// Invalid: The caller asked to not print the componentconfigs if defaulted, but defaultComponentConfigs() wasn't able to create default objects to use for reference
|
||||
if !ok {
|
||||
return []byte{}, fmt.Errorf("couldn't create a default componentconfig object")
|
||||
}
|
||||
|
||||
// If the real ComponentConfig object differs from the default, print it out. If not, there's no need to print it out, so skip it
|
||||
if !reflect.DeepEqual(realobj, defaultedobj) {
|
||||
contentBytes, err := registration.Marshal(realobj)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
componentConfigContent[string(kind)] = contentBytes
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the ComponentConfig files by kind when marshalling
|
||||
sortedComponentConfigFiles := consistentOrderByteSlice(componentConfigContent)
|
||||
allFiles = append(allFiles, sortedComponentConfigFiles...)
|
||||
return bytes.Join(allFiles, []byte(kubeadmconstants.YAMLDocumentSeparator)), nil
|
||||
}
|
||||
|
||||
// consistentOrderByteSlice takes a map of a string key and a byte slice, and returns a byte slice of byte slices
|
||||
// with consistent ordering, where the keys in the map determine the ordering of the return value. This has to be
|
||||
// done as the order of a for...range loop over a map in go is undeterministic, and could otherwise lead to flakes
|
||||
// in e.g. unit tests when marshalling content with a random order
|
||||
func consistentOrderByteSlice(content map[string][]byte) [][]byte {
|
||||
keys := []string{}
|
||||
sortedContent := [][]byte{}
|
||||
for key := range content {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, key := range keys {
|
||||
sortedContent = append(sortedContent, content[key])
|
||||
}
|
||||
return sortedContent
|
||||
}
|
||||
|
214
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/masterconfig_test.go
generated
vendored
214
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/masterconfig_test.go
generated
vendored
@@ -19,30 +19,23 @@ package config
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
|
||||
"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"
|
||||
kubeadmapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3"
|
||||
)
|
||||
|
||||
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_v1alpha3YAML = "testdata/conversion/master/v1alpha3.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 {
|
||||
@@ -66,45 +59,39 @@ 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,
|
||||
{ // v1alpha3 -> internal
|
||||
name: "v1alpha3ToInternal",
|
||||
in: master_v1alpha3YAML,
|
||||
out: master_internalYAML,
|
||||
groupVersion: kubeadm.SchemeGroupVersion,
|
||||
},
|
||||
{ // v1alpha1 -> internal -> v1alpha2
|
||||
name: "v1alpha1Tov1alpha2",
|
||||
in: master_v1alpha1YAML,
|
||||
out: master_v1alpha2YAML,
|
||||
groupVersion: v1alpha2.SchemeGroupVersion,
|
||||
{ // v1alpha2 -> internal -> v1alpha3
|
||||
name: "v1alpha2Tov1alpha3",
|
||||
in: master_v1alpha2YAML,
|
||||
out: master_v1alpha3YAML,
|
||||
groupVersion: kubeadmapiv1alpha3.SchemeGroupVersion,
|
||||
},
|
||||
{ // v1alpha3 -> internal -> v1alpha3
|
||||
name: "v1alpha3Tov1alpha3",
|
||||
in: master_v1alpha3YAML,
|
||||
out: master_v1alpha3YAML,
|
||||
groupVersion: kubeadmapiv1alpha3.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
|
||||
name: "incompleteYAMLToDefaultedv1alpha2",
|
||||
{ // v1alpha2 -> default -> validate -> internal -> v1alpha3
|
||||
name: "incompleteYAMLToDefaultedv1alpha3",
|
||||
in: master_incompleteYAML,
|
||||
out: master_defaultedYAML,
|
||||
groupVersion: v1alpha2.SchemeGroupVersion,
|
||||
groupVersion: kubeadmapiv1alpha3.SchemeGroupVersion,
|
||||
},
|
||||
{ // v1alpha1 (faulty) -> validation should fail
|
||||
{ // v1alpha2 -> validation should fail
|
||||
name: "invalidYAMLShouldFail",
|
||||
in: master_invalidYAML,
|
||||
expectedErr: true,
|
||||
@@ -114,7 +101,7 @@ func TestConfigFileAndDefaultsToInternalConfig(t *testing.T) {
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.name, func(t2 *testing.T) {
|
||||
|
||||
internalcfg, err := ConfigFileAndDefaultsToInternalConfig(rt.in, &v1alpha2.MasterConfiguration{})
|
||||
internalcfg, err := ConfigFileAndDefaultsToInternalConfig(rt.in, &kubeadmapiv1alpha3.InitConfiguration{})
|
||||
if err != nil {
|
||||
if rt.expectedErr {
|
||||
return
|
||||
@@ -122,7 +109,7 @@ func TestConfigFileAndDefaultsToInternalConfig(t *testing.T) {
|
||||
t2.Fatalf("couldn't unmarshal test data: %v", err)
|
||||
}
|
||||
|
||||
actual, err := kubeadmutil.MarshalToYamlForCodecs(internalcfg, rt.groupVersion, scheme.Codecs)
|
||||
actual, err := MarshalInitConfigurationToBytes(internalcfg, rt.groupVersion)
|
||||
if err != nil {
|
||||
t2.Fatalf("couldn't marshal internal object: %v", err)
|
||||
}
|
||||
@@ -140,85 +127,90 @@ 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()
|
||||
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
|
||||
in []string
|
||||
out []string
|
||||
func TestConsistentOrderByteSlice(t *testing.T) {
|
||||
var (
|
||||
aKind = "Akind"
|
||||
aFile = []byte(`
|
||||
kind: Akind
|
||||
apiVersion: foo.k8s.io/v1
|
||||
`)
|
||||
aaKind = "Aakind"
|
||||
aaFile = []byte(`
|
||||
kind: Aakind
|
||||
apiVersion: foo.k8s.io/v1
|
||||
`)
|
||||
abKind = "Abkind"
|
||||
abFile = []byte(`
|
||||
kind: Abkind
|
||||
apiVersion: foo.k8s.io/v1
|
||||
`)
|
||||
)
|
||||
var tests = []struct {
|
||||
name string
|
||||
in map[string][]byte
|
||||
expected [][]byte
|
||||
}{
|
||||
{
|
||||
name: "empty struct",
|
||||
name: "a_aa_ab",
|
||||
in: map[string][]byte{
|
||||
aKind: aFile,
|
||||
aaKind: aaFile,
|
||||
abKind: abFile,
|
||||
},
|
||||
expected: [][]byte{aaFile, abFile, aFile},
|
||||
},
|
||||
{
|
||||
name: "already lowercase",
|
||||
in: []string{"example.k8s.io"},
|
||||
out: []string{"example.k8s.io"},
|
||||
name: "a_ab_aa",
|
||||
in: map[string][]byte{
|
||||
aKind: aFile,
|
||||
abKind: abFile,
|
||||
aaKind: aaFile,
|
||||
},
|
||||
expected: [][]byte{aaFile, abFile, aFile},
|
||||
},
|
||||
{
|
||||
name: "ip addresses and uppercase",
|
||||
in: []string{"EXAMPLE.k8s.io", "10.100.0.1"},
|
||||
out: []string{"example.k8s.io", "10.100.0.1"},
|
||||
name: "aa_a_ab",
|
||||
in: map[string][]byte{
|
||||
aaKind: aaFile,
|
||||
aKind: aFile,
|
||||
abKind: abFile,
|
||||
},
|
||||
expected: [][]byte{aaFile, abFile, aFile},
|
||||
},
|
||||
{
|
||||
name: "punycode and uppercase",
|
||||
in: []string{"xn--7gq663byk9a.xn--fiqz9s", "ANOTHEREXAMPLE.k8s.io"},
|
||||
out: []string{"xn--7gq663byk9a.xn--fiqz9s", "anotherexample.k8s.io"},
|
||||
name: "aa_ab_a",
|
||||
in: map[string][]byte{
|
||||
aaKind: aaFile,
|
||||
abKind: abFile,
|
||||
aKind: aFile,
|
||||
},
|
||||
expected: [][]byte{aaFile, abFile, aFile},
|
||||
},
|
||||
{
|
||||
name: "ab_a_aa",
|
||||
in: map[string][]byte{
|
||||
abKind: abFile,
|
||||
aKind: aFile,
|
||||
aaKind: aaFile,
|
||||
},
|
||||
expected: [][]byte{aaFile, abFile, aFile},
|
||||
},
|
||||
{
|
||||
name: "ab_aa_a",
|
||||
in: map[string][]byte{
|
||||
abKind: abFile,
|
||||
aaKind: aaFile,
|
||||
aKind: aFile,
|
||||
},
|
||||
expected: [][]byte{aaFile, abFile, aFile},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
cfg := &v1alpha2.MasterConfiguration{
|
||||
APIServerCertSANs: test.in,
|
||||
}
|
||||
|
||||
LowercaseSANs(cfg.APIServerCertSANs)
|
||||
|
||||
if len(cfg.APIServerCertSANs) != len(test.out) {
|
||||
t.Fatalf("expected %d elements, got %d", len(test.out), len(cfg.APIServerCertSANs))
|
||||
}
|
||||
|
||||
for i, expected := range test.out {
|
||||
if cfg.APIServerCertSANs[i] != expected {
|
||||
t.Errorf("expected element %d to be %q, got %q", i, expected, cfg.APIServerCertSANs[i])
|
||||
}
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.name, func(t2 *testing.T) {
|
||||
actual := consistentOrderByteSlice(rt.in)
|
||||
if !reflect.DeepEqual(rt.expected, actual) {
|
||||
t2.Errorf("the expected and actual output differs.\n\texpected: %s\n\tout: %s\n", rt.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
53
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/nodeconfig.go
generated
vendored
53
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/nodeconfig.go
generated
vendored
@@ -19,38 +19,69 @@ package config
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"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"
|
||||
kubeadmapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
"k8s.io/kubernetes/pkg/util/node"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
)
|
||||
|
||||
// SetJoinDynamicDefaults checks and sets configuration values for the NodeConfiguration object
|
||||
func SetJoinDynamicDefaults(cfg *kubeadmapi.NodeConfiguration) error {
|
||||
cfg.NodeRegistration.Name = node.GetHostname(cfg.NodeRegistration.Name)
|
||||
// SetJoinDynamicDefaults checks and sets configuration values for the JoinConfiguration object
|
||||
func SetJoinDynamicDefaults(cfg *kubeadmapi.JoinConfiguration) error {
|
||||
|
||||
if err := SetNodeRegistrationDynamicDefaults(&cfg.NodeRegistration, cfg.ControlPlane); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := SetAPIEndpointDynamicDefaults(&cfg.APIEndpoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NodeConfigFileAndDefaultsToInternalConfig
|
||||
func NodeConfigFileAndDefaultsToInternalConfig(cfgPath string, defaultversionedcfg *kubeadmapiv1alpha2.NodeConfiguration) (*kubeadmapi.NodeConfiguration, error) {
|
||||
internalcfg := &kubeadmapi.NodeConfiguration{}
|
||||
func NodeConfigFileAndDefaultsToInternalConfig(cfgPath string, defaultversionedcfg *kubeadmapiv1alpha3.JoinConfiguration) (*kubeadmapi.JoinConfiguration, error) {
|
||||
internalcfg := &kubeadmapi.JoinConfiguration{}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
gvkmap, err := kubeadmutil.SplitYAMLDocuments(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
joinBytes := []byte{}
|
||||
for gvk, bytes := range gvkmap {
|
||||
if gvk.Kind == constants.JoinConfigurationKind || gvk.Kind == constants.NodeConfigurationKind {
|
||||
joinBytes = bytes
|
||||
}
|
||||
}
|
||||
|
||||
if len(joinBytes) == 0 {
|
||||
return nil, fmt.Errorf("no %s found in config file %q", constants.JoinConfigurationKind, cfgPath)
|
||||
}
|
||||
|
||||
if err := runtime.DecodeInto(kubeadmscheme.Codecs.UniversalDecoder(), joinBytes, 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
|
||||
@@ -63,7 +94,7 @@ func NodeConfigFileAndDefaultsToInternalConfig(cfgPath string, defaultversionedc
|
||||
return nil, err
|
||||
}
|
||||
// Validates cfg (flags/configs + defaults)
|
||||
if err := validation.ValidateNodeConfiguration(internalcfg).ToAggregate(); err != nil {
|
||||
if err := validation.ValidateJoinConfiguration(internalcfg).ToAggregate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
40
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/nodeconfig_test.go
generated
vendored
40
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/nodeconfig_test.go
generated
vendored
@@ -24,13 +24,13 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"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/v1alpha2"
|
||||
kubeadmapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
)
|
||||
|
||||
const (
|
||||
node_v1alpha1YAML = "testdata/conversion/node/v1alpha1.yaml"
|
||||
node_v1alpha2YAML = "testdata/conversion/node/v1alpha2.yaml"
|
||||
node_v1alpha3YAML = "testdata/conversion/node/v1alpha3.yaml"
|
||||
node_internalYAML = "testdata/conversion/node/internal.yaml"
|
||||
node_incompleteYAML = "testdata/defaulting/node/incomplete.yaml"
|
||||
node_defaultedYAML = "testdata/defaulting/node/defaulted.yaml"
|
||||
@@ -45,33 +45,39 @@ 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,
|
||||
out: node_v1alpha2YAML,
|
||||
groupVersion: v1alpha2.SchemeGroupVersion,
|
||||
{ // v1alpha3 -> internal
|
||||
name: "v1alpha3ToInternal",
|
||||
in: node_v1alpha3YAML,
|
||||
out: node_internalYAML,
|
||||
groupVersion: kubeadm.SchemeGroupVersion,
|
||||
},
|
||||
{ // v1alpha2 -> internal -> v1alpha3
|
||||
name: "v1alpha2Tov1alpha3",
|
||||
in: node_v1alpha2YAML,
|
||||
out: node_v1alpha3YAML,
|
||||
groupVersion: kubeadmapiv1alpha3.SchemeGroupVersion,
|
||||
},
|
||||
{ // v1alpha3 -> internal -> v1alpha3
|
||||
name: "v1alpha3Tov1alpha3",
|
||||
in: node_v1alpha3YAML,
|
||||
out: node_v1alpha3YAML,
|
||||
groupVersion: kubeadmapiv1alpha3.SchemeGroupVersion,
|
||||
},
|
||||
// These tests are reading one file that has only a subset of the fields populated, loading it using NodeConfigFileAndDefaultsToInternalConfig,
|
||||
// and then marshals the internal object to the expected groupVersion
|
||||
{ // v1alpha1 -> default -> validate -> internal -> v1alpha2
|
||||
{ // v1alpha2 -> default -> validate -> internal -> v1alpha3
|
||||
name: "incompleteYAMLToDefaulted",
|
||||
in: node_incompleteYAML,
|
||||
out: node_defaultedYAML,
|
||||
groupVersion: v1alpha2.SchemeGroupVersion,
|
||||
groupVersion: kubeadmapiv1alpha3.SchemeGroupVersion,
|
||||
},
|
||||
{ // v1alpha1 (faulty) -> validation should fail
|
||||
{ // v1alpha2 -> validation should fail
|
||||
name: "invalidYAMLShouldFail",
|
||||
in: node_invalidYAML,
|
||||
expectedErr: true,
|
||||
@@ -81,7 +87,7 @@ func TestNodeConfigFileAndDefaultsToInternalConfig(t *testing.T) {
|
||||
for _, rt := range tests {
|
||||
t.Run(rt.name, func(t2 *testing.T) {
|
||||
|
||||
internalcfg, err := NodeConfigFileAndDefaultsToInternalConfig(rt.in, &v1alpha2.NodeConfiguration{})
|
||||
internalcfg, err := NodeConfigFileAndDefaultsToInternalConfig(rt.in, &kubeadmapiv1alpha3.JoinConfiguration{})
|
||||
if err != nil {
|
||||
if rt.expectedErr {
|
||||
return
|
||||
|
@@ -1,7 +1,6 @@
|
||||
API:
|
||||
APIEndpoint:
|
||||
AdvertiseAddress: 192.168.2.2
|
||||
BindPort: 6443
|
||||
ControlPlaneEndpoint: ""
|
||||
APIServerCertSANs: null
|
||||
APIServerExtraArgs:
|
||||
authorization-mode: Node,RBAC,Webhook
|
||||
@@ -23,6 +22,143 @@ BootstrapTokens:
|
||||
CIImageRepository: ""
|
||||
CertificatesDir: /etc/kubernetes/pki
|
||||
ClusterName: kubernetes
|
||||
ComponentConfigs:
|
||||
KubeProxy:
|
||||
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: iptables
|
||||
NodePortAddresses: null
|
||||
OOMScoreAdj: -999
|
||||
PortRange: ""
|
||||
ResourceContainer: /kube-proxy
|
||||
UDPIdleTimeout: 250ms
|
||||
Kubelet:
|
||||
Address: 1.2.3.4
|
||||
Authentication:
|
||||
Anonymous:
|
||||
Enabled: false
|
||||
Webhook:
|
||||
CacheTTL: 2m0s
|
||||
Enabled: true
|
||||
X509:
|
||||
ClientCAFile: /etc/kubernetes/pki/ca.crt
|
||||
Authorization:
|
||||
Mode: Webhook
|
||||
Webhook:
|
||||
CacheAuthorizedTTL: 5m0s
|
||||
CacheUnauthorizedTTL: 30s
|
||||
CPUCFSQuota: true
|
||||
CPUCFSQuotaPeriod: 0s
|
||||
CPUManagerPolicy: none
|
||||
CPUManagerReconcilePeriod: 10s
|
||||
CgroupDriver: cgroupfs
|
||||
CgroupRoot: ""
|
||||
CgroupsPerQOS: true
|
||||
ClusterDNS:
|
||||
- 10.96.0.10
|
||||
ClusterDomain: cluster.local
|
||||
ConfigMapAndSecretChangeDetectionStrategy: Watch
|
||||
ContainerLogMaxFiles: 5
|
||||
ContainerLogMaxSize: 10Mi
|
||||
ContentType: application/vnd.kubernetes.protobuf
|
||||
EnableContentionProfiling: false
|
||||
EnableControllerAttachDetach: true
|
||||
EnableDebuggingHandlers: true
|
||||
EnforceNodeAllocatable:
|
||||
- pods
|
||||
EventBurst: 10
|
||||
EventRecordQPS: 5
|
||||
EvictionHard:
|
||||
imagefs.available: 15%
|
||||
memory.available: 100Mi
|
||||
nodefs.available: 10%
|
||||
nodefs.inodesFree: 5%
|
||||
EvictionMaxPodGracePeriod: 0
|
||||
EvictionMinimumReclaim: null
|
||||
EvictionPressureTransitionPeriod: 5m0s
|
||||
EvictionSoft: null
|
||||
EvictionSoftGracePeriod: null
|
||||
FailSwapOn: true
|
||||
FeatureGates: null
|
||||
FileCheckFrequency: 20s
|
||||
HTTPCheckFrequency: 20s
|
||||
HairpinMode: promiscuous-bridge
|
||||
HealthzBindAddress: 127.0.0.1
|
||||
HealthzPort: 10248
|
||||
IPTablesDropBit: 15
|
||||
IPTablesMasqueradeBit: 14
|
||||
ImageGCHighThresholdPercent: 85
|
||||
ImageGCLowThresholdPercent: 80
|
||||
ImageMinimumGCAge: 2m0s
|
||||
KubeAPIBurst: 10
|
||||
KubeAPIQPS: 5
|
||||
KubeReserved: null
|
||||
KubeReservedCgroup: ""
|
||||
KubeletCgroups: ""
|
||||
MakeIPTablesUtilChains: true
|
||||
MaxOpenFiles: 1000000
|
||||
MaxPods: 110
|
||||
NodeLeaseDurationSeconds: 40
|
||||
NodeStatusUpdateFrequency: 10s
|
||||
OOMScoreAdj: -999
|
||||
PodCIDR: ""
|
||||
PodPidsLimit: -1
|
||||
PodsPerCore: 0
|
||||
Port: 10250
|
||||
ProtectKernelDefaults: false
|
||||
QOSReserved: null
|
||||
ReadOnlyPort: 0
|
||||
RegistryBurst: 10
|
||||
RegistryPullQPS: 5
|
||||
ResolverConfig: /etc/resolv.conf
|
||||
RotateCertificates: true
|
||||
RuntimeRequestTimeout: 2m0s
|
||||
SerializeImagePulls: true
|
||||
ServerTLSBootstrap: false
|
||||
StaticPodPath: /etc/kubernetes/manifests
|
||||
StaticPodURL: ""
|
||||
StaticPodURLHeader: null
|
||||
StreamingConnectionIdleTimeout: 4h0m0s
|
||||
SyncFrequency: 1m0s
|
||||
SystemCgroups: ""
|
||||
SystemReserved: null
|
||||
SystemReservedCgroup: ""
|
||||
TLSCertFile: ""
|
||||
TLSCipherSuites: null
|
||||
TLSMinVersion: ""
|
||||
TLSPrivateKeyFile: ""
|
||||
VolumeStatsAggPeriod: 1m0s
|
||||
ControlPlaneEndpoint: ""
|
||||
ControllerManagerExtraArgs: null
|
||||
ControllerManagerExtraVolumes: null
|
||||
Etcd:
|
||||
@@ -35,116 +171,7 @@ Etcd:
|
||||
ServerCertSANs: null
|
||||
FeatureGates: null
|
||||
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:
|
||||
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
|
||||
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
|
||||
rotateCertificates: true
|
||||
runtimeRequestTimeout: 2m0s
|
||||
serializeImagePulls: true
|
||||
staticPodPath: /etc/kubernetes/manifests
|
||||
streamingConnectionIdleTimeout: 4h0m0s
|
||||
syncFrequency: 1m0s
|
||||
volumeStatsAggPeriod: 1m0s
|
||||
KubernetesVersion: v1.10.2
|
||||
KubernetesVersion: v1.11.2
|
||||
Networking:
|
||||
DNSDomain: cluster.local
|
||||
PodSubnet: ""
|
||||
|
@@ -1,149 +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
|
||||
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,146 +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
|
||||
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: ""
|
@@ -59,7 +59,7 @@ kubeProxy:
|
||||
scheduler: ""
|
||||
syncPeriod: 30s
|
||||
metricsBindAddress: 127.0.0.1:10249
|
||||
mode: ""
|
||||
mode: iptables
|
||||
nodePortAddresses: null
|
||||
oomScoreAdj: -999
|
||||
portRange: ""
|
||||
@@ -67,7 +67,7 @@ kubeProxy:
|
||||
udpIdleTimeout: 250ms
|
||||
kubeletConfiguration:
|
||||
baseConfig:
|
||||
address: 0.0.0.0
|
||||
address: 1.2.3.4
|
||||
authentication:
|
||||
anonymous:
|
||||
enabled: false
|
||||
@@ -86,10 +86,12 @@ kubeletConfiguration:
|
||||
clusterDNS:
|
||||
- 10.96.0.10
|
||||
clusterDomain: cluster.local
|
||||
configMapAndSecretChangeDetectionStrategy: Watch
|
||||
containerLogMaxFiles: 5
|
||||
containerLogMaxSize: 10Mi
|
||||
contentType: application/vnd.kubernetes.protobuf
|
||||
cpuCFSQuota: true
|
||||
cpuCFSQuotaPeriod: 0s
|
||||
cpuManagerPolicy: none
|
||||
cpuManagerReconcilePeriod: 10s
|
||||
enableControllerAttachDetach: true
|
||||
@@ -134,7 +136,7 @@ kubeletConfiguration:
|
||||
streamingConnectionIdleTimeout: 4h0m0s
|
||||
syncFrequency: 1m0s
|
||||
volumeStatsAggPeriod: 1m0s
|
||||
kubernetesVersion: v1.10.2
|
||||
kubernetesVersion: v1.11.2
|
||||
networking:
|
||||
dnsDomain: cluster.local
|
||||
podSubnet: ""
|
||||
|
156
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha3.yaml
generated
vendored
Normal file
156
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/config/testdata/conversion/master/v1alpha3.yaml
generated
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
apiEndpoint:
|
||||
advertiseAddress: 192.168.2.2
|
||||
bindPort: 6443
|
||||
apiVersion: kubeadm.k8s.io/v1alpha3
|
||||
bootstrapTokens:
|
||||
- groups:
|
||||
- system:bootstrappers:kubeadm:default-node-token
|
||||
token: s73ybu.6tw6wnqgp5z0wb77
|
||||
ttl: 24h0m0s
|
||||
usages:
|
||||
- signing
|
||||
- authentication
|
||||
kind: InitConfiguration
|
||||
nodeRegistration:
|
||||
criSocket: /var/run/dockershim.sock
|
||||
name: master-1
|
||||
taints:
|
||||
- effect: NoSchedule
|
||||
key: node-role.kubernetes.io/master
|
||||
---
|
||||
apiServerExtraArgs:
|
||||
authorization-mode: Node,RBAC,Webhook
|
||||
apiVersion: kubeadm.k8s.io/v1alpha3
|
||||
auditPolicy:
|
||||
logDir: /var/log/kubernetes/audit
|
||||
logMaxAge: 2
|
||||
path: ""
|
||||
certificatesDir: /etc/kubernetes/pki
|
||||
clusterName: kubernetes
|
||||
controlPlaneEndpoint: ""
|
||||
etcd:
|
||||
local:
|
||||
dataDir: /var/lib/etcd
|
||||
image: ""
|
||||
imageRepository: k8s.gcr.io
|
||||
kind: ClusterConfiguration
|
||||
kubernetesVersion: v1.11.2
|
||||
networking:
|
||||
dnsDomain: cluster.local
|
||||
podSubnet: ""
|
||||
serviceSubnet: 10.96.0.0/12
|
||||
unifiedControlPlaneImage: ""
|
||||
---
|
||||
apiVersion: kubeproxy.config.k8s.io/v1alpha1
|
||||
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
|
||||
kind: KubeProxyConfiguration
|
||||
metricsBindAddress: 127.0.0.1:10249
|
||||
mode: iptables
|
||||
nodePortAddresses: null
|
||||
oomScoreAdj: -999
|
||||
portRange: ""
|
||||
resourceContainer: /kube-proxy
|
||||
udpIdleTimeout: 250ms
|
||||
---
|
||||
address: 1.2.3.4
|
||||
apiVersion: kubelet.config.k8s.io/v1beta1
|
||||
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
|
||||
cpuCFSQuotaPeriod: 0s
|
||||
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
|
||||
kind: KubeletConfiguration
|
||||
kubeAPIBurst: 10
|
||||
kubeAPIQPS: 5
|
||||
makeIPTablesUtilChains: true
|
||||
maxOpenFiles: 1000000
|
||||
maxPods: 110
|
||||
nodeLeaseDurationSeconds: 40
|
||||
nodeStatusUpdateFrequency: 10s
|
||||
oomScoreAdj: -999
|
||||
podPidsLimit: -1
|
||||
port: 10250
|
||||
registryBurst: 10
|
||||
registryPullQPS: 5
|
||||
resolvConf: /etc/resolv.conf
|
||||
rotateCertificates: true
|
||||
runtimeRequestTimeout: 2m0s
|
||||
serializeImagePulls: true
|
||||
staticPodPath: /etc/kubernetes/manifests
|
||||
streamingConnectionIdleTimeout: 4h0m0s
|
||||
syncFrequency: 1m0s
|
||||
volumeStatsAggPeriod: 1m0s
|
@@ -1,5 +1,9 @@
|
||||
APIEndpoint:
|
||||
AdvertiseAddress: 192.168.2.2
|
||||
BindPort: 6443
|
||||
CACertPath: /etc/kubernetes/pki/ca.crt
|
||||
ClusterName: kubernetes
|
||||
ControlPlane: false
|
||||
DiscoveryFile: ""
|
||||
DiscoveryTimeout: 5m0s
|
||||
DiscoveryToken: abcdef.0123456789abcdef
|
||||
|
@@ -1,3 +1,4 @@
|
||||
advertiseAddress: 192.168.2.2
|
||||
apiVersion: kubeadm.k8s.io/v1alpha2
|
||||
caCertPath: /etc/kubernetes/pki/ca.crt
|
||||
clusterName: kubernetes
|
||||
|
@@ -1,14 +1,18 @@
|
||||
apiVersion: kubeadm.k8s.io/v1alpha1
|
||||
kind: NodeConfiguration
|
||||
apiEndpoint:
|
||||
advertiseAddress: 192.168.2.2
|
||||
bindPort: 6443
|
||||
apiVersion: kubeadm.k8s.io/v1alpha3
|
||||
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
|
||||
kind: JoinConfiguration
|
||||
nodeRegistration:
|
||||
criSocket: /var/run/dockershim.sock
|
||||
name: master-1
|
||||
tlsBootstrapToken: abcdef.0123456789abcdef
|
||||
token: abcdef.0123456789abcdef
|
@@ -1,12 +1,7 @@
|
||||
api:
|
||||
apiEndpoint:
|
||||
advertiseAddress: 192.168.2.2
|
||||
bindPort: 6443
|
||||
controlPlaneEndpoint: ""
|
||||
apiVersion: kubeadm.k8s.io/v1alpha2
|
||||
auditPolicy:
|
||||
logDir: /var/log/kubernetes/audit
|
||||
logMaxAge: 2
|
||||
path: ""
|
||||
apiVersion: kubeadm.k8s.io/v1alpha3
|
||||
bootstrapTokens:
|
||||
- groups:
|
||||
- system:bootstrappers:kubeadm:default-node-token
|
||||
@@ -15,129 +10,142 @@ bootstrapTokens:
|
||||
usages:
|
||||
- signing
|
||||
- authentication
|
||||
certificatesDir: /var/lib/kubernetes/pki
|
||||
clusterName: kubernetes
|
||||
etcd:
|
||||
local:
|
||||
dataDir: /var/lib/etcd
|
||||
image: ""
|
||||
imageRepository: my-company.com
|
||||
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
|
||||
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.192.0.10
|
||||
clusterDomain: cluster.global
|
||||
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
|
||||
rotateCertificates: true
|
||||
runtimeRequestTimeout: 2m0s
|
||||
serializeImagePulls: true
|
||||
staticPodPath: /etc/kubernetes/manifests
|
||||
streamingConnectionIdleTimeout: 4h0m0s
|
||||
syncFrequency: 1m0s
|
||||
volumeStatsAggPeriod: 1m0s
|
||||
kubernetesVersion: v1.10.2
|
||||
networking:
|
||||
dnsDomain: cluster.global
|
||||
podSubnet: ""
|
||||
serviceSubnet: 10.196.0.0/12
|
||||
kind: InitConfiguration
|
||||
nodeRegistration:
|
||||
criSocket: /var/run/criruntime.sock
|
||||
name: master-1
|
||||
taints:
|
||||
- effect: NoSchedule
|
||||
key: node-role.kubernetes.io/master
|
||||
---
|
||||
apiVersion: kubeadm.k8s.io/v1alpha3
|
||||
auditPolicy:
|
||||
logDir: /var/log/kubernetes/audit
|
||||
logMaxAge: 2
|
||||
path: ""
|
||||
certificatesDir: /var/lib/kubernetes/pki
|
||||
clusterName: kubernetes
|
||||
controlPlaneEndpoint: ""
|
||||
etcd:
|
||||
local:
|
||||
dataDir: /var/lib/etcd
|
||||
image: ""
|
||||
imageRepository: my-company.com
|
||||
kind: ClusterConfiguration
|
||||
kubernetesVersion: v1.11.2
|
||||
networking:
|
||||
dnsDomain: cluster.global
|
||||
podSubnet: 10.148.0.0/16
|
||||
serviceSubnet: 10.196.0.0/12
|
||||
unifiedControlPlaneImage: ""
|
||||
---
|
||||
apiVersion: kubeproxy.config.k8s.io/v1alpha1
|
||||
bindAddress: 0.0.0.0
|
||||
clientConnection:
|
||||
acceptContentTypes: ""
|
||||
burst: 10
|
||||
contentType: application/vnd.kubernetes.protobuf
|
||||
kubeconfig: /var/lib/kube-proxy/kubeconfig.conf
|
||||
qps: 5
|
||||
clusterCIDR: 10.148.0.0/16
|
||||
configSyncPeriod: 15m0s
|
||||
conntrack:
|
||||
max: null
|
||||
maxPerCore: 32768
|
||||
min: 131072
|
||||
tcpCloseWaitTimeout: 1h0m0s
|
||||
tcpEstablishedTimeout: 24h0m0s
|
||||
enableProfiling: false
|
||||
healthzBindAddress: 0.0.0.0:10256
|
||||
hostnameOverride: ""
|
||||
iptables:
|
||||
masqueradeAll: false
|
||||
masqueradeBit: 14
|
||||
minSyncPeriod: 0s
|
||||
syncPeriod: 30s
|
||||
ipvs:
|
||||
excludeCIDRs: null
|
||||
minSyncPeriod: 0s
|
||||
scheduler: ""
|
||||
syncPeriod: 30s
|
||||
kind: KubeProxyConfiguration
|
||||
metricsBindAddress: 127.0.0.1:10249
|
||||
mode: ""
|
||||
nodePortAddresses: null
|
||||
oomScoreAdj: -999
|
||||
portRange: ""
|
||||
resourceContainer: /kube-proxy
|
||||
udpIdleTimeout: 250ms
|
||||
---
|
||||
address: 0.0.0.0
|
||||
apiVersion: kubelet.config.k8s.io/v1beta1
|
||||
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.192.0.10
|
||||
clusterDomain: cluster.global
|
||||
configMapAndSecretChangeDetectionStrategy: Watch
|
||||
containerLogMaxFiles: 5
|
||||
containerLogMaxSize: 10Mi
|
||||
contentType: application/vnd.kubernetes.protobuf
|
||||
cpuCFSQuota: true
|
||||
cpuCFSQuotaPeriod: 100ms
|
||||
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
|
||||
kind: KubeletConfiguration
|
||||
kubeAPIBurst: 10
|
||||
kubeAPIQPS: 5
|
||||
makeIPTablesUtilChains: true
|
||||
maxOpenFiles: 1000000
|
||||
maxPods: 110
|
||||
nodeLeaseDurationSeconds: 40
|
||||
nodeStatusUpdateFrequency: 10s
|
||||
oomScoreAdj: -999
|
||||
podPidsLimit: -1
|
||||
port: 10250
|
||||
registryBurst: 10
|
||||
registryPullQPS: 5
|
||||
resolvConf: /etc/resolv.conf
|
||||
rotateCertificates: true
|
||||
runtimeRequestTimeout: 2m0s
|
||||
serializeImagePulls: true
|
||||
staticPodPath: /etc/kubernetes/manifests
|
||||
streamingConnectionIdleTimeout: 4h0m0s
|
||||
syncFrequency: 1m0s
|
||||
volumeStatsAggPeriod: 1m0s
|
||||
|
@@ -1,15 +1,18 @@
|
||||
# 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
|
||||
kubernetesVersion: v1.11.2
|
||||
networking:
|
||||
dnsDomain: cluster.global
|
||||
serviceSubnet: 10.196.0.0/12
|
||||
nodeName: master-1
|
||||
token: s73ybu.6tw6wnqgp5z0wb77
|
||||
podSubnet: 10.148.0.0/16
|
||||
nodeRegistration:
|
||||
criSocket: /var/run/criruntime.sock
|
||||
name: master-1
|
||||
|
@@ -1,4 +1,7 @@
|
||||
apiVersion: kubeadm.k8s.io/v1alpha2
|
||||
apiEndpoint:
|
||||
advertiseAddress: 192.168.2.2
|
||||
bindPort: 6443
|
||||
apiVersion: kubeadm.k8s.io/v1alpha3
|
||||
caCertPath: /etc/kubernetes/pki/ca.crt
|
||||
clusterName: kubernetes
|
||||
discoveryFile: ""
|
||||
@@ -7,7 +10,7 @@ discoveryToken: abcdef.0123456789abcdef
|
||||
discoveryTokenAPIServers:
|
||||
- kube-apiserver:6443
|
||||
discoveryTokenUnsafeSkipCAVerification: true
|
||||
kind: NodeConfiguration
|
||||
kind: JoinConfiguration
|
||||
nodeRegistration:
|
||||
criSocket: /var/run/dockershim.sock
|
||||
name: thegopher
|
||||
|
@@ -1,7 +1,9 @@
|
||||
apiVersion: kubeadm.k8s.io/v1alpha1
|
||||
advertiseAddress: 192.168.2.2
|
||||
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
|
||||
kubernetesVersion: v1.11.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
|
||||
|
Reference in New Issue
Block a user