可爱的 LXD 系统容器

  • tag: lxc lxd container linux
  • date: 2018-04

本文基于 ubuntu 16.04 操作。

LXD 是什么

很多人可能不知道 LXD,但可能听说过老牌容器 LXC(远早于 docker)。

[LXC][] 由 [Canonical Ltd][] 和 [Ubuntu][] 开发维护,其灵感可能来自 [OpenVZ][] 等轻量级虚拟机(容器)。
原有的 LXC 工具比较难用(需要用户了解一些底层知识),同时开发团队想要修改(优化)一些默认配置和特性(如安全增强,默认创建非特权容器)。
为了保持兼容性,不宜在旧的已有 LXC 工具(如 lxc-create, lxc-start 等)上动刀,于是新设计封装了一套上层运维操作工具,即 [LXD][]。
LXC 使用 C 开发,LXD 使用 golang 开发。早期版本的 docker 其实也是基于 LXC 封装,LXD 可能也借鉴了 docker 的一些思想。
LXD 拆分为 daemon(命令为 lxd)和客户端(命令为 lxc)两部分。

LXD 的定位很清晰:系统容器,直接对标虚拟机 ,甚至可以直接运行虚拟机镜像(但是不启动内核)。
系统容器运行整套操作系统(再说一次,除了内核),应用容器(如 docker)运行应用,两者不冲突。
可以在 LXD 容器里安装和使用 docker,跟在物理机和虚拟机上没什么两样。
LXD 还支持与 OpenStack 集成(nova-lxd 项目,可替代 OpenStack 上的虚拟机?)。

[LXD][] 远没有 docker 流行,网上资料不多。
通过 LXD 官方文档 和命令行帮助,已经足够轻松了解和使用 LXD,读来感觉非常可爱。

安装 LXD

从软件仓库安装 LXD

ubuntu 下可直接从软件仓库安装 LXD:

sudo aptitude install lxd lxd-client -y
  • 前面提到,lxd 拆分为 daemon 和客户端。lxd-client 是客户端软件包,安装后得到 lxc 命令。

去掉默认网桥 lxdbr0

当前版本 lxd 默认会拉起 lxdbr0 网桥,可修改 lxd.service 不要依赖 lxd-bridge.service,避免拉起这个默认网桥:

sudo systemctl stop lxd-bridge.service
sudo rsync -ai /{lib,etc}/systemd/system/lxd.service
sudo sed -r -e '/^(After|Requires)=/ s#lxd-bridge.service\s*##g' /etc/systemd/system/lxd.service -i
sudo systemctl daemon-reload

另外 /etc/default/lxd-bridge 文件包含 lxd 网桥相关配置,可配置 lxd 软件包修改此配置文件。

echo 'lxd lxd/setup-bridge boolean false' | sudo debconf-set-selections
echo 'lxd lxd/use-existing-bridge boolean true' | sudo debconf-set-selections
echo 'lxd lxd/bridge-name string br0' | sudo debconf-set-selections
sudo dpkg-reconfigure -f noninteractive lxd

从源码编译安装新版本 LXD

为了使用新版 LXD 功能和特性,可从源码编译安装新版本 LXD。

安装开发依赖。建议手动下载安装 golang 最新版本,其他依赖可直接从软件仓库安装:

sudo aptitude install acl dnsmasq-base git liblxc1 lxc-dev libacl1-dev make pkg-config rsync squashfs-tools tar xz-utils -y

从源码编译最新 release 版本:

mkdir lxd.gopath
cd lxd.gopath/
cat > .envrc <<< $'export GOPATH="${PWD}"\nGOROOT="$(readlink -f /opt/go1.10)"\nPATH="${GOROOT}/bin:${GOPATH}/bin:$PATH"'
direnv allow .
git clone git@github.com:lxc/lxd.git src/github.com/lxc/lxd
( cd src/github.com/lxc/lxd/ && git tag --sort=version:refname | tail )
( cd src/github.com/lxc/lxd/ && git reset --hard lxd-3.0.0 )
make -C src/github.com/lxc/lxd/

安装到 local 目录:

$ sudo install bin/lxd bin/lxc -t /usr/local/bin/ -v
'bin/lxd' -> '/usr/local/bin/lxd'
'bin/lxc' -> '/usr/local/bin/lxc'

转移软件包 lxd 可执行文件,使用本地新版本替代:

sudo systemctl stop lxd
sudo dpkg-divert --rename --add /usr/bin/lxc
sudo dpkg-divert --rename --add /usr/bin/lxd
sudo ln -sfT /usr/{local/,}bin/lxc
sudo ln -sfT /usr/{local/,}bin/lxd

其他办法:修改 lxd.service 使用新版本 lxd 可执行文件。

sudo systemctl stop lxd
sudo sed -r -e 's#(/usr/)(bin/lxd)b#1local/2#g' /etc/systemd/system/lxd.service -i
sudo systemctl daemon-reload


如果 `lxc` 命令被 hash 到系统路径,则需要解除 hash 以使用 local 下的新版 lxc 命令。

hash -d lxc

初始化 LXD daemon

LXD daemon, 有时也称作服务器(server)。
LXD 相关操作通常通过客户端 lxc 命令执行,但 lxd 命令也包含一些特殊操作。
一个用户可能会用到的操作是 lxd init,初始化 lxd daemon。

$ lxd init --help
Description:
  Configure the LXD daemon

Usage:
  lxd init [flags]

Examples:
  init --preseed
  init --auto [--network-address=IP] [--network-port=8443] [--storage-backend=dir]
              [--storage-create-device=DEVICE] [--storage-create-loop=SIZE]
              [--storage-pool=POOL] [--trust-password=PASSWORD]


Flags:
      --auto                    Automatic (non-interactive) mode
      --network-address         Address to bind LXD to (default: none)
      --network-port            Port to bind LXD to (default: 8443) (default -1)
      --preseed                 Pre-seed mode, expects YAML config from stdin
      --storage-backend         Storage backend to use (btrfs, dir, lvm or zfs, default: dir)
      --storage-create-device   Setup device based storage using DEVICE
      --storage-create-loop     Setup loop based storage with SIZE in GB (default -1)
      --storage-pool            Storage pool to use or create
      --trust-password          Password required to add new clients

Global Flags:
# ... ...

lxd init 也是与 daemon 通信完成操作,相当于一个特殊的 lxc 命令。其主要有两个操作,配置网络和存储。

配置网络

lxd 与 git 类似,采用分布式的架构,任意两个节点都可以相互通信。配置网络地址将其暴露到网络上,其他节点可使用密码连接。

lxd init --auto --network-address=0.0.0.0 --trust-password=1234

也可以直接使用 lxc 命令修改和查看网络地址(及其他 server 配置):

$ lxc config set core.https_address 0.0.0.0:8443

$ lxc config show 
config:
  core.https_address: 0.0.0.0:8443
  core.trust_password: true
  • 注意:修改配置后立即生效(类似自动 reload?),而不只是修改配置数据,操作非常方便。

配置存储

提供一个简便的命令,创建一个名为 default 的("默认")存储,并配置(名为 default 的)默认 profile 使用此存储创建容器。
创建一个名为 lxd 的 lvm vg,使用此 vg 创建 "默认" 存储。

lxd init --auto --storage-backend=lvm --storage-pool=lxd

当然也可以直接使用 lxc 命令查看和执行相关操作:

$ lxc storage list
+---------+-------------+--------+--------+---------+
|  NAME   | DESCRIPTION | DRIVER | SOURCE | USED BY |
+---------+-------------+--------+--------+---------+
| default |             | lvm    | lxd    | 1       |
+---------+-------------+--------+--------+---------+

$ lxc profile show default
config: {}
description: Default LXD profile
devices:
  root:
    path: /
    pool: default
    type: disk
name: default
used_by: []

LXD 存储

参考:https://lxd.readthedocs.io/en/latest/storage/

与 docker 不同,LXD 不区分容器和数据卷。
换句话说,容器根文件系统(容器卷)和数据卷在 LXD 使用完全相同的存储方案,统称为存储卷(storage volume),
唯一区别是容器卷会使用镜像进行初始化。
这有个好处,如设计一套存储计算分离的存储方案,则天然同时适用于容器卷和数据卷。
LXD 内置支持多种存储后端,如 dir, btrfs, lvm, zfs, ceph 等,推荐使用 zfs 和 btrfs。

为了方便我们可以使用熟悉的 lvm (thinpool)。前面已经介绍过创建和查看存储,在此不再敖述。

LXD remote

LXD 采用类似 git 分布式架构管理和分发镜像(和容器?),
任意两个节点都可以互相通信,并且许多操作天然支持访问和操作 remote 节点。

$ lxc remote list
+-----------------+------------------------------------------+---------------+-----------+--------+--------+
|      NAME       |                   URL                    |   PROTOCOL    | AUTH TYPE | PUBLIC | STATIC |
+-----------------+------------------------------------------+---------------+-----------+--------+--------+
| images          | https://images.linuxcontainers.org       | simplestreams |           | YES    | NO     |
+-----------------+------------------------------------------+---------------+-----------+--------+--------+
| local (default) | unix://                                  | lxd           | tls       | NO     | YES    |
+-----------------+------------------------------------------+---------------+-----------+--------+--------+
| ubuntu          | https://cloud-images.ubuntu.com/releases | simplestreams |           | YES    | YES    |
+-----------------+------------------------------------------+---------------+-----------+--------+--------+
| ubuntu-daily    | https://cloud-images.ubuntu.com/daily    | simplestreams |           | YES    | YES    |
+-----------------+------------------------------------------+---------------+-----------+--------+--------+
  • lxd 默认添加了 ubuntu 等 remote 节点。本地节点被当作一个名为 local 的特殊节点,同时也是默认节点。

添加远程节点:

lxc remote add han2017 https://han2017:8443/ --accept-certificate --password=1234

LXD 镜像管理

可以直接使用远程镜像创建容器,LXD 会自动拷贝镜像到本地 cache(私有镜像),并自动管理(自动更新,过期清理)。

也可以显式手动从远程节点拷贝镜像到本地:

lxc image copy ubuntu:16.04 local: --alias ubuntu/16.04 --public
lxc image copy han2017:ubuntu/16.04 local: --copy-aliases --public
$ lxc image list
+--------------+--------------+--------+---------------------------------------------+--------+----------+-----------------------------+
|    ALIAS     | FINGERPRINT  | PUBLIC |                 DESCRIPTION                 |  ARCH  |   SIZE   |         UPLOAD DATE         |
+--------------+--------------+--------+---------------------------------------------+--------+----------+-----------------------------+
| ubuntu/16.04 | be7cec7c9489 | yes    | ubuntu 16.04 LTS amd64 (release) (20180405) | x86_64 | 156.27MB | Apr 7, 2018 at 8:17am (UTC) |
+--------------+--------------+--------+---------------------------------------------+--------+----------+-----------------------------+

$ sudo tree -L 3 -a /var/lib/lxd/images/
/var/lib/lxd/images/
├── be7cec7c948958adfbb9bc7dbd292762d2388cc883466815fc2b6bc06bf06f5a
└── be7cec7c948958adfbb9bc7dbd292762d2388cc883466815fc2b6bc06bf06f5a.rootfs
  • 无法指定镜像存储(?),默认以文件形式保持在 /var/lib/lxd/images/ 目录下。
  • 镜像使用 id 标识,可以添加简单可读的别名。拷贝时可以指定目标别名,或者拷贝复用源节点上的别名。

LXD 容器配置

参考:https://lxd.readthedocs.io/en/latest/containers/

LXD 容器配置可划分为两部分:

  1. key/value 配置,使用 lxc configlxc profile 管理。
  2. 对标虚拟机概念,设备管理,使用 lxc config devicelxc profile device 管理。如磁盘设备,网络设备等。
    注意,容器内磁盘设备通常是使用文件系统,而不是块设备。

为了方便管理容器配置,LXD 支持使用 profile 预设管理容器配置模板。
lxc config 管理已创建容器实例配置,lxc profile 管理容器 profile 配置。
创建容器时可指定多个 profile,多个 profile 与容器自身配置叠加覆盖得到最终有效配置。

创建 LXD 容器

使用 lxc init 命令创建容器:

$ lxc init --help
Description:
  Create containers from images

Usage:
  lxc init [<remote>:]<image> [<remote>:][<name>] [flags]

Examples:
  lxc init ubuntu:16.04 u1

Flags:
  -c, --config      Config key/value to apply to the new container
  -e, --ephemeral   Ephemeral container
  -n, --network     Network name
  -p, --profile     Profile to apply to the new container
  -s, --storage     Storage pool name
      --target      Node name
  -t, --type        Instance type

$ lxc network list
+--------+----------+---------+-------------+---------+
|  NAME  |   TYPE   | MANAGED | DESCRIPTION | USED BY |
+--------+----------+---------+-------------+---------+
| br0    | bridge   | NO      |             | 0       |
+--------+----------+---------+-------------+---------+
| enp5s0 | physical | NO      |             | 0       |
+--------+----------+---------+-------------+---------+
  • -p 指定 profile, 可重复多次以指定多个 profile 叠加覆盖。不指定时默认使用 default
  • -c 指定容器 key/value 配置。
  • -s 使用指定存储池创建容器卷。容器卷未指定大小时默认与镜像大小相同。
  • -n 创建网卡设备连接到指定网络。可指定外部(手动管理的)网桥(或网卡等网络设备?)名。

可简化起见,可设置创建特权容器。
一个原因是,LXD 非特权容器默认开启了用户 idmap,虽然 LXD 对 idmap 做了很好的支持,
但 idmap 解决的问题比带来的问题更多,如与宿主机共享文件系统问题等。

修改默认 profile:

lxc profile set default security.privileged true

创建容器:

$ lxc list
+------+-------+------+------+------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+-------+------+------+------+-----------+

$ lxc storage volume list default
+------+------+-------------+---------+
| TYPE | NAME | DESCRIPTION | USED BY |
+------+------+-------------+---------+

$ sudo lvs lxd

$ lxc init ubuntu/16.04 test -s default -n br0
Creating test

$ lxc list
+------+---------+------+------+------------+-----------+
| NAME |  STATE  | IPV4 | IPV6 |    TYPE    | SNAPSHOTS |
+------+---------+------+------+------------+-----------+
| test | STOPPED |      |      | PERSISTENT | 0         |
+------+---------+------+------+------------+-----------+

$ lxc config show test
architecture: x86_64
# ... ...
devices:
  br0:
    nictype: bridged
    parent: br0
    type: nic
  root:
    path: /
    pool: default
    type: disk
ephemeral: false
profiles:
- default
stateful: false
description: ""

$ lxc storage volume list default
+-----------+------------------------------------------------------------------+-------------+---------+
|   TYPE    |                               NAME                               | DESCRIPTION | USED BY |
+-----------+------------------------------------------------------------------+-------------+---------+
| container | test                                                             |             | 1       |
+-----------+------------------------------------------------------------------+-------------+---------+
| image     | be7cec7c948958adfbb9bc7dbd292762d2388cc883466815fc2b6bc06bf06f5a |             | 1       |
+-----------+------------------------------------------------------------------+-------------+---------+

$ sudo lvs lxd
  LV                                                                      VG   Attr       LSize  Pool        Origin                                                                  Data%  Meta%  Move Log Cpy%Sync Convert
  LXDThinpool                                                             lxd  twi-aotz-- 98.00g                                                                                     0.91   0.09                            
  containers_test                                                         lxd  Vwi-a-tz-- 10.00g LXDThinpool images_be7cec7c948958adfbb9bc7dbd292762d2388cc883466815fc2b6bc06bf06f5a 8.90                                   
  images_be7cec7c948958adfbb9bc7dbd292762d2388cc883466815fc2b6bc06bf06f5a lxd  Vwi-a-tz-- 10.00g LXDThinpool                                                                         8.90                                   
  • 第一次在 lvm 存储上创建存储卷时,LXD 自动在指定 vg 上初始化 thinpool。
  • 第一次在 lvm 存储上创建容器时,LXD 自动使用镜像创建 lv 作为镜像卷。因此使用镜像第一次创建容器时,会有创建镜像卷的额外开销。
  • 创建容器时即完成创建容器卷(作为容器设备)(网卡等容器设备则是启动容器时才创建)。

    • 在 lvm thinpool 上创建容器时,容器卷即为镜像卷的快照,因此容器卷大小默认与镜像卷大小相同,可以快速完成创建。
    • 如果开启了 idmap(非特权容器),则 idmap 还会每次产生额外的开销(?),因此简单测试不开启 idmap 是正确的选择。
    • 如果设置容器卷大小,则还会产生 resize 的开销,注意 ext4 支持缩小和扩大,xfs 则只支持扩大,不支持缩小,存储文件系统选择 ext4 可能更通用。

启动 LXD 容器

启动容器:

$ brctl show
bridge name    bridge id        STP enabled    interfaces
br0        8000.0227625084a8    yes        enp5s0
                            tap0

$ lxc start test

$ brctl show
bridge name    bridge id        STP enabled    interfaces
br0        8000.0227625084a8    yes        enp5s0
                            tap0
                            vethKFYJSY

$ ip link show dev vethKFYJSY
6: vethKFYJSY@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br0 state UP mode DEFAULT group default qlen 1000
    link/ether fe:69:14:43:db:75 brd ff:ff:ff:ff:ff:ff link-netnsid 0

$ lxc exec -t test /bin/bash

root@test:~# ip -4 addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
5: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link-netnsid 0
    inet 192.168.100.77/24 brd 192.168.100.255 scope global eth0
       valid_lft forever preferred_lft forever
  • 启动容器时自动创建网络设备连接到指定网桥。
  • LXD 镜像通常默认使用 DHCP 配置网络,容器启动后自动使用 DHCP 配置好网络。

另外发现 lxc exec 的进程报 "not a tty":

root@test:~# tty
not a tty

root@test:~# ll /proc/$$/fd/0
lrwx------ 1 root root 64 Apr  7 09:24 /proc/445/fd/0 -> /dev/pts/2

root@test:~# findmnt /dev/
TARGET SOURCE FSTYPE OPTIONS
/dev   none   tmpfs  rw,relatime,size=492k,mode=755

root@test:~# findmnt /dev/pts/
TARGET   SOURCE FSTYPE OPTIONS
/dev/pts devpts devpts rw,relatime,gid=5,mode=620,ptmxmode=666

root@test:~# ls /dev/pts/
ptmx
  • lxc exec 进程使用的应该是从宿主机上继承的伪终端(上例即 /dev/pts/2)。
  • 容器内 devpts 与宿主机是隔离的(使用 lxcfs?),看不到该伪终端(但可以正常使用),因此报 "not a tty"。

宿主机上可看到相关进程信息如下:

$ pschain -C bash -fww f
UID        PID  PPID  C STIME TTY      STAT   TIME CMD
# ... ...
root     24225     1  0 4月06 ?       Ssl   11:43 /usr/bin/lxd --group lxd --logfile=/var/log/lxd/lxd.log
root     30251 24225  0 17:23 ?        Sl     0:00  \_ /usr/local/bin/lxd forkexec test /var/lib/lxd/containers /var/log/lxd/test/lxc.conf -- env TERM=xterm PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin HOME=/root USER=root LANG=C.UTF-8 -- cmd /bin/bash
root     30259 30251  0 17:23 pts/2    Ss+    0:00      \_ /bin/bash

$ sudo ls -l /proc/30259/fd/0 --color
lrwx------ 1 root root 64 4月   7 17:30 /proc/30259/fd/0 -> /dev/pts/2

如果要执行的命令强依赖正确设置 tty,一个简单的解决办法是 在容器内重新分配伪终端,如使用 script 命令包装要执行的命令。

$ lxc exec -t test /bin/bash

root@test:~# tty
not a tty

root@test:~# script -c /bin/bash /dev/null
Script started, file is /dev/null

root@test:~# tty
/dev/pts/0

可以在 lxc exec 时直接执行 script 命令:

$ lxc exec -t test -- script -c /bin/bash /dev/null
Script started, file is /dev/null

root@test:~# tty
/dev/pts/0

LXD 容器访问宿主机文件系统

容器添加磁盘(文件系统)设备,设置 source 为宿主机文件系统路径,即使用路径绑定,即可轻松访问宿主机文件系统。
LXD 支持动态添加路径绑定,操作立即生效,非常方便。

新建 profile 方便管理相关配置:

lxc profile create share-host
lxc profile set share-host security.privileged true
lxc profile device add share-host /etc/apt/ disk {source,path}=/etc/apt/
$ lxc profile show share-host 
config:
  security.privileged: "true"
description: ""
devices:
  /etc/apt/:
    path: /etc/apt/
    source: /etc/apt/
    type: disk
name: share-host
used_by: []
  • 为避免 idmap 问题,创建特权容器,设置 security.privileged=true

容器添加 profile:

$ lxc exec -t test findmnt /etc/apt/

$ lxc profile add test share-host
Profile share-host added to test

$ lxc config show test
# ... ...
profiles:
- default
- share-host
stateful: false
description: ""

$ lxc exec -t test findmnt /etc/apt/
TARGET   SOURCE                           FSTYPE OPTIONS
/etc/apt /dev/mapper/vg-ubu1604[/etc/apt] ext4   rw,relatime,errors=remount-ro,data=ordered
  • 可看到,容器可以动态添加 profile 配置,路径绑定(磁盘设备)立即生效。
$ lxc profile device add share-host /var/cache/apt/ disk {source,path}=/var/cache/apt/
Device /var/cache/apt/ added to share-host

$ lxc exec -t test findmnt /var/cache/apt/
TARGET         SOURCE                                FSTYPE OPTIONS
/var/cache/apt /dev/mapper/vg-ubu1604var[/cache/apt] ext4   rw,relatime,data=ordered
  • profile 可以动态添加路径绑定,使用了 profile 的容器立即自动更新生效。

制作 LXD 镜像

LXD 不支持分层镜像,镜像制作工具也没有 docker 完善。如何制作 LXD 镜像呢?

  1. LXD 镜像格式非常简单,rootfs + 元信息 + 模板文件(可选) 即可,纯手工制作 LXD 镜像也并非难事。
    虚拟机镜像 rootfs 即可直接作为 LXD 镜像的 rootfs,非常方便复用虚拟机镜像

参考:https://lxd.readthedocs.io/en/latest/image-handling/

  1. 可以直接将容器或容器快照发布为镜像。 只需要在模板容器上完成操作即可。

将容器发布为镜像:

$ lxc image list
+--------------+--------------+--------+---------------------------------------------+--------+----------+-----------------------------+
|    ALIAS     | FINGERPRINT  | PUBLIC |                 DESCRIPTION                 |  ARCH  |   SIZE   |         UPLOAD DATE         |
+--------------+--------------+--------+---------------------------------------------+--------+----------+-----------------------------+
| ubuntu/16.04 | be7cec7c9489 | yes    | ubuntu 16.04 LTS amd64 (release) (20180405) | x86_64 | 156.27MB | Apr 7, 2018 at 8:17am (UTC) |
+--------------+--------------+--------+---------------------------------------------+--------+----------+-----------------------------+

$ sudo tree -L 3 -a /var/lib/lxd/images/
/var/lib/lxd/images/
├── be7cec7c948958adfbb9bc7dbd292762d2388cc883466815fc2b6bc06bf06f5a
└── be7cec7c948958adfbb9bc7dbd292762d2388cc883466815fc2b6bc06bf06f5a.rootfs

$ lxc publish test --alias test --public
Container published with fingerprint: cd1d4f8ce11dc9b6ff2b0a2c45e3cf1bc1370bbb45724b245880b757636537d3

$ lxc image list
+--------------+--------------+--------+---------------------------------------------+--------+----------+-----------------------------+
|    ALIAS     | FINGERPRINT  | PUBLIC |                 DESCRIPTION                 |  ARCH  |   SIZE   |         UPLOAD DATE         |
+--------------+--------------+--------+---------------------------------------------+--------+----------+-----------------------------+
| test         | cd1d4f8ce11d | yes    |                                             | x86_64 | 243.98MB | Apr 7, 2018 at 4:40pm (UTC) |
+--------------+--------------+--------+---------------------------------------------+--------+----------+-----------------------------+
| ubuntu/16.04 | be7cec7c9489 | yes    | ubuntu 16.04 LTS amd64 (release) (20180405) | x86_64 | 156.27MB | Apr 7, 2018 at 8:17am (UTC) |
+--------------+--------------+--------+---------------------------------------------+--------+----------+-----------------------------+

$ sudo tree -L 3 -a /var/lib/lxd/images/
/var/lib/lxd/images/
├── be7cec7c948958adfbb9bc7dbd292762d2388cc883466815fc2b6bc06bf06f5a
├── be7cec7c948958adfbb9bc7dbd292762d2388cc883466815fc2b6bc06bf06f5a.rootfs
└── cd1d4f8ce11dc9b6ff2b0a2c45e3cf1bc1370bbb45724b245880b757636537d3

0 directories, 3 files

$ lxc storage volume list default
+-----------+------------------------------------------------------------------+-------------+---------+
|   TYPE    |                               NAME                               | DESCRIPTION | USED BY |
+-----------+------------------------------------------------------------------+-------------+---------+
| container | test                                                             |             | 1       |
+-----------+------------------------------------------------------------------+-------------+---------+
| image     | be7cec7c948958adfbb9bc7dbd292762d2388cc883466815fc2b6bc06bf06f5a |             | 1       |
+-----------+------------------------------------------------------------------+-------------+---------+
  • 新镜像以文件形式保存在 "/var/lib/lxd/images/", 将容器发布为镜像时默认不会创建镜像卷(第一次创建容器时创建镜像卷)。

使用新镜像创建容器:

$ lxc init test test2 -p share-host -p default -s default -n br0
Creating test2

$ lxc list
+-------+---------+------+------+------------+-----------+
| NAME  |  STATE  | IPV4 | IPV6 |    TYPE    | SNAPSHOTS |
+-------+---------+------+------+------------+-----------+
| test  | STOPPED |      |      | PERSISTENT | 0         |
+-------+---------+------+------+------------+-----------+
| test2 | STOPPED |      |      | PERSISTENT | 0         |
+-------+---------+------+------+------------+-----------+

$ lxc storage volume list default
+-----------+------------------------------------------------------------------+-------------+---------+
|   TYPE    |                               NAME                               | DESCRIPTION | USED BY |
+-----------+------------------------------------------------------------------+-------------+---------+
| container | test                                                             |             | 1       |
+-----------+------------------------------------------------------------------+-------------+---------+
| container | test2                                                            |             | 1       |
+-----------+------------------------------------------------------------------+-------------+---------+
| image     | be7cec7c948958adfbb9bc7dbd292762d2388cc883466815fc2b6bc06bf06f5a |             | 1       |
+-----------+------------------------------------------------------------------+-------------+---------+
| image     | cd1d4f8ce11dc9b6ff2b0a2c45e3cf1bc1370bbb45724b245880b757636537d3 |             | 1       |
+-----------+------------------------------------------------------------------+-------------+---------+

友好排版请 阅读原文

上一篇:spring bean scope 用法分析


下一篇:Github中watch、star、fork的用法