1.LXC的使用
1.1简介
LXC为Linux Container的简写。Linux Container容器是一种内核虚拟化技术,可以提供轻量级的虚拟化,以便隔离进程和资源,而且不需要提供指令解释机制以及全虚拟化的其他复杂性。相当于C++中的NameSpace。容器有效地将由单个操作系统管理的资源划分到孤立的组中,以更好地在孤立的组之间平衡有冲突的资源使用需求。与传统虚拟化技术相比,它的优势在于:
(1)与宿主机使用同一个内核,性能损耗小;
(2)不需要指令级模拟;
(3)不需要即时(Just-in-time)编译;
(4)容器可以在CPU核心的本地运行指令,不需要任何专门的解释机制;
(5)避免了准虚拟化和系统调用替换中的复杂性;
(6)轻量级隔离,在隔离的同时还提供共享机制,以实现容器与宿主机的资源共享。
总结:Linux Container是一种轻量级的虚拟化的手段。
Linux Container提供了在单一可控主机节点上支持多个相互隔离的server container同时执行的机制。Linux Container有点像chroot,提供了一个拥有自己进程和网络空间的虚拟环境,但又有别于虚拟机,因为lxc是一种操作系统层次上的资源的虚拟化。
1.2.0 前置工作
[root@yyx2 ~]#yum -y install epel-release //配置源
[root@yyx2 ~]# yum -y install net-tools //安装包
1.2 安装LXC
[root@yyx2 ~]# yum -y install lxc lxc-templates bridge-utils lxc-libs libcgroup libvirt perl debootstrap //下载lxc及其所需依赖包
1.3 网桥设置
[root@yyx2 ~]# brctl addbr virbr0 && brctl addif virbr0 ens33&&ip addr del dev ens33 192.168.141.128/24&&ifconfig virbr0 192.168.141.128/24 up&&route add default gw 192.168.141.1
//以上五步为同时执行,以免执行过程中导致Xshell断开连接
//addbr virbr0 添加网桥
//brctl addif virbr0 ens33 关联网卡
//ip addr del dev ens33 192.168.141.128/24 删除网卡ip
ifconfig virbr0 192.168.141.128/24 配置网桥ip
//route add default gw 192.168.141.1 设置默认网关
[root@yyx2 ~]# brctl show //查看网桥
bridge name bridge id STP enabled interfaces
virbr0 8000.000c2917d93d no ens33
[root@yyx2 ~]# ifconfig //查看网络设备
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::20c:29ff:fe17:d93d prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:17:d9:3d txqueuelen 1000 (Ethernet)
RX packets 44304 bytes 61905078 (59.0 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 8987 bytes 608737 (594.4 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
virbr0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 //网桥配置成功
inet 192.168.141.128 netmask 255.255.255.0 broadcast 192.168.141.255
inet6 fe80::20c:29ff:fe17:d93d prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:17:d9:3d txqueuelen 1000 (Ethernet)
RX packets 352 bytes 70134 (68.4 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 49 bytes 3894 (3.8 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
1.4 检查系统
[root@yyx2 ~]# lxc-checkconfig //查看系统是否满足容器使用的要求 都是enabled则可以使用
1.5 创建LXC
[root@yyx2 ~]# lxc-create --name=yyxnb -t /usr/share/lxc/templates/lxc-download //利用模板安装LXC
1.6 启动容器
[root@yyx2]# chroot /var/lib/lxc/myhost1/rootfs/ passwd //修改初始密码
1.7 常用命令操作
// lxc-create 创建一个系统对象
用法: lxc-create {-n name} [-f config_file] {-t template} [-B backingstore] [-- template-options]
// 选项
-n,--name #容器的主机名
-f,--config #指定配置文件以配置容器的虚拟化和隔离功能
-t template #调用模板脚本,可执行模板脚本的完整路径也可以作为参数传递。 “none”可用于强制lxc-create跳过rootfs创建。
-B backingstore #指定根文件储存路径的文件系统,可选:dir、lvm、loop、btrfs、zfs、best ,默认为dir,如果是dir可以使用--dir指定lxc主机的根在宿主机的存储路径。
-P, --lxcpath #自定义容器路径。默认值为/var/lib/lxc。
-o, --logfile #输出创建过程到一个日志文件中。
-l, --logpriority #将日志优先级设置为LEVEL,默认优先级为ERROR
-- #向template传递参数查看可选参数:lxc-create -t TEMPLATE -h,常用参数如下
-n,--name #容器标识符
-p,--path #指定容器根的创建路径,默认/var/lib/lxc/容器名/
-c,--clean #清除缓存
-R,--release #指定Centos的发行版本
--fqdn #用于DNS和系统命名的完全域名(FQDN)
--repo #指定创建容器是使用的yum源,这个是redhat系统的参数
-a,--arch #指定容器的架构,可选i686,x86_64
lxc-destroy
用法:lxc-destroy {-n name} [-f]
选项:-f, --force #强制删除
lxc-start
用法:lxc-start {-n name} [-f config_file] [-c console_device] [-L console_logfile] [-d] [-F] [-p pid_file] [-s KEY=VAL] [-C] [--share-[net|ipc|uts] name|pid] [command]
// 选项:
-n #指定容器名
-d, --daemon #后台运行
-F #前台运行,默认选项
-p, --pidfile #创建一个保存了pid的文件
-f, --rcfile #指定配置文件以配置容器的虚拟化和隔离功能。覆盖现有配置文件。
c, --console #指定一个前台运行容器的终端。不指定默认为当前终端。
-L, --console-log #把容器控制台输入保存到一个文件中。
-C, --close-all-fds #如果任何文件描述符被继承,关闭它们。 如果未指定此选项,则lxc-start将退出而失败。 注意:--daemon意味着--close-all-fds。
--share-net name|pid #从其他容器继承网络名称空间。
--share-ipc #从其他容器继承IPC命名空间。
--share-uts #从其他容器继承UTS命名空间。
lxc-autostart
// 选项:
-r,--reboot #重启容器
-s,--shutdown #设置定时关闭容器,使用-t 设置关闭时间。
-k,--kill #关闭容器
lxc-stop
// 选项:
-r,--reboot #重启容器
-k,--kill #关闭容器,默认选项
--nokill #挂起容器
--nolock #此选项避免使用任何API lxc锁定。
lxc-info
// 选项:
-s #显示状态
-p #显示pid
-i #显示IP地址
-S #显示内存使用
-H #显示原始数值
lxc-console
-t #指定连接的tty
lxc-clone
-o,--orig #要克隆的原始容器的名称
-n #新容器的名称
-p, --lxcpath #原始容器的系统文件路径,不选使用系统默认路径
-P, --newpath #新容器的系统文件路径
-K, --keepname #保留原容器的主机名
-M, --keepmac #使用和原容器相同的mac地址
lxc-checkconfig #检查当前内核lxc支持
lxc-config
lxc-monitor
lxc-top #容器统计信息
lxc-usernsexec #以root用户身份在容器内运行任务
可以使用-m 选项指定用户的uid以该用户的身份运行命令
lxc-freeze #冻结容器内运行的所有进程。
lxc-unfreeze #解冻容器内运行的所有进程。
lxc-execute #在指定的容器内运行指定的命令。
lxc-wait
lxc-snapshot #创建,列出和还原容器快照。
快照文件默认保存在var /lib/lxc-snaps/容器名
-c,--comment file #将文件中的注释信息和快照关联
-d,--destroy #删除快照
-L,--list #列出所有快照
-C #显示快照注释信息
-r #恢复快照
newname #恢复快照时用于指定容器的名称。可选参数 ,如果没有给出任何名称,则原始容器将被破坏,并且恢复的容器将占据其位置.
注意:在aufs,overlayfs或zfs支持的快照的情况下,删除原始快照是不可能的
lxc-cgroup
lxc-cgroup在相应子系统的容器cgroup中获取或设置状态对象(例如,'cpuset.cpus')的值(例如,'cpuset')。 如果没有指定[value],则显示状态对象的当前值; 否则设置。注意lxc-cgroup不会检查状态对象是否对运行的内核有效,或者对应的子系统包含在任何已安装的cgroup层次结构中
lxc-cgroup {-n name} {state-object} [value]
lxc-unshare
可用于在一组克隆的命名空间中运行任务。 此命令主要用于测试目的。 尽管它的名字,它始终使用克隆而不是非共享创建新的任务与新的命名空间。 除了测试内核回归之外,这应该没有区别。
-s namespaces #指定要附加到的命名空间
-u user #指定新任务应该成为的用户标识
-H hostname #在新容器中设置主机名。只有设置了UTSNAME命名空间才允许。
-i interfacename #将命名的界面移动到容器中。仅当NETWORK命名空间被设置时才允许。您可以多次指定此参数以将多个接口移动到容器中。
-d #守护程序,退出前不要等待容器退出
-M #在容器中挂载默认文件系统(/ proc / dev / shm和/ dev / mqueue)。如果设置MOUNT命名空间,则只有al-lowed。
lxc-attach
lxc-attach在由name指定的容器内运行指定的命令。 容器lxc-attach在名称指定的容器内运行指定的命令。 容器必须已经运行。 如果未指定命令,则将在容器内查找运行lxc-attach的用户的当前默认shell,然后执行。 如果容器内没有这样的用户,或容器没有工作的nsswitch机制这将失败。
-n,--name #容器的名称
-a, --arch #指定内核运行的架构
问题汇总
Socket error Event: 32 Error: 10053.
Connection closing...Socket close.
Connection closed by foreign host.
Disconnected from remote host(192.168.141.128:22) at 22:58:19.
Type `help' to learn how to use Xshell prompt.
//断开连接
原因:设置网桥的时候一步一步来的,导致Xshell断开连接。
解决方法:同时运行
Socket error Event: 32 Error: 10053.
Connection closing...Socket close.
Connection closed by foreign host.
Disconnected from remote host(192.168.141.128:22) at 22:58:19.
Type `help' to learn how to use Xshell prompt.
//再次出现这个情况
原因:本机缺少包导致ifconfig命令用不了,而中断命令执行过程
解决方法:去VMware虚拟机里面配置好IP并且安装net-tools包然后运行后续命令
2.容器的工作方式
一个容器由操作系统,用户文件和元数据组成。由此可知,每个容器都根据镜像来生成。这个镜像告诉Docker容器包含什么内容,运行什么程序,以及其他配置信息。
docker image是只读的,当一个容器运行一个镜像时,容器会在Union FS的顶层增加文件层。
运行下面一条执行,执行后会出现下面的信息:
[root@VM_0_5_centos ~]# docker run -i -t ubuntu /bin/bash
Unable to find image 'ubuntu:latest' locally
Trying to pull repository docker.io/library/ubuntu ...
latest: Pulling from docker.io/library/ubuntu
7ddbc47eeb70: Pull complete
c1bbdc448b72: Pull complete
8c3b70e39044: Pull complete
45d437916d57: Pull complete
Digest: sha256:6e9f67fa63b0323e9a1e587fd71c561ba48a034504fb804fd26fd8800039835d
Status: Downloaded newer image for docker.io/ubuntu:latest
root@b2ca7b248b17:/#
docker client 通过run 命令告诉Daemon启动一个新的容器,这个指令至少需要包括:
(1)、需要运行什么image,这里使用的是ubuntu基础镜像
(2)、需要在容器启动是运行什么命令,这里使用的是/bin/bash。是否需要进入应用程序,这里指定 -i -t,表示进入容器交互模式
那么具体到内部的流程是怎么样的呢?
(1)、拉取ubuntu镜像:docker检查本地是否存在ubuntu镜像,如果就自动从docker hub拉取,如果存在就进入下一步。
(2)、创建一个容器:一旦本地存在ubuntu镜像,docker将通过它来创建容器。
(3)、分配文件系统并挂载一个RW层:容器是创建在文件系统中的,并且在其之上增加了一层读写层。由此可以看出容器并不会改变原始的镜像。
(4)、分配网络/桥接模式:创建一个桥接网络接口,使容器可以和本地主机进行通信。
(5)、设置一个IP地址:根据本地网络情况,选取一个可用的IP挂载到容器之上。
(6)、启动一个进程:这里就是/bin/bash
(7)、抓取应用程序的输出:将程序的stdin、stdout、和stderr进行捕捉,这样就可以看到程序的运行情况。至此,就拥有了一个运行的容器。通过容器,可以运行程序,并且进行交互。当程序执行完毕,可以停止和删除程序。
3.CGroup的功能
控制组(CGroups)是Linux内核的一个特性,用来对共享资源进行隔离、限制、审计等。只有能控制分配到容器的资源,Docker才能避免多个容器同时运行时的系统资源竞争。
控制组可以提供对容器的内存、CPU、磁盘IO等资源进行限制。
CGroups能够限制的资源有:
- blkio:块设备IO
- cpu:CPU
- cpuacct:CPU资源使用报告
- cpuset:多处理器平台上的CPU集合
- devices:设备访问
- freezer:挂起或恢复任务
- memory:内存用量及报告
- perf_event:对cgroup中的任务进行统一性能测试
- net_cls:cgroup中的任务创建的数据报文的类别标识符
具体来看,控制组提供如下功能:
- 资源限制(Resource Limitting)组可以设置为不超过设定的内存限制。比如:内存子系统可以为进行组设定一个内存使用上限,一旦进程组使用的内存达到限额再申请内存,就会发出Out of Memory警告
- 优先级(Prioritization)通过优先级让一些组优先得到更多的CPU等资源
- 资源审计(Accounting)用来统计系统实际上把多少资源用到合适的目的上,可以使用cpuacct子系统记录某个进程组使用的CPU时间
- 隔离(Isolation)为组隔离命名空间,这样一个组不会看到另一个组的进程、网络连接和文件系统
- 控制(Control)挂起、恢复和重启等操作
安装Docker后,用户可以在/sys/fs/cgroup/memory/docker/
目录下看到对Docker组应用的各种限制项,包括
[root@yyx2 templates]# cd /sys/fs/cgroup/memory/
[root@yyx2 memory]# ls
cgroup.clone_children memory.kmem.tcp.limit_in_bytes memory.pressure_level
cgroup.event_control memory.kmem.tcp.max_usage_in_bytes memory.soft_limit_in_bytes
cgroup.procs memory.kmem.tcp.usage_in_bytes memory.stat
cgroup.sane_behavior memory.kmem.usage_in_bytes memory.swappiness
init.scope memory.limit_in_bytes memory.usage_in_bytes
machine.slice memory.max_usage_in_bytes memory.use_hierarchy
memory.failcnt memory.memsw.failcnt notify_on_release
memory.force_empty memory.memsw.limit_in_bytes release_agent
memory.kmem.failcnt memory.memsw.max_usage_in_bytes system.slice
memory.kmem.limit_in_bytes memory.memsw.usage_in_bytes tasks
memory.kmem.max_usage_in_bytes memory.move_charge_at_immigrate user.slice
memory.kmem.slabinfo memory.numa_stat
memory.kmem.tcp.failcnt memory.oom_control
用户可以通过修改这些文件值来控制组限制Docker应用资源。
4.容器的基本概念
容器的本质实际上是一个进程,是一个视图被隔离,资源受限的进程。
容器就是一个视图隔离、资源可限制、独立文件系统的进程集合。所谓“视图隔离”就是能够看到部分进程以及具有独立的主机名等;控制资源使用率则是可以对于内存大小以及 CPU 使用个数等进行限制。容器就是一个进程集合,它将系统的其他资源隔离开来,具有自己独立的资源视图。
容器具有一个独立的文件系统,因为使用的是系统的资源,所以在独立的文件系统内不需要具备内核相关的代码或者工具,我们只需要提供容器所需的二进制文件、配置文件以及依赖即可。只要容器运行时所需的文件集合都能够具备,那么这个容器就能够运行起来。