Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kubeadm: Group centric component configs #85639

Merged
merged 1 commit into from Dec 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 0 additions & 2 deletions cmd/kubeadm/app/apis/kubeadm/BUILD
Expand Up @@ -25,8 +25,6 @@ go_library(
"//staging/src/k8s.io/cluster-bootstrap/token/api:go_default_library",
"//staging/src/k8s.io/cluster-bootstrap/token/util:go_default_library",
"//staging/src/k8s.io/cluster-bootstrap/util/secrets:go_default_library",
"//staging/src/k8s.io/kube-proxy/config/v1alpha1:go_default_library",
"//staging/src/k8s.io/kubelet/config/v1beta1:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
],
)
Expand Down
4 changes: 2 additions & 2 deletions cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go
Expand Up @@ -30,7 +30,7 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
fuzzInitConfiguration,
fuzzClusterConfiguration,
fuzzComponentConfigs,
fuzzComponentConfigMap,
fuzzDNS,
fuzzNodeRegistration,
fuzzLocalEtcd,
Expand Down Expand Up @@ -116,7 +116,7 @@ func fuzzDNS(obj *kubeadm.DNS, c fuzz.Continue) {
obj.Type = kubeadm.CoreDNS
}

func fuzzComponentConfigs(obj *kubeadm.ComponentConfigs, c fuzz.Continue) {
func fuzzComponentConfigMap(obj *kubeadm.ComponentConfigMap, c fuzz.Continue) {
// This is intentionally empty because component config does not exists in the public api
// (empty mean all ComponentConfigs fields nil, and this is necessary for getting roundtrip passing)
}
Expand Down
38 changes: 26 additions & 12 deletions cmd/kubeadm/app/apis/kubeadm/types.go
Expand Up @@ -19,8 +19,8 @@ package kubeadm
import (
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
kubeproxyconfigv1alpha1 "k8s.io/kube-proxy/config/v1alpha1"
kubeletconfigv1beta1 "k8s.io/kubelet/config/v1beta1"

"k8s.io/apimachinery/pkg/runtime/schema"
)

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
Expand Down Expand Up @@ -62,9 +62,9 @@ type InitConfiguration struct {
type ClusterConfiguration struct {
metav1.TypeMeta

// ComponentConfigs holds internal ComponentConfig struct types known to kubeadm, should long-term only exist in the internal kubeadm API
// ComponentConfigs holds component configs known to kubeadm, should long-term only exist in the internal kubeadm API
// +k8s:conversion-gen=false
ComponentConfigs ComponentConfigs
ComponentConfigs ComponentConfigMap

// Etcd holds configuration for etcd.
Etcd Etcd
Expand Down Expand Up @@ -181,14 +181,6 @@ type ImageMeta struct {
//TODO: evaluate if we need also a ImageName based on user feedbacks
}

// ComponentConfigs holds known internal ComponentConfig types for other components
type ComponentConfigs struct {
// Kubelet holds the ComponentConfiguration for the kubelet
Kubelet *kubeletconfigv1beta1.KubeletConfiguration
// KubeProxy holds the ComponentConfiguration for the kube-proxy
KubeProxy *kubeproxyconfigv1alpha1.KubeProxyConfiguration
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// ClusterStatus contains the cluster status. The ClusterStatus will be stored in the kubeadm-config
Expand Down Expand Up @@ -424,3 +416,25 @@ type HostPathMount struct {
// PathType is the type of the HostPath.
PathType v1.HostPathType
}

// DocumentMap is a convenient way to describe a map between a YAML document and its GVK type
// +k8s:deepcopy-gen=false
type DocumentMap map[schema.GroupVersionKind][]byte

// ComponentConfig holds a known component config
type ComponentConfig interface {
// DeepCopy should create a new deep copy of the component config in place
DeepCopy() ComponentConfig

// Marshal is marshalling the config into a YAML document returned as a byte slice
Marshal() ([]byte, error)

// Unmarshal loads the config from a document map. No config in the document map is no error.
Unmarshal(docmap DocumentMap) error

// Default patches the component config with kubeadm preferred defaults
Default(cfg *ClusterConfiguration, localAPIEndpoint *APIEndpoint)
}

// ComponentConfigMap is a map between a group name (as in GVK group) and a ComponentConfig
type ComponentConfigMap map[string]ComponentConfig
3 changes: 0 additions & 3 deletions cmd/kubeadm/app/apis/kubeadm/validation/BUILD
Expand Up @@ -32,12 +32,9 @@ go_test(
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1beta2:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//staging/src/k8s.io/kube-proxy/config/v1alpha1:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/k8s.io/utils/pointer:go_default_library",
],
)

Expand Down
2 changes: 1 addition & 1 deletion cmd/kubeadm/app/apis/kubeadm/validation/validation.go
Expand Up @@ -64,7 +64,7 @@ func ValidateClusterConfiguration(c *kubeadm.ClusterConfiguration) field.ErrorLi
allErrs = append(allErrs, ValidateFeatureGates(c.FeatureGates, field.NewPath("featureGates"))...)
allErrs = append(allErrs, ValidateHostPort(c.ControlPlaneEndpoint, field.NewPath("controlPlaneEndpoint"))...)
allErrs = append(allErrs, ValidateEtcd(&c.Etcd, field.NewPath("etcd"))...)
allErrs = append(allErrs, componentconfigs.Known.Validate(c)...)
allErrs = append(allErrs, componentconfigs.Validate(c)...)
return allErrs
}

Expand Down
54 changes: 0 additions & 54 deletions cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go
Expand Up @@ -20,16 +20,12 @@ import (
"io/ioutil"
"os"
"testing"
"time"

"github.com/spf13/pflag"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation/field"
kubeproxyconfigv1alpha1 "k8s.io/kube-proxy/config/v1alpha1"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
utilpointer "k8s.io/utils/pointer"
)

func TestValidateToken(t *testing.T) {
Expand Down Expand Up @@ -448,31 +444,6 @@ func TestValidateInitConfiguration(t *testing.T) {
DataDir: "/some/path",
},
},
ComponentConfigs: kubeadm.ComponentConfigs{
KubeProxy: &kubeproxyconfigv1alpha1.KubeProxyConfiguration{
BindAddress: "192.168.59.103",
HealthzBindAddress: "0.0.0.0:10256",
MetricsBindAddress: "127.0.0.1:10249",
ClusterCIDR: "192.168.59.0/24",
UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second},
ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second},
IPTables: kubeproxyconfigv1alpha1.KubeProxyIPTablesConfiguration{
MasqueradeAll: true,
SyncPeriod: metav1.Duration{Duration: 5 * time.Second},
MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second},
},
IPVS: kubeproxyconfigv1alpha1.KubeProxyIPVSConfiguration{
SyncPeriod: metav1.Duration{Duration: 10 * time.Second},
MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second},
},
Conntrack: kubeproxyconfigv1alpha1.KubeProxyConntrackConfiguration{
MaxPerCore: utilpointer.Int32Ptr(1),
Min: utilpointer.Int32Ptr(1),
TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second},
},
},
},
Networking: kubeadm.Networking{
ServiceSubnet: "10.96.0.1/12",
DNSDomain: "cluster.local",
Expand All @@ -494,31 +465,6 @@ func TestValidateInitConfiguration(t *testing.T) {
DataDir: "/some/path",
},
},
ComponentConfigs: kubeadm.ComponentConfigs{
KubeProxy: &kubeproxyconfigv1alpha1.KubeProxyConfiguration{
BindAddress: "192.168.59.103",
HealthzBindAddress: "0.0.0.0:10256",
MetricsBindAddress: "127.0.0.1:10249",
ClusterCIDR: "192.168.59.0/24",
UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second},
ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second},
IPTables: kubeproxyconfigv1alpha1.KubeProxyIPTablesConfiguration{
MasqueradeAll: true,
SyncPeriod: metav1.Duration{Duration: 5 * time.Second},
MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second},
},
IPVS: kubeproxyconfigv1alpha1.KubeProxyIPVSConfiguration{
SyncPeriod: metav1.Duration{Duration: 10 * time.Second},
MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second},
},
Conntrack: kubeproxyconfigv1alpha1.KubeProxyConntrackConfiguration{
MaxPerCore: utilpointer.Int32Ptr(1),
Min: utilpointer.Int32Ptr(1),
TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second},
},
},
},
Networking: kubeadm.Networking{
ServiceSubnet: "2001:db8::1/98",
DNSDomain: "cluster.local",
Expand Down
38 changes: 19 additions & 19 deletions cmd/kubeadm/app/apis/kubeadm/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion cmd/kubeadm/app/cmd/BUILD
Expand Up @@ -84,7 +84,6 @@ go_test(
"//cmd/kubeadm/app/apis/output/scheme:go_default_library",
"//cmd/kubeadm/app/apis/output/v1alpha1:go_default_library",
"//cmd/kubeadm/app/cmd/options:go_default_library",
"//cmd/kubeadm/app/componentconfigs:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/features:go_default_library",
"//cmd/kubeadm/app/util:go_default_library",
Expand Down
50 changes: 34 additions & 16 deletions cmd/kubeadm/app/cmd/config.go
Expand Up @@ -116,7 +116,7 @@ func NewCmdConfigPrintJoinDefaults(out io.Writer) *cobra.Command {
}

func newCmdConfigPrintActionDefaults(out io.Writer, action string, configBytesProc func() ([]byte, error)) *cobra.Command {
componentConfigs := []string{}
kinds := []string{}
cmd := &cobra.Command{
Use: fmt.Sprintf("%s-defaults", action),
Short: fmt.Sprintf("Print default %s configuration, that can be used for 'kubeadm %s'", action, action),
Expand All @@ -127,11 +127,15 @@ func newCmdConfigPrintActionDefaults(out io.Writer, action string, configBytesPr
not perform the real computation for creating a token.
`), action, action, placeholderToken),
RunE: func(cmd *cobra.Command, args []string) error {
return runConfigPrintActionDefaults(out, componentConfigs, configBytesProc)
groups, err := mapLegacyKindsToGroups(kinds)
if err != nil {
return err
}
return runConfigPrintActionDefaults(out, groups, configBytesProc)
},
}
cmd.Flags().StringSliceVar(&componentConfigs, "component-configs", componentConfigs,
fmt.Sprintf("A comma-separated list for component config API objects to print the default values for. Available values: %v. If this flag is not set, no component configs will be printed.", getSupportedComponentConfigAPIObjects()))
cmd.Flags().StringSliceVar(&kinds, "component-configs", kinds,
fmt.Sprintf("A comma-separated list for component config API objects to print the default values for. Available values: %v. If this flag is not set, no component configs will be printed.", getSupportedComponentConfigKinds()))
return cmd
}

Expand All @@ -154,35 +158,49 @@ func runConfigPrintActionDefaults(out io.Writer, componentConfigs []string, conf
return nil
}

func getDefaultComponentConfigBytes(apiObject string) ([]byte, error) {
registration, ok := componentconfigs.Known[componentconfigs.RegistrationKind(apiObject)]
if !ok {
return []byte{}, errors.Errorf("--component-configs needs to contain some of %v", getSupportedComponentConfigAPIObjects())
}

func getDefaultComponentConfigBytes(group string) ([]byte, error) {
defaultedInitConfig, err := getDefaultedInitConfig()
if err != nil {
return []byte{}, err
}

realObj, ok := registration.GetFromInternalConfig(&defaultedInitConfig.ClusterConfiguration)
componentCfg, ok := defaultedInitConfig.ComponentConfigs[group]
if !ok {
return []byte{}, errors.New("GetFromInternalConfig failed")
return []byte{}, errors.Errorf("cannot get defaulted config for component group %q", group)
}

return registration.Marshal(realObj)
return componentCfg.Marshal()
}

// getSupportedComponentConfigAPIObjects returns all currently supported component config API object names
func getSupportedComponentConfigAPIObjects() []string {
// legacyKindToGroupMap maps between the old API object types and the new way of specifying component configs (by group)
var legacyKindToGroupMap = map[string]string{
"KubeletConfiguration": componentconfigs.KubeletGroup,
"KubeProxyConfiguration": componentconfigs.KubeProxyGroup,
}

// getSupportedComponentConfigKinds returns all currently supported component config API object names
func getSupportedComponentConfigKinds() []string {
objects := []string{}
for componentType := range componentconfigs.Known {
for componentType := range legacyKindToGroupMap {
objects = append(objects, string(componentType))
}
sort.Strings(objects)
return objects
}

func mapLegacyKindsToGroups(kinds []string) ([]string, error) {
groups := []string{}
for _, kind := range kinds {
group, ok := legacyKindToGroupMap[kind]
if ok {
groups = append(groups, group)
} else {
return nil, errors.Errorf("--component-configs needs to contain some of %v", getSupportedComponentConfigKinds())
}
}
return groups, nil
}

func getDefaultedInitConfig() (*kubeadmapi.InitConfiguration, error) {
initCfg := &kubeadmapiv1beta2.InitConfiguration{
LocalAPIEndpoint: kubeadmapiv1beta2.APIEndpoint{AdvertiseAddress: "1.2.3.4"},
Expand Down