虚拟化技术分类:kernel级别、容器级别、库级别、应用级别
这种虚拟化技术隔离效果最好,但是性能消耗也高
vm的user进程需要发起system call的时候,需要调用vm.kernel但是真正执行的是host.kernel
使用BT,或者HVM,加速转换。
内存虚拟化:shadow MMU
CPU虚拟化:tagged TLB
lxc:linux container
openvz:
xen或者kvm隔离效果比较好,
容器技术:隔离的是user space
wine
cywin
jvm
...
Docker的核心目标:Configure Once, Run Anything
容器规范:容器包括Docker、CoreOS的rkt。由Docker、CoreOS、Google若干公司成立Open Container initiative(OCI)的组织,定义了两个规范:runtime spec和image format spec保证可移植性和可操作性
容器runtime:容器运行环境,类似于jvm为java进程提供运行环境一样。lxc(早起Docker使用)、libcontainer(现在Docker使用)和rkt(CoreOS)是目前主流的runtime
容器管理工具:lxd是lxc对应的管理工具,runc是docker engine的管理工具,rkt cli和rkt的管理工具
容器定义工具:docker imange/docker file/ACI (CoreOS的rtk容器的image格式)
registries:存放image //https://quay.io https://hub.docker.com
容器OS:专门运行容器的os //CoreOS,atomic,ubuntu core
容器编排技术:docker swarm/kubernetes/mesos+marathon
容器管理平台:Rancher/ContainerShip
基于容器的Paas:Deis/Flynn/Dokku
容器网络:flanne/weave/openvswtich/ip netns/calico ....
服务发现:etcd,consul,zookeeper
监控:docker ps/top/stats sysdig,weave Scope,cAdvisor/Heapster
数据管理:Rex-Ray
日志管理:logsput /docker logs
安全性:OpenSCAP
容器虚拟化依赖到的NS:name space
pstree:
PID 1:用户和内核交互的进程
假如us1中的进程,需要使用root权限和内核交互,它是否能够看到id号为1的进程,并且各us又是隔离的?
yum -y install psmisc //安装该包
内核级别,环境隔离;类似chroot机制
PID NameSpace: kernel 2.6.24虚拟出各种pid,每一个用户空间都可以虚拟一个pid为1的进程
PID隔离
Network NameSpace: kernel 2.6.29 实现网络隔离
网路设备,网络栈,端口号等网络资源隔离
User NameSpace:用户隔离,每一个userspace可有同样的用户名的用户
用户和yoghurt组资源隔离,kernel 3.8 +
IPC NameSpace:进程间通信 kernel 2.6.79
信号量,消息队列和共享内存等隔离
UTS NameSpace: kernel 2.6.19
主机名和域名的隔离
Mount NameSpace: us1能看到的fs一定是自己能够看到的fs,us2挂载的专有设备,fs是us1不能看到的
挂载点隔离(FS)隔离;kernel 2.4.19
为了对不同namespace访问
API:clone(),setns(),unshare();
clone:实现线程的系统调用,来实现新线程的。
setns:设定namespace的属性,假如某个进程到某个NS
unshare:非共享机制,进程脱离一个NS,关联到另一个NS
查看:
mount //可以查看挂载情况
lssubsys -m //查看各个名称空间的挂载情况
一个NS一个占用整个 userspace 的100%,其他NS就没资源用了,因此出现了CGroup
CGroup: linux control group:控制组
内核级别:限制,控制与一个进程组群的资源;
可以限制:内存,cpu等
kernel 2.6.24 收入内核
资源:CPU,内存,IO
CGroup的功能:
Resource limitation:资源限制
Prioritization:优先级控制;哪一个NS更优先获得CPU和资源
Account:统计和审计,主要为了计费
Control:挂起和恢复 进程
查看:mount -t cgroup
/sys/fs/cgroup
进程启用在哪里,代表只能使用多少资源
倒置的树状结构。
每一资源都是一棵树,cpu是一个,内存是一个,io也是一个,..也可以内存和cpu一棵树
还有其他很多的资源等。有的是重合的,有的是独立的。
术语集:
task(任务):cgroups的术语中,task就表示系统的一个进程。
cgroup(控制组):cgroups 中的资源控制都以cgroup为单位实现。cgroup表示按某种资源控制标准划分而成的任务组,包含一个或多个子系统。
一个任务可以加入某个cgroup,也可以从某个cgroup迁移到另外一个cgroup。
subsystem(子系统):cgroups中的subsystem就是一个资源调度控制器(Resource Controller)。比如CPU子系统可以控制CPU时间分配,内存子系统可以限制cgroup内存使用量。
hierarchy(层级树):hierarchy由一系列cgroup以一个树状结构排列而成,
每个hierarchy通过绑定对应的subsystem进行资源调度。
hierarchy中的cgroup节点可以包含零或多个子节点,子节点继承父节点的属性。
整个系统可以有多个hierarchy。
图1:
CGroup的子系统(subsystem):
blkio// 块设备的io资源分配,disk
cpu //设定cpu的限制 ,仅能使用40%
cpuacct //报告cgroup中所使用的cpu资源
cpuset //为cgroup中的任务分配cpu和内存资源,
分配你使用哪一个cpu 和memory,分配可以分配整个
memory //设定内存的使用限制
限制内存使用的空间,例如分配的是1个核心,但是仅运行使用40%
devices //控制cgroup中的任务对设备的访问;
freezer //挂起和回复cgroup中的任务;
net_cls(classid),使用等级级别标识符来标记网络数据包,以实现基于tc完成对不同的cgroup中产生的流量的控制;
perf_event:使用后使cgroup中的任务可以进行统一的性能测试
hugetlb;大的tlb,大内存页,hugetlb让大内存页提高命中率,对HugeTLB系统进行限制;
Union FS:它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下
Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像)
另外,不同 Docker 容器就可以共享一些基础的文件系统层,同时再加上自己独有的改动层,大大提高了存储的效率
UnionFS:把不同的物理位置的目录,合并到同一个目录中
假如有两个文件或者目录名一样?
叠加:先后顺序,最前面的才是可写的
AUFS:Another UnionFS 、Alternative UFS、Advanced UFS
但是AUFS不是内核的版本,但是ubuntu是没有的,
Docker 依赖于AUFS,用于提高性能
Docker目前支持的 Union 文件系统种类包括 AUFS, btrfs, vfs 和 DeviceMapper
原因:
之前复制bin,sbin等程序到一个目录中,chroot后可以执行
ns1和ns2一个需要ls,一个需要cat命令,但是ls和cat命令有重复使用的库,可以把该库做成一个联合库(只读)
可以把公共部分做成一个目录,ns1只放ls独有的,ns2只放cat独有的,用ls或者cat独有的联合底层公共的库即可
目的:减少disk占用
centos 不支持AUFS但是支持UNIONFS //UNIONFS没有AUFS强悍
还有另外一种方案:Device mapper
多系统机制
md:multi disks
http://www.tldp.org/HOWTO/Multi-Disk-HOWTO-1.html
dm:device mapper
Kernel 2.6 引入的最重要的技术之一,用于在内核中支持逻辑卷管理的通用设备的映射机制;
从逻辑设备到物理设备的映射框架机制,在该机制下,用户可以很方便的根据自己的需要制定实现存储资源的管理策略,
当前比较流行的 Linux 下的逻辑卷管理器如
LVM2(Linux Volume Manager 2 version)
EVMS(Enterprise Volume Management System)
dmraid(Device Mapper Raid Tool)等都是基于该机制实现?。
它包含三个重要的对象概念,mapped device、映射表、target device
mapped device:可以理解成为内核向外提供的逻辑设备,它通过映射表描述的映射关系和 target device 建立映射
target device:逻辑设备映射到的一个物理设备
https://www.ibm.com/developerworks/cn/linux/l-devmapper/
为底层块设备提供抽象设备,
Mapped Device:映射的设备
Mapping table:虚拟设备到物理设备的映射
Target Device:被映射的设备
lVM就依赖于device mapper机制。但是不建议device mapper在docker技术中使用,因为有诸多不稳定性。
Linux内核是第0层-->Docker镜像,是一个只读的镜像,位于第1层,它不能被修改或不能保存状态。
一个Docker镜像可以构建于另一个Docker镜像之上,这种层叠关系可以是多层的。
第1层的镜像层我们称之为基础镜像(Base Image),其他层的镜像(除了最顶层)我们称之为父层镜像(Parent Image)。
这些镜像继承了他们的父层镜像的所有属性和设置,并在Dockerfile中添加了自己的配置。
Docker镜像通过镜像ID进行识别。镜像ID是一个64字符的十六进制的字符串。
但是当我们运行镜像时,通常我们不会使用镜像ID来引用镜像,而是使用镜像名来引用。
要列出本地所有有效的镜像,可以使用命令
可以用同一个镜像启动多个Docker容器,这些容器启动后都是活动的,彼此还是相互隔离的。对其中一个容器所做的变更只会局限于那个容器本身。
附件1:进程间通信常用的方式:
C方法包括管道(PIPE)、消息排队、旗语、共用内存以及套接字(Socket)
图layer:
假如 运行了三个Nginx容器
第一个cn(conainer) 使用80port,第二个cn也是用80 port,但是内核之有一个80端口
方法:映射,
kernel: 8080 -> cn2.80
kernle: 888 -> cn1.80
==============================
启动docker容器,需要加载images,server从dockerHUB上下载images
把所依赖到的多个images,叠加为一个UnionFS,然后在该容器中运行
可以从公共dockerhub下载,也可以自制
可以共享让别人访问。
可以创建私有hub
图3:
docker client:docker的client工具,用户使用docker的接口,docker client与docker daemon通信。并将结果返回给client
docker daemon:运行在宿主机,Docker的守护进程,用户可通过docker client与其交互;
image :只读的,基于aufs或者UnionFS叠加在一起,用来创建container
一个镜像可以运行多个container;镜像文件可以通过Dockerfile创建,也可以从docker hub/registry 下载
repository
公共仓库 //提供有base image Docuer hub/registry
私有仓库 //docker repository
docker container:docker的运行实例,容器是一个隔离环境
docker link:各docker之间的通信,openvswtich,netns构建,
docker volume:容器中的数据的持久化
graph:维护和下载镜像信息,以及它们之间的关系
graph-driver:用于实现和graphdb交互的接口
docker-daemon:借助于graphDB来及其所维护的所有容器,以及他们之间的连接关系
例如运行多个容器的话,LAMP,要运行3个容器,三个容器要连接起来,这叫做链接机制。一个container可能建立n个链接关系
graphDB:各容器之间的链接关系
graph:维护已经下载的各镜像的关系
Image: 一个只读的镜像模板。可以自己创建一个镜像也可以从网站上下载镜像供自己使用。镜像包含了一个RFS.一个镜像可以创建很多容器。
Container:由docker client通过镜像创建的实例,用户在容器中运行应用,一旦创建后就可以看做是一个简单的RFS,每个应用运行在隔离的容器中,享用独自的权限,用户,网络。确保安全与互相干扰
两者在创建后,都是一堆layer的统一视角,唯一的却别是镜像最上面那一层是只读的,不可以修改,但是容器最上面一层是rw的,提供给用户操作
repository:仓库,最大的是docker hub,类似于google 的aosp,当然也可以本地搭,比如mig事业群就有自己的repo。
镜像:包含了启动docker容器所需要的文件系统层级结构,及其内容
一个应用程序运行所需的:程序文件、库文件、配置文件、等
基于UnionFS采用分层的结构实现;
rootfs:用户空间,完整而独立的根FS,
bootfs:最底层,引导启动一个容器必须的FS和OS的kernel,主要是用于区分不同container
安装Docker:
https://mirrors.aliyun.com/docker-engine/yum/repo/main/centos/7/
yum install docker-engine
[root@node1 ~]# rpm -ql docker-engine |egrep -v "share"
/etc/udev/rules.d/80-docker.rules
/usr/bin/docker
/usr/bin/docker-containerd
/usr/bin/docker-containerd-ctr
/usr/bin/docker-containerd-shim
/usr/bin/docker-init
/usr/bin/docker-proxy
/usr/bin/docker-runc
/usr/bin/dockerd
/usr/lib/systemd/system/docker.service
docker子命令有很多
systemctl start docker.service
docker images //查看镜像
docker search centos
Name DESCRIPTION STARS STARS OFFICAL AUTOMATED
星 自动生成
darksheer/centos //用户名:镜像名
docker pull busybox //拉取官方镜像 base iamge
tag : lastest //最新版本,默认最新版本
docker pull hub.mt.com:5000/busybox //执行私有仓库获取image,必须支持ssl。或者禁止使用tls
docker help run //运行
docker run [OPTIONS] IMAGS [COMMAND] [AEG,...]
//image应该有一个运行起来后,默认运行的命令。
-t --tty=false 分配一个默认的伪终端
-i --interactive=false 打开之后运行在交互式
[root@node1 ~]# docker run -it busybox:latest /bin/sh
docker ps //查看正在运行的 docker
需要借助于外 volume 保存创建的数据。
docker help commit //基于当前容器的所有修改,创建一个新的images
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
容器生命周期管理 — docker [run|start|stop|restart|kill|rm|pause|unpause]
容器操作运维 — docker [ps|inspect|top|attach|events|logs|wait|export|port]
容器rootfs命令 — docker [commit|cp|diff]
镜像仓库 — docker [login|pull|push|search]
本地镜像管理 — docker [images|rmi|tag|build|history|save|import]
其他命令 — docker [info|version]
docker run -it centos:latest /bin/bash
run命令:
--name //指定一个容器名
-i --interactive=false 交互模式
-t --tty=false //终端
--net=default //桥相关
-d,--detach=false //后台运行容器
ifconfig //docker0 一个虚拟接口
一半在虚拟机, 一半在宿主机
docker kill c98dac012556 //kill 掉容器,容器ID
docker ps -a //可以查看所有的。关闭后,默认还是会占用内存,可以在启动的时候
docker run --rm //退出则,rm自动移除容器
docker rm c98dac012556 //删除该容器
docker image的创建:
1.基于dockerfile
2.基于运行中的容器修改
//仅仅是打包最上面一层,只有最上面一层是可写的。
注:docker help $OPTIONS //查看帮助信息
registry:保存docker镜像及docker镜像层次结构和元数据,用于管理和维护下载的image的组件
包含了n个仓库,每个仓库包含了n个image
repository:镜像库,可以认为是registry的一个组件
一个resitry可以有多个仓库(repository),
例如: centos系列的,ubuntu的,aix的,等...
或者:tom的,jerry的,
由具有某个功能的镜像的所有相关版本构成的集合;
index:管理用户的账号、访问权限、镜像及镜像标签相关的
docker search centos//就是根据index进行查找的
graph:本地端的,从registry中下载的各docker镜像需要保存在本地,此功能由graph完成
/var/lib/docker/graph ,目录中保存下载的docker 镜像的相关数据。
与镜像相关的命令:images,search,pull,push,login,logout
创建镜像:commit,build
删除本地镜像:rmi
[root@node1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos newuser 60c8bd28f7e1 About an hour ago 281MB
busybox latest c75bebcdd211 7 days ago 1.11MB
centos latest 8140d0c64310 11 days ago 193MB
//newuser和latest都属于 centos镜像库[仓库],
latest和newuser是image 名字,centos和busybox是两个仓库
老版本的叫做docker-engine,新版本的叫做docker-ce
CentOS7上安装
yum install docker -y
CentOS6安装
yum install docker-io -y
实验1:关闭后删除容器
[root@node1 ~]# docker run -it centos:latest /bin/bash
在home中 useradd centos
[root@node1 ~]# docker commit faecb4def9d5 centos:newuser
[root@node1 ~]# docker images
有 newuser
[root@node1 ~]# docker kill faecb4def9d5
[root@node1 ~]# docker rm faecb4def9d5
[root@node1 ~]# docker ps -a
没有之前的容器了
[root@node1 ~]# docker run -it --rm centos:newuser /bin/bash
rm用于关闭后,就删除容器
[root@3f20a3c7f5df /]# id centos
uid=1000(centos) gid=1000(centos) groups=1000(centos)
[root@3f20a3c7f5df /]# exit
实验2:docker后台运行而不退出
[root@localhost ~]# docker run -dit -h wolf1 --name wolf_mt docker.io/centos /bin/bash
5e5a2ade8c73f715e3bcd0b3a849c33082c186b5cc36914cc00286957dd77351
// -d参数保证后台运行
[root@localhost ~]# docker exec -it wolf_mt bash
[root@wolf1 /]# exit
exit
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5e5a2ade8c73 docker.io/centos "/bin/bash" 32 seconds ago Up 30 seconds wolf_mt
[root@localhost ~]# docker run -d -h wolf --name test docker.io/centos date //对于date命令执行一次后就结束了,因此就直接退出了
2f108a4b4753567bbecee6bcf0cb8303184fc0e17d3b8c39e11df7021e286316
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2f108a4b4753 docker.io/centos "date" 55 seconds ago Exited (0) 52 seconds ago test
实验3:docker export(import)和save(load)的区别
docker save -o images.tar postgres:9.6 mongo:3.4 //将镜像库中的postgres和mongo打包
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3623943d369f postgres:9.6 "docker-entrypoint..." 3 hours ago Up 3 hours 5432/tcp postgres
docker save -o b.tar postgres //image名字
docker save -o c.tar postgres:9.6 //NAMES字段,这个文件是layer级别的(很长一串数字表示的)
ls -al
-rwxrwxrwx 1 root root 277886464 8月 26 14:40 b.tar
-rwxrwxrwx 1 root root 277886464 8月 26 14:41 c.tar
docker save如果指定的是container,docker save将保存的是容器背后的image。
docker load -i images.tar //加载镜像 ,如果本地镜像库已经存在这两个镜像,将会被覆盖。
用途:打包镜像然后上传到其他镜像
docker export是用来将container的文件系统进行打包 //看到的是和根fs一样的文件
#docker export -o rtools.tar caf6f35bfbbd /容器id/容器名
进入之后,看到的是容器的fs
docker export -o postgres-export.tar postgres
docker import postgres-export.tar postgres:latest
docker import将container导入后会成为一个image,而不是恢复为一个container
docker import可以指定IMAGE[:TAG],说明我们可以为镜像指定新名称。如果本地镜像库中已经存在同名的镜像,则原有镜像的名称将会被剥夺,赋给新的镜像。原有镜像将成为孤魂野鬼,只能通过IMAGE ID进行操作。
用途:主要用来制作基础镜像比如你从一个ubuntu镜像启动一个容器,然后安装一些软件和进行一些设置后给别人使用
实验4:配置国内docker 仓库
注:使用默认的docker reg去pull镜像下载较慢
可以配置daocloud、ali等
1)https://dev.aliyun.com/search.html 注册并登陆
点击镜像加速器->复制“您的专属加速器地址”->修改json文件
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-‘EOF‘
{
"registry-mirrors": ["https://ysupenjm.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
参考博客:
http://wiki.ubuntu.org.cn/OpenVZ
https://blog.csdn.net/xingwangc2014/article/details/50449851
https://www.cnblogs.com/xcloudbiz/articles/5526262.html
https://segmentfault.com/a/1190000009583199 //容器的runtime
https://blog.csdn.net/zjin_hua/article/details/52041757
https://ruby-china.org/topics/22004
https://blog.csdn.net/lwyeluo/article/details/51765309 //源码安装
https://www.server110.com/docker/201411/11121.html
原文地址:http://blog.51cto.com/hmtk520/2096677