如何使用LXC编译Linux并创建应用程序容器

时间:2020-03-05 15:28:28  来源:igfitidea点击:

LXC(LinuX容器)是一种操作系统级虚拟化方法,用于在单个主机上运行多个隔离的Linux系统(容器)。

Linux内核包含用于资源隔离(CPU,内存,块I/O,网络等)的cgroup(控制组),不需要启动任何虚拟机。
Cgroup还提供名称空间隔离,以完全隔离应用程序对操作环境的视图,包括进程树,网络,用户ID和已挂载的文件系统。

LXC结合了cgroup和名称空间支持,为应用程序提供了隔离的环境。

命名空间隔离

  • pid
  • mnt
  • net
  • uts
  • ipc
  • user

与cgroup隔离

  • memory
  • cpu
  • blkio
  • devices

1)LXC的内核

选择高于Linux内核版本– 3.3的任何内核,并确保通过“ make menuconfig”或者内核编译过程启用以下选项。

filename: linux-3.3/.config
CONFIG_USER_SCHED=n
CONFIG_CGROUPS=y
CONFIG_CGROUP_SCHED=y
CONFIG_CGROUP_DEBUG=y
CONFIG_CGROUP_NS=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CPUSETS=y
CONFIG_PROC_PID_CPUSET=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_RESOURCE_COUNTERS=y
CONFIG_NAMESPACES=y
CONFIG_UTS_NS=y
CONFIG_IPC_NS=y
CONFIG_USER_NS=y
CONFIG_PID_NS=y
CONFIG_NET_NS=y
CONFIG_VLAN_8021Q=y
CONFIG_VLAN_8021Q_GVRP=n
CONFIG_MACVLAN=y
CONFIG_VETH=y
CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
CONFIG_SECURITY_FILE_CAPABILITIES=y
CONFIG_FAIR_GROUP_SCHED=y
CONFIG_RT_GROUP_SCHED=n
CONFIG_BLK_CGROUP=n
CONFIG_MACVTAP=n
CONFIG_CFS_BANDWIDTH=y
CONFIG_NETPRIO_CGROUP=y

2)编译lxc

从https://linuxcontainers.org/downloads/下载LXC源,选择任何版本lxc-x.x.x.tar.gz

示例汇编

[katla@regina]# tar xvf lxc-1.0.4.tar.gz
[katla@regina]# cd lxc-1.0.4
[katla@regina]# export CC=arm-gnu-eabi-linux-gcc; ./configure --host=arm
[katla@regina]# make
[katla@regina]# ls * | grep lxc-*
lxc-create lxc-start lxc-execute lxc-console lxc-stop lxc-freeze lxc-ps lxc-monitor lxc-unfreeze lxc-info ..

将这些二进制文件复制到在编译的Linux内核之上运行的目标的rootfs的/usr/bin或者/sbin或者/bin目录中。

3)LXC和网络

目标机(ARM)上的网桥设置和linux主机接口(eth0)配置

bridge-start
brctl show
brctl addbr host0
ifconfig eth0 192.168.10.2 up
route add default gw 10.140.47.254 eth0
ifconfig host0 192.168.10.1 up

4)运行应用程序容器

我们可以使用lxc-execute命令创建一个应用程序容器(名称:guest),其中可以运行与系统其余部分有效隔离的命令。

例如,以下命令创建一个名为guest的应用程序容器,该容器运行sleep 300秒。

[katla@regina]# lxc-execute -n guest -- sleep 300

在容器处于活动状态时,我们可以通过从另一个窗口运行lxc-ls --active和lxc-info -n guest等命令来对其进行监视。

[katla@regina]# lxc-ls --active guest
[katla@regina]# lxc-info -n guest
state: RUNNING pid: 4021

如果需要自定义应用程序容器,则可以使用配置文件。

例如,我们可能想要更改容器的网络配置或者其安装的系统目录。

以下示例显示了一个示例配置文件中的设置,在该配置文件中,除装入条目外,大多数rootfs都不共享,以确保lxc-init以及某些库和二进制目录路径可用。

lxc.utsname = guest
lxc.tty = 1
lxc.pts = 1
lxc.rootfs = /tmp/guest/rootfs
lxc.mount.entry=/lib /tmp/guest/rootfs/lib none ro,bind 0 0
lxc.mount.entry=/usr/libexec /tmp/guest/rootfs/usr/lib none ro,bind 0 0
lxc.mount.entry=/lib64 /tmp/guest/rootfs/lib64 none ro,bind 0 0
lxc.mount.entry=/usr/lib64 /tmp/guest/rootfs/usr/lib64 none ro,bind 0 0
lxc.mount.entry=/bin /tmp/guest/rootfs/bin none ro,bind 0 0
lxc.mount.entry=/usr/bin /tmp/guest/rootfs/usr/bin none ro,bind 0 0
lxc.cgroup.cpuset.cpus=1

需要/usr/libexec的安装项,以便容器可以访问主机系统上的/usr/libexec/lxc/lxc-init。

示例配置文件同时挂载/bin和/usr/bin。
实际上,我们应该将应用程序容器安装的主机系统目录限制为仅容器运行应用程序所需的目录。

笔记
为避免与系统容器发生潜在冲突,请不要将/container目录用于应用程序容器。

我们还必须在rootfs目录下配置所需的目录:

[katla@regina]# TMPDIR=/tmp/guest/rootfs
[katla@regina]# mkdir -p $TMPDIR/lib $TMPDIR/usr/lib $TMPDIR/lib32 $TMPDIR/usr/lib32 \ $TMPDIR/bin $TMPDIR/usr/bin $TMPDIR/dev/pts $TMPDIR/dev/shm $TMPDIR/proc

在此示例中,除了配置文件中定义的安装点条目之外,目录还包括/dev/pts,/dev/shm和/proc。

然后,我们可以使用-f选项将配置文件(config)指定为lxc-execute:

[katla@regina]# lxc-execute -n guest -f config -- ps -ef
UID PID PPID C STIME TTY TIME CMD
0 1 0 0 07:36 ? 00:00:00 /usr/lib/lxc/lxc-init -- ps -ef 0 2 1 0 08:46 ? 00:00:00 ps -ef

此示例显示ps命令作为lxc-init的子级运行。

对于系统容器,我们可以在配置文件中设置cgroup条目,并使用lxc-cgroup命令来控制应用程序容器可以访问的系统资源。

注意:

lxc-execute用于运行共享主机根文件系统的应用程序容器,而不是运行我们使用lxc-create创建的系统容器。
使用lxc-start运行系统容器。

5)示例配置和日志

Filename: /etc/fstab
cgroup /cgroup cgroup defaults 0 0
Filename: /etc/lxc/guest/config
# Default pivot location
lxc.pivotdir = lxc_putold
# Default mount entries
lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0
lxc.mount.entry = sysfs sys sysfs defaults 0 0
lxc.mount.entry = /sys/fs/fuse/connections sys/fs/fuse/connections none bind,optional 0 0
# Default console settings
lxc.tty = 4 lxc.pts = 1024
# Default capabilities
lxc.cap.drop = sys_module mac_admin mac_override sys_time
# When using LXC with apparmor, the container will be confined by default.
# If you wish for it to instead run unconfined, copy the following line
# (uncommented) to the container's configuration file.
#lxc.aa_profile = unconfined
# To support container nesting on an Ubuntu host while retaining most of
# apparmor's added security, use the following two lines instead.
#lxc.aa_profile = lxc-container-default-with-nesting
#lxc.hook.mount = /usr/share/lxc/hooks/mountcgroups
# If you wish to allow mounting block filesystems, then use the following
# line instead, and make sure to grant access to the block device and/or loop
# devices below in lxc.cgroup.devices.allow.
#lxc.aa_profile = lxc-container-default-with-mounting
# Default cgroup limits lxc.cgroup.devices.deny = a
## Allow any mknod (but not using the node)
lxc.cgroup.devices.allow = c *:* m
lxc.cgroup.devices.allow = b *:* m
## /dev/null and zero
lxc.cgroup.devices.allow = c 1:3 rwm
lxc.cgroup.devices.allow = c 1:5 rwm
## consoles
lxc.cgroup.devices.allow = c 5:0 rwm
lxc.cgroup.devices.allow = c 5:1 rwm
## /dev/{,u}random lxc.cgroup.devices.allow = c 1:8 rwm
lxc.cgroup.devices.allow = c 1:9 rwm ## /dev/pts/*
lxc.cgroup.devices.allow = c 5:2 rwm
lxc.cgroup.devices.allow = c 136:* rwm
## rtc
lxc.cgroup.devices.allow = c 254:0 rm