From ef85747e14bd160fb1b1e08fbfc083c648e9cc57 Mon Sep 17 00:00:00 2001 From: Ivan Shvedunov Date: Tue, 18 Apr 2017 14:39:46 +0300 Subject: [PATCH 1/7] Fix serialization of EnforceNodeAllocatable EnforceNodeAllocatable being `nil` and `[]` are treated in different ways by kubelet. Namely, `nil` is replaced with `[]string{"pods"}` by the defaulting mechanism. E.g. if you run kubelet in Docker-in-Docker environment you may need to run it with the following options: `--cgroups-per-qos=false --enforce-node-allocatable=` (this corresponds to EnforceNodeAllocatable being empty array and not null) If you then grab kubelet configuration via /configz and try to reuse it for dynamic kubelet config, kubelet will think that EnforceNodeAllocatable is null, failing to run in the Docker-in-Docker environment. Encountered this while updating Virtlet for Kubernetes 1.6 (the dev environment is based on kubeadm-dind-cluster) --- pkg/apis/componentconfig/v1alpha1/types.go | 2 +- .../componentconfig/v1alpha1/zz_generated.conversion.go | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkg/apis/componentconfig/v1alpha1/types.go b/pkg/apis/componentconfig/v1alpha1/types.go index 8211e8f0aaa..65dece7529b 100644 --- a/pkg/apis/componentconfig/v1alpha1/types.go +++ b/pkg/apis/componentconfig/v1alpha1/types.go @@ -601,7 +601,7 @@ type KubeletConfiguration struct { // This flag specifies the various Node Allocatable enforcements that Kubelet needs to perform. // This flag accepts a list of options. Acceptible options are `pods`, `system-reserved` & `kube-reserved`. // Refer to [Node Allocatable](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node-allocatable.md) doc for more information. - EnforceNodeAllocatable []string `json:"enforceNodeAllocatable,omitempty"` + EnforceNodeAllocatable []string `json:"enforceNodeAllocatable"` // This flag, if set, will avoid including `EvictionHard` limits while computing Node Allocatable. // Refer to [Node Allocatable](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node-allocatable.md) doc for more information. ExperimentalNodeAllocatableIgnoreEvictionThreshold bool `json:"experimentalNodeAllocatableIgnoreEvictionThreshold,omitempty"` diff --git a/pkg/apis/componentconfig/v1alpha1/zz_generated.conversion.go b/pkg/apis/componentconfig/v1alpha1/zz_generated.conversion.go index f607ea6174c..93b79ff25fa 100644 --- a/pkg/apis/componentconfig/v1alpha1/zz_generated.conversion.go +++ b/pkg/apis/componentconfig/v1alpha1/zz_generated.conversion.go @@ -729,7 +729,11 @@ func autoConvert_componentconfig_KubeletConfiguration_To_v1alpha1_KubeletConfigu out.KubeReserved = *(*map[string]string)(unsafe.Pointer(&in.KubeReserved)) out.SystemReservedCgroup = in.SystemReservedCgroup out.KubeReservedCgroup = in.KubeReservedCgroup - out.EnforceNodeAllocatable = *(*[]string)(unsafe.Pointer(&in.EnforceNodeAllocatable)) + if in.EnforceNodeAllocatable == nil { + out.EnforceNodeAllocatable = make([]string, 0) + } else { + out.EnforceNodeAllocatable = *(*[]string)(unsafe.Pointer(&in.EnforceNodeAllocatable)) + } out.ExperimentalNodeAllocatableIgnoreEvictionThreshold = in.ExperimentalNodeAllocatableIgnoreEvictionThreshold return nil } From 11f1152e7732657af85f0bbbef4172c42aeecd97 Mon Sep 17 00:00:00 2001 From: Humble Chirammal Date: Thu, 18 May 2017 17:08:13 +0530 Subject: [PATCH 2/7] Add missing parameters of iscsi volume source to describe printer. Signed-off-by: Humble Chirammal --- pkg/printers/internalversion/describe.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pkg/printers/internalversion/describe.go b/pkg/printers/internalversion/describe.go index f24eff9c88c..2cec7c85170 100644 --- a/pkg/printers/internalversion/describe.go +++ b/pkg/printers/internalversion/describe.go @@ -818,8 +818,12 @@ func printISCSIVolumeSource(iscsi *api.ISCSIVolumeSource, w PrefixWriter) { " Lun:\t%v\n"+ " ISCSIInterface\t%v\n"+ " FSType:\t%v\n"+ - " ReadOnly:\t%v\n", - iscsi.TargetPortal, iscsi.IQN, iscsi.Lun, iscsi.ISCSIInterface, iscsi.FSType, iscsi.ReadOnly) + " ReadOnly:\t%v\n"+ + " Portals:\t%v\n"+ + " DiscoveryCHAPAuth:\t%v\n"+ + " SessionCHAPAuth:\t%v\n"+ + " SecretRef:\t%v\n", + iscsi.TargetPortal, iscsi.IQN, iscsi.Lun, iscsi.ISCSIInterface, iscsi.FSType, iscsi.ReadOnly, iscsi.Portals, iscsi.DiscoveryCHAPAuth, iscsi.SessionCHAPAuth, iscsi.SecretRef) } func printGlusterfsVolumeSource(glusterfs *api.GlusterfsVolumeSource, w PrefixWriter) { From 032e2f66521a514d7163a2b9ceb6b089421c4aeb Mon Sep 17 00:00:00 2001 From: Andy Goldstein Date: Tue, 16 May 2017 15:22:00 -0400 Subject: [PATCH 3/7] kube-proxy: add --write-config flag Add --write-config flag to kube-proxy to write the default configuration values to the specified file location. --- cmd/kube-proxy/app/BUILD | 5 ++ cmd/kube-proxy/app/server.go | 126 +++++++++++++++++++++++------- cmd/kube-proxy/app/server_test.go | 98 +++++++++++++++++++++-- hack/verify-flags/known-flags.txt | 1 + 4 files changed, 195 insertions(+), 35 deletions(-) diff --git a/cmd/kube-proxy/app/BUILD b/cmd/kube-proxy/app/BUILD index 6272d270da2..1c274c83e94 100644 --- a/cmd/kube-proxy/app/BUILD +++ b/cmd/kube-proxy/app/BUILD @@ -45,6 +45,9 @@ go_library( "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/github.com/spf13/pflag: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/runtime/serializer:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", @@ -67,9 +70,11 @@ go_test( deps = [ "//pkg/api:go_default_library", "//pkg/apis/componentconfig:go_default_library", + "//pkg/util:go_default_library", "//pkg/util/iptables:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", ], ) diff --git a/cmd/kube-proxy/app/server.go b/cmd/kube-proxy/app/server.go index eb98919eda0..059debb8f92 100644 --- a/cmd/kube-proxy/app/server.go +++ b/cmd/kube-proxy/app/server.go @@ -25,11 +25,15 @@ import ( "net" "net/http" "net/http/pprof" - "runtime" + "os" + goruntime "runtime" "strings" "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apimachinery/pkg/runtime/serializer/json" "k8s.io/apimachinery/pkg/types" utilnet "k8s.io/apimachinery/pkg/util/net" utilruntime "k8s.io/apimachinery/pkg/util/runtime" @@ -89,6 +93,8 @@ func checkKnownProxyMode(proxyMode string) bool { type Options struct { // ConfigFile is the location of the proxy server's configuration file. ConfigFile string + // WriteConfigTo is the path where the default configuration will be written. + WriteConfigTo string // CleanupAndExit, when true, makes the proxy server clean up iptables rules, then exit. CleanupAndExit bool @@ -104,11 +110,15 @@ type Options struct { master string // healthzPort is the port to be used by the healthz server. healthzPort int32 + + scheme *runtime.Scheme + codecs serializer.CodecFactory } // AddFlags adds flags to fs and binds them to options. func AddFlags(options *Options, fs *pflag.FlagSet) { fs.StringVar(&options.ConfigFile, "config", options.ConfigFile, "The path to the configuration file.") + fs.StringVar(&options.WriteConfigTo, "write-config-to", options.WriteConfigTo, "If set, write the default configuration values to this file and exit.") fs.BoolVar(&options.CleanupAndExit, "cleanup-iptables", options.CleanupAndExit, "If true cleanup iptables rules and exit.") // All flags below here are deprecated and will eventually be removed. @@ -151,17 +161,37 @@ func AddFlags(options *Options, fs *pflag.FlagSet) { utilfeature.DefaultFeatureGate.AddFlag(fs) } +func NewOptions() (*Options, error) { + o := &Options{ + config: new(componentconfig.KubeProxyConfiguration), + healthzPort: 10256, + } + + o.scheme = runtime.NewScheme() + o.codecs = serializer.NewCodecFactory(o.scheme) + + if err := componentconfig.AddToScheme(o.scheme); err != nil { + return nil, err + } + if err := v1alpha1.AddToScheme(o.scheme); err != nil { + return nil, err + } + + return o, nil +} + // Complete completes all the required options. -func (o Options) Complete() error { - if len(o.ConfigFile) == 0 { - glog.Warning("WARNING: all flags other than --config and --cleanup-iptables are deprecated. Please begin using a config file ASAP.") +func (o *Options) Complete() error { + if len(o.ConfigFile) == 0 && len(o.WriteConfigTo) == 0 { + glog.Warning("WARNING: all flags other than --config, --write-config-to, and --cleanup-iptables are deprecated. Please begin using a config file ASAP.") o.applyDeprecatedHealthzPortToConfig() } + return nil } // Validate validates all the required options. -func (o Options) Validate(args []string) error { +func (o *Options) Validate(args []string) error { if len(args) != 0 { return errors.New("no arguments are supported") } @@ -169,11 +199,15 @@ func (o Options) Validate(args []string) error { return nil } -func (o Options) Run() error { +func (o *Options) Run() error { config := o.config + if len(o.WriteConfigTo) > 0 { + return o.writeConfigFile() + } + if len(o.ConfigFile) > 0 { - if c, err := loadConfigFromFile(o.ConfigFile); err != nil { + if c, err := o.loadConfigFromFile(o.ConfigFile); err != nil { return err } else { config = c @@ -182,7 +216,7 @@ func (o Options) Run() error { } } - proxyServer, err := NewProxyServer(config, o.CleanupAndExit, o.master) + proxyServer, err := NewProxyServer(config, o.CleanupAndExit, o.scheme, o.master) if err != nil { return err } @@ -190,13 +224,43 @@ func (o Options) Run() error { return proxyServer.Run() } +func (o *Options) writeConfigFile() error { + var encoder runtime.Encoder + mediaTypes := o.codecs.SupportedMediaTypes() + for _, info := range mediaTypes { + if info.MediaType == "application/yaml" { + encoder = info.Serializer + break + } + } + if encoder == nil { + return errors.New("unable to locate yaml encoder") + } + encoder = json.NewYAMLSerializer(json.DefaultMetaFactory, o.scheme, o.scheme) + encoder = o.codecs.EncoderForVersion(encoder, v1alpha1.SchemeGroupVersion) + + configFile, err := os.Create(o.WriteConfigTo) + if err != nil { + return err + } + defer configFile.Close() + + if err := encoder.Encode(o.config, configFile); err != nil { + return err + } + + fmt.Printf("Wrote configuration to: %s\n", o.WriteConfigTo) + + return nil +} + // applyDeprecatedHealthzPortToConfig sets o.config.HealthzBindAddress from // flags passed on the command line based on the following rules: // // 1. If --healthz-port is 0, disable the healthz server. // 2. Otherwise, use the value of --healthz-port for the port portion of // o.config.HealthzBindAddress -func (o Options) applyDeprecatedHealthzPortToConfig() { +func (o *Options) applyDeprecatedHealthzPortToConfig() { if o.healthzPort == 0 { o.config.HealthzBindAddress = "" return @@ -212,13 +276,18 @@ func (o Options) applyDeprecatedHealthzPortToConfig() { // loadConfigFromFile loads the contents of file and decodes it as a // KubeProxyConfiguration object. -func loadConfigFromFile(file string) (*componentconfig.KubeProxyConfiguration, error) { +func (o *Options) loadConfigFromFile(file string) (*componentconfig.KubeProxyConfiguration, error) { data, err := ioutil.ReadFile(file) if err != nil { return nil, err } - configObj, gvk, err := api.Codecs.UniversalDecoder().Decode(data, nil, nil) + return o.loadConfig(data) +} + +// loadConfig decodes data as a KubeProxyConfiguration object. +func (o *Options) loadConfig(data []byte) (*componentconfig.KubeProxyConfiguration, error) { + configObj, gvk, err := o.codecs.UniversalDecoder().Decode(data, nil, nil) if err != nil { return nil, err } @@ -229,15 +298,15 @@ func loadConfigFromFile(file string) (*componentconfig.KubeProxyConfiguration, e return config, nil } -func applyDefaults(in *componentconfig.KubeProxyConfiguration) (*componentconfig.KubeProxyConfiguration, error) { - external, err := api.Scheme.ConvertToVersion(in, v1alpha1.SchemeGroupVersion) +func (o *Options) applyDefaults(in *componentconfig.KubeProxyConfiguration) (*componentconfig.KubeProxyConfiguration, error) { + external, err := o.scheme.ConvertToVersion(in, v1alpha1.SchemeGroupVersion) if err != nil { return nil, err } - api.Scheme.Default(external) + o.scheme.Default(external) - internal, err := api.Scheme.ConvertToVersion(external, componentconfig.SchemeGroupVersion) + internal, err := o.scheme.ConvertToVersion(external, componentconfig.SchemeGroupVersion) if err != nil { return nil, err } @@ -249,9 +318,9 @@ func applyDefaults(in *componentconfig.KubeProxyConfiguration) (*componentconfig // NewProxyCommand creates a *cobra.Command object with default parameters func NewProxyCommand() *cobra.Command { - opts := Options{ - config: new(componentconfig.KubeProxyConfiguration), - healthzPort: 10256, + opts, err := NewOptions() + if err != nil { + glog.Fatalf("Unable to initialize command options: %v", err) } cmd := &cobra.Command{ @@ -270,14 +339,13 @@ with the apiserver API to configure the proxy.`, }, } - var err error - opts.config, err = applyDefaults(opts.config) + opts.config, err = opts.applyDefaults(opts.config) if err != nil { glog.Fatalf("unable to create flag defaults: %v", err) } flags := cmd.Flags() - AddFlags(&opts, flags) + AddFlags(opts, flags) cmd.MarkFlagFilename("config", "yaml", "yml", "json") @@ -344,7 +412,7 @@ func createClients(config componentconfig.ClientConnectionConfiguration, masterO } // NewProxyServer returns a new ProxyServer. -func NewProxyServer(config *componentconfig.KubeProxyConfiguration, cleanupAndExit bool, master string) (*ProxyServer, error) { +func NewProxyServer(config *componentconfig.KubeProxyConfiguration, cleanupAndExit bool, scheme *runtime.Scheme, master string) (*ProxyServer, error) { if config == nil { return nil, errors.New("config is required") } @@ -367,7 +435,7 @@ func NewProxyServer(config *componentconfig.KubeProxyConfiguration, cleanupAndEx // Create a iptables utils. execer := exec.New() - if runtime.GOOS == "windows" { + if goruntime.GOOS == "windows" { netshInterface = utilnetsh.New(execer) } else { dbus = utildbus.New() @@ -387,7 +455,7 @@ func NewProxyServer(config *componentconfig.KubeProxyConfiguration, cleanupAndEx // Create event recorder hostname := nodeutil.GetHostname(config.HostnameOverride) eventBroadcaster := record.NewBroadcaster() - recorder := eventBroadcaster.NewRecorder(api.Scheme, clientv1.EventSource{Component: "kube-proxy", Host: hostname}) + recorder := eventBroadcaster.NewRecorder(scheme, clientv1.EventSource{Component: "kube-proxy", Host: hostname}) var healthzServer *healthcheck.HealthzServer if len(config.HealthzBindAddress) > 0 { @@ -434,7 +502,7 @@ func NewProxyServer(config *componentconfig.KubeProxyConfiguration, cleanupAndEx userspace.CleanupLeftovers(iptInterface) } else { glog.V(0).Info("Using userspace Proxier.") - if runtime.GOOS == "windows" { + if goruntime.GOOS == "windows" { // This is a proxy.LoadBalancer which NewProxier needs but has methods we don't need for // our config.EndpointsConfigHandler. loadBalancer := winuserspace.NewLoadBalancerRR() @@ -479,7 +547,7 @@ func NewProxyServer(config *componentconfig.KubeProxyConfiguration, cleanupAndEx proxier = proxierUserspace } // Remove artifacts from the pure-iptables Proxier, if not on Windows. - if runtime.GOOS != "windows" { + if goruntime.GOOS != "windows" { glog.V(0).Info("Tearing down pure-iptables proxy rules.") // TODO this has side effects that should only happen when Run() is invoked. iptables.CleanupLeftovers(iptInterface) @@ -487,7 +555,7 @@ func NewProxyServer(config *componentconfig.KubeProxyConfiguration, cleanupAndEx } // Add iptables reload function, if not on Windows. - if runtime.GOOS != "windows" { + if goruntime.GOOS != "windows" { iptInterface.AddReloadFunc(proxier.Sync) } @@ -580,7 +648,7 @@ func (s *ProxyServer) Run() error { } // Tune conntrack, if requested - if s.Conntracker != nil && runtime.GOOS != "windows" { + if s.Conntracker != nil && goruntime.GOOS != "windows" { max, err := getConntrackMax(s.ConntrackConfiguration) if err != nil { return err @@ -654,7 +722,7 @@ func getConntrackMax(config componentconfig.KubeProxyConntrackConfiguration) (in } if config.MaxPerCore > 0 { floor := int(config.Min) - scaled := int(config.MaxPerCore) * runtime.NumCPU() + scaled := int(config.MaxPerCore) * goruntime.NumCPU() if scaled > floor { glog.V(3).Infof("getConntrackMax: using scaled conntrack-max-per-core") return scaled, nil diff --git a/cmd/kube-proxy/app/server_test.go b/cmd/kube-proxy/app/server_test.go index 846894eeb15..b7337fe6c2b 100644 --- a/cmd/kube-proxy/app/server_test.go +++ b/cmd/kube-proxy/app/server_test.go @@ -18,15 +18,19 @@ package app import ( "fmt" + "reflect" "runtime" "strings" "testing" + "time" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/diff" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/componentconfig" + "k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util/iptables" ) @@ -132,14 +136,17 @@ func Test_getProxyMode(t *testing.T) { // This test verifies that Proxy Server does not crash when CleanupAndExit is true. func TestProxyServerWithCleanupAndExit(t *testing.T) { - options := Options{ - config: &componentconfig.KubeProxyConfiguration{ - BindAddress: "0.0.0.0", - }, - CleanupAndExit: true, + options, err := NewOptions() + if err != nil { + t.Fatal(err) } - proxyserver, err := NewProxyServer(options.config, options.CleanupAndExit, options.master) + options.config = &componentconfig.KubeProxyConfiguration{ + BindAddress: "0.0.0.0", + } + options.CleanupAndExit = true + + proxyserver, err := NewProxyServer(options.config, options.CleanupAndExit, options.scheme, options.master) assert.Nil(t, err) assert.NotNil(t, proxyserver) @@ -203,3 +210,82 @@ func TestGetConntrackMax(t *testing.T) { } } } + +func TestLoadConfig(t *testing.T) { + yaml := `apiVersion: componentconfig/v1alpha1 +bindAddress: 9.8.7.6 +clientConnection: + acceptContentTypes: "abc" + burst: 100 + contentType: content-type + kubeconfig: "/path/to/kubeconfig" + qps: 7 +clusterCIDR: "1.2.3.0/24" +configSyncPeriod: 15s +conntrack: + max: 4 + maxPerCore: 2 + min: 1 + tcpCloseWaitTimeout: 10s + tcpEstablishedTimeout: 20s +featureGates: "all" +healthzBindAddress: 1.2.3.4:12345 +hostnameOverride: "foo" +iptables: + masqueradeAll: true + masqueradeBit: 17 + minSyncPeriod: 10s + syncPeriod: 60s +kind: KubeProxyConfiguration +metricsBindAddress: 2.3.4.5:23456 +mode: "iptables" +oomScoreAdj: 17 +portRange: "2-7" +resourceContainer: /foo +udpTimeoutMilliseconds: 123ms +` + + expected := &componentconfig.KubeProxyConfiguration{ + BindAddress: "9.8.7.6", + ClientConnection: componentconfig.ClientConnectionConfiguration{ + AcceptContentTypes: "abc", + Burst: 100, + ContentType: "content-type", + KubeConfigFile: "/path/to/kubeconfig", + QPS: 7, + }, + ClusterCIDR: "1.2.3.0/24", + ConfigSyncPeriod: metav1.Duration{Duration: 15 * time.Second}, + Conntrack: componentconfig.KubeProxyConntrackConfiguration{ + Max: 4, + MaxPerCore: 2, + Min: 1, + TCPCloseWaitTimeout: metav1.Duration{Duration: 10 * time.Second}, + TCPEstablishedTimeout: metav1.Duration{Duration: 20 * time.Second}, + }, + FeatureGates: "all", + HealthzBindAddress: "1.2.3.4:12345", + HostnameOverride: "foo", + IPTables: componentconfig.KubeProxyIPTablesConfiguration{ + MasqueradeAll: true, + MasqueradeBit: util.Int32Ptr(17), + MinSyncPeriod: metav1.Duration{Duration: 10 * time.Second}, + SyncPeriod: metav1.Duration{Duration: 60 * time.Second}, + }, + MetricsBindAddress: "2.3.4.5:23456", + Mode: "iptables", + OOMScoreAdj: util.Int32Ptr(17), + PortRange: "2-7", + ResourceContainer: "/foo", + UDPIdleTimeout: metav1.Duration{Duration: 123 * time.Millisecond}, + } + + options, err := NewOptions() + assert.NoError(t, err) + + config, err := options.loadConfig([]byte(yaml)) + assert.NoError(t, err) + if !reflect.DeepEqual(expected, config) { + t.Fatalf("unexpected config, diff = %s", diff.ObjectDiff(config, expected)) + } +} diff --git a/hack/verify-flags/known-flags.txt b/hack/verify-flags/known-flags.txt index 39835b626fb..6cc33c52f86 100644 --- a/hack/verify-flags/known-flags.txt +++ b/hack/verify-flags/known-flags.txt @@ -724,6 +724,7 @@ watch-cache-sizes watch-only whitelist-override-label windows-line-endings +write-config-to www-prefix zone-id zone-name From 22ab45b5759b01341a2b030915da68842e9bd135 Mon Sep 17 00:00:00 2001 From: Xing Zhou Date: Tue, 25 Apr 2017 10:17:28 +0800 Subject: [PATCH 4/7] While calculating pod's cpu limits, need to count in init-container. Need to count in init-container when calculating a pod's cpu limits. Otherwise, may cause pod start failure due to "invalid argument" error while trying to write "cpu.cfs_quota_us" file. --- pkg/kubelet/cm/helpers_linux.go | 40 ++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/pkg/kubelet/cm/helpers_linux.go b/pkg/kubelet/cm/helpers_linux.go index 2e0d41b9c52..ca2f7235ca0 100644 --- a/pkg/kubelet/cm/helpers_linux.go +++ b/pkg/kubelet/cm/helpers_linux.go @@ -26,6 +26,7 @@ import ( libcontainercgroups "github.com/opencontainers/runc/libcontainer/cgroups" "k8s.io/kubernetes/pkg/api/v1" + "k8s.io/kubernetes/pkg/api/v1/resource" "k8s.io/kubernetes/pkg/kubelet/qos" ) @@ -84,28 +85,41 @@ func MilliCPUToShares(milliCPU int64) int64 { // ResourceConfigForPod takes the input pod and outputs the cgroup resource config. func ResourceConfigForPod(pod *v1.Pod) *ResourceConfig { - // sum requests and limits, track if limits were applied for each resource. + // sum requests and limits. + reqs, limits, err := resource.PodRequestsAndLimits(pod) + if err != nil { + return &ResourceConfig{} + } + cpuRequests := int64(0) cpuLimits := int64(0) memoryLimits := int64(0) - memoryLimitsDeclared := true - cpuLimitsDeclared := true - for _, container := range pod.Spec.Containers { - cpuRequests += container.Resources.Requests.Cpu().MilliValue() - cpuLimits += container.Resources.Limits.Cpu().MilliValue() - if container.Resources.Limits.Cpu().IsZero() { - cpuLimitsDeclared = false - } - memoryLimits += container.Resources.Limits.Memory().Value() - if container.Resources.Limits.Memory().IsZero() { - memoryLimitsDeclared = false - } + if request, found := reqs[v1.ResourceCPU]; found { + cpuRequests = request.MilliValue() + } + if limit, found := limits[v1.ResourceCPU]; found { + cpuLimits = limit.MilliValue() + } + if limit, found := limits[v1.ResourceMemory]; found { + memoryLimits = limit.Value() } // convert to CFS values cpuShares := MilliCPUToShares(cpuRequests) cpuQuota, cpuPeriod := MilliCPUToQuota(cpuLimits) + // track if limits were applied for each resource. + memoryLimitsDeclared := true + cpuLimitsDeclared := true + for _, container := range pod.Spec.Containers { + if container.Resources.Limits.Cpu().IsZero() { + cpuLimitsDeclared = false + } + if container.Resources.Limits.Memory().IsZero() { + memoryLimitsDeclared = false + } + } + // determine the qos class qosClass := qos.GetPodQOS(pod) From 7dabb8b2e2a60a780ff4a9318147449beb2addfe Mon Sep 17 00:00:00 2001 From: zhengjiajin <393926893@qq.com> Date: Fri, 19 May 2017 13:36:17 +0800 Subject: [PATCH 5/7] fix changelog not work --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1eefe82406f..029b63a0458 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,7 +66,7 @@ - [Downloads for v1.6.0](#downloads-for-v160) - [Client Binaries](#client-binaries-9) - [Server Binaries](#server-binaries-9) - - [WARNING: etcd backup strongly recommended](#warning:-etcd-backup-strongly-recommended) + - [WARNING: etcd backup strongly recommended](#warning-etcd-backup-strongly-recommended) - [Major updates and release themes](#major-updates-and-release-themes) - [Action Required](#action-required-3) - [Certificates API](#certificates-api) @@ -393,8 +393,8 @@ - [Known Issues](#known-issues-1) - [Notable Changes to Existing Behavior](#notable-changes-to-existing-behavior-1) - [Deployments](#deployments) - - [kubectl rolling-update: < v1.4.0 client vs >=v1.4.0 cluster](#kubectl-rolling-update:-<-v140-client-vs->=v140-cluster) - - [kubectl delete: < v1.4.0 client vs >=v1.4.0 cluster](#kubectl-delete:-<-v140-client-vs->=v140-cluster) + - [kubectl rolling-update: < v1.4.0 client vs >=v1.4.0 cluster](#kubectl-rolling-update--v140-client-vs-v140-cluster) + - [kubectl delete: < v1.4.0 client vs >=v1.4.0 cluster](#kubectl-delete--v140-client-vs-v140-cluster) - [DELETE operation in REST API](#delete-operation-in-rest-api) - [Action Required Before Upgrading](#action-required-before-upgrading-1) - [optionally, remove the old secret](#optionally-remove-the-old-secret) From a26897362bfe3ef163882ea7ca296c4dcaff8d9e Mon Sep 17 00:00:00 2001 From: Jordan Liggitt Date: Fri, 19 May 2017 10:31:54 -0400 Subject: [PATCH 6/7] Use name from node object on create --- .../admission/noderestriction/admission.go | 15 ++++++++++++-- .../noderestriction/admission_test.go | 20 +++++++++++++++---- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/plugin/pkg/admission/noderestriction/admission.go b/plugin/pkg/admission/noderestriction/admission.go index 7eabfdf7a73..155763b3bca 100644 --- a/plugin/pkg/admission/noderestriction/admission.go +++ b/plugin/pkg/admission/noderestriction/admission.go @@ -196,8 +196,19 @@ func (c *nodePlugin) admitPodStatus(nodeName string, a admission.Attributes) err } func (c *nodePlugin) admitNode(nodeName string, a admission.Attributes) error { - if a.GetName() != nodeName { - return admission.NewForbidden(a, fmt.Errorf("cannot modify other nodes")) + requestedName := a.GetName() + + // On create, get name from new object if unset in admission + if len(requestedName) == 0 && a.GetOperation() == admission.Create { + node, ok := a.GetObject().(*api.Node) + if !ok { + return admission.NewForbidden(a, fmt.Errorf("unexpected type %T", a.GetObject())) + } + requestedName = node.Name + } + + if requestedName != nodeName { + return admission.NewForbidden(a, fmt.Errorf("node %s cannot modify node %s", nodeName, requestedName)) } return nil } diff --git a/plugin/pkg/admission/noderestriction/admission_test.go b/plugin/pkg/admission/noderestriction/admission_test.go index 5cb0eb23bb8..71cea49e870 100644 --- a/plugin/pkg/admission/noderestriction/admission_test.go +++ b/plugin/pkg/admission/noderestriction/admission_test.go @@ -356,6 +356,12 @@ func Test_nodePlugin_Admit(t *testing.T) { attributes: admission.NewAttributesRecord(mynodeObj, nil, nodeKind, mynodeObj.Namespace, mynodeObj.Name, nodeResource, "", admission.Create, mynode), err: "", }, + { + name: "allow create of my node pulling name from object", + podsGetter: noExistingPods, + attributes: admission.NewAttributesRecord(mynodeObj, nil, nodeKind, mynodeObj.Namespace, "", nodeResource, "", admission.Create, mynode), + err: "", + }, { name: "allow update of my node", podsGetter: existingPods, @@ -380,25 +386,31 @@ func Test_nodePlugin_Admit(t *testing.T) { name: "forbid create of other node", podsGetter: noExistingPods, attributes: admission.NewAttributesRecord(othernodeObj, nil, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "", admission.Create, mynode), - err: "cannot modify other nodes", + err: "cannot modify node", + }, + { + name: "forbid create of other node pulling name from object", + podsGetter: noExistingPods, + attributes: admission.NewAttributesRecord(othernodeObj, nil, nodeKind, othernodeObj.Namespace, "", nodeResource, "", admission.Create, mynode), + err: "cannot modify node", }, { name: "forbid update of other node", podsGetter: existingPods, attributes: admission.NewAttributesRecord(othernodeObj, othernodeObj, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "", admission.Update, mynode), - err: "cannot modify other nodes", + err: "cannot modify node", }, { name: "forbid delete of other node", podsGetter: existingPods, attributes: admission.NewAttributesRecord(nil, nil, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "", admission.Delete, mynode), - err: "cannot modify other nodes", + err: "cannot modify node", }, { name: "forbid update of other node status", podsGetter: existingPods, attributes: admission.NewAttributesRecord(othernodeObj, othernodeObj, nodeKind, othernodeObj.Namespace, othernodeObj.Name, nodeResource, "status", admission.Update, mynode), - err: "cannot modify other nodes", + err: "cannot modify node", }, // Unrelated objects From 96ae34685e60d0e06917156b77629d8e4c853e5b Mon Sep 17 00:00:00 2001 From: Daniel Nardo Date: Thu, 18 May 2017 10:06:04 -0700 Subject: [PATCH 7/7] Add ip-masq-agent addon to the addons folder. This also ensures that under gce we add this daemonset if the non-masq-cidr is set to 0/0. --- .../addons/ip-masq-agent/ip-masq-agent.yaml | 38 +++++++++++++++++++ cluster/gce/gci/configure-helper.sh | 3 ++ 2 files changed, 41 insertions(+) create mode 100644 cluster/addons/ip-masq-agent/ip-masq-agent.yaml diff --git a/cluster/addons/ip-masq-agent/ip-masq-agent.yaml b/cluster/addons/ip-masq-agent/ip-masq-agent.yaml new file mode 100644 index 00000000000..cc24c28d2d5 --- /dev/null +++ b/cluster/addons/ip-masq-agent/ip-masq-agent.yaml @@ -0,0 +1,38 @@ +# https://github.com/kubernetes-incubator/ip-masq-agent/blob/v2.0.0/README.md +apiVersion: extensions/v1beta1 +kind: DaemonSet +metadata: + name: ip-masq-agent + namespace: kube-system + labels: + addonmanager.kubernetes.io/mode: Reconcile +spec: + template: + metadata: + labels: + k8s-app: ip-masq-agent + annotations: + scheduler.alpha.kubernetes.io/critical-pod: '' + scheduler.alpha.kubernetes.io/tolerations: | + [{"key": "dedicated", "value": "master", "effect": "NoSchedule" }, + {"key":"CriticalAddonsOnly", "operator":"Exists"}] + spec: + hostNetwork: true + containers: + - name: ip-masq-agent + image: gcr.io/google-containers/ip-masq-agent-amd64:v2.0.0 + securityContext: + privileged: true + volumeMounts: + - name: config + mountPath: /etc/config + volumes: + - name: config + configMap: + # Note this ConfigMap must be created in the same namespace as the daemon pods - this spec uses kube-system + name: ip-masq-agent + optional: true + items: + # The daemon looks for its config in a YAML file at /etc/config/ip-masq-agent + - key: config + path: ip-masq-agent diff --git a/cluster/gce/gci/configure-helper.sh b/cluster/gce/gci/configure-helper.sh index f6c63049730..5e18fcc3b40 100644 --- a/cluster/gce/gci/configure-helper.sh +++ b/cluster/gce/gci/configure-helper.sh @@ -1423,6 +1423,9 @@ function start-kube-addons { if [[ "${ENABLE_DEFAULT_STORAGE_CLASS:-}" == "true" ]]; then setup-addon-manifests "addons" "storage-class/gce" fi + if [[ "${NON_MASQUERADE_CIDR:-}" == "0.0.0.0/0" ]]; then + setup-addon-manifests "addons" "ip-masq-agent" + fi # Place addon manager pod manifest. cp "${src_dir}/kube-addon-manager.yaml" /etc/kubernetes/manifests