2016-07-07 16:58:55 +00:00
/ *
Copyright 2016 The Kubernetes Authors .
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 (
"sort"
"github.com/golang/glog"
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
"k8s.io/kubernetes/pkg/util/wait"
)
const (
// The limit on the number of buffered container deletion requests
// This number is a bit arbitrary and may be adjusted in the future.
containerDeletorBufferLimit = 50
)
type containerStatusbyCreatedList [ ] * kubecontainer . ContainerStatus
type podContainerDeletor struct {
worker chan <- kubecontainer . ContainerID
containersToKeep int
}
func ( a containerStatusbyCreatedList ) Len ( ) int { return len ( a ) }
func ( a containerStatusbyCreatedList ) Swap ( i , j int ) { a [ i ] , a [ j ] = a [ j ] , a [ i ] }
func ( a containerStatusbyCreatedList ) Less ( i , j int ) bool { return a [ i ] . CreatedAt . After ( a [ j ] . CreatedAt ) }
func newPodContainerDeletor ( runtime kubecontainer . Runtime , containersToKeep int ) * podContainerDeletor {
buffer := make ( chan kubecontainer . ContainerID , containerDeletorBufferLimit )
go wait . Until ( func ( ) {
for {
select {
case id := <- buffer :
runtime . DeleteContainer ( id )
}
}
} , 0 , wait . NeverStop )
return & podContainerDeletor {
worker : buffer ,
containersToKeep : containersToKeep ,
}
}
2016-08-09 22:37:23 +00:00
// getContainersToDeleteInPod returns the exited containers in a pod whose name matches the name inferred from filterContainerId (if not empty), ordered by the creation time from the latest to the earliest.
// If filterContainerId is empty, all dead containers in the pod are returned.
func getContainersToDeleteInPod ( filterContainerId string , podStatus * kubecontainer . PodStatus , containersToKeep int ) containerStatusbyCreatedList {
matchedContainer := func ( filterContainerId string , podStatus * kubecontainer . PodStatus ) * kubecontainer . ContainerStatus {
if filterContainerId == "" {
return nil
2016-07-07 16:58:55 +00:00
}
2016-08-09 22:37:23 +00:00
for _ , containerStatus := range podStatus . ContainerStatuses {
if containerStatus . ID . ID == filterContainerId {
return containerStatus
}
2016-07-07 16:58:55 +00:00
}
2016-08-09 22:37:23 +00:00
return nil
} ( filterContainerId , podStatus )
if filterContainerId != "" && matchedContainer == nil {
glog . Warningf ( "Container %q not found in pod's containers" , filterContainerId )
2016-07-07 16:58:55 +00:00
return containerStatusbyCreatedList { }
}
2016-08-09 22:37:23 +00:00
// Find the exited containers whose name matches the name of the container with id being filterContainerId
2016-07-07 16:58:55 +00:00
var candidates containerStatusbyCreatedList
2016-08-09 22:37:23 +00:00
for _ , containerStatus := range podStatus . ContainerStatuses {
if containerStatus . State != kubecontainer . ContainerStateExited {
continue
}
if matchedContainer == nil || matchedContainer . Name == containerStatus . Name {
2016-07-07 16:58:55 +00:00
candidates = append ( candidates , containerStatus )
}
}
2016-08-02 01:14:52 +00:00
if len ( candidates ) <= containersToKeep {
2016-07-07 16:58:55 +00:00
return containerStatusbyCreatedList { }
}
sort . Sort ( candidates )
2016-08-02 01:14:52 +00:00
return candidates [ containersToKeep : ]
2016-07-07 16:58:55 +00:00
}
// deleteContainersInPod issues container deletion requests for containers selected by getContainersToDeleteInPod.
2016-08-09 22:37:23 +00:00
func ( p * podContainerDeletor ) deleteContainersInPod ( filterContainerId string , podStatus * kubecontainer . PodStatus , removeAll bool ) {
2016-08-02 01:14:52 +00:00
containersToKeep := p . containersToKeep
if removeAll {
containersToKeep = 0
}
2016-08-09 22:37:23 +00:00
for _ , candidate := range getContainersToDeleteInPod ( filterContainerId , podStatus , containersToKeep ) {
2016-07-07 16:58:55 +00:00
select {
case p . worker <- candidate . ID :
default :
glog . Warningf ( "Failed to issue the request to remove container %v" , candidate . ID )
}
}
}