LXC为Linux Container的简写,也就是我们平常说的容器。容器有效地将由单个操作系统管理的资源划分到孤立的组中,以更好地在孤立的组之间平衡有冲突的资源使用需求。容器在提供隔离的同时,还通过共享这些资源节省开销,这意味着容器比真正的虚拟化的开销要小得多。容器是一种轻量级的虚拟化技术,和qemu或者vmware比起来,它们和增强的chroot更像一些,因为容器不用仿真硬件设备,而是和宿主机共用一套操作系统。容器更像solaris的zones或者bsd的jails。容器更像是独立开发的linux的一项功能,因此容器可以工作在虚拟机之上。与虚拟化相比,这样既不需要指令级模拟,也不需要即时编译。容器可以在核心cpu本地运行指令,而不需要任何专门的解释机制,此外,也避免了半虚拟化和系统调用替换中的复杂性。通过提供一种创建和进入容器的方式,操作系统让应用程序就像在独立的机器上运行一样,但又能共享很多底层的资源。例如,可以有效地共享公共文件(比如 glibc)的页缓存,因为所有容器都使用相同的内核,而且所有容器还常常共享相同的 libc 库(取决于容器配置)。这种共享常常可以扩展到目录中其他不需要写入内容的文件。

     LXC提供了在单一可控主机节点上支持多个相互隔离的server container同时执行,Linux Container有点像chroot,提供了一个拥有自己进程和网络空间的虚拟环境。LXC 通过利用内核的CGroup来提供用户空间的对象,用来保证资源的隔离和对于应用或者系统的资源控制,通过namespaces提供资源隔离。容器有两个用户空间(user-space),每个利用相同的内核功能,一种是libvirt允许通过LXC驱动来使用lxc容器,例如lxc:///。这和其他驱动一样,使用起来非常方便。另一个实现叫LXC,它不兼容libvirt,但是提供了灵活的用户空间工具。可以在两者之间切换。本文主要讲解LXC的用法,不涉及利用libvirt来使用lxc容器。

    详细信息参考官网:LXC

实验环境:ubuntu12.04

1  安装

apt-get install lxc

   会自动依赖一些需要的包,例如cgroup-lite、lvm2、debootstarp,如果要使用libvirt来管理,则需要安装libvirt-lxc,这两个是可以同时安装的

2  建立LXC

    1  LXC的配置文件

       1  主要有两个upstart jobs

            /etc/init/lxc-net.conf    只有在/etc/default/lxc中设置use_lxc_bridge为true时,该文件才会生效,用来设置nat bridge以供容器使用

            /etc/init/lxc.conf    只有在/etc/default/lxc中设置lxc_auto为true时,该文件才会生效,他用来在开机时自动启动/etc/lxc/auto/目录下的一些lxc实例配置文件,里面的文件都是软连接

       2  /etc/lxc/lxc.conf 默认容器配置文件,它直接使用lxc-net创建的lxc bridge,如果在创建容器时没有指定配置文件,则这个容器会被使用。

       3  /usr/share/doc/lxc/examples目录下包含一些配置文件例子

       4 容器的管理员工具都在/usr/bin目录下

       5 /etc/apparmor.d/lxc/lxc-default 包含一些MAC策略,用来保护容器。

       6 /var/lib/lxc 包含容器的配置信息和存储的地方

    2  lxcbr0

        当USE_LXC_BRIDGE被设置为true(默认就是true),会产生一个叫lxcbr0的网桥,这个网桥地址为10.0.3.1,所以容器可以使用10.0.3.0/24网段的地址,一个

dnsmasq会监听在网桥地址上,因此如果已经有另一个dnsmasq监听在所有网络接口上,会导致lxc-net启动失败,并且创建lxcbr0失败。

    3  使用单独分开的文件系统来存储容器

        LXC存储容器信息,如果是root用户启动,则存储在/var/lib/lxc目录下,容器产生的临时文件则存储在/var/cache/lxc下面。如果你不想把容器的信息存储

在/var下面,则可以用单独的空间来存储容器信息。例如把单独的磁盘挂在相关目录下,或者相关目录采用软连接。

    4  LXC备份

        可以使用lvm来备份容器,如果你的/var采用的btrfs文件系统,则LXC的管理员工具可以觉察并自动的克隆容器来备份。

    5  apparmor

        apparmor是LXC自带的保护

    6 CGroup 

       cgroup是一个内核级别的功能模块,用来控制进程级别的一些资源访问。

    7  权限

       容器的管理员工具必须使用root账户运行

    8  LXC Upstart Jobs

        lxc upstart jobs     ln -s /var/lib/lxc/CN/config /etc/lxc/auto/CN.conf

3  容器管理员

   1 创建容器  lxc-create

lxc-create -t ubuntu -n CN

       使用lxc-create创建一个容器,容器的chroots环境默认在/var/lib/lxc/CN/rootfs,默认的初始化配置在/var/lib/lxc/CN/fstab和/var/lib/lxc/CN/config。CN是容器名称。-t后面是模板名称,-n后面是容器名称。

       也可以查看模板的帮助   lxc-create -t ubuntu -h 

       ubuntu模板可以创建一个ubuntu系统的容器,默认是10.04LTS,使用debootstrap来创建容器的文件系统,你也可以产生和宿主系统相同的容器系统

lxc-create -t ubuntu -n CN -- -r lucid


        跟-r参数,你也可以跟-a i386在64位的系统上产生32位的容器,跟-r参数,你也可以跟-a i386在64位的系统上产生32位的容器,产生的容器默认有一个用户 叫ubuntu,密码是ubuntu, 如果你想给容器注入一个ssh key可以使用-S sshkey.pub,如果你想给容器注入一个用户,则可以使用-b name,则会自动复制系统 中的name的名称和密码到容器中,你也可以产生其他系统的容器,例如debian,默认是debian6系统。还有各种各样的模板。模板在/usr/share/lxc/templates目

录下。

      备份容器,主要跟参数-B

lxc-create -t ubuntu -n CN -B lvm --vgname schroots --fssize 5G --fstype xfs


   2  克隆容器

lxc-clone -o C1 -n C2

       利用容器C1克隆一个C2,如果你的/var/lib/lxc是btrfs文件系统,则创建的C2系统是C1的一个快照

  3  启动和停止容器

      如果你要启动一个容器:

lxc-start -n container /sbin/init loglevel=debug


      lxc-start将会在容器中执行/sbin/init,你可以提供一个不同的程序来执行,也可以跟参数。如果你没有指定-d参数,你会在终端看到一个console,如果你指定了 -d(daemon)则看不到console,lxc-start启动后会立即成功退出,即时启动失败也是会立即退出的,这时你可以使用lxc-wait和lxc-monitor来检查启动结果。也可以 把启动过程保存在日志中lxc-start -o lxc.debug -l DEBUG -n container  -l级别 -o文件名,你也可以把配置参数都放到一个文件中,然后用-s参数来启动。

      While lxc-start runs the container's /sbin/init, lxc-execute uses a minimal init program called lxc-init, which attempts to mount /proc, /dev/mqueue, and /dev/shm, executes the programs specified on the command line, and waits for those to finish executing. lxc-start is intended to be used for system containers, while lxc-execute is intended for application containers (see this article for more)

      如果你要停止一个容器:

           有多种方法,例如登陆进容器里面执行shutdown、reboot、poweroff等等。但是最简单的关闭一个容器则是执行lxc-shutdown -c NC,NC,你也可以跟一个-t参数,来延迟一段时间后再关闭容器,你也可以使用lxc-stop -n CN立即关闭容器。

  4  容器的冻结

     lxc-freeze -n CN 则会阻止所有的进程直到容器恢复lxc-unfreeze -n CN

  5  容器的监控

     lxc-monitor可以监控容器的状态,-n参数后面跟容器名称,也可以监控多个容器 lxc-monitor -n cont[0-5]*

  6  lxc-wait waits for a specific state change and then exits



  7  console

      容器都是可以配置有几个console的,/dev/console总是存在的,可以再lxc.tty定义个数,一般默认是4,lxc-console -n container -t 3

  8  容器检查,有几个命令可以收集目前的容器的而信息

lxc-ls     第一行列出目前存在的容器,第二行列出目前在运行的容器
   lxc-list  提供相同的信息,格式化输出,先列出运行的容器,后面列出停止的容器。
   lxc-ps   列出容器里面的进程,可以使用--后面跟ps命令的参数 lxc-ps -n plain -- -ef
   lxc-info 提供容器的状态和容器的进程pid
   lxc-cgroup  可以查看和设置容器的资源限制。lxc-cgroup -n CN memory.limit_in_bytes 300000000
   lxc-netstat  在运行的容器中执行netstat
   lxc-backup  /  lxc-restore


   9  破坏容器

       lxc-destroy -n CN ,如果容器在运行,则可以加-f参数,强制停止并破坏

  10 Ephemeral containers  一次性容器

        lxc-start-ephemeral -b jdoe -o CN -- /home/jdoe/run_my_job   任务执行完,容器就丢弃

   其他相关命令如下:

Command

Synopsis

lxc-attach

(NOT SUPPORTED) Run a command in a running container

lxc-backup

Back up the root filesystems for all lvm-backed containers

lxc-cgroup

View and set container control group settings

lxc-checkconfig

Verify host support for containers

lxc-checkpoint

(NOT SUPPORTED) Checkpoint a running container

lxc-clone

Clone a new container from an existing one

lxc-console

Open a console in a running container

lxc-create

Create a new container

lxc-destroy

Destroy an existing container

lxc-execute

Run a command in a (not running) application container

lxc-freeze

Freeze a running container

lxc-info

Print information on the state of a container

lxc-kill

Send a signal to a container's init

lxc-list

List all containers

lxc-ls

List all containers with shorter output than lxc-list

lxc-monitor

Monitor state changes of one or more containers

lxc-netstat

Execute netstat in a running container

lxc-ps

View process info in a running container

lxc-restart

(NOT SUPPORTED) Restart a checkpointed container

lxc-restore

Restore containers from backups made by lxc-backup

lxc-setcap

(NOT RECOMMENDED) Set file capabilities on LXC tools

lxc-setuid

(NOT RECOMMENDED) Set or remove setuid bits on LXC tools

lxc-shutdown

Safely shut down a container

lxc-start

Start a stopped container

lxc-start-ephemeral

Start an ephemeral (one-time) container

lxc-stop

Immediately stop a running container

lxc-unfreeze

Unfreeze a frozen container

lxc-unshare

Testing tool to manually unshare namespaces

lxc-version

Print the version of the LXC tools

lxc-wait

Wait for a container to reach a particular state





4  配置文件


    容器的设置由LXC配置选项来控制。选项通过一些参数来指定,在容器创建时,可以指定一个配置文件。然而,用于创建的模版通常会插入它们自己的配置选项,所以我们在这时通常只指定网络配置选项。对于其他配置,最好在容器创建以后再编辑配置文件,默认用于容器启动的配置文件是/var/lib/lxc/CN/config,lxc-start可以通过-f filename参数来指定一个替代性的配置文件。特殊的配置参数可以在lxc-start启动时通过-s key=value参数来替代配置文件中参数。这通常比编辑容器配置文件要好。

   LXC容器的网络配置非常具有伸缩性。它通过lxc.network.type配置文件项来触发。如果没有这个配置项,则容器将共享主机的网络堆栈。容器中的服务和网络连接将使用物理主机的IP地址。如果至少有一个lxc.network.type配置项,则容器将使用一个私有(2层)网络堆栈。这样它就会有自己的网络接口和防火墙规则。 这些

lxc.network.type选项有:

lxc.network.type=empty - 容器除了loopback网卡接口没有其他网络接口
lxc.network.type=veth - 这时默认用于ubuntu或ubuntu-cloud模版的配置,用于创建于一个veth网络隧道(network tunnel)。tunnel的一段就是位于容器内部的网络接口,另一端则连接到物理主机的网桥上。可以通过添加更多的lxc.network.type=veth配置项到容器配置文件以创建更多tunnel。tunnel的物理主机端将通过配置项 lxc.network.link = lxcbr0 来指定。
lxc.network.type=phys 将物理网卡传递给容器。
另外两个选项是使用 vlan 或 macvlan,然而这两种方式更为复杂不在这里讨论。 一些其他的网络选项有:
lxc.network.flags 可以设置为 up 可以确保网络接口是up的。
lxc.network.hwaddr 设置在容器钟的网络接口的mac地址
lxc.network.ipv4 和 lxc.network.ipv6 如果设置静态IP地址,则该参数设置各自的IP地址
lxc.network.name 设置容器内的网卡命名方式。如果没有指定,则默认(例如第一个网卡命名为eth0)命名方法是一个很好的选择。
lxc.network.lxcscript.up 设置一个脚本在主机端网络被设置时调用。可以查看lxc.conf手册有关详细内容。

     Cgroup选项可以通过lxc.cgroup对象来设置,lxc.cgroup.subsystem.item = value 让LXC可以设置 cgroup 子系统的参数值。比较方便的hi可以将参数写入容器控制组subsystem子系统的item项的value。 例如,要设置内存限制为 320M 则添加lxc.cgroup.memory.limit_in_bytes = 320000000

     Rootfs, mounts and fstab的设置

lxc.rootfs = /var/lib/lxc/CN/rootfs
lxc.mount.entry=proc /var/lib/lxc/CN/rootfs/proc proc nodev,noexec,nosuid 0 0
lxc.mount = /var/lib/lxc/CN/fstab



     第一行配置设置容器的根文件系统已经挂载在 /var/lib/lxc/CN/rootfs ,如果文件系统是一个块设备(例如一个LVM逻辑卷),则该块设备的路径必须存在。

    每个 lxc.mount.entry 行必须包含一个要挂载的正确的fstab格式的内容。这个目标目录必须以/var/lib/lxc/CN/rootfs开头,即使这个lxc.rootfs指向一个块设备。

    最后,lxc.mount指定了一个文件,以fstab格式,包含需要挂载的项目。注意在容器init进程启动之前,这些所有的挂载点必须要先挂载好。这种方式才可以将物理主机的挂载目录bind到容器中。




参考官方文档:ubuntu12.04 LXC Doc