mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-04 09:49:50 +00:00
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:
parent
0ac247c6a7
commit
03d11bcf4e
@ -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,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user