Merge pull request #3817 from mrunalp/feature/shared_ipc

Shared IPC namespace for containers in a pod
pull/6/head
Tim Hockin 2015-01-27 15:41:34 -08:00
commit 7e6f3af937
6 changed files with 116 additions and 110 deletions

View File

@ -50,7 +50,7 @@ var (
address = util.IP(net.ParseIP("127.0.0.1"))
port = flag.Uint("port", ports.KubeletPort, "The port for the info server to serve on")
hostnameOverride = flag.String("hostname_override", "", "If non-empty, will use this string as identification instead of the actual hostname.")
networkContainerImage = flag.String("network_container_image", kubelet.NetworkContainerImage, "The image that network containers in each pod will use.")
podInfraContainerImage = flag.String("pod_infra_container_image", kubelet.PodInfraContainerImage, "The image whose network/ipc namespaces containers in each pod will use.")
dockerEndpoint = flag.String("docker_endpoint", "", "If non-empty, use this for the docker endpoint to communicate with")
etcdServerList util.StringList
etcdConfigFile = flag.String("etcd_config", "", "The config file for the etcd client. Mutually exclusive with -etcd_servers")
@ -136,7 +136,7 @@ func main() {
ManifestURL: *manifestURL,
FileCheckFrequency: *fileCheckFrequency,
HttpCheckFrequency: *httpCheckFrequency,
NetworkContainerImage: *networkContainerImage,
PodInfraContainerImage: *podInfraContainerImage,
SyncFrequency: *syncFrequency,
RegistryPullQPS: *registryPullQPS,
RegistryBurst: *registryBurst,

View File

@ -37,6 +37,10 @@ import (
"github.com/golang/glog"
)
const (
PodInfraContainerName = "POD" // This should match the constant defined in kubelet
)
// DockerInterface is an abstract interface for testability. It abstracts the interface of docker.Client.
type DockerInterface interface {
ListContainers(options docker.ListContainersOptions) ([]docker.APIContainers, error)
@ -372,8 +376,8 @@ var (
// ErrNoContainersInPod is returned when there are no containers for a given pod
ErrNoContainersInPod = errors.New("no containers exist for this pod")
// ErrNoNetworkContainerInPod is returned when there is no network container for a given pod
ErrNoNetworkContainerInPod = errors.New("No network container exists for this pod")
// ErrNoPodInfraContainerInPod is returned when there is no pod infra container for a given pod
ErrNoPodInfraContainerInPod = errors.New("No pod infra container exists for this pod")
// ErrContainerCannotRun is returned when a container is created, but cannot run properly
ErrContainerCannotRun = errors.New("Container cannot run")
@ -401,7 +405,7 @@ func inspectContainer(client DockerInterface, dockerID, containerName, tPath str
containerStatus.State.Running = &api.ContainerStateRunning{
StartedAt: util.NewTime(inspectResult.State.StartedAt),
}
if containerName == "net" && inspectResult.NetworkSettings != nil {
if containerName == PodInfraContainerName && inspectResult.NetworkSettings != nil {
containerStatus.PodIP = inspectResult.NetworkSettings.IPAddress
}
waiting = false
@ -454,7 +458,7 @@ func GetDockerPodInfo(client DockerInterface, manifest api.PodSpec, podFullName
for _, container := range manifest.Containers {
expectedContainers[container.Name] = container
}
expectedContainers["net"] = api.Container{}
expectedContainers[PodInfraContainerName] = api.Container{}
containers, err := client.ListContainers(docker.ListContainersOptions{All: true})
if err != nil {
@ -498,9 +502,9 @@ func GetDockerPodInfo(client DockerInterface, manifest api.PodSpec, podFullName
return nil, ErrNoContainersInPod
}
// First make sure we are not missing network container
if _, found := info["net"]; !found {
return nil, ErrNoNetworkContainerInPod
// First make sure we are not missing pod infra container
if _, found := info[PodInfraContainerName]; !found {
return nil, ErrNoPodInfraContainerInPod
}
if len(info) < (len(manifest.Containers) + 1) {

View File

@ -24,6 +24,7 @@ import (
"strconv"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/dockertools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/types"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/golang/glog"
@ -77,7 +78,7 @@ func (h *httpActionHandler) Run(podFullName string, uid types.UID, container *ap
glog.Errorf("unable to get pod info, event handlers may be invalid.")
return err
}
netInfo, found := status.Info[networkContainerName]
netInfo, found := status.Info[dockertools.PodInfraContainerName]
if found {
host = netInfo.PodIP
} else {

View File

@ -72,7 +72,7 @@ func NewMainKubelet(
etcdClient tools.EtcdClient,
kubeClient *client.Client,
rootDirectory string,
networkContainerImage string,
podInfraContainerImage string,
resyncInterval time.Duration,
pullQPS float32,
pullBurst int,
@ -106,7 +106,7 @@ func NewMainKubelet(
kubeClient: kubeClient,
rootDirectory: rootDirectory,
resyncInterval: resyncInterval,
networkContainerImage: networkContainerImage,
podInfraContainerImage: podInfraContainerImage,
podWorkers: newPodWorkers(),
dockerIDToRef: map[dockertools.DockerID]*api.ObjectReference{},
runner: dockertools.NewDockerContainerCommandRunner(dockerClient),
@ -142,15 +142,15 @@ type serviceLister interface {
// Kubelet is the main kubelet implementation.
type Kubelet struct {
hostname string
dockerClient dockertools.DockerInterface
kubeClient *client.Client
rootDirectory string
networkContainerImage string
podWorkers *podWorkers
resyncInterval time.Duration
pods []api.BoundPod
sourceReady SourceReadyFn
hostname string
dockerClient dockertools.DockerInterface
kubeClient *client.Client
rootDirectory string
podInfraContainerImage string
podWorkers *podWorkers
resyncInterval time.Duration
pods []api.BoundPod
sourceReady SourceReadyFn
// Needed to report events for containers belonging to deleted/modified pods.
// Tracks references for reporting events
@ -583,7 +583,7 @@ func containerRef(pod *api.BoundPod, container *api.Container) (*api.ObjectRefer
fieldPath, err := fieldPath(pod, container)
if err != nil {
// TODO: figure out intelligent way to refer to containers that we implicitly
// start (like the network container). This is not a good way, ugh.
// start (like the pod infra container). This is not a good way, ugh.
fieldPath = "implicitly required container " + container.Name
}
ref, err := api.GetPartialReference(pod, fieldPath)
@ -619,7 +619,7 @@ func (kl *Kubelet) getRef(id dockertools.DockerID) (ref *api.ObjectReference, ok
}
// Run a single container from a pod. Returns the docker container ID
func (kl *Kubelet) runContainer(pod *api.BoundPod, container *api.Container, podVolumes volumeMap, netMode string) (id dockertools.DockerID, err error) {
func (kl *Kubelet) runContainer(pod *api.BoundPod, container *api.Container, podVolumes volumeMap, netMode, ipcMode string) (id dockertools.DockerID, err error) {
ref, err := containerRef(pod, container)
if err != nil {
glog.Errorf("Couldn't make a ref to pod %v, container %v: '%v'", pod.Name, container.Name, err)
@ -684,6 +684,7 @@ func (kl *Kubelet) runContainer(pod *api.BoundPod, container *api.Container, pod
PortBindings: portBindings,
Binds: binds,
NetworkMode: netMode,
IpcMode: ipcMode,
Privileged: privileged,
}
if pod.Spec.DNSPolicy == api.DNSClusterFirst {
@ -878,21 +879,20 @@ func (kl *Kubelet) killContainerByID(ID, name string) error {
}
const (
networkContainerName = "net"
NetworkContainerImage = "kubernetes/pause:latest"
PodInfraContainerImage = "kubernetes/pause:latest"
)
// createNetworkContainer starts the network container for a pod. Returns the docker container ID of the newly created container.
func (kl *Kubelet) createNetworkContainer(pod *api.BoundPod) (dockertools.DockerID, error) {
// createPodInfraContainer starts the pod infra container for a pod. Returns the docker container ID of the newly created container.
func (kl *Kubelet) createPodInfraContainer(pod *api.BoundPod) (dockertools.DockerID, error) {
var ports []api.Port
// Docker only exports ports from the network container. Let's
// Docker only exports ports from the pod infra container. Let's
// collect all of the relevant ports and export them.
for _, container := range pod.Spec.Containers {
ports = append(ports, container.Ports...)
}
container := &api.Container{
Name: networkContainerName,
Image: kl.networkContainerImage,
Name: dockertools.PodInfraContainerName,
Image: kl.podInfraContainerImage,
Ports: ports,
}
ref, err := containerRef(pod, container)
@ -915,7 +915,7 @@ func (kl *Kubelet) createNetworkContainer(pod *api.BoundPod) (dockertools.Docker
if ref != nil {
record.Eventf(ref, "pulled", "Successfully pulled image %q", container.Image)
}
return kl.runContainer(pod, container, nil, "")
return kl.runContainer(pod, container, nil, "", "")
}
func (kl *Kubelet) pullImage(img string, ref *api.ObjectReference) error {
@ -987,19 +987,19 @@ func (kl *Kubelet) syncPod(pod *api.BoundPod, dockerContainers dockertools.Docke
return err
}
// Make sure we have a network container
var netID dockertools.DockerID
if netDockerContainer, found, _ := dockerContainers.FindPodContainer(podFullName, uid, networkContainerName); found {
netID = dockertools.DockerID(netDockerContainer.ID)
// Make sure we have a pod infra container
var podInfraContainerID dockertools.DockerID
if podInfraDockerContainer, found, _ := dockerContainers.FindPodContainer(podFullName, uid, dockertools.PodInfraContainerName); found {
podInfraContainerID = dockertools.DockerID(podInfraDockerContainer.ID)
} else {
glog.V(2).Infof("Network container doesn't exist for pod %q, killing and re-creating the pod", podFullName)
count, err := kl.killContainersInPod(pod, dockerContainers)
if err != nil {
return err
}
netID, err = kl.createNetworkContainer(pod)
podInfraContainerID, err = kl.createPodInfraContainer(pod)
if err != nil {
glog.Errorf("Failed to introspect network container: %v; Skipping pod %q", err, podFullName)
glog.Errorf("Failed to introspect pod infra container: %v; Skipping pod %q", err, podFullName)
return err
}
if count > 0 {
@ -1011,7 +1011,7 @@ func (kl *Kubelet) syncPod(pod *api.BoundPod, dockerContainers dockertools.Docke
}
}
}
containersToKeep[netID] = empty{}
containersToKeep[podInfraContainerID] = empty{}
podVolumes, err := kl.mountExternalVolumes(pod)
if err != nil {
@ -1023,7 +1023,7 @@ func (kl *Kubelet) syncPod(pod *api.BoundPod, dockerContainers dockertools.Docke
if err != nil {
glog.Errorf("Unable to get pod with name %q and uid %q info, health checks may be invalid", podFullName, uid)
}
netInfo, found := podStatus.Info[networkContainerName]
netInfo, found := podStatus.Info[dockertools.PodInfraContainerName]
if found {
podStatus.PodIP = netInfo.PodIP
}
@ -1058,10 +1058,10 @@ func (kl *Kubelet) syncPod(pod *api.BoundPod, dockerContainers dockertools.Docke
}
killedContainers[containerID] = empty{}
// Also kill associated network container
if netContainer, found, _ := dockerContainers.FindPodContainer(podFullName, uid, networkContainerName); found {
if err := kl.killContainer(netContainer); err != nil {
glog.V(1).Infof("Failed to kill network container %q: %v", netContainer.ID, err)
// Also kill associated pod infra container
if podInfraContainer, found, _ := dockerContainers.FindPodContainer(podFullName, uid, dockertools.PodInfraContainerName); found {
if err := kl.killContainer(podInfraContainer); err != nil {
glog.V(1).Infof("Failed to kill pod infra container %q: %v", podInfraContainer.ID, err)
continue
}
}
@ -1112,7 +1112,8 @@ func (kl *Kubelet) syncPod(pod *api.BoundPod, dockerContainers dockertools.Docke
}
}
// TODO(dawnchen): Check RestartPolicy.DelaySeconds before restart a container
containerID, err := kl.runContainer(pod, &container, podVolumes, "container:"+string(netID))
namespaceMode := fmt.Sprintf("container:%v", podInfraContainerID)
containerID, err := kl.runContainer(pod, &container, podVolumes, namespaceMode, namespaceMode)
if err != nil {
// TODO(bburns) : Perhaps blacklist a container after N failures?
glog.Errorf("Error running pod %q container %q: %v", podFullName, container.Name, err)
@ -1222,7 +1223,7 @@ func (kl *Kubelet) SyncPods(pods []api.BoundPod) error {
desiredPods[uid] = empty{}
// Add all containers (including net) to the map.
desiredContainers[podContainer{podFullName, uid, networkContainerName}] = empty{}
desiredContainers[podContainer{podFullName, uid, dockertools.PodInfraContainerName}] = empty{}
for _, cont := range pod.Spec.Containers {
desiredContainers[podContainer{podFullName, uid, cont.Name}] = empty{}
}

View File

@ -336,8 +336,8 @@ func TestSyncPodsDoesNothing(t *testing.T) {
ID: "1234",
},
{
// network container
Names: []string{"/k8s_net_foo.new.test_12345678_0"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_12345678_0"},
ID: "9876",
},
}
@ -426,7 +426,7 @@ func matchString(t *testing.T, pattern, str string) bool {
func TestSyncPodsCreatesNetAndContainer(t *testing.T) {
kubelet, fakeDocker := newTestKubelet(t)
kubelet.networkContainerImage = "custom_image_name"
kubelet.podInfraContainerImage = "custom_image_name"
fakeDocker.ContainerList = []docker.APIContainers{}
err := kubelet.SyncPods([]api.BoundPod{
{
@ -455,7 +455,7 @@ func TestSyncPodsCreatesNetAndContainer(t *testing.T) {
found := false
for _, c := range fakeDocker.ContainerList {
if c.Image == "custom_image_name" && strings.HasPrefix(c.Names[0], "/k8s_net") {
if c.Image == "custom_image_name" && strings.HasPrefix(c.Names[0], "/k8s_POD") {
found = true
}
}
@ -464,7 +464,7 @@ func TestSyncPodsCreatesNetAndContainer(t *testing.T) {
}
if len(fakeDocker.Created) != 2 ||
!matchString(t, "k8s_net\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[0]) ||
!matchString(t, "k8s_POD\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[0]) ||
!matchString(t, "k8s_bar\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[1]) {
t.Errorf("Unexpected containers created %v", fakeDocker.Created)
}
@ -475,7 +475,7 @@ func TestSyncPodsCreatesNetAndContainerPullsImage(t *testing.T) {
kubelet, fakeDocker := newTestKubelet(t)
puller := kubelet.dockerPuller.(*dockertools.FakeDockerPuller)
puller.HasImages = []string{}
kubelet.networkContainerImage = "custom_image_name"
kubelet.podInfraContainerImage = "custom_image_name"
fakeDocker.ContainerList = []docker.APIContainers{}
err := kubelet.SyncPods([]api.BoundPod{
{
@ -507,7 +507,7 @@ func TestSyncPodsCreatesNetAndContainerPullsImage(t *testing.T) {
}
if len(fakeDocker.Created) != 2 ||
!matchString(t, "k8s_net\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[0]) ||
!matchString(t, "k8s_POD\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[0]) ||
!matchString(t, "k8s_bar\\.[a-f0-9]+_foo.new.test_", fakeDocker.Created[1]) {
t.Errorf("Unexpected containers created %v", fakeDocker.Created)
}
@ -518,8 +518,8 @@ func TestSyncPodsWithNetCreatesContainer(t *testing.T) {
kubelet, fakeDocker := newTestKubelet(t)
fakeDocker.ContainerList = []docker.APIContainers{
{
// network container
Names: []string{"/k8s_net_foo.new.test_12345678_0"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_12345678_0"},
ID: "9876",
},
}
@ -560,8 +560,8 @@ func TestSyncPodsWithNetCreatesContainerCallsHandler(t *testing.T) {
kubelet.httpClient = &fakeHttp
fakeDocker.ContainerList = []docker.APIContainers{
{
// network container
Names: []string{"/k8s_net_foo.new.test_12345678_0"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_12345678_0"},
ID: "9876",
},
}
@ -666,8 +666,8 @@ func TestSyncPodsDeletesWhenSourcesAreReady(t *testing.T) {
ID: "1234",
},
{
// network container
Names: []string{"/k8s_net_foo.new.test_12345678_42"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_12345678_42"},
ID: "9876",
},
}
@ -714,8 +714,8 @@ func TestSyncPodsDeletesWhenContainerSourceReady(t *testing.T) {
ID: "7492",
},
{
// network container
Names: []string{"/k8s_net_boo.default.testSource_12345678_42"},
// pod infra container
Names: []string{"/k8s_POD_boo.default.testSource_12345678_42"},
ID: "3542",
},
@ -725,8 +725,8 @@ func TestSyncPodsDeletesWhenContainerSourceReady(t *testing.T) {
ID: "1234",
},
{
// network container
Names: []string{"/k8s_net_foo.new.otherSource_12345678_42"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.otherSource_12345678_42"},
ID: "9876",
},
}
@ -767,8 +767,8 @@ func TestSyncPodsDeletes(t *testing.T) {
ID: "1234",
},
{
// network container
Names: []string{"/k8s_net_foo.new.test_12345678_42"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_12345678_42"},
ID: "9876",
},
{
@ -805,8 +805,8 @@ func TestSyncPodDeletesDuplicate(t *testing.T) {
ID: "1234",
},
"9876": &docker.APIContainers{
// network container
Names: []string{"/k8s_net_bar.new.test_12345678_2222"},
// pod infra container
Names: []string{"/k8s_POD_bar.new.test_12345678_2222"},
ID: "9876",
},
"4567": &docker.APIContainers{
@ -865,8 +865,8 @@ func TestSyncPodBadHash(t *testing.T) {
ID: "1234",
},
"9876": &docker.APIContainers{
// network container
Names: []string{"/k8s_net_foo.new.test_12345678_42"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_12345678_42"},
ID: "9876",
},
}
@ -912,8 +912,8 @@ func TestSyncPodUnhealthy(t *testing.T) {
ID: "1234",
},
"9876": &docker.APIContainers{
// network container
Names: []string{"/k8s_net_foo.new.test_12345678_42"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_12345678_42"},
ID: "9876",
},
}
@ -1559,8 +1559,8 @@ func TestSyncPodEventHandlerFails(t *testing.T) {
}
dockerContainers := dockertools.DockerContainers{
"9876": &docker.APIContainers{
// network container
Names: []string{"/k8s_net_foo.new.test_12345678_42"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_12345678_42"},
ID: "9876",
},
}
@ -1607,33 +1607,33 @@ func TestKubeletGarbageCollection(t *testing.T) {
{
containers: []docker.APIContainers{
{
// network container
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
ID: "1876",
},
{
// network container
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
ID: "2876",
},
{
// network container
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
ID: "3876",
},
{
// network container
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
ID: "4876",
},
{
// network container
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
ID: "5876",
},
{
// network container
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
ID: "6876",
},
},
@ -1651,38 +1651,38 @@ func TestKubeletGarbageCollection(t *testing.T) {
{
containers: []docker.APIContainers{
{
// network container
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
ID: "1876",
},
{
// network container
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
ID: "2876",
},
{
// network container
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
ID: "3876",
},
{
// network container
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
ID: "4876",
},
{
// network container
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
ID: "5876",
},
{
// network container
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
ID: "6876",
},
{
// network container
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
ID: "7876",
},
},
@ -1707,8 +1707,8 @@ func TestKubeletGarbageCollection(t *testing.T) {
{
containers: []docker.APIContainers{
{
// network container
Names: []string{"/k8s_net_foo.new.test_.deadbeef_42"},
// pod infra container
Names: []string{"/k8s_POD_foo.new.test_.deadbeef_42"},
ID: "1876",
},
},
@ -1896,7 +1896,7 @@ func TestSyncPodsWithPullPolicy(t *testing.T) {
kubelet, fakeDocker := newTestKubelet(t)
puller := kubelet.dockerPuller.(*dockertools.FakeDockerPuller)
puller.HasImages = []string{"existing_one", "want:latest"}
kubelet.networkContainerImage = "custom_image_name"
kubelet.podInfraContainerImage = "custom_image_name"
fakeDocker.ContainerList = []docker.APIContainers{}
err := kubelet.SyncPods([]api.BoundPod{
{

View File

@ -153,13 +153,13 @@ func SimpleRunKubelet(client *client.Client,
masterServiceNamespace string,
volumePlugins []volume.Plugin) {
kcfg := KubeletConfig{
KubeClient: client,
EtcdClient: etcdClient,
DockerClient: dockerClient,
HostnameOverride: hostname,
RootDirectory: rootDir,
ManifestURL: manifestURL,
NetworkContainerImage: kubelet.NetworkContainerImage,
KubeClient: client,
EtcdClient: etcdClient,
DockerClient: dockerClient,
HostnameOverride: hostname,
RootDirectory: rootDir,
ManifestURL: manifestURL,
PodInfraContainerImage: kubelet.PodInfraContainerImage,
Port: port,
Address: util.IP(net.ParseIP(address)),
EnableServer: true,
@ -256,7 +256,7 @@ type KubeletConfig struct {
FileCheckFrequency time.Duration
HttpCheckFrequency time.Duration
Hostname string
NetworkContainerImage string
PodInfraContainerImage string
SyncFrequency time.Duration
RegistryPullQPS float64
RegistryBurst int
@ -282,7 +282,7 @@ func createAndInitKubelet(kc *KubeletConfig, pc *config.PodConfig) (*kubelet.Kub
kc.EtcdClient,
kc.KubeClient,
kc.RootDirectory,
kc.NetworkContainerImage,
kc.PodInfraContainerImage,
kc.SyncFrequency,
float32(kc.RegistryPullQPS),
kc.RegistryBurst,