因为科技技术的高度发展,在物理机服务器性能愈来愈高的今天,不少生产环境中使用的服务器,因为没有不少的用户访问,而致使性能过剩。而生产中又须要在多台服务器上部署业务。若是老是购买物理服务器,显然会形成经济成本大大增长,这时候就须要虚拟化技术来完成物理机性能的合理分配。
虚拟化技术在上世纪已经诞生,可是上世纪的物理机性能显然没法提供大规模的虚拟化环境,因此没有流行开来。最现现在虚拟化技术已经以势不可挡之势步入各个公司的生产环境中,不经可以大幅节约成本,还能够提升 IT 敏捷性、灵活性和可扩展性。
虚拟机技术中最早诞生的是主机级虚拟化,主机级虚拟化典型的表明即是KVM/XEN,它能够在物理机之上部署多台虚拟机同时运行,而各个虚拟机之间互不影响,即便某一台服务器因为各类缘由“寿终正寝”以后,也不会影响到其它虚拟机和宿主机的正常运行。可是这种技术的缺点也很明显,每一个虚拟机都有单独的内核空间,对系统的资源消耗至关大。
而容器虚拟化技术则解决了这一难题,它不须要在运行是安装一个庞大的内核,而只是将运行某个服务的环境集成在一个容器中,大大减小了对系统资源的消耗,而且有“秒级”的自愈功能,一个容器宕机以后可当即弃之,随后头也不回的重启一个容器接替它的位置,固然此功能须要运维人员对容器进行很好的优化才能实现。node
虽然容器虚拟化技术有种种好处,可是在宿主机之上运行N个容器,如何让这些容器之间的运行稳定,且各个容器之间环境互不影响,就成为了迫在眉睫的问题。每一个容器占用系统资源较少,可麻雀虽少,也得五脏俱全。它也得具有主机名,网卡,用户等资源。为了解决此各个容器之间不冲突,就得使用到Linux Namespace
namespace 是 Linux 系统的底层概念,在内核层实现,即有一些不一样类型的命名空间被部署在内核之中,各个docker容器运行时共享一个宿主机的内核。与此同时,每一个宿主机之间要相互隔离的运行,并意识不到别的容器的存在,觉得本身就是这个“世界”的主宰,那么一个容器必须有以下几类namespacelinux
[root@node1 ~]#docker exec -it k1 bash [root@3864270aea99 /]# ls / #独立根文件系统 anaconda-post.log dev home lib64 mnt proc run srv tmp var bin etc lib media opt root sbin sys usr
[root@node1 ~]#docker exec -it k1 bash [root@3864270aea99 /]# hostname #主机名 3864270aea99 [root@3864270aea99 /]# uname -a #内核版本,注意此处也是宿主机的内核版本 Linux 3864270aea99 3.10.0-957.el7.x86_64 #1 SMP Thu Nov 8 23:39:32 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
[root@node1 ~]#docker exec -it k1 bash [root@3864270aea99 /]# top top - 03:13:35 up 2:17, 0 users, load average: 0.00, 0.03, 0.06 Tasks: 3 total, 1 running, 2 sleeping, 0 stopped, 0 zombie %Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 995896 total, 146980 free, 216372 used, 632544 buff/cache KiB Swap: 2097148 total, 2096884 free, 264 used. 558252 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND #容器的PID 1 root 20 0 11820 1680 1408 S 0.0 0.2 0:00.02 bash 44 root 20 0 11820 1888 1508 S 0.0 0.2 0:00.02 bash 57 root 20 0 56192 2008 1468 R 0.0 0.2 0:00.02 top
容器内网卡逻辑架构图
查看容器内网卡git
[root@3864270aea99 /]# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255 ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet) RX packets 4190 bytes 39525574 (37.6 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 3233 bytes 179563 (175.3 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
查看宿主机的上容器网卡的映射docker
[root@node1 ~]#ifconfig veth4ce4103: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet6 fe80::c061:9aff:fe02:ce89 prefixlen 64 scopeid 0x20<link> ether c2:61:9a:02:ce:89 txqueuelen 0 (Ethernet) RX packets 3234 bytes 179605 (175.3 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 4191 bytes 39525616 (37.6 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
查看自动生成的防火墙规则安全
[root@node1 ~]#iptables -vnL Chain INPUT (policy ACCEPT 7764 packets, 77M bytes) pkts bytes target prot opt in out source destination Chain FORWARD (policy DROP 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 7409 40M DOCKER-USER all -- * * 0.0.0.0/0 0.0.0.0/0 7409 40M DOCKER-ISOLATION-STAGE-1 all -- * * 0.0.0.0/0 0.0.0.0/0 4179 39M ACCEPT all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED 0 0 DOCKER all -- * docker0 0.0.0.0/0 0.0.0.0/0 3230 134K ACCEPT all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0 0 0 ACCEPT all -- docker0 docker0 0.0.0.0/0 0.0.0.0/0
root@node1 ~]#docker exec -it k1 bash [root@3864270aea99 /]# cat /etc/passwd #每一个容器中都有相应的用户 root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin dbus:x:81:81:System message bus:/:/sbin/nologin
在使用VMware建立虚拟机时,每一个虚拟在安装和启动以前都会有这么一个界面来设置这个虚拟机以前,能够设置此虚拟机占用宿主机的内存,CPU,网卡等硬件设备的大小。
容器亦是如此,虽然一个容器内的程序能够在其“领地”内行使对全部资源使用权利,但仍是要对其作资源限制,容器亦是如此,若是不对容器使用的资源作任何限制,当容器内的资源不够时,容器便会侵蚀宿主机的资源,直至把宿主机的资源占完,成为这台物理机新的“主人”。
对容器的资源限制还能够提升对于宿主机的安全性,假设一个容器出现漏洞被别人拿到控制权后,资源限制可以使其只可以使用这个容器中的资源,而没法对宿主机的资源造成危害。
那么为了不物理机的“主人”被其它容器取而代之,就须要一些手段来限制,主要使用的技术即是Linux control groups,简称Linux Cgroups。它的主要做用是限制一个进程组可以使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等。此外,还可以对进程进行优先级设置,以及将进程挂起和恢复等操做。
在容器使用的过程当中,一旦内存超过时初给它分配了空间,那么内核将主动杀死这个容器所使用的进程。
此功能在内核层默认已经开启。bash
[root@node1 ~]#cat /boot/config-3.10.0-957.el7.x86_64 | grep CGROUP #验证系统的Cgroups是否开启 CONFIG_CGROUPS=y #CONFIG_CGROUP_DEBUG is not set CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_PIDS=y CONFIG_CGROUP_DEVICE=y CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_HUGETLB=y CONFIG_CGROUP_PERF=y CONFIG_CGROUP_SCHED=y CONFIG_BLK_CGROUP=y #CONFIG_DEBUG_BLK_CGROUP is not set CONFIG_NETFILTER_XT_MATCH_CGROUP=m CONFIG_NET_CLS_CGROUP=y CONFIG_NETPRIO_CGROUP=y
Cgroup的具体实现服务器
[root@node1 ~]#ll /sys/fs/cgroup/ 总用量 0 drwxr-xr-x 2 root root 0 7月 3 21:02 blkio lrwxrwxrwx 1 root root 11 7月 3 21:02 cpu -> cpu,cpuacct lrwxrwxrwx 1 root root 11 7月 3 21:02 cpuacct -> cpu,cpuacct drwxr-xr-x 2 root root 0 7月 3 21:02 cpu,cpuacct drwxr-xr-x 2 root root 0 7月 3 21:02 cpuset drwxr-xr-x 4 root root 0 7月 3 21:02 devices drwxr-xr-x 2 root root 0 7月 3 21:02 freezer drwxr-xr-x 2 root root 0 7月 3 21:02 hugetlb drwxr-xr-x 2 root root 0 7月 3 21:02 memory lrwxrwxrwx 1 root root 16 7月 3 21:02 net_cls -> net_cls,net_prio drwxr-xr-x 2 root root 0 7月 3 21:02 net_cls,net_prio lrwxrwxrwx 1 root root 16 7月 3 21:02 net_prio -> net_cls,net_prio drwxr-xr-x 2 root root 0 7月 3 21:02 perf_event drwxr-xr-x 2 root root 0 7月 3 21:02 pids drwxr-xr-x 4 root root 0 7月 3 21:02 systemd
blkio:块设备 IO 限制
cpu:使用调度程序为 cgroup 任务提供 cpu 的访问
cpuacct:产生 cgroup 任务的 cpu 资源报告
cpuset:若是是多核心的 cpu,这个子系统会为 cgroup 任务分配单独的 cpu 和内存
devices:容许或拒绝 cgroup 任务对设备的访问
freezer:暂停和恢复 cgroup 任务。
memory:设置每一个 cgroup 的内存限制以及产生内存资源报告
ns:命名空间子系统
perf_event:增长了对每 group 的监测跟踪的能力,能够监测属于某个特定的 group 的所 有线程以及运行在特定 CPU 上的线程
有了这些就具有了容器的基础运行环境,可是还须要有相应的容器建立与删除的管理工具、以及怎么样把容器运行起来、容器数据怎么处理、怎么进行启动与关闭等问题须要解决,因而容器管理技术便应运而生。网络
容器的管理技术早期诞生的有 Linux Container(LXC),它能够提供轻量级的虚拟化来隔离各个容器之间的通信。可是LXC启动容器依赖于模板,而模板须要一步步创构建文件系统、准备基础目录及可执行程序等一堆步骤才可以使容器运行,另外后期代码升级也须要从新从头构建模板。
这就与容器的理念背道而驰,容器自己是为了简化操做而诞生的,如此大费周折的启动一个容器,显然不是生产环境中所指望的。后来docker的横空出世,便以势不可挡之势侵占了大部分LXC的市场。
然而并非说docker启动容器时不须要模板,docker也是须要的。只是它把这些模板包装成为一个个的镜像。而docker的镜像便可以保存在一个公共的地方供全部人共享使用,也能够保存在本地的私有仓库中使用。
当咱们在使用镜像时,只要把别人制做的镜像下载下来就可使用。若是咱们以为别人的配置不符合生产环境中的需求,咱们还能够在别人制做的镜像基础之上作自定义配置,配置完成后保存为本身的一个镜像。如此造成了前人栽树后人乘凉的良性循环,这也是容器技术愈来愈火爆的缘由之一
docker官方镜像仓库地址:https://hub.docker.com/架构
docker 主机(Host):一个物理机或虚拟机,用于运行 docker 服务进程和容器。
docker 服务端(Server):docker 守护进程,运行 docker 容器。
docker 客户端(Client):客户端使用 docker 命令或其余工具调用 docker API。
docker 仓库(Registry): 保存镜像的仓库,相似于 git 或 svn 这样的版本控制系
docker 镜像(Images):镜像能够理解为建立实例使用的模板。
docker 容器(Container): 容器是从镜像生成对外提供服务的一个或一组服务。运维