mirror of https://github.com/k3s-io/k3s
kubelet/rkt: minor updates to match rkt v0.7.0.
parent
ea59172874
commit
558e692f93
|
@ -25,28 +25,26 @@ import (
|
|||
// be returned to kubelet, and kubelet will use this for
|
||||
// container level operations.
|
||||
type containerID struct {
|
||||
uuid string // uuid of the pod.
|
||||
appName string // name of the app in that pod.
|
||||
imageID string // id of the image. TODO(yifan): Depreciate this.
|
||||
uuid string // rkt uuid of the pod.
|
||||
appName string // Name of the app in that pod.
|
||||
}
|
||||
|
||||
// buildContainerID constructs the containers's ID using containerID,
|
||||
// which containers the pod uuid and the container name.
|
||||
// The result can be used to globally identify a container.
|
||||
// which consists of the pod uuid and the container name.
|
||||
// The result can be used to uniquely identify a container.
|
||||
func buildContainerID(c *containerID) string {
|
||||
return fmt.Sprintf("%s:%s:%s", c.uuid, c.appName, c.imageID)
|
||||
return fmt.Sprintf("%s:%s", c.uuid, c.appName)
|
||||
}
|
||||
|
||||
// parseContainerID parses the containerID into pod uuid and the container name. The
|
||||
// results can be used to get more information of the container.
|
||||
func parseContainerID(id string) (*containerID, error) {
|
||||
tuples := strings.Split(id, ":")
|
||||
if len(tuples) != 3 {
|
||||
if len(tuples) != 2 {
|
||||
return nil, fmt.Errorf("rkt: cannot parse container ID for: %v", id)
|
||||
}
|
||||
return &containerID{
|
||||
uuid: tuples[0],
|
||||
appName: tuples[1],
|
||||
imageID: tuples[2],
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -38,6 +38,9 @@ const (
|
|||
Deleting = "deleting" // This covers pod.isExitedDeleting and pod.isDeleting.
|
||||
Exited = "exited" // This covers pod.isExited and pod.isExitedGarbage.
|
||||
Garbage = "garbage"
|
||||
|
||||
// The prefix before the app name for each app's exit code in the output of 'rkt status'.
|
||||
exitCodePrefix = "app-"
|
||||
)
|
||||
|
||||
// podInfo is the internal type that represents the state of
|
||||
|
@ -49,12 +52,21 @@ type podInfo struct {
|
|||
ip string
|
||||
// The pid of the init process in the pod.
|
||||
pid int
|
||||
// A map from image hashes to exit codes.
|
||||
// TODO(yifan): Should be appName to exit code in the future.
|
||||
// A map of [app name]:[exit code].
|
||||
exitCodes map[string]int
|
||||
// TODO(yifan): Expose [app name]:[image id].
|
||||
}
|
||||
|
||||
// parsePodInfo parses the result of 'rkt status' into podInfo.
|
||||
//
|
||||
// Example output of 'rkt status':
|
||||
//
|
||||
// state=exited
|
||||
// pid=-1
|
||||
// exited=true
|
||||
// app-etcd=0 # The exit code of the app "etcd" in the pod.
|
||||
// app-redis=0 # The exit code of the app "redis" in the pod.
|
||||
//
|
||||
func parsePodInfo(status []string) (*podInfo, error) {
|
||||
p := &podInfo{
|
||||
pid: -1,
|
||||
|
@ -80,12 +92,14 @@ func parsePodInfo(status []string) (*podInfo, error) {
|
|||
}
|
||||
p.pid = pid
|
||||
}
|
||||
if strings.HasPrefix(tuples[0], "sha512") {
|
||||
|
||||
if strings.HasPrefix(tuples[0], exitCodePrefix) {
|
||||
exitcode, err := strconv.Atoi(tuples[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse exit code from %s : %v", tuples[1], err)
|
||||
}
|
||||
p.exitCodes[tuples[0]] = exitcode
|
||||
appName := strings.TrimPrefix(tuples[0], exitCodePrefix)
|
||||
p.exitCodes[appName] = exitcode
|
||||
}
|
||||
}
|
||||
return p, nil
|
||||
|
@ -94,30 +108,27 @@ func parsePodInfo(status []string) (*podInfo, error) {
|
|||
// getIPFromNetworkInfo returns the IP of a pod by parsing the network info.
|
||||
// The network info looks like this:
|
||||
//
|
||||
// default:ip4=172.16.28.3, database:ip4=172.16.28.42
|
||||
// default:ip4=172.16.28.3
|
||||
// database:ip4=172.16.28.42
|
||||
//
|
||||
func getIPFromNetworkInfo(networkInfo string) string {
|
||||
parts := strings.Split(networkInfo, ",")
|
||||
|
||||
for _, part := range parts {
|
||||
if strings.HasPrefix(part, "default:") {
|
||||
tuples := strings.Split(part, "=")
|
||||
if len(tuples) == 2 {
|
||||
return tuples[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// getContainerStatus creates the api.containerStatus of a container from the podInfo.
|
||||
// TODO(yifan): Get more detailed info such as Image, ImageID, etc.
|
||||
func (p *podInfo) getContainerStatus(container *kubecontainer.Container) api.ContainerStatus {
|
||||
var status api.ContainerStatus
|
||||
status.Name = container.Name
|
||||
status.Image = container.Image
|
||||
containerID, _ := parseContainerID(string(container.ID))
|
||||
status.ImageID = containerID.imageID
|
||||
status.ContainerID = string(container.ID)
|
||||
// TODO(yifan): Add image ID info.
|
||||
|
||||
switch p.state {
|
||||
case Running:
|
||||
|
@ -130,11 +141,12 @@ func (p *podInfo) getContainerStatus(container *kubecontainer.Container) api.Con
|
|||
case Embryo, Preparing, Prepared:
|
||||
status.State = api.ContainerState{Waiting: &api.ContainerStateWaiting{}}
|
||||
case AbortedPrepare, Deleting, Exited, Garbage:
|
||||
exitCode, ok := p.exitCodes[status.ImageID]
|
||||
exitCode, ok := p.exitCodes[status.Name]
|
||||
if !ok {
|
||||
glog.Warningf("rkt: Cannot get exit code for container %v", container)
|
||||
}
|
||||
exitCode = -1
|
||||
|
||||
}
|
||||
status.State = api.ContainerState{
|
||||
Terminated: &api.ContainerStateTerminated{
|
||||
ExitCode: exitCode,
|
||||
|
|
|
@ -48,17 +48,13 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
rktBinName = "rkt"
|
||||
|
||||
acversion = "0.5.1"
|
||||
rktMinimumVersion = "0.5.4"
|
||||
systemdMinimumVersion = "215"
|
||||
acVersion = "0.6.1"
|
||||
rktMinimumVersion = "0.7.0"
|
||||
systemdMinimumVersion = "219"
|
||||
|
||||
systemdServiceDir = "/run/systemd/system"
|
||||
rktDataDir = "/var/lib/rkt"
|
||||
rktLocalConfigDir = "/etc/rkt"
|
||||
rktMetadataServiceFile = "rkt-metadata.service"
|
||||
rktMetadataSocketFile = "rkt-metadata.socket"
|
||||
|
||||
kubernetesUnitPrefix = "k8s"
|
||||
unitKubernetesSection = "X-Kubernetes"
|
||||
|
@ -133,7 +129,8 @@ func New(config *Config,
|
|||
}
|
||||
|
||||
// Test if rkt binary is in $PATH.
|
||||
rktBinAbsPath, err := exec.LookPath(rktBinName)
|
||||
// TODO(yifan): Use a kubelet flag to read the path.
|
||||
rktBinAbsPath, err := exec.LookPath("rkt")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot find rkt binary: %v", err)
|
||||
}
|
||||
|
@ -167,7 +164,7 @@ func New(config *Config,
|
|||
}
|
||||
|
||||
func (r *runtime) buildCommand(args ...string) *exec.Cmd {
|
||||
cmd := exec.Command(rktBinName)
|
||||
cmd := exec.Command(r.rktBinAbsPath)
|
||||
cmd.Args = append(cmd.Args, r.config.buildGlobalOptions()...)
|
||||
cmd.Args = append(cmd.Args, args...)
|
||||
return cmd
|
||||
|
@ -187,7 +184,8 @@ func (r *runtime) runCommand(args ...string) ([]string, error) {
|
|||
|
||||
// makePodServiceFileName constructs the unit file name for a pod using its UID.
|
||||
func makePodServiceFileName(uid types.UID) string {
|
||||
// TODO(yifan): Revisit this later, decide whether we want to use UID.
|
||||
// TODO(yifan): Add name for readability? We need to consider the
|
||||
// limit of the length.
|
||||
return fmt.Sprintf("%s_%s.service", kubernetesUnitPrefix, uid)
|
||||
}
|
||||
|
||||
|
@ -377,7 +375,6 @@ func (r *runtime) getImageManifest(image string) (*appcschema.ImageManifest, err
|
|||
}
|
||||
|
||||
// makePodManifest transforms a kubelet pod spec to the rkt pod manifest.
|
||||
// TODO(yifan): Use the RunContainerOptions generated by GenerateRunContainerOptions().
|
||||
func (r *runtime) makePodManifest(pod *api.Pod) (*appcschema.PodManifest, error) {
|
||||
var globalPortMappings []kubecontainer.PortMapping
|
||||
manifest := appcschema.BlankPodManifest()
|
||||
|
@ -463,8 +460,7 @@ func newUnitOption(section, name, value string) *unit.UnitOption {
|
|||
return &unit.UnitOption{Section: section, Name: name, Value: value}
|
||||
}
|
||||
|
||||
// TODO(yifan): Remove the receiver once we can solve the appName->imageID problem.
|
||||
func (r *runtime) apiPodToruntimePod(uuid string, pod *api.Pod) *kubecontainer.Pod {
|
||||
func apiPodToruntimePod(uuid string, pod *api.Pod) *kubecontainer.Pod {
|
||||
p := &kubecontainer.Pod{
|
||||
ID: pod.UID,
|
||||
Name: pod.Name,
|
||||
|
@ -472,12 +468,8 @@ func (r *runtime) apiPodToruntimePod(uuid string, pod *api.Pod) *kubecontainer.P
|
|||
}
|
||||
for i := range pod.Spec.Containers {
|
||||
c := &pod.Spec.Containers[i]
|
||||
img, err := r.getImageByName(c.Image)
|
||||
if err != nil {
|
||||
glog.Warningf("rkt: Cannot get image for %q: %v", c.Image, err)
|
||||
}
|
||||
p.Containers = append(p.Containers, &kubecontainer.Container{
|
||||
ID: types.UID(buildContainerID(&containerID{uuid, c.Name, img.id})),
|
||||
ID: types.UID(buildContainerID(&containerID{uuid, c.Name})),
|
||||
Name: c.Name,
|
||||
Image: c.Image,
|
||||
Hash: kubecontainer.HashContainer(c),
|
||||
|
@ -503,7 +495,7 @@ func (r *runtime) preparePod(pod *api.Pod) (string, bool, error) {
|
|||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
manifestFile, err := ioutil.TempFile("", "manifest")
|
||||
manifestFile, err := ioutil.TempFile("", fmt.Sprintf("manifest-%s-", pod.Name))
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
|
@ -533,18 +525,26 @@ func (r *runtime) preparePod(pod *api.Pod) (string, bool, error) {
|
|||
return "", false, fmt.Errorf("cannot get uuid from 'rkt prepare'")
|
||||
}
|
||||
uuid := output[0]
|
||||
glog.V(4).Infof("'rkt prepare' returns %q.", uuid)
|
||||
glog.V(4).Infof("'rkt prepare' returns %q", uuid)
|
||||
|
||||
p := r.apiPodToruntimePod(uuid, pod)
|
||||
p := apiPodToruntimePod(uuid, pod)
|
||||
b, err := json.Marshal(p)
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
|
||||
runPrepared := fmt.Sprintf("%s run-prepared --private-net=%v %s", r.rktBinAbsPath, !pod.Spec.HostNetwork, uuid)
|
||||
var runPrepared string
|
||||
if pod.Spec.HostNetwork {
|
||||
runPrepared = fmt.Sprintf("%s run-prepared --mds-register=false %s", r.rktBinAbsPath, uuid)
|
||||
} else {
|
||||
runPrepared = fmt.Sprintf("%s run-prepared --mds-register=false --private-net %s", r.rktBinAbsPath, uuid)
|
||||
}
|
||||
|
||||
units := []*unit.UnitOption{
|
||||
newUnitOption(unitKubernetesSection, unitRktID, uuid),
|
||||
newUnitOption(unitKubernetesSection, unitPodName, string(b)),
|
||||
// This makes the service show up for 'systemctl list-units' even if it exits successfully.
|
||||
newUnitOption("Service", "RemainAfterExit", "true"),
|
||||
newUnitOption("Service", "ExecStart", runPrepared),
|
||||
}
|
||||
|
||||
|
@ -934,7 +934,7 @@ func (r *runtime) GarbageCollect() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Note: In rkt, the container ID is in the form of "UUID:appName:ImageID", where
|
||||
// Note: In rkt, the container ID is in the form of "UUID:appName", where
|
||||
// appName is the container name.
|
||||
func (r *runtime) RunInContainer(containerID string, cmd []string) ([]byte, error) {
|
||||
glog.V(4).Infof("Rkt running in container.")
|
||||
|
@ -943,9 +943,7 @@ func (r *runtime) RunInContainer(containerID string, cmd []string) ([]byte, erro
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO(yifan): Use appName instead of imageID.
|
||||
// see https://github.com/coreos/rkt/pull/640
|
||||
args := append([]string{}, "enter", "--imageid", id.imageID, id.uuid)
|
||||
args := append([]string{}, "enter", fmt.Sprintf("--app=%s", id.appName), id.uuid)
|
||||
args = append(args, cmd...)
|
||||
|
||||
result, err := r.runCommand(args...)
|
||||
|
@ -956,8 +954,8 @@ func (r *runtime) AttachContainer(containerID string, stdin io.Reader, stdout, s
|
|||
return errors.New("unimplemented")
|
||||
}
|
||||
|
||||
// Note: In rkt, the container ID is in the form of "UUID:appName:ImageID", where
|
||||
// appName is the container name.
|
||||
// Note: In rkt, the container ID is in the form of "UUID:appName", where UUID is
|
||||
// the rkt UUID, and appName is the container name.
|
||||
func (r *runtime) ExecInContainer(containerID string, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool) error {
|
||||
glog.V(4).Infof("Rkt execing in container.")
|
||||
|
||||
|
@ -965,9 +963,7 @@ func (r *runtime) ExecInContainer(containerID string, cmd []string, stdin io.Rea
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO(yifan): Use appName instead of imageID.
|
||||
// see https://github.com/coreos/rkt/pull/640
|
||||
args := append([]string{}, "enter", "--imageid", id.imageID, id.uuid)
|
||||
args := append([]string{}, "enter", fmt.Sprintf("--app=%s", id.appName), id.uuid)
|
||||
args = append(args, cmd...)
|
||||
command := r.buildCommand(args...)
|
||||
|
||||
|
@ -1116,12 +1112,13 @@ func (r *runtime) getPodInfos() (map[string]*podInfo, error) {
|
|||
return result, nil
|
||||
}
|
||||
|
||||
// Example output of current 'rkt list --full' (version == 0.4.2):
|
||||
// UUID ACI STATE NETWORKS
|
||||
// 2372bc17-47cb-43fb-8d78-20b31729feda foo running default:ip4=172.16.28.3
|
||||
// bar
|
||||
// 40e2813b-9d5d-4146-a817-0de92646da96 foo exited
|
||||
// 40e2813b-9d5d-4146-a817-0de92646da96 bar exited
|
||||
// Example output of 'rkt list --full' (version == 0.7.0):
|
||||
//
|
||||
// UUID APP ACI STATE NETWORKS
|
||||
// 2372bc17-47cb-43fb-8d78-20b31729feda foo coreos.com/etcd running default:ip4=172.16.28.3
|
||||
// bar nginx running
|
||||
// 40e2813b-9d5d-4146-a817-0de92646da96 foo redis exited
|
||||
// 40e2813b-9d5d-4146-a817-0de92646da96 bar busybox exited
|
||||
//
|
||||
// With '--no-legend', the first line is eliminated.
|
||||
for _, line := range output {
|
||||
|
@ -1171,8 +1168,9 @@ func (r *runtime) listImages() ([]image, error) {
|
|||
}
|
||||
|
||||
// getImageByName tries to find the image info with the given image name.
|
||||
// TODO(yifan): Replace with 'rkt image cat-manifest'.
|
||||
func (r *runtime) getImageByName(imageName string) (image, error) {
|
||||
// TODO(yifan): Print hash in rkt image?
|
||||
// TODO(yifan): Print hash in 'rkt image cat-manifest'?
|
||||
images, err := r.listImages()
|
||||
if err != nil {
|
||||
return image{}, err
|
||||
|
@ -1181,9 +1179,7 @@ func (r *runtime) getImageByName(imageName string) (image, error) {
|
|||
var name, version string
|
||||
nameVersion := strings.Split(imageName, ":")
|
||||
|
||||
// TODO(yifan): Currently the name cannot include "_", it is replaced
|
||||
// by "-". See the issue in appc/spec: https://github.com/appc/spec/issues/406.
|
||||
name, err = appctypes.SanitizeACName(nameVersion[0])
|
||||
name, err = appctypes.SanitizeACIdentifier(nameVersion[0])
|
||||
if err != nil {
|
||||
return image{}, err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue