docker是什么?
Docker原本是指在船只停靠港口之后将商品移进或移出的工人。 箱子和物品的大小和形状各异,而有经验的码头工人能以合算的方式手工将商品装入船只,因而他们倍受青睐。对在我们来说,箱子和物品代指各种软件,船代指服务器。
Docker名如logo,是装载在“蓝鲸”这条大船上的集装箱,容器就是通过集装箱将“应用程序”封装在一起,同时保证集装箱之间不会互相影响且方便调配。
comment:!(@attachment/Clipboard_2020-03-18-09-18-29.png)
comment:!(@attachment/Clipboard_2020-03-18-09-18-50.png)
- 部署软件到不同环境所需的工作量巨大。 即使不是采用手工运行脚本的方式在不同机器上进行软件配备(还是有很多人这么做) ,用户也不得不全力应付那些配置管理工具,它们掌管着渴求资源且快速变化的环境的状态。 即便将这些工作封装到虚拟机中,还是需要花费大量时间来部署这些虚拟机、 等待它们启动并管理它们所产生的额外的资源开销。
- 使用Docker,配置工作从资源管理中分离了出来,而部署工作则是微不足道的:运行 ,环境的镜像会被拉取下来并准备运行,所消耗的资源更少并且是内含的,因此不会干扰其他环境。
上文摘自《doaker实践》
docker是如何实现的?
实现docker使用了哪些核心技术? namespace!
命名空间(namespaces)是 Linux 为我们提供的用于分离进程树、网络接口、挂载点以及进程间通信等资源的方法。在日常使用 Linux 或者 macOS 时,我们并没有运行多个完全分离的服务器的需要,但是如果我们在服务器上启动了多个服务,这些服务其实会相互影响的,每一个服务都能看到其他服务的进程,也可以访问宿主机器上的任意文件,这是很多时候我们都不愿意看到的,我们更希望运行在同一台机器上的不同服务能做到完全隔离,就像运行在多台不同的机器上一样。
网络和进程namespace
使用docker启动名字为nginx的容器,顾名思义容器内启动nginx进程。1
2
3[root@managementa ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cf00e06b02de goharbor/nginx-photon:v1.9.1 "nginx -g 'daemon of…" 4 months ago Up 12 days (healthy) 0.0.0.0:80->8080/tcp nginx
查看系统的进程,发现容器内的进程在系统下是可见的。所以docker中的资源是逻辑分隔的(类似沙箱)并不是物理分隔的。1
2
3
4
5
6
7
8
9[root@managementa ~]# ps aux
4 0 2337 1 20 0 1346300 58512 wait Ssl ? 72:40 /usr/local/docker/dockerd
4 0 2371 2337 20 0 1121184 31476 futex_ Ssl ? 52:26 containerd --config /var/run/docker/containerd/containerd.toml --log-level info
0 0 3729 2371 20 0 109020 10124 futex_ Sl ? 15:16 containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/cf00e06b02deb2c9891867
4 10000 3746 3729 20 0 30148 3364 sigsus Ss ? 0:00 nginx: master process nginx -g daemon off;
1 10000 3830 3746 20 0 30592 1612 ep_pol S ? 0:12 nginx: worker process
1 10000 3831 3746 20 0 30592 1360 ep_pol S ? 0:00 nginx: worker process
1 10000 3832 3746 20 0 30592 1360 ep_pol S ? 0:00 nginx: worker process
1 10000 3833 3746 20 0 30592 1360 ep_pol S ? 0:00 nginx: worker process
逻辑分隔是通过namespace分隔的,下面输出namespace内核对象的地址。地址是不同的证明系统进程和docker的进程使用的不同的namespace。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15[root@managementa ~]# ll /proc/3746/ns && ll /proc/1/ns
总用量 0
lrwxrwxrwx 1 10000 10000 0 3月 5 15:23 ipc -> ipc:[4026533278]
lrwxrwxrwx 1 10000 10000 0 3月 5 15:23 mnt -> mnt:[4026533276]
lrwxrwxrwx 1 10000 10000 0 3月 5 15:22 net -> net:[4026533281]
lrwxrwxrwx 1 10000 10000 0 3月 5 15:23 pid -> pid:[4026533279]
lrwxrwxrwx 1 10000 10000 0 3月 18 09:33 user -> user:[4026531837]
lrwxrwxrwx 1 10000 10000 0 3月 5 15:23 uts -> uts:[4026533277]
总用量 0
lrwxrwxrwx 1 root root 0 3月 18 09:26 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 3月 18 09:26 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 root root 0 3月 18 09:26 net -> net:[4026531956]
lrwxrwxrwx 1 root root 0 3月 18 09:26 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 3月 18 09:26 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 3月 18 09:26 uts -> uts:[4026531838]
切换namespace进入docker的命名空间执行ip命令,docker的命名空间是看不到系统中网络信息的,二者是隔离的。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16[root@managementa ~]# mkdir /var/run/netns
[root@managementa ~]# ln -s /proc/3746/ns/net /var/run/netns/nginx
[root@managementa ~]# ip netns
nginx (id: 8)
[root@managementa ~]# ip netns exec nginx ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
20: eth0@if21: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:12:00:08 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.18.0.8/16 brd 172.18.255.255 scope global eth0
valid_lft forever preferred_lft forever
[root@managementa ~]# docker inspect --format '{{.NetworkSettings.Networks.harbor_harbor.IPAddress}}' nginx
172.18.0.8
进入docker内部,是不可见系统下的进程,只能看到docker命名空间下的进程,二者是隔离的。1
2
3
4
5
6
7
8[root@managementa ~]# docker exec nginx ps -ef
UID PID PPID C STIME TTY TIME CMD
nginx 1 0 0 02:39:47 ? 00:00:00 nginx: master process nginx -g daemon off;
nginx 6 1 0 02:39:47 ? 00:00:00 nginx: worker process
nginx 7 1 0 02:39:47 ? 00:00:00 nginx: worker process
nginx 8 1 0 02:39:47 ? 00:00:00 nginx: worker process
nginx 9 1 0 02:39:47 ? 00:00:00 nginx: worker process
nginx 16 0 4 02:40:25 ? 00:00:00 ps -ef
挂载点namespace
unshare可以产生新的挂载点,如下。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[root@managementa ~]# echo $$
2152701
[root@managementa ~]# unshare --mount /bin/bash
[root@managementa ~]# echo $$
2291330
[root@managementa ~]# history -c
[root@managementa ~]# ps -ef | grep 2152701
root 2152701 2152550 0 09:10 pts/0 00:00:00 -bash
root 2291330 2152701 0 11:00 pts/0 00:00:00 /bin/bash
root 2291356 2291330 0 11:00 pts/0 00:00:00 grep --color=auto 2152701
[root@managementa ~]# ll /proc/{1,2152701,2291330}/ns
/proc/1/ns:
总用量 0
lrwxrwxrwx 1 root root 0 3月 18 09:26 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 3月 18 09:26 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 root root 0 3月 18 09:26 net -> net:[4026531956]
lrwxrwxrwx 1 root root 0 3月 18 09:26 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 3月 18 09:26 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 3月 18 09:26 uts -> uts:[4026531838]
/proc/2152701/ns:
总用量 0
lrwxrwxrwx 1 root root 0 3月 18 11:02 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 3月 18 11:02 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 root root 0 3月 18 11:02 net -> net:[4026531956]
lrwxrwxrwx 1 root root 0 3月 18 11:02 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 3月 18 11:02 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 3月 18 11:02 uts -> uts:[4026531838]
/proc/2291330/ns:
总用量 0
lrwxrwxrwx 1 root root 0 3月 18 11:02 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 3月 18 11:02 mnt -> mnt:[4026532991]
lrwxrwxrwx 1 root root 0 3月 18 11:02 net -> net:[4026531956]
lrwxrwxrwx 1 root root 0 3月 18 11:02 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 3月 18 11:02 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 3月 18 11:02 uts -> uts:[4026531838]
看下docker都挂载了啥?1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16[root@managementa ~]# docker exec nginx mount
rootfs on / type rootfs (rw)
overlay on / type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/AX7GD6WXQ4X3K7HVOUWKTN2DWM:/var/lib/docker/overlay2/l/EOKSEG57EUUAGCYKGTZ2JJZCTH:/var/lib/docker/overlay2/l/EQ37V7KVDX6LDSL36FUDOEVYDN,upperdir=/var/lib/docker/overlay2/2e07771e2b3ec9b7de929155cb223f10b28d0b925b3a0d87772d8452b1eba73e/diff,workdir=/var/lib/docker/overlay2/2e07771e2b3ec9b7de929155cb223f10b28d0b925b3a0d87772d8452b1eba73e/work)
...
[root@managementa ~]# ls /var/lib/docker/overlay2/l/AX7GD6WXQ4X3K7HVOUWKTN2DWM /var/lib/docker/overlay2/l/EOKSEG57EUUAGCYKGTZ2JJZCTH /var/lib/docker/overlay2/l/EQ37V7KVDX6LDSL36FUDOEVYDN /var/lib/docker/overlay2/2e07771e2b3ec9b7de929155cb223f10b28d0b925b3a0d87772d8452b1eba73e/diff
/var/lib/docker/overlay2/2e07771e2b3ec9b7de929155cb223f10b28d0b925b3a0d87772d8452b1eba73e/diff:
tmp var
/var/lib/docker/overlay2/l/AX7GD6WXQ4X3K7HVOUWKTN2DWM:
dev etc
/var/lib/docker/overlay2/l/EOKSEG57EUUAGCYKGTZ2JJZCTH:
etc usr var
/var/lib/docker/overlay2/l/EQ37V7KVDX6LDSL36FUDOEVYDN:
bin boot dev etc home lib lib64 media mnt proc root run sbin srv sys tmp usr var
1 | [root@managementa ~]# ll /var/lib/docker/overlay2/l/AX7GD6WXQ4X3K7HVOUWKTN2DWM /var/lib/docker/overlay2/l/EOKSEG57EUUAGCYKGTZ2JJZCTH /var/lib/docker/overlay2/l/EQ37V7KVDX6LDSL36FUDOEVYDN /var/lib/docker/overlay2/2e07771e2b3ec9b7de929155cb223f10b28d0b925b3a0d87772d8452b1eba73e/diff |
上面说明:
- image文件被docker挂载在内部,作为rootfs。
- image是分层的(看名字diff,merged)。
- image中有docker启动的重要依赖环境。
总结
docker的核心技术是namespace。
- windows是否支持docker?不是原生支持的,需要安装虚拟机。
- 使用docker是否损失很多性能?目前看几乎不损失性能。
- 为什么docker是轻量级的。
- docker是否可以任意迁移。是
docker优点
替代虚拟机(VM)
Docker可以在很多情况下替代虚拟机。 如果用户只关心应用程序,而不是操作系统,可以用Docker替代虚拟机,并将操作系统交给其他人去考虑。 Docker不仅启动速度比虚拟机快,迁移时也更为轻量,同时得益于它的分层文件系统,与其他人分享变更时更简单、 更快捷。 而且,它牢牢地扎根在命令行中,非常适合脚本化。
软件原型
如果想快速体验软件,同时避免干扰目前的设置或配备一个虚拟机的麻烦,Docker可以在几毫秒内提供一个沙箱环境。 在亲身体验之前,很难感受到这种解放的效果。
打包软件
因为对Linux用户而言,Docker镜像实际上没有依赖,所以非常适合用于打包软件(构建镜像文件后任意部署)。 用户可以构建镜像,并确保它可以运行在任何现代Linux机器上——就像Java一样,但不需要JVM。
让微服务架构成为可能
Docker 有助于将一个复杂系统分解成一系列可组合的部分,这让用户可以用更离散的方式来思考其服务。 用户可以在不影响全局的前提下重组软件使其各部分更易于管理和可插拔。
网络建模
由于可以在一台机器上启动数百个(甚至数千个) 隔离的容器,因此对网络进行建模轻而易举。 这对于现实世界场景的测试非常有用,而且所费无几。
离线时启用全栈生产力
因为可以将系统的所有部分捆绑在Docker容器中,所以用户可以将其编排运行在笔记本电脑中移动办公,即便在离线时也没问题。
降低调试支出
不同团队之间关于软件交付的复杂谈判在业内司空见惯。 我们亲身经历过不计其数的这类讨论:失效的库、 有问题的依赖、 更新被错误实施或是执行顺序有误,甚至可能根本没执行以及无法重现的错误等。 估计读者也遇到过。 Docker让用户可以清晰地说明(即便是脚本的形式)在一个属性已知的系统上调试问题的步骤,错误和环境重现变得更简单,而且通常与所提供的宿主机环境是分离的。
文档化软件依赖及接触点
通过使用结构化方式构建镜像,为迁移到不同环境做好准备,Docker 强制用户从一个基本出发点开始明确地记录软件依赖。 即使用户不打算在所有地方都使用Docker,这种对文档记录的需要也有助于在其他地方安装软件。
启用持续交付
持续交付(continuous delivery,CD) 是一个基于流水线的软件交付范型,该流水线通过一个自动化(或半自动化) 流程在每次变动时重新构建系统然后交付到生产环境中。
上文摘自《doaker实践》
docker与k8s
如何把docker组合成一个集群?其中一个领先的方案就是k8s,docker组成集群需要做什么?
- 分布式操作docker,给k8s一个创建容器指令,它需要从服务器集群中选择合适的机器创建容器。
- k8s维护docker集群的状态,比如docker挂了,k8s检测到会尝试重启,或者启动一个新的docker。
- docker压力很大,如何扩容,k8s会动态扩容。
- 多个docker运行相同的服务,k8s会负载均衡。
- 如何在不停止服务的情况下让docker(docker中的服务war包)滚动升级。
- docker之间的网络如何连通。(flannel,openvswitch)
k8s架构
Kubernetes主要由以下几个核心组件组成:
- etcd保存了整个集群的状态;
- apiserver提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制;
- controller manager负责维护集群的状态,比如故障检测、自动扩展、滚动更新等;
- scheduler负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上;
- kubelet负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理;
- Container runtime负责镜像管理以及Pod和容器的真正运行(CRI);
- kube-proxy负责为Service提供cluster内部的服务发现和负载均衡;
- node 的职责是运行容器应用。Node 由 Master 管理,Node 负责监控并汇报容器的状态,并根据 Master 的要求管理容器的生命周期。Node 运行在 Linux 操作系统,可以是物理机或者是虚拟机。
- pod是 Kubernetes 的最小工作单元。每个 Pod 包含一个或多个容器。Pod 中的容器会作为一个整体被 Master 调度到一个 Node 上运行。pod为docker创建的一个容器。
除了核心组件,还有一些推荐的Add-ons:
- kube-dns负责为整个集群提供DNS服务
- Ingress Controller为服务提供外网入口(在host文件中配置,实现一个端口访问多个网站)
- Dashboard提供GUI
- Fluentd-elasticsearch提供集群日志采集、存储与查询
一个问题 - 如何让kubectl更方便,更方便的监控k8s ==> rancher , 如下配置rancher可以选择生成。
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
27apiVersion: v1
kind: ReplicationController
metadata:
name: tomcat-infoverisystem
labels:
name: tomcat-infoverisystem
spec:
replicas: 1
selector:
name: tomcat-infoverisystem
template:
metadata:
labels:
name: tomcat-infoverisystem
spec:
containers:
- name: tomcat-infoverisystem
image: 192.168.106.117/library/tomcat:8.5.35
ports:
- containerPort: 8080
volumeMounts:
- name: tomcat-war-pvc
mountPath: "/usr/local/tomcat/webapps"
volumes:
- name: tomcat-war-pvc
persistentVolumeClaim:
claimName: tomcat-war-pvc
结合docker架构说明如何构建docker集群:
还差一点,docker集群的实现必须有私有的镜像服务器。
一个案例
关于CI/CD
持续集成(CI)
持续交付(CD)
持续部署(CD),生产环境是自动部署的。
持续部署实现(gitlab控制gitlabrunner执行job)
1、文档中名词保持一致,或者加一个定义。
比如Docker是集装箱,tomcat是容器,集装箱和容器是什么样的关联。图上描述的有点乱,前后不一致。各种软件、容器、应用程序、集装箱、船只、港口、码头都什么关系描述不清楚。
合算的方式手工将商品装入船只,合算指的是啥。
docker优点可以先说,然后再引申话题,展开docker是如何实现的。描述所有优点后再针对每个优点分别展开介绍:介绍docker如何实现,持续集成流程和持续交付流程介绍。
docker以前总结的缺点也要提一下。
技术来源:省厅服务器华为虚拟云平台100多万,公司为降低这部分费用,准备搭建自研的虚拟化云平台,并经过不断地运行验证过程逐步替换掉华为服务器节点。
目前进展:公司已经搭建完成,运行了哪些系统和服务,能够实现了XXX功能,自动漂移等。
用户现场搭建了虚拟化平台,目前作为备用服务器,后续经过验证问问后会逐步替换掉华为虚拟化平台。
技术路线:为后续产品线技术路线成熟提供技术支撑储备,包括微服务化、持续集成、持续实现、快速部署、快速升级。
图片改成自己的