LXC即Linux Container,是一个类似Docker和OpenVZ的无需硬件虚拟化的内核容器虚拟化技术,可以对资源进行控制和隔离。本文记录在Debian 11上安装LXC,创建一个基于Debian的LXC容器,并将该容器的网络桥接到tinc的过程。

安装和配置LXC

注:以下命令均在root权限下执行。
在Debian上,直接使用apt即可安装所需的软件包,用于实现桥接功能的bridge-utils作为依赖包会随lxc自动安装:

apt-get update
apt-get install lxc 

安装完成以后,默认的配置工具会自动添加一个网桥lxcbr0,新创建的容器默认桥接到这个网桥上,并通过NAT访问网络。
此时,已经可使用模板创建容器了。在/usr/share/lxc/templates下可以看到各个系统的预置模板(如果没有该目录或该目录里没有系统模板文件,则需要手动安装lxc-templates软件包)。其中,创建容器时会从软件源下载所需的软件包,默认软件源与系统配置的软件源不一致(即/etc/apt中的配置文件),如果需要修改软件源,则需要修改模板文件。以Debian为例,编辑/usr/share/lxc/templates/lxc-debian文件,找到MIRROR和SECURITY_MIRROR所在行,将该行中的软件源地址修改为所需的地址,之后保存即可。
然后运行lxc-create即可创建容器,-t参数指定容器的系统环境,-n参数指定容器的名字,自行替换为所需的名称即可:

lxc-create -t debian -n lxc-deb1

如果在Ubuntu或其他Debian Based发行版可能遇到签名错误的情况,这是由于没有导入相应发行版的GPG Key,提示如下:

Downloading debian minimal ...
I: Retrieving InRelease 
I: Checking Release signature
E: Release signed by unknown key (key id 605C66F00D6C9793)
   The specified keyring /var/cache/lxc/debian/archive-key.gpg may be incorrect or out of date.
   You can find the latest Debian release key at https://ftp-master.debian.org/keys.html
Failed to download the rootfs, aborting.
Failed to download 'debian base'
failed to install debian

可以到提示的地址https://ftp-master.debian.org/keys.html中找到后缀为asc的release key文件,如Debian 11的文件为https://ftp-master.debian.org/keys/release-11.asc,将其下载下来,之后添加到/var/cache/lxc/debian/archive-key.gpg中:

gpg --no-default-keyring --keyring /var/cache/lxc/debian/archive-key.gpg --import release-11.asc

如果执行如下命令时:

gpg --no-default-keyring --keyring /var/cache/lxc/debian/archive-key.gpg --list-key

看到有Debian Stable Release Key (11/bullseye)项,则添加成功,重新执行lxc-create命令即可。
创建完成以后,可以在/var/lib/lxc中看到以容器名字命名的路径。其中,路径内config文件即为该容器的配置文件,rootfs即为该容器的根目录。
如果希望能够通过ssh使用密码连接上容器,首先需要给容器设置一个root密码。先chroot进入容器的根目录中,然后运行passwd设置密码

chroot /var/lib/lxc/lxc-deb1/rootfs
passwd
exit

然后编辑sshd的配置文件,允许密码登录。编辑/var/lib/lxc/lxc-deb1/rootfs/etc/ssh/sshd_config文件,将PermitRootLogin设置为yes:

#PermitRootLogin prohibit-password
PermitRootLogin yes

如果需要将容器的端口暴露到公共网络,则不推荐使用密码登录。如需使用密钥登录,则直接将自己的密钥对中的公钥写入到/var/lib/lxc/lxc-deb1/rootfs/root/.ssh/authorized_keys中即可。
此时,已经可以启用容器了。通过lxc-start命令指定容器的名字启动容器。

lxc-start lxc-deb1

通过lxc-info可以查看容器的信息,一个输出例子如下

# lxc-info lxc-deb1
Name:           lxc-deb1
State:          RUNNING
PID:            2258
IP:             10.0.3.13
Link:           veth3mTv41
 TX bytes:      66.07 KiB
 RX bytes:      57.23 KiB
 Total bytes:   123.30 KiB

其中,可以看到容器桥接到默认网桥后通过dhcp分配的IP地址。利用这个IP地址,就可以通过ssh登录到容器中了。
在本机中,主机在网桥的地址为10.0.3.1,容器的地址为10.0.3.13,容器将默认网关设置为lxcbr0中主机的地址,LXC自动配置了NAT转发,使得容器能够访问网络。容器的默认DNS同样为主机地址,即地址解析通过主机进行。
此时在主机中,已经可以通过端口转发,让其他设备通过主机的网卡访问容器中的服务。端口转发可以使用iptables(配置DNAT和SNAT,但是需要容器的默认网关为主机)或者brook(使用relay模式,容器只需桥接到网桥上即可。项目地址为https://github.com/txthinking/brook)实现。
如果需要关闭容器,使用lxc-stop命令:

lxc-stop lxc-deb1

如果需要删除容器,使用lxc-destroy命令:

lxc-destroy lxc-deb1

将LXC容器桥接到tinc网络

tinc的安装和配置过程已在搭建tinc实现异地构建局域网中进行了记录。
此处需要对相关配置进行修改。interface继续以mynet为例,新建的网桥命名为br-mynet。主机在tinc网络中的地址为10.20.20.2/24,分配给容器的地址为10.20.20.3/24。注意修改之前建议先关闭tinc服务,且tinc的配置必须为交换机(switch)模式。
首先,编辑/etc/network/interface文件,将tinc的接口设置为手动模式,添加网桥并桥接到tinc的接口。在/etc/network/interface添加以下内容:

iface mynet inet manual

iface br-mynet inet static
        address 10.20.20.2/24
        bridge-ports mynet
        bridge-stp off
        bridge-fd 0

配置ip地址的部分工作将不再由tinc-up文件完成,该文件修改为

#!/bin/bash
ifup br-mynet

同时,tinc-down文件修改为

#!/bin/bash
ifdown br-mynet

之后启动tinc,即可看到原本的interface不再有ip地址,ip地址分配给了br-mynet,正常情况下tinc网络仍可以正常工作。
将容器关机后,修改容器的配置文件/var/lib/lxc/lxc-deb1/config(该配置文件的说明可参考https://linuxcontainers.org/lxc/manpages/man5/lxc.container.conf.5.html),添加一个桥接到br-mynet的网卡,并设置静态IP。添加的内容参考如下:

lxc.net.1.type = veth
lxc.net.1.hwaddr = 12:34:56:78:9a:bc
lxc.net.1.link = br-mynet
lxc.net.1.flags = up
lxc.net.1.ipv4.address = 10.20.20.3/24
lxc.net.1.ipv4.gateway = 10.20.20.1

其中,hwaddr为指定的mac地址,注意不要与其他网卡冲突。address和gateway为配置的静态IP。配置gateway以后,容器默认会通过该gateway访问网络。如果tinc网络中有DHCP服务器,address和gateway参数可以省略,容器将通过DHCP获取IP地址。如果tinc中没有网关,gateway选项可以省略。
再次启动容器,进入容器后可以看到有两张网卡,新增加的网卡绑定为tinc网络中的地址。此时,tinc网络内的其他设备就可以通过tinc网络访问该容器了。

备注

LXC和Docker的网络支持macvlan模式,但是在测试中,可能是tun设备的原因`macvlan偶尔会出现异常发包,从而干扰tinc网络。该问题仅偶尔出现,尚未排查到出错的原因。
如果需要在LXC内直接安装tinc,需要为该容器启用tun设备,向容器的config文件填入以下内容:

# Enable Tun
lxc.cgroup2.devices.allow = c 10:200 rwm
lxc.mount.entry = /dev/net dev/net none bind,create=dir 0 0

其中,内核5.5.15以上的系统使用cgroup2。对于老版本内核的系统,lxc.cgroup2.devices.allow需要修改为lxc.cgroup.devices.allow。修改以后重启容器即可。

标签: Linux, tinc, SDLAN

添加新评论