首页 > 系统 > Linux > 正文

Linux 容器的使用

2024-06-28 13:24:41
字体:
来源:转载
供稿:网友
linux 容器的使用Linux 容器的使用

Linux 容器在 v2.6.29版本之后就加入到内核之中了, 之前虽然也听说过, 但一直没有太留心, 一直使用 KVM 来创建虚拟机.直至最近 Docker 大出风头, 才开始关注. 想了解一下 Linux 容器究竟是什么? 与现有虚拟机技术(Xen, KVM等)有什么区别?

Linux 容器技术出现的很早, 其实也是一直虚拟化技术, 但似乎一直没有 Xen, KVM 这些来的出名.同时, 在实现原理上, 和Xen, KVM之类的也是有很大区别的.下面简单说明下目前4类虚拟技术的区别: (下面说明中, VM:虚拟机, HOST:主机, 即安装虚拟机的机器)

  1. 传统的虚拟化技术 (VirtualBox, VMware) 通过在Linux上安装虚拟化软件, 然后通过虚拟化软件来安装虚拟机系统, 大致结构如下:

    VM1VM2VM3......
    VirtualBoxorVMWareor...
    LinuxKernel
    硬件

    VM是由虚拟化软件(VirtualBox, VMWare…)来管理的, Linux Kernel不能直接管理到各个VM.

  2. Xen (半虚拟化) Xen是Linux上历史比较长的虚拟化技术, 它的虚拟化结构大致如下:

    LinuxKernelVM1VM2VM3......
    Xen
    硬件

    Xen的虚拟化原理是在 Linux Kernel和硬件之间加入一层 Xen代码, 有Xen来管理Linux Kernel和其它的VM.

  3. KVM (最新的虚拟化技术) 相比其它的虚拟化技术, KVM是比较新的, 它需要CPU的支持. 它的虚拟化结构大致如下:

    VM1VM2VM3......
    KVM(由内核管理)
    LinuxKernel
    硬件

    这个结构和传统的虚拟化技术很类似, 有一点不同的是, KVM和Linux Kernel是紧密结合的,所以Linux Kernel能够更好的管理 VMs, VM的性能会比传统的虚拟化技术更好.

  4. Linux 容器 (LXC - linux container) LXC 是非常轻量级的, 它将 VM 的进程也伪装成 HOST 的进程. 大致的结构如下:

    p1(HOST),p2(VM),p3(VM),p4(HOST)......
    LinuxKernel
    硬件

    那么, 对于某些系统进程, PID是固定的, 比如 init进程的PID=1, VM中的 init进程的PID是如何处理的呢?原来, VM的 init进程的PID在 HOST的进程表中会显示成其它PID(>1).

    从上面可以看出, LXC这种虚拟化, VM的进程就像HOST的进程一样运行, 管理, 所以创建和销毁都是非常快速的.

: 参考 http://veck.logdown.com/posts/200566-compare-of-kvm-and-lxc

Linux 容器相关的2个重要概念

Linux容器功能是基于 cgroups 和 Namespace 来实现的. 所以要了解 Linux 容器必须先了解 cgroup 和 Namespace.

cgroups

cgroups 是将任意进程进行分组化管理的 Linux 内核功能.通过cgroups可以有效的隔离各类进程, 同时还可以控制进程的资源占用(CPU, 内存等等)情况.使用示例: (debian v7.6 x86_64)

mount -t tmpfs cgroup_root /sys/fs/cgroupmkdir /sys/fs/cgroup/testmount -t cgroup -ocpuset test /sys/fs/cgroup/test

此时, test目录就是一个 cgroup, 这里 -o 指定了 cpuset, cpuset是Linux中既定的一种cgroup, 后面有时间重新写博客详细介绍.test 目录有cgroup必须的各个文件

cd /sys/fs/cgroup/testls -ltotal 0-rw-r--r-- 1 root root 0 Aug 14 14:34 cgroup.clone_children--w--w--w- 1 root root 0 Aug 14 14:34 cgroup.event_control-rw-r--r-- 1 root root 0 Aug 14 14:34 cgroup.PRocs-rw-r--r-- 1 root root 0 Aug 14 14:34 cpuset.cpu_exclusive-rw-r--r-- 1 root root 0 Aug 14 14:34 cpuset.cpus-rw-r--r-- 1 root root 0 Aug 14 14:34 cpuset.mem_exclusive-rw-r--r-- 1 root root 0 Aug 14 14:34 cpuset.mem_hardwall-rw-r--r-- 1 root root 0 Aug 14 14:34 cpuset.memory_migrate-r--r--r-- 1 root root 0 Aug 14 14:34 cpuset.memory_pressure-rw-r--r-- 1 root root 0 Aug 14 14:34 cpuset.memory_pressure_enabled-rw-r--r-- 1 root root 0 Aug 14 14:34 cpuset.memory_spread_page-rw-r--r-- 1 root root 0 Aug 14 14:34 cpuset.memory_spread_slab-rw-r--r-- 1 root root 0 Aug 14 14:34 cpuset.mems-rw-r--r-- 1 root root 0 Aug 14 14:34 cpuset.sched_load_balance-rw-r--r-- 1 root root 0 Aug 14 14:34 cpuset.sched_relax_domain_level-rw-r--r-- 1 root root 0 Aug 14 14:34 notify_on_release-rw-r--r-- 1 root root 0 Aug 14 14:34 release_agent-rw-r--r-- 1 root root 0 Aug 14 14:34 tasks

其中部分文件介绍.

文件名R/W用途
release_agentRW删除分组时执行的命令. 这个文件只存在于根分组
notify_on_releaseRW设置是否执行 release/_agent. 为1时执行
tasksRW属于分组的线程 TID 列表
cgroup.procsR属于分组的进程 PID 列表. 仅包括多线程进程的线程leader的TID, 这点与 tasks 不同
cgroup.event_controlRW监视状态变化的分组删除事件的配置文件

在cgroup中还可以建立子cgroup, 建立的方法很简单, 只要创建文件夹即可.

cd /sys/fs/cgroup/testmkdir test-childls -l test-child    # 创建了文件夹之后, 自动生成cgroup需要的文件total 0-rw-r--r-- 1 root root 0 Aug 14 15:10 cgroup.clone_children--w--w--w- 1 root root 0 Aug 14 15:10 cgroup.event_control-rw-r--r-- 1 root root 0 Aug 14 15:10 cgroup.procs-rw-r--r-- 1 root root 0 Aug 14 15:10 cpuset.cpu_exclusive-rw-r--r-- 1 root root 0 Aug 14 15:10 cpuset.cpus-rw-r--r-- 1 root root 0 Aug 14 15:10 cpuset.mem_exclusive-rw-r--r-- 1 root root 0 Aug 14 15:10 cpuset.mem_hardwall-rw-r--r-- 1 root root 0 Aug 14 15:10 cpuset.memory_migrate-r--r--r-- 1 root root 0 Aug 14 15:10 cpuset.memory_pressure-rw-r--r-- 1 root root 0 Aug 14 15:10 cpuset.memory_spread_page-rw-r--r-- 1 root root 0 Aug 14 15:10 cpuset.memory_spread_slab-rw-r--r-- 1 root root 0 Aug 14 15:10 cpuset.mems-rw-r--r-- 1 root root 0 Aug 14 15:10 cpuset.sched_load_balance-rw-r--r-- 1 root root 0 Aug 14 15:10 cpuset.sched_relax_domain_level-rw-r--r-- 1 root root 0 Aug 14 15:10 notify_on_release-rw-r--r-- 1 root root 0 Aug 14 15:10 tasks

注意, 删除子cgroup的时候, 要用 rmdir 来删除文件夹, 用 rm -rf 的方法无法删除

cd /sys/fs/cgroup/testrmdir test-child

: 参考内核文档 Documentation/cgroups/cgroups.txt

Namespace (命名空间)

使用Namespace, 可以让每个进程组有独立的PID, ipC和网络空间.Namespace的生效主要是通过 clone系统调用来实现的.clone系统调用的第3个参数flags就是通过设置Namespace来划分资源的.参数种类如下:

名称说明
CLONE_NEWIPC划分IPC(进程间通信)命名空间, 信号量(semaphore), 共享内存, 消息队列等进程间通信用的资源
CLONE_NEWNET划分网络命名空间. 分配网络接口
CLONE_NEWNS划分挂载的命名空间. 与chroot同样分配新的根文件系统
CLONE_NEWPID划分 PID 命名空间. 分配新的进程ID空间
CLONE_NEWUTS划分 UTS(Universal Time sharing System)命名空间. 分配新的 UTS 空间
Linux 容器的使用方法 (以下命令基于 debian v7.5)
  1. 安装 LXC

    apt-get install lxclxc-checkconfig   # 安装完成后, 用这个命令检查系统是否可以使用 lxc# 我的debian系统上有个 missingCgroup namespace: CONFIG_CGROUP_NSmissing# 对于这个missing, 可能是由于系统中没有挂载cgroup导致的, 挂载一个cgroup即可mount -t cgroup cgroup /mnt/cgroup
  2. 创建容器 从现有模板创建容器, 比较慢, 需要下载

    # 创建一个 debian 系统lxc-create -n test -t debian

    这样创建的容器默认在 /var/lib/lxc/test 中, 为了将容器创建在我们指定的位置, 可以写个简单的配置文件lxc.conf, 里面只需要一句

    lxc.rootfs = /home/lxc/test

    然后,

    lxc-create -n test -t debian -f /path/to/lxc.conf

    这样, 就把容器创建在了 /home/lxc/test 中了, /var/lib/lxc/test 中只有一个 config文件(这个config文件可以作为 lxc-create 命令 -f 参数对应配置文件的参考)

  3. 启动容器 启动后就进行入了虚拟机的控制台了. (果然像传说一样, 几秒就启动完成了 ^_^)

    lxc-start -n test
  4. 停止容器 在主机中输入停止的命令.

    lxc-stop -n test
  5. 销毁容器 销毁之前, 可以通过 lxc-ls 来查看有几个容器

    lxc-ls  testlxc-destroy -n testlxc-ls

: 参考URL - http://obdnmagazine.blogspot.com/2013/07/tested-lxc-080-rc1-debian-wheezyax3a6.html

容器示例 - 配置python uliweb 开发环境

尝试在容器配置一次开发环境, 然后通过复制容器, 形成多个虚拟机.

# 主机中root@debian-113:~# uliweb   # 主机中没有安装uliweb 软件包-bash: uliweb: command not foundroot@debian-113:~# lxc-start -n test# 虚拟机登录界面, 输入用户名和密码# 虚拟机中root@test:~# apt-get install pythonroot@test:~# apt-get install python-piproot@test:~# pip install Uliwebroot@test:~# uliweb --versionUliweb version is 0.3.1

主机中设置网桥, 虚拟机用桥接方式上网, 确保每个虚拟机有独立的IP

# 主机中root@debian-113:~# lxc-stop -n testroot@debian-113:~# apt-cache search bridge-utilsroot@debian-113:~# brctl addbr br0# 配置主机的网桥root@debian-113:/var/lib/lxc/test# cat /etc/network/interfaces # This file describes the network interfaces available on your system# and how to activate them. For more information, see interfaces(5).# The loopback network interfaceauto lo#auto eth0iface lo inet loopback# 追加的网桥配置    auto br0iface br0 inet staticaddress 192.168.1.113netmask 255.255.255.0gateway 192.168.1.1   bridge_ports eth0   bridge_stp on   bridge_fd 0root@debian-113:/var/lib/lxc/test# /etc/init.d/networking restart

配置容器的网络(也是在主机中修改容器的配置文件)

root@debian-113:/var/lib/lxc/test# cat /var/lib/lxc/test/config... ... (很多默认生成的配置)# network  <-- 这个 network 相关的是要追加的lxc.network.type = vethlxc.network.flags = uplxc.network.link = br0lxc.network.name = eth0

启动Linux容器, 进入虚拟机

root@debian-113:/var/lib/lxc/test# lxc-start -n test# 登录进入虚拟机, 确认虚拟机的IProot@test:~# cat /etc/network/interfaces  <-- 默认是自动获取IPauto loiface lo inet loopbackauto eth0iface eth0 inet dhcproot@test:~# ifconfig   <-- 我的机器自动分配的 192.168.1.167# 创建一个简单的uliweb工程root@test:~# cd /home/root@test:/home# mkdir CM-webroot@test:/home# cd CM-web/root@test:/home/CM-web# uliweb makeproject testroot@test:/home/CM-web# cd test/root@test:/home/CM-web/test# uliweb makeapp first_approot@test:/home/CM-web/test# uliweb runserver -h 0.0.0.0

启动Web服务后, 就可以在主机的浏览器中 通过 http://192.168.1.167:8000/ 来访问虚拟机中的web服务了.

最后, 复制一个新的容器, 也就是再重新生成一个上面的 python uliweb 开发环境

# 在主机中root@debian-113:~# cd /var/lib/lxcroot@debian-113:/var/lib/lxc# cp -r test test2# 修改 test2/config 如下lxc.utsname = test2           <-- 修改名称xc.rootfs = /home/lxc/test2   <-- 修改 rootfs位置... ...                       <-- 其它部分不用修改, 和 test 一样就行root@debian-113:/var/lib/lxc# cd /home/lxc/root@debian-113:/home/lxc# cp -r test test2  <-- 重新复制一份 rootfsroot@debian-113:/home/lxc# lxc-start -n test2  <-- 启动 test2 虚拟机, 其中环境和 test一样, IP会不一样, 自动获取的# 进入 test2 虚拟机中, 可以直接启动之前的 uliweb 测试工程, 也可以从主机中访问其web服务.

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表