目录

安装incus部署lxc容器

这篇文章介绍了如何安装incus

注意
注1、本人使用的系统为debian13

1 安装incus

1.1 命令安装incus

sudo apt install incus-base

安装btrfs

sudo apt install btrfs-progs

1.2 配置incus

初始化incus,全部默认下一步即可

incus admin init

检查内核转发是否已开启 (1 为开启)

sysctl net.ipv4.ip_forward

开启incusbr0网桥的DHCP

incus network set incusbr0 ipv4.dhcp true

创建一个alpine容器

incus launch images:alpine/edge alpine01
incus launch images:debian/12 debian01

进入容器 (Shell)

incus shell alpine01

其他incus命令

查看所有容器状态        incus list
停止容器               incus stop debian01
启动已有的容器          incus start debian01
删除容器(需先停止)	incus delete debian01
查看容器详细信息	incus info debian01

1.3 配置容器静态ipv4

查看网桥网段

incus network show incusbr0

配置静态IP,重启生效

# 语法:incus config device set <容器名> <网卡名> ipv4.address <静态IP>
incus config device set alpine01 eth0 ipv4.address 10.1.168.165
incus config device override alpine01 eth0 ipv4.address=10.1.168.165   # 首次使用解绑模板eth0

容器内配置静态ip

# 配置ip
ip addr add 10.157.232.10/24 dev eth0
# 配置网关
ip route add default via 10.157.232.1 dev eth0
# 配置dns
nano /etc/resolv.conf
# 配置systemd-resolved
ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
systemctl restart systemd-resolved

其他设置

# 设置主机名
sudo hostnamectl set-hostname 新主机名

# 设置语言
sudo dpkg-reconfigure locales

# 设置时区
sudo timedatectl set-timezone Asia/Shanghai

1.4 关闭Incus防火墙

关闭防火墙incus防火墙,使用母鸡防火墙

incus network set incusbr0 ipv4.firewall false
incus network set incusbr0 ipv6.firewall false

1.5 配置端口转发

编辑配置文件

sudo nano /etc/nftables.conf

放置如下内容

#!/usr/sbin/nft -f

# 清除旧规则
flush ruleset

# 定义变量
define WAN_IF = "ens18"          # !!!请根据实际情况修改此网卡名!!!
define BRIDGE_IF = "incusbr0"    # Incus 默认网桥名

# ==========================================
# 1. 过滤表:负责安全性(谁能进,谁能过)
# ==========================================
table inet filter {
    chain input {
        type filter hook input priority filter; policy drop;

        # 允许本地回环
        iif "lo" accept
        # 允许已建立和关联的连接 (回包)
        ct state established,related accept
        # 允许 Ping (可选)
        ip protocol icmp accept
        ip6 nexthdr icmpv6 accept

        # 允许管理服务:宿主机 SSH 。相当于宿主机防火墙
        tcp dport 22 accept
        tcp dport 80 accept

        # 兼容 Incus:允许容器获取 IP (DHCP) 和请求 DNS
        iifname $BRIDGE_IF udp dport { 53, 67 } accept
        iifname $BRIDGE_IF tcp dport { 53, 67 } accept
    }

    chain forward {
        type filter hook forward priority filter; policy drop;

        # 允许已建立和关联的连接
        ct state established,related accept

        # 允许容器访问外部网络
        iifname $BRIDGE_IF oifname $WAN_IF accept

        # 允许容器之间互相通信
        iifname $BRIDGE_IF oifname $BRIDGE_IF accept

        # 【核心安全规则】
        # 自动放行在 NAT 表中命中转发规则的所有流量 (含 TCP 和 UDP)
        ct status dnat accept
    }

    chain output {
        type filter hook output priority filter; policy accept;
    }
}

# ==========================================
# 2. NAT表:负责转发逻辑(改写目标地址)
# ==========================================
table ip nat {
    # 端口转发映射映射表
    # 结构: [ 协议 . 外部端口 ] : [ 内部IP . 内部端口 ]
    map port_forward_map {
        type inet_proto . inet_service : ipv4_addr . inet_service
        elements = {
            tcp . 56256 : 10.239.122.103 . 22,
            tcp . 8080  : 10.239.122.42 . 80,
            udp . 8080  : 10.239.122.42 . 80,
            udp . 51820 : 10.239.122.43 . 51820
        }
    }

    chain prerouting {
        type nat hook prerouting priority dstnat; policy accept;

        # 核心转发指令:基于协议和端口自动查找 Map 并执行 DNAT
        dnat ip addr . port to meta l4proto . th dport map @port_forward_map
    }

    chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;

        # 伪装出口流量,让容器能上网
        oifname $WAN_IF masquerade
    }
}

验证文件

sudo nft -c -f /etc/nftables.conf

应用配置,重启电脑后端口转发可能失效,再次运行此命令

sudo nft -f /etc/nftables.conf

进入容器 (Shell)

incus shell alpine01

命令行临时添加,重启后失效

# 同时增加一条 TCP 转发
sudo nft add element ip nat port_forward_map { tcp . 7777 : 10.239.122.41 . 7777 }

# 同时增加一条 UDP 转发
sudo nft add element ip nat port_forward_map { udp . 7777 : 10.239.122.41 . 7777 }

自动保存当前运行的规则。如果你通过命令行临时添加了很多规则,懒得再去手动改文件,可以直接把内存中运行的“完美状态”覆盖到配置文件里:

sudo sh -c "nft list ruleset > /etc/nftables.conf"

注意:这会把文件顶部的#!/usr/sbin/nft -f等注释删掉,但规则是完整的。

2 打包lxc镜像

2.1 手动打包镜像

安装debootstrap

sudo apt install debootstrap tar xz-utils

创建一个干净的工作目录

mkdir -p ~/incus-build/rootfs
cd ~/incus-build

构建Rootfs根文件系统

sudo debootstrap --variant=minbase --arch=arm64 trixie ./rootfs http://mirrors.tuna.tsinghua.edu.cn/debian/
sudo debootstrap --variant=minbase --no-check-gpg  --arch=loong64 sid ./rootfs https://mirrors.aliyun.com/debian-ports/

现在的 rootfs 目录只是的一堆死文件,我们需要进入内部进行配置,否则容器启动会报错或无法联网。

sudo chroot ./rootfs /bin/bash

设置 PATH 环境变量

export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

配置网络(Incus 依赖 DHCP,必须配置)

# 安装网络工具和 SSH
apt update
apt install debian-ports-archive-keyring
apt install -y iproute2 iputils-ping curl openssh-server bash-completion nano ifupdown isc-dhcp-client sudo dialog perl

# 配置网卡自动获取 IP (ifupdown 方式)
cat <<EOF > /etc/network/interfaces
# interfaces(5) file used by ifup(8) and ifdown(8)
# Include files from /etc/network/interfaces.d:
source /etc/network/interfaces.d/*

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp
EOF

设置 root 密码(否则你进不去)

passwd root

允许 root 登录 SSH

sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config

清理垃圾并退出

apt-get clean
rm -rf /var/lib/apt/lists/*
exit

编写元数据 (Metadata)模板,可以从此镜像站抄,incus.tar.xz为元数据。

#在工作目录下创建模板文件夹
mkdir templates

配置自动主机名 (Hostname)

#在工作目录下创建模板文件夹
cd templates
nano hostname.tpl

文件内容

{{ container.name }}

编写/etc/hosts模板 (templates/hosts.tpl)

nano hosts.tpl

文件内容

127.0.0.1   localhost
127.0.1.1   {{ container.name }}

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

工作目录下创建 metadata.yaml

cat <<EOF > metadata.yaml
architecture: "x86_64"
creation_date: $(date +%s)
properties:
  description: "My Scratch Debian 12"
  os: "debian"
  release: "bookworm"
EOF

配置 metadata.yaml

architecture: "x86_64"
creation_date: 1706870400
properties:
  description: "Debian with Auto-Hostname"
  os: "debian"
  release: "bookworm"

# 核心配置在这里
templates:
  # 1. 目标文件在容器内的绝对路径
  /etc/hostname:
    # 什么时候触发替换?(create=创建时, copy=从快照恢复时, start=每次启动时)
    when:
      - create
      - copy
    # 使用哪个模板文件?(相对于 metadata 压缩包内的 templates/ 目录)
    template: hostname.tpl

  # 2. 配置 hosts 文件
  /etc/hosts:
    when:
      - create
      - copy
    template: hosts.tpl

打包 Metadata

tar -cJvf ./metadata.tar.xz metadata.yaml templates/

打包 Rootfs: 关键点: 必须进入 rootfs 目录内部打包,且使用 –numeric-owner 保持 UID/GID 为数字,防止跨系统用户映射错误

cd rootfs
sudo tar --numeric-owner -cJvf ../rootfs.tar.xz .
cd ..

导入并测试

# 导入镜像
incus image import metadata.tar.xz rootfs.tar.xz --alias debian-sid

# 启动容器测试
incus launch debian-sid debian01

# 查看是否运行
incus list

# 进入容器
incus shell debian01