mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-28 14:07:14 +00:00
Merge pull request #6813 from vmarmol/in-container
Run Kubelet and Kube-proxy in resource-only containers.
This commit is contained in:
commit
d912398d07
@ -44,6 +44,7 @@ type ProxyServer struct {
|
|||||||
HealthzPort int
|
HealthzPort int
|
||||||
HealthzBindAddress util.IP
|
HealthzBindAddress util.IP
|
||||||
OOMScoreAdj int
|
OOMScoreAdj int
|
||||||
|
ResourceContainer string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewProxyServer creates a new ProxyServer object with default parameters
|
// NewProxyServer creates a new ProxyServer object with default parameters
|
||||||
@ -53,6 +54,7 @@ func NewProxyServer() *ProxyServer {
|
|||||||
HealthzPort: 10249,
|
HealthzPort: 10249,
|
||||||
HealthzBindAddress: util.IP(net.ParseIP("127.0.0.1")),
|
HealthzBindAddress: util.IP(net.ParseIP("127.0.0.1")),
|
||||||
OOMScoreAdj: -899,
|
OOMScoreAdj: -899,
|
||||||
|
ResourceContainer: "/kube-proxy",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,14 +65,23 @@ func (s *ProxyServer) AddFlags(fs *pflag.FlagSet) {
|
|||||||
fs.IntVar(&s.HealthzPort, "healthz_port", s.HealthzPort, "The port to bind the health check server. Use 0 to disable.")
|
fs.IntVar(&s.HealthzPort, "healthz_port", s.HealthzPort, "The port to bind the health check server. Use 0 to disable.")
|
||||||
fs.Var(&s.HealthzBindAddress, "healthz_bind_address", "The IP address for the health check server to serve on, defaulting to 127.0.0.1 (set to 0.0.0.0 for all interfaces)")
|
fs.Var(&s.HealthzBindAddress, "healthz_bind_address", "The IP address for the health check server to serve on, defaulting to 127.0.0.1 (set to 0.0.0.0 for all interfaces)")
|
||||||
fs.IntVar(&s.OOMScoreAdj, "oom_score_adj", s.OOMScoreAdj, "The oom_score_adj value for kube-proxy process. Values must be within the range [-1000, 1000]")
|
fs.IntVar(&s.OOMScoreAdj, "oom_score_adj", s.OOMScoreAdj, "The oom_score_adj value for kube-proxy process. Values must be within the range [-1000, 1000]")
|
||||||
|
fs.StringVar(&s.ResourceContainer, "resource_container", s.ResourceContainer, "Absolute name of the resource-only container to create and run the Kube-proxy in (Default: /kube-proxy).")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the specified ProxyServer. This should never exit.
|
// Run runs the specified ProxyServer. This should never exit.
|
||||||
func (s *ProxyServer) Run(_ []string) error {
|
func (s *ProxyServer) Run(_ []string) error {
|
||||||
|
// TODO(vmarmol): Use container config for this.
|
||||||
if err := util.ApplyOomScoreAdj(0, s.OOMScoreAdj); err != nil {
|
if err := util.ApplyOomScoreAdj(0, s.OOMScoreAdj); err != nil {
|
||||||
glog.Info(err)
|
glog.Info(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run in its own container.
|
||||||
|
if err := util.RunInResourceContainer(s.ResourceContainer); err != nil {
|
||||||
|
glog.Warningf("Failed to start in resource-only container %q: %v", s.ResourceContainer, err)
|
||||||
|
} else {
|
||||||
|
glog.Infof("Running in resource-only container %q", s.ResourceContainer)
|
||||||
|
}
|
||||||
|
|
||||||
serviceConfig := config.NewServiceConfig()
|
serviceConfig := config.NewServiceConfig()
|
||||||
endpointsConfig := config.NewEndpointsConfig()
|
endpointsConfig := config.NewEndpointsConfig()
|
||||||
|
|
||||||
|
@ -96,6 +96,7 @@ type KubeletServer struct {
|
|||||||
TLSPrivateKeyFile string
|
TLSPrivateKeyFile string
|
||||||
CertDirectory string
|
CertDirectory string
|
||||||
NodeStatusUpdateFrequency time.Duration
|
NodeStatusUpdateFrequency time.Duration
|
||||||
|
ResourceContainer string
|
||||||
|
|
||||||
// Flags intended for testing
|
// Flags intended for testing
|
||||||
|
|
||||||
@ -147,6 +148,7 @@ func NewKubeletServer() *KubeletServer {
|
|||||||
HostNetworkSources: kubelet.FileSource,
|
HostNetworkSources: kubelet.FileSource,
|
||||||
CertDirectory: "/var/run/kubernetes",
|
CertDirectory: "/var/run/kubernetes",
|
||||||
NodeStatusUpdateFrequency: 10 * time.Second,
|
NodeStatusUpdateFrequency: 10 * time.Second,
|
||||||
|
ResourceContainer: "/kubelet",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,6 +198,7 @@ func (s *KubeletServer) AddFlags(fs *pflag.FlagSet) {
|
|||||||
fs.StringVar(&s.NetworkPluginName, "network_plugin", s.NetworkPluginName, "<Warning: Alpha feature> The name of the network plugin to be invoked for various events in kubelet/pod lifecycle")
|
fs.StringVar(&s.NetworkPluginName, "network_plugin", s.NetworkPluginName, "<Warning: Alpha feature> The name of the network plugin to be invoked for various events in kubelet/pod lifecycle")
|
||||||
fs.StringVar(&s.CloudProvider, "cloud_provider", s.CloudProvider, "The provider for cloud services. Empty string for no provider.")
|
fs.StringVar(&s.CloudProvider, "cloud_provider", s.CloudProvider, "The provider for cloud services. Empty string for no provider.")
|
||||||
fs.StringVar(&s.CloudConfigFile, "cloud_config", s.CloudConfigFile, "The path to the cloud provider configuration file. Empty string for no configuration file.")
|
fs.StringVar(&s.CloudConfigFile, "cloud_config", s.CloudConfigFile, "The path to the cloud provider configuration file. Empty string for no configuration file.")
|
||||||
|
fs.StringVar(&s.ResourceContainer, "resource_container", s.ResourceContainer, "Absolute name of the resource-only container to create and run the Kubelet in (Default: /kubelet).")
|
||||||
|
|
||||||
// Flags intended for testing, not recommended used in production environments.
|
// Flags intended for testing, not recommended used in production environments.
|
||||||
fs.BoolVar(&s.ReallyCrashForTesting, "really_crash_for_testing", s.ReallyCrashForTesting, "If true, when panics occur crash. Intended for testing.")
|
fs.BoolVar(&s.ReallyCrashForTesting, "really_crash_for_testing", s.ReallyCrashForTesting, "If true, when panics occur crash. Intended for testing.")
|
||||||
@ -207,6 +210,7 @@ func (s *KubeletServer) Run(_ []string) error {
|
|||||||
util.ReallyCrash = s.ReallyCrashForTesting
|
util.ReallyCrash = s.ReallyCrashForTesting
|
||||||
rand.Seed(time.Now().UTC().UnixNano())
|
rand.Seed(time.Now().UTC().UnixNano())
|
||||||
|
|
||||||
|
// TODO(vmarmol): Do this through container config.
|
||||||
if err := util.ApplyOomScoreAdj(0, s.OOMScoreAdj); err != nil {
|
if err := util.ApplyOomScoreAdj(0, s.OOMScoreAdj); err != nil {
|
||||||
glog.Info(err)
|
glog.Info(err)
|
||||||
}
|
}
|
||||||
@ -293,6 +297,7 @@ func (s *KubeletServer) Run(_ []string) error {
|
|||||||
ImageGCPolicy: imageGCPolicy,
|
ImageGCPolicy: imageGCPolicy,
|
||||||
Cloud: cloud,
|
Cloud: cloud,
|
||||||
NodeStatusUpdateFrequency: s.NodeStatusUpdateFrequency,
|
NodeStatusUpdateFrequency: s.NodeStatusUpdateFrequency,
|
||||||
|
ResourceContainer: s.ResourceContainer,
|
||||||
}
|
}
|
||||||
|
|
||||||
RunKubelet(&kcfg, nil)
|
RunKubelet(&kcfg, nil)
|
||||||
@ -412,6 +417,7 @@ func SimpleKubelet(client *client.Client,
|
|||||||
ImageGCPolicy: imageGCPolicy,
|
ImageGCPolicy: imageGCPolicy,
|
||||||
Cloud: cloud,
|
Cloud: cloud,
|
||||||
NodeStatusUpdateFrequency: 10 * time.Second,
|
NodeStatusUpdateFrequency: 10 * time.Second,
|
||||||
|
ResourceContainer: "/kubelet",
|
||||||
}
|
}
|
||||||
return &kcfg
|
return &kcfg
|
||||||
}
|
}
|
||||||
@ -534,6 +540,7 @@ type KubeletConfig struct {
|
|||||||
ImageGCPolicy kubelet.ImageGCPolicy
|
ImageGCPolicy kubelet.ImageGCPolicy
|
||||||
Cloud cloudprovider.Interface
|
Cloud cloudprovider.Interface
|
||||||
NodeStatusUpdateFrequency time.Duration
|
NodeStatusUpdateFrequency time.Duration
|
||||||
|
ResourceContainer string
|
||||||
}
|
}
|
||||||
|
|
||||||
func createAndInitKubelet(kc *KubeletConfig) (k KubeletBootstrap, pc *config.PodConfig, err error) {
|
func createAndInitKubelet(kc *KubeletConfig) (k KubeletBootstrap, pc *config.PodConfig, err error) {
|
||||||
@ -576,7 +583,8 @@ func createAndInitKubelet(kc *KubeletConfig) (k KubeletBootstrap, pc *config.Pod
|
|||||||
kc.CadvisorInterface,
|
kc.CadvisorInterface,
|
||||||
kc.ImageGCPolicy,
|
kc.ImageGCPolicy,
|
||||||
kc.Cloud,
|
kc.Cloud,
|
||||||
kc.NodeStatusUpdateFrequency)
|
kc.NodeStatusUpdateFrequency,
|
||||||
|
kc.ResourceContainer)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
@ -122,7 +122,8 @@ func NewMainKubelet(
|
|||||||
cadvisorInterface cadvisor.Interface,
|
cadvisorInterface cadvisor.Interface,
|
||||||
imageGCPolicy ImageGCPolicy,
|
imageGCPolicy ImageGCPolicy,
|
||||||
cloud cloudprovider.Interface,
|
cloud cloudprovider.Interface,
|
||||||
nodeStatusUpdateFrequency time.Duration) (*Kubelet, error) {
|
nodeStatusUpdateFrequency time.Duration,
|
||||||
|
resourceContainer string) (*Kubelet, error) {
|
||||||
if rootDirectory == "" {
|
if rootDirectory == "" {
|
||||||
return nil, fmt.Errorf("invalid root directory %q", rootDirectory)
|
return nil, fmt.Errorf("invalid root directory %q", rootDirectory)
|
||||||
}
|
}
|
||||||
@ -228,6 +229,7 @@ func NewMainKubelet(
|
|||||||
nodeRef: nodeRef,
|
nodeRef: nodeRef,
|
||||||
containerManager: containerManager,
|
containerManager: containerManager,
|
||||||
nodeStatusUpdateFrequency: nodeStatusUpdateFrequency,
|
nodeStatusUpdateFrequency: nodeStatusUpdateFrequency,
|
||||||
|
resourceContainer: resourceContainer,
|
||||||
}
|
}
|
||||||
|
|
||||||
klet.podManager = newBasicPodManager(klet.kubeClient)
|
klet.podManager = newBasicPodManager(klet.kubeClient)
|
||||||
@ -358,6 +360,10 @@ type Kubelet struct {
|
|||||||
// status. Kubelet may fail to update node status reliablly if the value is too small,
|
// status. Kubelet may fail to update node status reliablly if the value is too small,
|
||||||
// as it takes time to gather all necessary node information.
|
// as it takes time to gather all necessary node information.
|
||||||
nodeStatusUpdateFrequency time.Duration
|
nodeStatusUpdateFrequency time.Duration
|
||||||
|
|
||||||
|
// The name of the resource-only container to run the Kubelet in (empty for no container).
|
||||||
|
// Name must be absolute.
|
||||||
|
resourceContainer string
|
||||||
}
|
}
|
||||||
|
|
||||||
// getRootDir returns the full path to the directory under which kubelet can
|
// getRootDir returns the full path to the directory under which kubelet can
|
||||||
@ -536,6 +542,16 @@ func (kl *Kubelet) Run(updates <-chan PodUpdate) {
|
|||||||
if kl.kubeClient == nil {
|
if kl.kubeClient == nil {
|
||||||
glog.Warning("No api server defined - no node status update will be sent.")
|
glog.Warning("No api server defined - no node status update will be sent.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Move Kubelet to a container.
|
||||||
|
if kl.resourceContainer != "" {
|
||||||
|
err := util.RunInResourceContainer(kl.resourceContainer)
|
||||||
|
if err != nil {
|
||||||
|
glog.Warningf("Failed to move Kubelet to container %q: %v", kl.resourceContainer, err)
|
||||||
|
}
|
||||||
|
glog.Infof("Running in container %q", kl.resourceContainer)
|
||||||
|
}
|
||||||
|
|
||||||
go kl.syncNodeStatus()
|
go kl.syncNodeStatus()
|
||||||
kl.statusManager.Start()
|
kl.statusManager.Start()
|
||||||
kl.syncLoop(updates, kl)
|
kl.syncLoop(updates, kl)
|
||||||
|
41
pkg/util/resource_container_linux.go
Normal file
41
pkg/util/resource_container_linux.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2015 Google Inc. All rights reserved.
|
||||||
|
|
||||||
|
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 util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/docker/libcontainer/cgroups/fs"
|
||||||
|
"github.com/docker/libcontainer/configs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Creates resource-only containerName if it does not already exist and moves
|
||||||
|
// the current process to it.
|
||||||
|
//
|
||||||
|
// containerName must be an absolute container name.
|
||||||
|
func RunInResourceContainer(containerName string) error {
|
||||||
|
manager := fs.Manager{
|
||||||
|
Cgroups: &configs.Cgroup{
|
||||||
|
Name: containerName,
|
||||||
|
AllowAllDevices: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return manager.Apply(os.Getpid())
|
||||||
|
}
|
27
pkg/util/resource_container_unsupported.go
Normal file
27
pkg/util/resource_container_unsupported.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// +build !linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2015 Google Inc. All rights reserved.
|
||||||
|
|
||||||
|
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 util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RunInResourceContainer(containerName string) error {
|
||||||
|
return errors.New("resource-only containers unsupported in this platform")
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user