mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-13 05:46:16 +00:00
kubelet: Add container reference manager.
Move the reference managing logic into container reference manager. This enables pluggable container runtime to manage the container references.
This commit is contained in:
parent
dc0fdcc6f4
commit
a06bc96414
87
pkg/kubelet/container_reference_manager.go
Normal file
87
pkg/kubelet/container_reference_manager.go
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2014 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 kubelet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ContainerRefManager manages the references for the containers.
|
||||||
|
// The references are used for reporting events such as creation,
|
||||||
|
// failure, etc. This manager is thread-safe, no locks are necessary
|
||||||
|
// for the caller.
|
||||||
|
type ContainerRefManager struct {
|
||||||
|
sync.RWMutex
|
||||||
|
// TODO(yifan): To use strong type.
|
||||||
|
containerIDToRef map[string]*api.ObjectReference
|
||||||
|
}
|
||||||
|
|
||||||
|
// newContainerRefManager creates and returns a container reference manager
|
||||||
|
// with empty contents.
|
||||||
|
func newContainerRefManager() *ContainerRefManager {
|
||||||
|
c := ContainerRefManager{}
|
||||||
|
c.containerIDToRef = make(map[string]*api.ObjectReference)
|
||||||
|
return &c
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetRef stores a reference to a pod's container, associating it with the given container id.
|
||||||
|
func (c *ContainerRefManager) SetRef(id string, ref *api.ObjectReference) {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
|
c.containerIDToRef[id] = ref
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearRef forgets the given container id and its associated container reference.
|
||||||
|
// TODO(yifan): This is currently never called. Consider to remove this function,
|
||||||
|
// or figure out when to clear the references.
|
||||||
|
func (c *ContainerRefManager) ClearRef(id string) {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
|
delete(c.containerIDToRef, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRef returns the container reference of the given id, or (nil, false) if none is stored.
|
||||||
|
func (c *ContainerRefManager) GetRef(id string) (ref *api.ObjectReference, ok bool) {
|
||||||
|
c.RLock()
|
||||||
|
defer c.RUnlock()
|
||||||
|
ref, ok = c.containerIDToRef[id]
|
||||||
|
return ref, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateContainerRef returns an *api.ObjectReference which references the given container within the
|
||||||
|
// given pod. Returns an error if the reference can't be constructed or the container doesn't
|
||||||
|
// actually belong to the pod.
|
||||||
|
// TODO: Pods that came to us by static config or over HTTP have no selfLink set, which makes
|
||||||
|
// this fail and log an error. Figure out how we want to identify these pods to the rest of the
|
||||||
|
// system.
|
||||||
|
// TODO(yifan): Revisit this function later, for current case, it does not need to use ContainerRefManager
|
||||||
|
// as a receiver, and does not need to be exported.
|
||||||
|
func (c *ContainerRefManager) GenerateContainerRef(pod *api.Pod, container *api.Container) (*api.ObjectReference, error) {
|
||||||
|
fieldPath, err := fieldPath(pod, container)
|
||||||
|
if err != nil {
|
||||||
|
// TODO: figure out intelligent way to refer to containers that we implicitly
|
||||||
|
// 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)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ref, nil
|
||||||
|
}
|
@ -218,7 +218,7 @@ func NewMainKubelet(
|
|||||||
rootDirectory: rootDirectory,
|
rootDirectory: rootDirectory,
|
||||||
resyncInterval: resyncInterval,
|
resyncInterval: resyncInterval,
|
||||||
podInfraContainerImage: podInfraContainerImage,
|
podInfraContainerImage: podInfraContainerImage,
|
||||||
containerIDToRef: map[string]*api.ObjectReference{},
|
containerRefManager: newContainerRefManager(),
|
||||||
runner: dockertools.NewDockerContainerCommandRunner(dockerClient),
|
runner: dockertools.NewDockerContainerCommandRunner(dockerClient),
|
||||||
httpClient: &http.Client{},
|
httpClient: &http.Client{},
|
||||||
pullQPS: pullQPS,
|
pullQPS: pullQPS,
|
||||||
@ -296,8 +296,7 @@ type Kubelet struct {
|
|||||||
|
|
||||||
// Needed to report events for containers belonging to deleted/modified pods.
|
// Needed to report events for containers belonging to deleted/modified pods.
|
||||||
// Tracks references for reporting events
|
// Tracks references for reporting events
|
||||||
containerIDToRef map[string]*api.ObjectReference
|
containerRefManager *ContainerRefManager
|
||||||
refLock sync.RWMutex
|
|
||||||
|
|
||||||
// Optional, defaults to simple Docker implementation
|
// Optional, defaults to simple Docker implementation
|
||||||
dockerPuller dockertools.DockerPuller
|
dockerPuller dockertools.DockerPuller
|
||||||
@ -685,54 +684,9 @@ func fieldPath(pod *api.Pod, container *api.Container) (string, error) {
|
|||||||
return "", fmt.Errorf("container %#v not found in pod %#v", container, pod)
|
return "", fmt.Errorf("container %#v not found in pod %#v", container, pod)
|
||||||
}
|
}
|
||||||
|
|
||||||
// containerRef returns an *api.ObjectReference which references the given container within the
|
|
||||||
// given pod. Returns an error if the reference can't be constructed or the container doesn't
|
|
||||||
// actually belong to the pod.
|
|
||||||
// TODO: Pods that came to us by static config or over HTTP have no selfLink set, which makes
|
|
||||||
// this fail and log an error. Figure out how we want to identify these pods to the rest of the
|
|
||||||
// system.
|
|
||||||
func containerRef(pod *api.Pod, container *api.Container) (*api.ObjectReference, error) {
|
|
||||||
fieldPath, err := fieldPath(pod, container)
|
|
||||||
if err != nil {
|
|
||||||
// TODO: figure out intelligent way to refer to containers that we implicitly
|
|
||||||
// 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)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return ref, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// setRef stores a reference to a pod's container, associating it with the given docker id.
|
|
||||||
func (kl *Kubelet) setRef(id string, ref *api.ObjectReference) {
|
|
||||||
kl.refLock.Lock()
|
|
||||||
defer kl.refLock.Unlock()
|
|
||||||
if kl.containerIDToRef == nil {
|
|
||||||
kl.containerIDToRef = map[string]*api.ObjectReference{}
|
|
||||||
}
|
|
||||||
kl.containerIDToRef[id] = ref
|
|
||||||
}
|
|
||||||
|
|
||||||
// clearRef forgets the given docker id and its associated container reference.
|
|
||||||
func (kl *Kubelet) clearRef(id string) {
|
|
||||||
kl.refLock.Lock()
|
|
||||||
defer kl.refLock.Unlock()
|
|
||||||
delete(kl.containerIDToRef, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// getRef returns the container reference of the given id, or (nil, false) if none is stored.
|
|
||||||
func (kl *Kubelet) getRef(id string) (ref *api.ObjectReference, ok bool) {
|
|
||||||
kl.refLock.RLock()
|
|
||||||
defer kl.refLock.RUnlock()
|
|
||||||
ref, ok = kl.containerIDToRef[id]
|
|
||||||
return ref, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run a single container from a pod. Returns the docker container ID
|
// Run a single container from a pod. Returns the docker container ID
|
||||||
func (kl *Kubelet) runContainer(pod *api.Pod, container *api.Container, podVolumes volumeMap, netMode, ipcMode string) (id dockertools.DockerID, err error) {
|
func (kl *Kubelet) runContainer(pod *api.Pod, container *api.Container, podVolumes volumeMap, netMode, ipcMode string) (id dockertools.DockerID, err error) {
|
||||||
ref, err := containerRef(pod, container)
|
ref, err := kl.containerRefManager.GenerateContainerRef(pod, container)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Couldn't make a ref to pod %v, container %v: '%v'", pod.Name, container.Name, err)
|
glog.Errorf("Couldn't make a ref to pod %v, container %v: '%v'", pod.Name, container.Name, err)
|
||||||
}
|
}
|
||||||
@ -773,7 +727,7 @@ func (kl *Kubelet) runContainer(pod *api.Pod, container *api.Container, podVolum
|
|||||||
}
|
}
|
||||||
// Remember this reference so we can report events about this container
|
// Remember this reference so we can report events about this container
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
kl.setRef(dockerContainer.ID, ref)
|
kl.containerRefManager.SetRef(dockerContainer.ID, ref)
|
||||||
kl.recorder.Eventf(ref, "created", "Created with docker id %v", dockerContainer.ID)
|
kl.recorder.Eventf(ref, "created", "Created with docker id %v", dockerContainer.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -993,7 +947,7 @@ func (kl *Kubelet) killContainerByID(ID string) error {
|
|||||||
kl.readiness.remove(ID)
|
kl.readiness.remove(ID)
|
||||||
err := kl.dockerClient.StopContainer(ID, 10)
|
err := kl.dockerClient.StopContainer(ID, 10)
|
||||||
|
|
||||||
ref, ok := kl.getRef(ID)
|
ref, ok := kl.containerRefManager.GetRef(ID)
|
||||||
if !ok {
|
if !ok {
|
||||||
glog.Warningf("No ref for pod '%v'", ID)
|
glog.Warningf("No ref for pod '%v'", ID)
|
||||||
} else {
|
} else {
|
||||||
@ -1043,7 +997,7 @@ func (kl *Kubelet) createPodInfraContainer(pod *api.Pod) (dockertools.DockerID,
|
|||||||
Image: kl.podInfraContainerImage,
|
Image: kl.podInfraContainerImage,
|
||||||
Ports: ports,
|
Ports: ports,
|
||||||
}
|
}
|
||||||
ref, err := containerRef(pod, container)
|
ref, err := kl.containerRefManager.GenerateContainerRef(pod, container)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Couldn't make a ref to pod %v, container %v: '%v'", pod.Name, container.Name, err)
|
glog.Errorf("Couldn't make a ref to pod %v, container %v: '%v'", pod.Name, container.Name, err)
|
||||||
}
|
}
|
||||||
@ -1201,7 +1155,7 @@ func (kl *Kubelet) getPodInfraContainer(podFullName string, uid types.UID,
|
|||||||
func (kl *Kubelet) pullImageAndRunContainer(pod *api.Pod, container *api.Container, podVolumes *volumeMap,
|
func (kl *Kubelet) pullImageAndRunContainer(pod *api.Pod, container *api.Container, podVolumes *volumeMap,
|
||||||
podInfraContainerID dockertools.DockerID) (dockertools.DockerID, error) {
|
podInfraContainerID dockertools.DockerID) (dockertools.DockerID, error) {
|
||||||
podFullName := kubecontainer.GetPodFullName(pod)
|
podFullName := kubecontainer.GetPodFullName(pod)
|
||||||
ref, err := containerRef(pod, container)
|
ref, err := kl.containerRefManager.GenerateContainerRef(pod, container)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Couldn't make a ref to pod %v, container %v: '%v'", pod.Name, container.Name, err)
|
glog.Errorf("Couldn't make a ref to pod %v, container %v: '%v'", pod.Name, container.Name, err)
|
||||||
}
|
}
|
||||||
|
@ -110,6 +110,7 @@ func newTestKubelet(t *testing.T) *TestKubelet {
|
|||||||
kubelet.cadvisor = mockCadvisor
|
kubelet.cadvisor = mockCadvisor
|
||||||
podManager, fakeMirrorClient := newFakePodManager()
|
podManager, fakeMirrorClient := newFakePodManager()
|
||||||
kubelet.podManager = podManager
|
kubelet.podManager = podManager
|
||||||
|
kubelet.containerRefManager = newContainerRefManager()
|
||||||
return &TestKubelet{kubelet, fakeDocker, mockCadvisor, fakeKubeClient, waitGroup, fakeMirrorClient}
|
return &TestKubelet{kubelet, fakeDocker, mockCadvisor, fakeKubeClient, waitGroup, fakeMirrorClient}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ func (kl *Kubelet) probeContainer(pod *api.Pod, status api.PodStatus, container
|
|||||||
glog.V(1).Infof("Readiness probe failed/errored: %v, %v", ready, err)
|
glog.V(1).Infof("Readiness probe failed/errored: %v, %v", ready, err)
|
||||||
kl.readiness.set(containerID, false)
|
kl.readiness.set(containerID, false)
|
||||||
|
|
||||||
ref, ok := kl.getRef(containerID)
|
ref, ok := kl.containerRefManager.GetRef(containerID)
|
||||||
if !ok {
|
if !ok {
|
||||||
glog.Warningf("No ref for pod '%v' - '%v'", containerID, container.Name)
|
glog.Warningf("No ref for pod '%v' - '%v'", containerID, container.Name)
|
||||||
} else {
|
} else {
|
||||||
|
@ -153,6 +153,7 @@ func makeTestKubelet(result probe.Result, err error) *Kubelet {
|
|||||||
err: err,
|
err: err,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
containerRefManager: newContainerRefManager(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,6 +79,7 @@ func TestRunOnce(t *testing.T) {
|
|||||||
cadvisor: cadvisor,
|
cadvisor: cadvisor,
|
||||||
nodeLister: testNodeLister{},
|
nodeLister: testNodeLister{},
|
||||||
statusManager: newStatusManager(nil),
|
statusManager: newStatusManager(nil),
|
||||||
|
containerRefManager: newContainerRefManager(),
|
||||||
}
|
}
|
||||||
|
|
||||||
kb.networkPlugin, _ = network.InitNetworkPlugin([]network.NetworkPlugin{}, "", network.NewFakeHost(nil))
|
kb.networkPlugin, _ = network.InitNetworkPlugin([]network.NetworkPlugin{}, "", network.NewFakeHost(nil))
|
||||||
|
Loading…
Reference in New Issue
Block a user