Add a dockershim package
Add a new docker integration with kubelet using the new runtime API. This change adds the package with some skeletons, and implements some of the basic operations.
This commit is contained in:
		| @@ -22,9 +22,8 @@ import ( | |||||||
| 	runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" | 	runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // RuntimeService interface defines the interfaces that should be implemented | // RuntimeService interface should be implemented by a container runtime. | ||||||
| // by a container runtime. | // The methods should be thread-safe. | ||||||
| // Thread safety is required from implementations of this interface. |  | ||||||
| type RuntimeService interface { | type RuntimeService interface { | ||||||
| 	// Version returns the runtime name, runtime version and runtime API version | 	// Version returns the runtime name, runtime version and runtime API version | ||||||
| 	Version(apiVersion string) (*runtimeApi.VersionResponse, error) | 	Version(apiVersion string) (*runtimeApi.VersionResponse, error) | ||||||
| @@ -33,40 +32,39 @@ type RuntimeService interface { | |||||||
| 	CreatePodSandbox(config *runtimeApi.PodSandboxConfig) (string, error) | 	CreatePodSandbox(config *runtimeApi.PodSandboxConfig) (string, error) | ||||||
| 	// StopPodSandbox stops the sandbox. If there are any running containers in the | 	// StopPodSandbox stops the sandbox. If there are any running containers in the | ||||||
| 	// sandbox, they should be force terminated. | 	// sandbox, they should be force terminated. | ||||||
| 	StopPodSandbox(podSandBoxID string) error | 	StopPodSandbox(podSandboxID string) error | ||||||
| 	// DeletePodSandbox deletes the sandbox. If there are any running containers in the | 	// DeletePodSandbox deletes the sandbox. If there are running containers in the | ||||||
| 	// sandbox, they should be force deleted. | 	// sandbox, they should be forcibly deleted. | ||||||
| 	DeletePodSandbox(podSandBoxID string) error | 	DeletePodSandbox(podSandboxID string) error | ||||||
| 	// PodSandboxStatus returns the Status of the PodSandbox. | 	// PodSandboxStatus returns the Status of the PodSandbox. | ||||||
| 	PodSandboxStatus(podSandBoxID string) (*runtimeApi.PodSandboxStatus, error) | 	PodSandboxStatus(podSandboxID string) (*runtimeApi.PodSandboxStatus, error) | ||||||
| 	// ListPodSandbox returns a list of SandBox. | 	// ListPodSandbox returns a list of Sandbox. | ||||||
| 	ListPodSandbox(filter *runtimeApi.PodSandboxFilter) ([]*runtimeApi.PodSandbox, error) | 	ListPodSandbox(filter *runtimeApi.PodSandboxFilter) ([]*runtimeApi.PodSandbox, error) | ||||||
| 	// CreateContainer creates a new container in specified PodSandbox | 	// CreateContainer creates a new container in specified PodSandbox. | ||||||
| 	CreateContainer(podSandBoxID string, config *runtimeApi.ContainerConfig, sandboxConfig *runtimeApi.PodSandboxConfig) (string, error) | 	CreateContainer(podSandboxID string, config *runtimeApi.ContainerConfig, sandboxConfig *runtimeApi.PodSandboxConfig) (string, error) | ||||||
| 	// StartContainer starts the container. | 	// StartContainer starts the container. | ||||||
| 	StartContainer(rawContainerID string) error | 	StartContainer(rawContainerID string) error | ||||||
| 	// StopContainer stops a running container with a grace period (i.e., timeout). | 	// StopContainer stops a running container with a grace period (i.e., timeout). | ||||||
| 	StopContainer(rawContainerID string, timeout int64) error | 	StopContainer(rawContainerID string, timeout int64) error | ||||||
| 	// RemoveContainer removes the container. If the container is running, the container | 	// RemoveContainer removes the container. | ||||||
| 	// should be force removed. |  | ||||||
| 	RemoveContainer(rawContainerID string) error | 	RemoveContainer(rawContainerID string) error | ||||||
| 	// ListContainers lists all containers by filters. | 	// ListContainers lists all containers by filters. | ||||||
| 	ListContainers(filter *runtimeApi.ContainerFilter) ([]*runtimeApi.Container, error) | 	ListContainers(filter *runtimeApi.ContainerFilter) ([]*runtimeApi.Container, error) | ||||||
| 	// ContainerStatus returns the container status. | 	// ContainerStatus returns the status of the container. | ||||||
| 	ContainerStatus(rawContainerID string) (*runtimeApi.ContainerStatus, error) | 	ContainerStatus(rawContainerID string) (*runtimeApi.ContainerStatus, error) | ||||||
| 	// Exec execute a command in the container. | 	// Exec executes a command in the container. | ||||||
| 	Exec(rawContainerID string, cmd []string, tty bool, stdin io.Reader, stdout, stderr io.WriteCloser) error | 	Exec(rawContainerID string, cmd []string, tty bool, stdin io.Reader, stdout, stderr io.WriteCloser) error | ||||||
| } | } | ||||||
|  |  | ||||||
| // ImageManagerService interface defines the interfaces that should be implemented | // ImageManagerService interface should be implemented by a container image | ||||||
| // by a container image manager. | // manager. | ||||||
| // Thread safety is required from implementations of this interface. | // The methods should be thread-safe. | ||||||
| type ImageManagerService interface { | type ImageManagerService interface { | ||||||
| 	// ListImages lists existing images. | 	// ListImages lists the existing images. | ||||||
| 	ListImages(filter *runtimeApi.ImageFilter) ([]*runtimeApi.Image, error) | 	ListImages(filter *runtimeApi.ImageFilter) ([]*runtimeApi.Image, error) | ||||||
| 	// ImageStatus returns the status of the image. | 	// ImageStatus returns the status of the image. | ||||||
| 	ImageStatus(image *runtimeApi.ImageSpec) (*runtimeApi.Image, error) | 	ImageStatus(image *runtimeApi.ImageSpec) (*runtimeApi.Image, error) | ||||||
| 	// PullImage pulls a image with authentication config. | 	// PullImage pulls an image with the authentication config. | ||||||
| 	PullImage(image *runtimeApi.ImageSpec, auth *runtimeApi.AuthConfig) error | 	PullImage(image *runtimeApi.ImageSpec, auth *runtimeApi.AuthConfig) error | ||||||
| 	// RemoveImage removes the image. | 	// RemoveImage removes the image. | ||||||
| 	RemoveImage(image *runtimeApi.ImageSpec) error | 	RemoveImage(image *runtimeApi.ImageSpec) error | ||||||
|   | |||||||
							
								
								
									
										91
									
								
								pkg/kubelet/dockershim/convert.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								pkg/kubelet/dockershim/convert.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | |||||||
|  | /* | ||||||
|  | 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 dockershim | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"strings" | ||||||
|  |  | ||||||
|  | 	dockertypes "github.com/docker/engine-api/types" | ||||||
|  | 	runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // This file contains helper functions to convert docker API types to runtime | ||||||
|  | // API types, or vice versa. | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	// Status of a container returned by docker ListContainers | ||||||
|  | 	statusRunningPrefix = "Up" | ||||||
|  | 	statusCreatedPrefix = "Created" | ||||||
|  | 	statusExitedPrefix  = "Exited" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func toRuntimeAPIImage(image *dockertypes.Image) (*runtimeApi.Image, error) { | ||||||
|  | 	if image == nil { | ||||||
|  | 		return nil, fmt.Errorf("unable to convert a nil pointer to a runtime API image") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	size := uint64(image.VirtualSize) | ||||||
|  | 	return &runtimeApi.Image{ | ||||||
|  | 		Id:          &image.ID, | ||||||
|  | 		RepoTags:    image.RepoTags, | ||||||
|  | 		RepoDigests: image.RepoDigests, | ||||||
|  | 		Size_:       &size, | ||||||
|  | 	}, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func toRuntimeAPIContainer(c *dockertypes.Container) *runtimeApi.Container { | ||||||
|  | 	state := toRuntimeAPIContainerState(c.Status) | ||||||
|  | 	return &runtimeApi.Container{ | ||||||
|  | 		Id:       &c.ID, | ||||||
|  | 		Name:     &c.Names[0], | ||||||
|  | 		Image:    &runtimeApi.ImageSpec{Image: &c.Image}, | ||||||
|  | 		ImageRef: &c.ImageID, | ||||||
|  | 		State:    &state, | ||||||
|  | 		Labels:   c.Labels, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func toDockerContainerStatus(state runtimeApi.ContainerState) string { | ||||||
|  | 	switch state { | ||||||
|  | 	case runtimeApi.ContainerState_CREATED: | ||||||
|  | 		return "created" | ||||||
|  | 	case runtimeApi.ContainerState_RUNNING: | ||||||
|  | 		return "running" | ||||||
|  | 	case runtimeApi.ContainerState_EXITED: | ||||||
|  | 		return "exited" | ||||||
|  | 	case runtimeApi.ContainerState_UNKNOWN: | ||||||
|  | 		fallthrough | ||||||
|  | 	default: | ||||||
|  | 		return "unknown" | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func toRuntimeAPIContainerState(state string) runtimeApi.ContainerState { | ||||||
|  | 	// Parse the state string in dockertypes.Container. This could break when | ||||||
|  | 	// we upgrade docker. | ||||||
|  | 	switch { | ||||||
|  | 	case strings.HasPrefix(state, statusRunningPrefix): | ||||||
|  | 		return runtimeApi.ContainerState_RUNNING | ||||||
|  | 	case strings.HasPrefix(state, statusExitedPrefix): | ||||||
|  | 		return runtimeApi.ContainerState_EXITED | ||||||
|  | 	case strings.HasPrefix(state, statusCreatedPrefix): | ||||||
|  | 		return runtimeApi.ContainerState_CREATED | ||||||
|  | 	default: | ||||||
|  | 		return runtimeApi.ContainerState_UNKNOWN | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										41
									
								
								pkg/kubelet/dockershim/convert_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								pkg/kubelet/dockershim/convert_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | /* | ||||||
|  | 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 dockershim | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestConvertDockerStatusToRuntimeAPIState(t *testing.T) { | ||||||
|  | 	testCases := []struct { | ||||||
|  | 		input    string | ||||||
|  | 		expected runtimeApi.ContainerState | ||||||
|  | 	}{ | ||||||
|  | 		{input: "Up 5 hours", expected: runtimeApi.ContainerState_RUNNING}, | ||||||
|  | 		{input: "Exited (0) 2 hours ago", expected: runtimeApi.ContainerState_EXITED}, | ||||||
|  | 		{input: "Created", expected: runtimeApi.ContainerState_CREATED}, | ||||||
|  | 		{input: "Random string", expected: runtimeApi.ContainerState_UNKNOWN}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for i, test := range testCases { | ||||||
|  | 		if actual := toRuntimeAPIContainerState(test.input); actual != test.expected { | ||||||
|  | 			t.Errorf("Test[%d]: expected %q, got %q", i, test.expected, actual) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										18
									
								
								pkg/kubelet/dockershim/doc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								pkg/kubelet/dockershim/doc.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | /* | ||||||
|  | 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. | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | // Docker integration using pkg/kubelet/api/v1alpha1/runtime/api.pb.go. | ||||||
|  | package dockershim | ||||||
							
								
								
									
										203
									
								
								pkg/kubelet/dockershim/docker_container.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								pkg/kubelet/dockershim/docker_container.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,203 @@ | |||||||
|  | /* | ||||||
|  | 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 dockershim | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  |  | ||||||
|  | 	dockertypes "github.com/docker/engine-api/types" | ||||||
|  | 	dockercontainer "github.com/docker/engine-api/types/container" | ||||||
|  | 	dockerfilters "github.com/docker/engine-api/types/filters" | ||||||
|  | 	dockerstrslice "github.com/docker/engine-api/types/strslice" | ||||||
|  | 	runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // ListContainers lists all containers matching the filter. | ||||||
|  | func (ds *dockerService) ListContainers(filter *runtimeApi.ContainerFilter) ([]*runtimeApi.Container, error) { | ||||||
|  | 	opts := dockertypes.ContainerListOptions{All: true} | ||||||
|  |  | ||||||
|  | 	opts.Filter = dockerfilters.NewArgs() | ||||||
|  | 	if filter != nil { | ||||||
|  | 		if filter.Name != nil { | ||||||
|  | 			opts.Filter.Add("name", filter.GetName()) | ||||||
|  | 		} | ||||||
|  | 		if filter.Id != nil { | ||||||
|  | 			opts.Filter.Add("id", filter.GetId()) | ||||||
|  | 		} | ||||||
|  | 		if filter.State != nil { | ||||||
|  | 			opts.Filter.Add("status", toDockerContainerStatus(filter.GetState())) | ||||||
|  | 		} | ||||||
|  | 		if filter.PodSandboxId != nil { | ||||||
|  | 			// TODO: implement this after sandbox functions are implemented. | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if filter.LabelSelector != nil { | ||||||
|  | 			for k, v := range filter.LabelSelector { | ||||||
|  | 				opts.Filter.Add("label", fmt.Sprintf("%s=%s", k, v)) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	containers, err := ds.client.ListContainers(opts) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	// Convert docker to runtime api containers. | ||||||
|  | 	result := []*runtimeApi.Container{} | ||||||
|  | 	for _, c := range containers { | ||||||
|  | 		result = append(result, toRuntimeAPIContainer(&c)) | ||||||
|  | 	} | ||||||
|  | 	return result, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // CreateContainer creates a new container in the given PodSandbox | ||||||
|  | // Note: docker doesn't use LogPath yet. | ||||||
|  | // TODO: check if the default values returned by the runtime API are ok. | ||||||
|  | func (ds *dockerService) CreateContainer(podSandboxID string, config *runtimeApi.ContainerConfig, sandboxConfig *runtimeApi.PodSandboxConfig) (string, error) { | ||||||
|  | 	if config == nil { | ||||||
|  | 		return "", fmt.Errorf("container config is nil") | ||||||
|  | 	} | ||||||
|  | 	if sandboxConfig == nil { | ||||||
|  | 		return "", fmt.Errorf("sandbox config is nil for container %q", config.GetName()) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Merge annotations and labels because docker supports only labels. | ||||||
|  | 	// TODO: add a prefix to annotations so that we can distinguish labels and | ||||||
|  | 	// annotations when reading back them from the docker container. | ||||||
|  | 	// TODO: should we apply docker-specific labels? | ||||||
|  | 	labels := config.GetLabels() | ||||||
|  | 	for k, v := range config.GetAnnotations() { | ||||||
|  | 		if _, ok := labels[k]; !ok { | ||||||
|  | 			// Only write to labels if the key doesn't exist. | ||||||
|  | 			labels[k] = v | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	image := "" | ||||||
|  | 	if iSpec := config.GetImage(); iSpec != nil { | ||||||
|  | 		image = iSpec.GetImage() | ||||||
|  | 	} | ||||||
|  | 	createConfig := dockertypes.ContainerCreateConfig{ | ||||||
|  | 		Name: config.GetName(), | ||||||
|  | 		Config: &dockercontainer.Config{ | ||||||
|  | 			// TODO: set User. | ||||||
|  | 			Hostname:   sandboxConfig.GetHostname(), | ||||||
|  | 			Entrypoint: dockerstrslice.StrSlice(config.GetCommand()), | ||||||
|  | 			Cmd:        dockerstrslice.StrSlice(config.GetArgs()), | ||||||
|  | 			Env:        generateEnvList(config.GetEnvs()), | ||||||
|  | 			Image:      image, | ||||||
|  | 			WorkingDir: config.GetWorkingDir(), | ||||||
|  | 			Labels:     labels, | ||||||
|  | 			// Interactive containers: | ||||||
|  | 			OpenStdin: config.GetStdin(), | ||||||
|  | 			StdinOnce: config.GetStdinOnce(), | ||||||
|  | 			Tty:       config.GetTty(), | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Fill the HostConfig. | ||||||
|  | 	hc := &dockercontainer.HostConfig{ | ||||||
|  | 		Binds:          generateMountBindings(config.GetMounts()), | ||||||
|  | 		ReadonlyRootfs: config.GetReadonlyRootfs(), | ||||||
|  | 		Privileged:     config.GetPrivileged(), | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Apply options derived from the sandbox config. | ||||||
|  | 	if lc := sandboxConfig.GetLinux(); lc != nil { | ||||||
|  | 		// Apply Cgroup options. | ||||||
|  | 		// TODO: Check if this works with per-pod cgroups. | ||||||
|  | 		hc.CgroupParent = lc.GetCgroupParent() | ||||||
|  |  | ||||||
|  | 		// Apply namespace options. | ||||||
|  | 		sandboxNSMode := fmt.Sprintf("container:%v", podSandboxID) | ||||||
|  | 		hc.NetworkMode = dockercontainer.NetworkMode(sandboxNSMode) | ||||||
|  | 		hc.IpcMode = dockercontainer.IpcMode(sandboxNSMode) | ||||||
|  | 		hc.UTSMode = "" | ||||||
|  | 		hc.PidMode = "" | ||||||
|  |  | ||||||
|  | 		nsOpts := lc.GetNamespaceOptions() | ||||||
|  | 		if nsOpts != nil { | ||||||
|  | 			if nsOpts.GetHostNetwork() { | ||||||
|  | 				hc.UTSMode = namespaceModeHost | ||||||
|  | 			} | ||||||
|  | 			if nsOpts.GetHostPid() { | ||||||
|  | 				hc.PidMode = namespaceModeHost | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Apply Linux-specific options if applicable. | ||||||
|  | 	if lc := config.GetLinux(); lc != nil { | ||||||
|  | 		// Apply resource options. | ||||||
|  | 		// TODO: Check if the units are correct. | ||||||
|  | 		// TODO: Can we assume the defaults are sane? | ||||||
|  | 		rOpts := lc.GetResources() | ||||||
|  | 		if rOpts != nil { | ||||||
|  | 			hc.Resources = dockercontainer.Resources{ | ||||||
|  | 				Memory:     rOpts.GetMemoryLimitInBytes(), | ||||||
|  | 				MemorySwap: -1, // Always disable memory swap. | ||||||
|  | 				CPUShares:  rOpts.GetCpuShares(), | ||||||
|  | 				CPUQuota:   rOpts.GetCpuQuota(), | ||||||
|  | 				CPUPeriod:  rOpts.GetCpuPeriod(), | ||||||
|  | 				// TODO: Need to set devices. | ||||||
|  | 			} | ||||||
|  | 			hc.OomScoreAdj = int(rOpts.GetOomScoreAdj()) | ||||||
|  | 		} | ||||||
|  | 		// Note: ShmSize is handled in kube_docker_client.go | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// TODO: Seccomp support. Need to figure out how to pass seccomp options | ||||||
|  | 	// through the runtime API (annotations?).See dockerManager.getSecurityOpts() | ||||||
|  | 	// for the details. Always set the default seccomp profile for now. | ||||||
|  | 	hc.SecurityOpt = []string{fmt.Sprintf("%s=%s", "seccomp", defaultSeccompProfile)} | ||||||
|  | 	// TODO: Add or drop capabilities. | ||||||
|  |  | ||||||
|  | 	createConfig.HostConfig = hc | ||||||
|  | 	createResp, err := ds.client.CreateContainer(createConfig) | ||||||
|  | 	if createResp != nil { | ||||||
|  | 		return createResp.ID, err | ||||||
|  | 	} | ||||||
|  | 	return "", err | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // StartContainer starts the container. | ||||||
|  | func (ds *dockerService) StartContainer(rawContainerID string) error { | ||||||
|  | 	return ds.client.StartContainer(rawContainerID) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // StopContainer stops a running container with a grace period (i.e., timeout). | ||||||
|  | func (ds *dockerService) StopContainer(rawContainerID string, timeout int64) error { | ||||||
|  | 	return ds.client.StopContainer(rawContainerID, int(timeout)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // RemoveContainer removes the container. | ||||||
|  | // TODO: If a container is still running, should we forcibly remove it? | ||||||
|  | func (ds *dockerService) RemoveContainer(rawContainerID string) error { | ||||||
|  | 	return ds.client.RemoveContainer(rawContainerID, dockertypes.ContainerRemoveOptions{RemoveVolumes: true}) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ContainerStatus returns the container status. | ||||||
|  | // TODO: Implement the function. | ||||||
|  | func (ds *dockerService) ContainerStatus(rawContainerID string) (*runtimeApi.ContainerStatus, error) { | ||||||
|  | 	return nil, fmt.Errorf("not implemented") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Exec execute a command in the container. | ||||||
|  | // TODO: Implement the function. | ||||||
|  | func (ds *dockerService) Exec(rawContainerID string, cmd []string, tty bool, stdin io.Reader, stdout, stderr io.WriteCloser) error { | ||||||
|  | 	return fmt.Errorf("not implemented") | ||||||
|  | } | ||||||
							
								
								
									
										85
									
								
								pkg/kubelet/dockershim/docker_image.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								pkg/kubelet/dockershim/docker_image.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | |||||||
|  | /* | ||||||
|  | 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 dockershim | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  |  | ||||||
|  | 	dockertypes "github.com/docker/engine-api/types" | ||||||
|  | 	runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // This file implements methods in ImageManagerService. | ||||||
|  |  | ||||||
|  | // ListImages lists existing images. | ||||||
|  | func (ds *dockerService) ListImages(filter *runtimeApi.ImageFilter) ([]*runtimeApi.Image, error) { | ||||||
|  | 	opts := dockertypes.ImageListOptions{} | ||||||
|  | 	if filter != nil { | ||||||
|  | 		if imgSpec := filter.GetImage(); imgSpec != nil { | ||||||
|  | 			opts.MatchName = imgSpec.GetImage() | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	images, err := ds.client.ListImages(opts) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	result := []*runtimeApi.Image{} | ||||||
|  | 	for _, i := range images { | ||||||
|  | 		apiImage, err := toRuntimeAPIImage(&i) | ||||||
|  | 		if err != nil { | ||||||
|  | 			// TODO: log an error message? | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		result = append(result, apiImage) | ||||||
|  | 	} | ||||||
|  | 	return result, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ImageStatus returns the status of the image. | ||||||
|  | func (ds *dockerService) ImageStatus(image *runtimeApi.ImageSpec) (*runtimeApi.Image, error) { | ||||||
|  | 	images, err := ds.ListImages(&runtimeApi.ImageFilter{Image: image}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	if len(images) != 1 { | ||||||
|  | 		return nil, fmt.Errorf("ImageStatus returned more than one image: %+v", images) | ||||||
|  | 	} | ||||||
|  | 	return images[0], nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // PullImage pulls a image with authentication config. | ||||||
|  | func (ds *dockerService) PullImage(image *runtimeApi.ImageSpec, auth *runtimeApi.AuthConfig) error { | ||||||
|  | 	// TODO: add default tags for images or should this be done by kubelet? | ||||||
|  | 	return ds.client.PullImage(image.GetImage(), | ||||||
|  | 		dockertypes.AuthConfig{ | ||||||
|  | 			Username:      auth.GetUsername(), | ||||||
|  | 			Password:      auth.GetPassword(), | ||||||
|  | 			ServerAddress: auth.GetServerAddress(), | ||||||
|  | 			IdentityToken: auth.GetIdentityToken(), | ||||||
|  | 			RegistryToken: auth.GetRegistryToken(), | ||||||
|  | 		}, | ||||||
|  | 		dockertypes.ImagePullOptions{}, | ||||||
|  | 	) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // RemoveImage removes the image. | ||||||
|  | func (ds *dockerService) RemoveImage(image *runtimeApi.ImageSpec) error { | ||||||
|  | 	_, err := ds.client.RemoveImage(image.GetImage(), dockertypes.ImageRemoveOptions{PruneChildren: true}) | ||||||
|  | 	return err | ||||||
|  | } | ||||||
							
								
								
									
										51
									
								
								pkg/kubelet/dockershim/docker_sandbox.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								pkg/kubelet/dockershim/docker_sandbox.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | |||||||
|  | /* | ||||||
|  | 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 dockershim | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  |  | ||||||
|  | 	runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // CreatePodSandbox creates a pod-level sandbox. | ||||||
|  | // The definition of PodSandbox is at https://github.com/kubernetes/kubernetes/pull/25899 | ||||||
|  | func (ds *dockerService) CreatePodSandbox(config *runtimeApi.PodSandboxConfig) (string, error) { | ||||||
|  | 	return "", fmt.Errorf("Not implemented") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // StopPodSandbox stops the sandbox. If there are any running containers in the | ||||||
|  | // sandbox, they should be force terminated. | ||||||
|  | func (ds *dockerService) StopPodSandbox(podSandboxID string) error { | ||||||
|  | 	return fmt.Errorf("Not implemented") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // DeletePodSandbox deletes the sandbox. If there are running containers in the | ||||||
|  | // sandbox, they should be forcibly deleted. | ||||||
|  | func (ds *dockerService) DeletePodSandbox(podSandboxID string) error { | ||||||
|  | 	return fmt.Errorf("Not implemented") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // PodSandboxStatus returns the Status of the PodSandbox. | ||||||
|  | func (ds *dockerService) PodSandboxStatus(podSandboxID string) (*runtimeApi.PodSandboxStatus, error) { | ||||||
|  | 	return nil, fmt.Errorf("Not implemented") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ListPodSandbox returns a list of Sandbox. | ||||||
|  | func (ds *dockerService) ListPodSandbox(filter *runtimeApi.PodSandboxFilter) ([]*runtimeApi.PodSandbox, error) { | ||||||
|  | 	return nil, fmt.Errorf("Not implemented") | ||||||
|  | } | ||||||
							
								
								
									
										78
									
								
								pkg/kubelet/dockershim/docker_service.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								pkg/kubelet/dockershim/docker_service.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | |||||||
|  | /* | ||||||
|  | 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 dockershim | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  |  | ||||||
|  | 	"k8s.io/kubernetes/pkg/api" | ||||||
|  | 	runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" | ||||||
|  | 	kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" | ||||||
|  | 	"k8s.io/kubernetes/pkg/kubelet/dockertools" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	dockerRuntimeName = "docker" | ||||||
|  | 	kubeAPIVersion    = "0.1.0" | ||||||
|  |  | ||||||
|  | 	// String used to detect docker host mode for various namespaces (e.g. | ||||||
|  | 	// networking). Must match the value returned by docker inspect -f | ||||||
|  | 	// '{{.HostConfig.NetworkMode}}'. | ||||||
|  | 	namespaceModeHost = "host" | ||||||
|  |  | ||||||
|  | 	defaultSeccompProfile = "unconfined" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func NewDockerSevice(client dockertools.DockerInterface) DockerLegacyService { | ||||||
|  | 	return &dockerService{ | ||||||
|  | 		client: dockertools.NewInstrumentedDockerInterface(client), | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // DockerLegacyService is an interface that embeds both the new | ||||||
|  | // RuntimeService and ImageService interfaces, while including legacy methods | ||||||
|  | // for backward compatibility. | ||||||
|  | type DockerLegacyService interface { | ||||||
|  | 	kubecontainer.RuntimeService | ||||||
|  | 	kubecontainer.ImageManagerService | ||||||
|  |  | ||||||
|  | 	// Supporting legacy methods for docker. | ||||||
|  | 	GetContainerLogs(pod *api.Pod, containerID kubecontainer.ContainerID, logOptions *api.PodLogOptions, stdout, stderr io.Writer) (err error) | ||||||
|  | 	kubecontainer.ContainerAttacher | ||||||
|  | 	PortForward(pod *kubecontainer.Pod, port uint16, stream io.ReadWriteCloser) error | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type dockerService struct { | ||||||
|  | 	client dockertools.DockerInterface | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Version returns the runtime name, runtime version and runtime API version | ||||||
|  | func (ds *dockerService) Version(apiVersion string) (*runtimeApi.VersionResponse, error) { | ||||||
|  | 	v, err := ds.client.Version() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, fmt.Errorf("docker: failed to get docker version: %v", err) | ||||||
|  | 	} | ||||||
|  | 	runtimeAPIVersion := kubeAPIVersion | ||||||
|  | 	name := dockerRuntimeName | ||||||
|  | 	return &runtimeApi.VersionResponse{ | ||||||
|  | 		Version:           &runtimeAPIVersion, | ||||||
|  | 		RuntimeName:       &name, | ||||||
|  | 		RuntimeVersion:    &v.Version, | ||||||
|  | 		RuntimeApiVersion: &v.APIVersion, | ||||||
|  | 	}, nil | ||||||
|  | } | ||||||
							
								
								
									
										78
									
								
								pkg/kubelet/dockershim/helpers.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								pkg/kubelet/dockershim/helpers.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | |||||||
|  | /* | ||||||
|  | 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 dockershim | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  |  | ||||||
|  | 	dockerapiversion "github.com/docker/engine-api/types/versions" | ||||||
|  | 	runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // apiVersion implements kubecontainer.Version interface by implementing | ||||||
|  | // Compare() and String(). It uses the compare function of engine-api to | ||||||
|  | // compare docker apiversions. | ||||||
|  | type apiVersion string | ||||||
|  |  | ||||||
|  | func (v apiVersion) String() string { | ||||||
|  | 	return string(v) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (v apiVersion) Compare(other string) (int, error) { | ||||||
|  | 	if dockerapiversion.LessThan(string(v), other) { | ||||||
|  | 		return -1, nil | ||||||
|  | 	} else if dockerapiversion.GreaterThan(string(v), other) { | ||||||
|  | 		return 1, nil | ||||||
|  | 	} | ||||||
|  | 	return 0, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // generateEnvList converts KeyValue list to a list of strings, in the form of | ||||||
|  | // '<key>=<value>', which can be understood by docker. | ||||||
|  | func generateEnvList(envs []*runtimeApi.KeyValue) (result []string) { | ||||||
|  | 	for _, env := range envs { | ||||||
|  | 		result = append(result, fmt.Sprintf("%s=%s", env.GetKey(), env.GetValue())) | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // generateMountBindings converts the mount list to a list of strings that | ||||||
|  | // can be understood by docker. | ||||||
|  | // Each element in the string is in the form of: | ||||||
|  | // '<HostPath>:<ContainerPath>', or | ||||||
|  | // '<HostPath>:<ContainerPath>:ro', if the path is read only, or | ||||||
|  | // '<HostPath>:<ContainerPath>:Z', if the volume requires SELinux | ||||||
|  | // relabeling and the pod provides an SELinux label | ||||||
|  | func generateMountBindings(mounts []*runtimeApi.Mount) (result []string) { | ||||||
|  | 	// TODO: resolve podHasSELinuxLabel | ||||||
|  | 	for _, m := range mounts { | ||||||
|  | 		bind := fmt.Sprintf("%s:%s", m.GetHostPath(), m.GetContainerPath()) | ||||||
|  | 		readOnly := m.GetReadonly() | ||||||
|  | 		if readOnly { | ||||||
|  | 			bind += ":ro" | ||||||
|  | 		} | ||||||
|  | 		if m.GetSelinuxRelabel() { | ||||||
|  | 			if readOnly { | ||||||
|  | 				bind += ",Z" | ||||||
|  | 			} else { | ||||||
|  | 				bind += ":Z" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		result = append(result, bind) | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
							
								
								
									
										43
									
								
								pkg/kubelet/dockershim/legacy.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								pkg/kubelet/dockershim/legacy.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | |||||||
|  | /* | ||||||
|  | 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 dockershim | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  |  | ||||||
|  | 	"k8s.io/kubernetes/pkg/api" | ||||||
|  | 	kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" | ||||||
|  | 	"k8s.io/kubernetes/pkg/util/term" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // This file implements the functions that are needed for backward | ||||||
|  | // compatibility. Therefore, it imports various kubernetes packages | ||||||
|  | // directly. | ||||||
|  |  | ||||||
|  | // TODO: implement the methods in this file. | ||||||
|  | func (ds *dockerService) AttachContainer(id kubecontainer.ContainerID, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan term.Size) (err error) { | ||||||
|  | 	return fmt.Errorf("not implemented") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (ds *dockerService) GetContainerLogs(pod *api.Pod, containerID kubecontainer.ContainerID, logOptions *api.PodLogOptions, stdout, stderr io.Writer) (err error) { | ||||||
|  | 	return fmt.Errorf("not implemented") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (ds *dockerService) PortForward(pod *kubecontainer.Pod, port uint16, stream io.ReadWriteCloser) error { | ||||||
|  | 	return fmt.Errorf("not implemented") | ||||||
|  | } | ||||||
| @@ -225,7 +225,7 @@ func NewDockerManager( | |||||||
| 	seccompProfileRoot string, | 	seccompProfileRoot string, | ||||||
| 	options ...kubecontainer.Option) *DockerManager { | 	options ...kubecontainer.Option) *DockerManager { | ||||||
| 	// Wrap the docker client with instrumentedDockerInterface | 	// Wrap the docker client with instrumentedDockerInterface | ||||||
| 	client = newInstrumentedDockerInterface(client) | 	client = NewInstrumentedDockerInterface(client) | ||||||
|  |  | ||||||
| 	// Work out the location of the Docker runtime, defaulting to /var/lib/docker | 	// Work out the location of the Docker runtime, defaulting to /var/lib/docker | ||||||
| 	// if there are any problems. | 	// if there are any problems. | ||||||
|   | |||||||
| @@ -30,7 +30,7 @@ type instrumentedDockerInterface struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| // Creates an instrumented DockerInterface from an existing DockerInterface. | // Creates an instrumented DockerInterface from an existing DockerInterface. | ||||||
| func newInstrumentedDockerInterface(dockerClient DockerInterface) DockerInterface { | func NewInstrumentedDockerInterface(dockerClient DockerInterface) DockerInterface { | ||||||
| 	return instrumentedDockerInterface{ | 	return instrumentedDockerInterface{ | ||||||
| 		client: dockerClient, | 		client: dockerClient, | ||||||
| 	} | 	} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Yu-Ju Hong
					Yu-Ju Hong