mirror of https://github.com/k3s-io/k3s
Merge pull request #12880 from yifan-gu/pod_status
kubelet: refactor kubecontainer.Pod, remove PodStatus from it.pull/6/head
commit
a90b67f276
|
@ -118,11 +118,6 @@ type Pod struct {
|
||||||
// List of containers that belongs to this pod. It may contain only
|
// List of containers that belongs to this pod. It may contain only
|
||||||
// running containers, or mixed with dead ones (when GetPods(true)).
|
// running containers, or mixed with dead ones (when GetPods(true)).
|
||||||
Containers []*Container
|
Containers []*Container
|
||||||
// The status of the pod.
|
|
||||||
// TODO(yifan): Inspect and get the statuses for all pods can be expensive,
|
|
||||||
// maybe we want to get one pod's status at a time (e.g. GetPodStatus()
|
|
||||||
// for the particular pod after we GetPods()).
|
|
||||||
Status api.PodStatus
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerID is a type that identifies a container.
|
// ContainerID is a type that identifies a container.
|
||||||
|
@ -294,7 +289,6 @@ func (p *Pod) ToAPIPod() *api.Pod {
|
||||||
pod.UID = p.ID
|
pod.UID = p.ID
|
||||||
pod.Name = p.Name
|
pod.Name = p.Name
|
||||||
pod.Namespace = p.Namespace
|
pod.Namespace = p.Namespace
|
||||||
pod.Status = p.Status
|
|
||||||
|
|
||||||
for _, c := range p.Containers {
|
for _, c := range p.Containers {
|
||||||
var container api.Container
|
var container api.Container
|
||||||
|
|
|
@ -18,13 +18,13 @@ package rkt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
@ -45,6 +45,7 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/probe"
|
"k8s.io/kubernetes/pkg/probe"
|
||||||
"k8s.io/kubernetes/pkg/securitycontext"
|
"k8s.io/kubernetes/pkg/securitycontext"
|
||||||
"k8s.io/kubernetes/pkg/types"
|
"k8s.io/kubernetes/pkg/types"
|
||||||
|
"k8s.io/kubernetes/pkg/util/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -624,18 +625,18 @@ func (r *runtime) RunPod(pod *api.Pod, pullSecrets []api.Secret) error {
|
||||||
|
|
||||||
// makeRuntimePod constructs the container runtime pod. It will:
|
// makeRuntimePod constructs the container runtime pod. It will:
|
||||||
// 1, Construct the pod by the information stored in the unit file.
|
// 1, Construct the pod by the information stored in the unit file.
|
||||||
// 2, Construct the pod status from pod info.
|
// 2, Return the rkt uuid.
|
||||||
func (r *runtime) makeRuntimePod(unitName string, podInfos map[string]*podInfo) (*kubecontainer.Pod, error) {
|
func (r *runtime) makeRuntimePod(unitName string) (*kubecontainer.Pod, string, error) {
|
||||||
f, err := os.Open(path.Join(systemdServiceDir, unitName))
|
f, err := os.Open(path.Join(systemdServiceDir, unitName))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
var pod kubecontainer.Pod
|
var pod kubecontainer.Pod
|
||||||
opts, err := unit.Deserialize(f)
|
opts, err := unit.Deserialize(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
var rktID string
|
var rktID string
|
||||||
|
@ -647,24 +648,19 @@ func (r *runtime) makeRuntimePod(unitName string, podInfos map[string]*podInfo)
|
||||||
case unitPodName:
|
case unitPodName:
|
||||||
err = json.Unmarshal([]byte(opt.Value), &pod)
|
err = json.Unmarshal([]byte(opt.Value), &pod)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
case unitRktID:
|
case unitRktID:
|
||||||
rktID = opt.Value
|
rktID = opt.Value
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("rkt: Unexpected key: %q", opt.Name)
|
return nil, "", fmt.Errorf("rkt: Unexpected key: %q", opt.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(rktID) == 0 {
|
if len(rktID) == 0 {
|
||||||
return nil, fmt.Errorf("rkt: cannot find rkt ID of pod %v, unit file is broken", pod)
|
return nil, "", fmt.Errorf("rkt: cannot find rkt ID of pod %v, unit file is broken", pod)
|
||||||
}
|
}
|
||||||
info, found := podInfos[rktID]
|
return &pod, "", nil
|
||||||
if !found {
|
|
||||||
return nil, fmt.Errorf("rkt: cannot find info for pod %q, rkt uuid: %q", pod.Name, rktID)
|
|
||||||
}
|
|
||||||
pod.Status = info.toPodStatus(&pod)
|
|
||||||
return &pod, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPods runs 'systemctl list-unit' and 'rkt list' to get the list of rkt pods.
|
// GetPods runs 'systemctl list-unit' and 'rkt list' to get the list of rkt pods.
|
||||||
|
@ -679,20 +675,13 @@ func (r *runtime) GetPods(all bool) ([]*kubecontainer.Pod, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(yifan): Now we are getting the status of the pod as well.
|
|
||||||
// Probably we can leave much of the work to GetPodStatus().
|
|
||||||
podInfos, err := r.getPodInfos()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var pods []*kubecontainer.Pod
|
var pods []*kubecontainer.Pod
|
||||||
for _, u := range units {
|
for _, u := range units {
|
||||||
if strings.HasPrefix(u.Name, kubernetesUnitPrefix) {
|
if strings.HasPrefix(u.Name, kubernetesUnitPrefix) {
|
||||||
if !all && u.SubState != "running" {
|
if !all && u.SubState != "running" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
pod, err := r.makeRuntimePod(u.Name, podInfos)
|
pod, _, err := r.makeRuntimePod(u.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Warningf("rkt: Cannot construct pod from unit file: %v.", err)
|
glog.Warningf("rkt: Cannot construct pod from unit file: %v.", err)
|
||||||
continue
|
continue
|
||||||
|
@ -712,18 +701,81 @@ func (r *runtime) KillPod(pod kubecontainer.Pod) error {
|
||||||
return r.systemd.Reload()
|
return r.systemd.Reload()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPodStatus currently invokes GetPods() to return the status.
|
type byModTime []os.FileInfo
|
||||||
// TODO(yifan): Split the get status logic from GetPods().
|
|
||||||
func (r *runtime) GetPodStatus(pod *api.Pod) (*api.PodStatus, error) {
|
func (b byModTime) Len() int { return len(b) }
|
||||||
pods, err := r.GetPods(true)
|
func (b byModTime) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
|
||||||
|
func (b byModTime) Less(i, j int) bool { return b[i].ModTime().After(b[j].ModTime()) }
|
||||||
|
|
||||||
|
// listUnitFiles reads the systemd directory and returns a list of rkt
|
||||||
|
// service file names, sorted by the modification date from newest to oldest.
|
||||||
|
// TODO(yifan): Listing all units under the directory is inefficent, consider to
|
||||||
|
// create the list during startup, and then record every unit creation to avoid
|
||||||
|
// reading the whole directory.
|
||||||
|
func listUnitFiles() ([]string, error) {
|
||||||
|
files, err := ioutil.ReadDir(systemdServiceDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
p := kubecontainer.Pods(pods).FindPodByID(pod.UID)
|
|
||||||
if len(p.Containers) == 0 {
|
sort.Sort(byModTime(files))
|
||||||
return nil, fmt.Errorf("cannot find status for pod: %q", kubecontainer.BuildPodFullName(pod.Name, pod.Namespace))
|
|
||||||
|
var rktFiles []string
|
||||||
|
for _, f := range files {
|
||||||
|
if strings.HasPrefix(f.Name(), kubernetesUnitPrefix) {
|
||||||
|
rktFiles = append(rktFiles, f.Name())
|
||||||
}
|
}
|
||||||
return &p.Status, nil
|
}
|
||||||
|
return rktFiles, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getPodStatus reads the service file and invokes 'rkt status $UUID' to get the
|
||||||
|
// pod's status.
|
||||||
|
func (r *runtime) getPodStatus(serviceName string) (*api.PodStatus, error) {
|
||||||
|
// TODO(yifan): Get rkt uuid from the service file name.
|
||||||
|
pod, uuid, err := r.makeRuntimePod(serviceName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
podInfo, err := r.getPodInfo(uuid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
status := podInfo.toPodStatus(pod)
|
||||||
|
return &status, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPodStatus returns the status of the given pod.
|
||||||
|
func (r *runtime) GetPodStatus(pod *api.Pod) (*api.PodStatus, error) {
|
||||||
|
unitNames, err := listUnitFiles()
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("rkt: Cannot list unit files: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var status *api.PodStatus
|
||||||
|
var errlist []error
|
||||||
|
for _, name := range unitNames {
|
||||||
|
if !strings.Contains(name, string(pod.UID)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if status != nil {
|
||||||
|
// This means the pod has been restarted.
|
||||||
|
for _, c := range status.ContainerStatuses {
|
||||||
|
c.RestartCount++
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
status, err = r.getPodStatus(name)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("rkt: Cannot get pod status for pod %q, service file %q: %v", pod.Name, name, err)
|
||||||
|
errlist = append(errlist, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status, errors.NewAggregate(errlist)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version invokes 'rkt version' to get the version information of the rkt
|
// Version invokes 'rkt version' to get the version information of the rkt
|
||||||
|
@ -978,7 +1030,7 @@ func (r *runtime) RunInContainer(containerID string, cmd []string) ([]byte, erro
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runtime) AttachContainer(containerID string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool) error {
|
func (r *runtime) AttachContainer(containerID string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool) error {
|
||||||
return errors.New("unimplemented")
|
return fmt.Errorf("unimplemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: In rkt, the container ID is in the form of "UUID:appName", where UUID is
|
// Note: In rkt, the container ID is in the form of "UUID:appName", where UUID is
|
||||||
|
@ -1126,6 +1178,20 @@ func isUUID(input string) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getPodInfo returns the pod info of a single pod according
|
||||||
|
// to the uuid.
|
||||||
|
func (r *runtime) getPodInfo(uuid string) (*podInfo, error) {
|
||||||
|
status, err := r.runCommand("status", uuid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
info, err := parsePodInfo(status)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return info, nil
|
||||||
|
}
|
||||||
|
|
||||||
// getPodInfos returns a map of [pod-uuid]:*podInfo
|
// getPodInfos returns a map of [pod-uuid]:*podInfo
|
||||||
func (r *runtime) getPodInfos() (map[string]*podInfo, error) {
|
func (r *runtime) getPodInfos() (map[string]*podInfo, error) {
|
||||||
result := make(map[string]*podInfo)
|
result := make(map[string]*podInfo)
|
||||||
|
|
Loading…
Reference in New Issue