Docker命令行分析-cp-v1.12.3

Docker的copy命令可以在容器与物理机之间拷贝内容。本次分析将介绍copy命令是如何实现的。

client端

在Docker client端,copy命令由runCopy()执行。runCopy()定义在/api/client/container/cp.go中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
func runCopy(dockerCli *client.DockerCli, opts copyOptions) error {
srcContainer, srcPath := splitCpArg(opts.source)
dstContainer, dstPath := splitCpArg(opts.destination)
var direction copyDirection
if srcContainer != "" {
direction |= fromContainer
}
if dstContainer != "" {
direction |= toContainer
}
cpParam := &cpConfig{
followLink: opts.followLink,
}
ctx := context.Background()
switch direction {
case fromContainer:
return copyFromContainer(ctx, dockerCli, srcContainer, srcPath, dstPath, cpParam)
case toContainer:
return copyToContainer(ctx, dockerCli, srcPath, dstContainer, dstPath, cpParam)
case acrossContainers:
// Copying between containers isn't supported.
return fmt.Errorf("copying between containers is not supported")
default:
// User didn't specify any container.
return fmt.Errorf("must specify at least one container source")
}
}

阅读全文

tar-stream-demo

在Docker的save, cp等命令,都使用到了文件打包传输的功能。所以,这次分析将介绍这方面的一个demo,demo的功能如下:
从服务端拷贝:

  1. 在服务端读取文件,然后把文件写入数据流中;
  2. 在客户端读取数据流中的内容,然后还原成文件。

阅读全文

Docker命令分行分析-run-v1.12.3

Docker的run命令可以运行一个容器,支持的过程分为两步:Create和Start。

client端

先来看下Docker client端的run实现,实现函数为runRun(),定义在/pkg/client/container/run.go中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
func runRun(dockerCli *client.DockerCli, flags *pflag.FlagSet, opts *runOptions, copts *runconfigopts.ContainerOptions) error {
stdout, stderr, stdin := dockerCli.Out(), dockerCli.Err(), dockerCli.In()
client := dockerCli.Client()
// TODO: pass this as an argument
cmdPath := "run"
......
//***1.8.3中只有config, hostConfig,现在多了一个networkingConfig***//
//***config, hostConfig和networkingConfig详见docker inspect的结果***//
config, hostConfig, networkingConfig, err := runconfigopts.Parse(flags, copts)
// just in case the Parse does not exit
if err != nil {
reportError(stderr, cmdPath, err.Error(), true)
return cli.StatusError{StatusCode: 125}
}
if hostConfig.OomKillDisable != nil && *hostConfig.OomKillDisable && hostConfig.Memory == 0 {
fmt.Fprintf(stderr, "WARNING: Disabling the OOM killer on containers without setting a '-m/--memory' limit may be dangerous.\n")
}
//***检测DNS是否合法***//
if len(hostConfig.DNS) > 0 {
// check the DNS settings passed via --dns against
// localhost regexp to warn if they are trying to
// set a DNS to a localhost address
for _, dnsIP := range hostConfig.DNS {
if dns.IsLocalhost(dnsIP) {
fmt.Fprintf(stderr, "WARNING: Localhost DNS setting (--dns=%s) may fail in containers.\n", dnsIP)
break
}
}
}
......
//***WithCancel context***//
ctx, cancelFun := context.WithCancel(context.Background())
//***create container***//
createResponse, err := createContainer(ctx, dockerCli, config, hostConfig, networkingConfig, hostConfig.ContainerIDFile, opts.name)
......
//***处理attach相关的参数***//
attach := config.AttachStdin || config.AttachStdout || config.AttachStderr
if attach {
......
}
//***defer这种形式的用法第一次见到,可以学着用下***//
//***如需auto remove,在defer中remove container***//
if opts.autoRemove {
defer func() {
// Explicitly not sharing the context as it could be "Done" (by calling cancelFun)
// and thus the container would not be removed.
if err := removeContainer(dockerCli, context.Background(), createResponse.ID, true, false, true); err != nil {
fmt.Fprintf(stderr, "%v\n", err)
}
}()
}
//start the container
//***Fankang***//
//***start container***//
if err := client.ContainerStart(ctx, createResponse.ID, types.ContainerStartOptions{}); err != nil {
......
}
......
}

阅读全文

kubelet分析(七)-dockerManager(2)-v1.5.2

kubelet通过DockerManager与docker交互,即DockerManager对于kubelet来说就是一种runtime。本次分析将介绍dockerManager。

dockerManager

DockerManager定义在/pkg/kbuelet/dockertools/docker_manager.go中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
type DockerManager struct {
client DockerInterface
recorder record.EventRecorder
containerRefManager *kubecontainer.RefManager
os kubecontainer.OSInterface
machineInfo *cadvisorapi.MachineInfo
// The image name of the pod infra container.
podInfraContainerImage string
// (Optional) Additional environment variables to be set for the pod infra container.
podInfraContainerEnv []api.EnvVar
// TODO(yifan): Record the pull failure so we can eliminate the image checking?
// Lower level docker image puller.
dockerPuller DockerPuller
// wrapped image puller.
imagePuller images.ImageManager
// Root of the Docker runtime.
dockerRoot string
// cgroup driver used by Docker runtime.
cgroupDriver string
// Directory of container logs.
containerLogsDir string
// Network plugin.
networkPlugin network.NetworkPlugin
// Health check results.
//***livenessManager为liveness检测结果***//
livenessManager proberesults.Manager
// RuntimeHelper that wraps kubelet to generate runtime container options.
runtimeHelper kubecontainer.RuntimeHelper
// Runner of lifecycle events.
runner kubecontainer.HandlerRunner
// Handler used to execute commands in containers.
//***Fankang***//
//***在容器中执行命令***//
execHandler ExecHandler
// Used to set OOM scores of processes.
oomAdjuster *oom.OOMAdjuster
// Get information from /proc mount.
procFs procfs.ProcFSInterface
// If true, enforce container cpu limits with CFS quota support
cpuCFSQuota bool
// Container GC manager
//***container回收器***//
containerGC *containerGC
// Support for gathering custom metrics.
enableCustomMetrics bool
// If true, the "hairpin mode" flag is set on container interfaces.
// A false value means the kubelet just backs off from setting it,
// it might already be true.
configureHairpinMode bool
// Provides image stats
//***Fankang***//
//***镜像信息提供者***//
*imageStatsProvider
// The version cache of docker daemon.
versionCache *cache.ObjectCache
// Directory to host local seccomp profiles.
seccompProfileRoot string
}

阅读全文

kubelet分析(七)-dockerManager(1)-v1.5.2

dockerManager负责在kubelet中与docker打交道。dockerManager会把pod的相关信息转换成具体的docker实现,并管理docker容器。在介绍dockerManager之前,先介绍dockerManager会用到的一些其他概念:containerGC, ExecHandler, imageStatsProvider及instrumentedDockerInterface,当然,这里介绍的概念的实现在kubelet中都是最底层的实现,都是基于docker runtime的。

阅读全文

kubelet分析(六)-proberManager-v1.5.2

proberManager用来检测Kubernetes集群中Pod的健康状态。目前Kubernetes支持livenessProber和readinessProber两种:

  • livenessProber: 用来检测容器中的程序是否健康并确定何时重启容器;
  • readinessProber: 用来检测容器中的程序是否就绪,就绪意味着该容器可以接收处理流量。

阅读全文

kubelet分析(五)-podManager-v1.5.2

podManager

podManager在kubelet中负责内存中pod及mirrorPod的维护,任何在本节点上创建或删除操作都会同步更新podManager,即可以认为podManager中存储了本节点上运行的pod的信息。这里要对mirrorPod做下说明,在kubernetes中,如果是static pod,则由kubelet直接创建,这时系统很难管理这部分pod;所以系统会在kubelet中创建一个static pod对应的mirrorPod,来表示static pod。
podManager定义在/pkg/kubelet/pod/pod_manager.go中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
type basicManager struct {
// Protects all internal maps.
lock sync.RWMutex
//***UID与pod的映射***//
// Regular pods indexed by UID.
podByUID map[types.UID]*api.Pod
// Mirror pods indexed by UID.
mirrorPodByUID map[types.UID]*api.Pod
//***FullName与pod的映射***//
// Pods indexed by full name for easy access.
podByFullName map[string]*api.Pod
mirrorPodByFullName map[string]*api.Pod
// Mirror pod UID to pod UID map.
translationByUID map[types.UID]types.UID
// A mirror pod client to create/delete mirror pods.
MirrorClient
}

阅读全文

kubelet分析(四)-statusManager-v1.5.2

podStatus

一个pod的status如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
status:
conditions:
- lastProbeTime: null
lastTransitionTime: 2017-12-07T01:25:11Z
status: "True"
type: Initialized
- lastProbeTime: null
lastTransitionTime: 2017-12-17T09:13:41Z
status: "True"
type: Ready
- lastProbeTime: null
lastTransitionTime: 2017-12-07T01:25:11Z
status: "True"
type: PodScheduled
containerStatuses:
- containerID: docker://397a1f998a38c6549c73df6220fa672eb45e1b8fa317e07a1ca428ed8b108c34
image: ubuntu-ssh:v1
imageID: docker://sha256:27312dad4272a61739c317b90bfab5bc129e38696df5c606b1041199caf03ea4
lastState: {}
name: ubuntu
ready: true
restartCount: 0
state:
running:
startedAt: 2017-12-17T09:13:40Z

阅读全文

kubelet分析(三)-volumeManager-v1.5.2

本次分析将介绍kubelet的volumeManager。volumeManager负责维护volume挂载与ETCD中数据的一致性。

actualStateOfWorld

actualStateOfWorld代表了目前物理主机上volume的挂载状态,定义在/pkg/kubelet/volumemanager/cache/actual_state_of_world.go中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
type actualStateOfWorld struct {
// nodeName is the name of this node. This value is passed to Attach/Detach
nodeName types.NodeName
// attachedVolumes is a map containing the set of volumes the kubelet volume
// manager believes to be successfully attached to this node. Volume types
// that do not implement an attacher interface are assumed to be in this
// state by default.
// The key in this map is the name of the volume and the value is an object
// containing more information about the attached volume.
//***记录volume被attached***//
attachedVolumes map[api.UniqueVolumeName]attachedVolume
// volumePluginMgr is the volume plugin manager used to create volume
// plugin objects.
volumePluginMgr *volume.VolumePluginMgr
sync.RWMutex
}

阅读全文

kubelet分析(二)-podWorker-v1.5.2

上次分析了所有pod事件都会被处理后放置到updates channel中,即介绍了updates数据的生产者,本次分析将介绍updates数据的消费者。

syncLoopIteration

在/pkg/kbuelet/kubelet.go中,有:

1
2
3
4
5
//***此updates就是PodConfig中的updates***//
func (kl *Kubelet) Run(updates <-chan kubetypes.PodUpdate) {
......
kl.syncLoop(updates, kl)
}

阅读全文