蚊章汇 - Stéphane Graber
type: channel
link: https://linuxcn.bwsl.wang/author/361/
description: Stéphane Graber
items: 使用 LXD 容器运行 Ubuntu Core
items: 在 LXD 2.3 及以上版本中管理网络
items: LXD 2.0 系列（十二）：调试，及给 LXD 做贡献
items: LXD 2.0 系列（十一）：LXD 和 OpenStack
items: LXD 2.0 系列（十）：LXD 和 Juju
items: LXD 2.0 系列（九）：实时迁移
items: LXD 2.0 系列（八）：LXD 中的 LXD
items: LXD 2.0 系列（七）：LXD 中的 Docker
items: LXD 2.0 系列（六）：远程主机及容器迁移
items: LXD 2.0 系列（五）：镜像管理

使用 LXD 容器运行 Ubuntu Core
type: item
date: 2017-11-23T08:42:53+08:00
description: Ubuntu Core 是什么？Ubuntu Core 是完全基于 snap 包构建，并且完全事务化的 Ubuntu 版本。该系统大部分是只读的，所有已安装的应用全部来自 snap 包，完全使用事务化更新。这意味着不管在系统更新还是安装软件的时候遇到问题，整个系统都可以回退到之前的状态并且记录这个错误。最新版是在 2016 年 11 月发布的 Ubuntu Core 16。注意，Ubuntu Core 限制只能够安装 snap 包（而非 “传统” 软件包），并且有相当数量的 snap 包在当前环境下不能正常运行，或者需要人工干预（创建用户和用户组等）才能正常运行。随着新版的 snapd 和 “core” snap 包发布，Ubuntu Core 每周都会得到改进。环境需求就 LXD 而言，Ubuntu Core 仅仅相当于另一个 Linux 发行版。也就是说，snapd 需要挂载无特权的 FUSE 和 AppArmor 命名空间以及软件栈，像下面这样：一个新版的使用 Ubuntu 官方内核的系统一个新版的 LXD创建一个 Ubuntu Core 容器当前 Ubuntu Core 镜像发布在社区的镜像服务器。你可以像这样启动一个新的容器：stgraber@dakara:~$ lxc launch images:ubuntu-core/16 ubuntu-core Creating ubuntu-core Starting ubuntu-core 这个容器启动需要一点点时间，它会先执行第一阶段的加载程序，加载程序会确定使用哪一个镜像（镜像是只读的），并且在系统上设置一个可读层，你不要在这一阶段中断容器执行，这个时候什么都没有，所以执行 lxc exec 将会出错。几秒钟之后，执行 lxc list 将会展示容器的 IP 地址，这表明已经启动了 Ubuntu Core：stgraber@dakara:~$ lxc list +-------------+---------+----------------------+----------------------------------------------+------------+-----------+ | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS | +-------------+---------+----------------------+----------------------------------------------+------------+-----------+ | ubuntu-core | RUNNING | 10.90.151.104 (eth0) | 2001:470:b368:b2b5:216:3eff:fee1:296f (eth0) | PERSISTENT | 0 | +-------------+---------+----------------------+----------------------------------------------+------------+-----------+ 之后你就可以像使用其他的交互一样和这个容器进行交互：stgraber@dakara:~$ lxc exec ubuntu-core bash root@ubuntu-core:~# snap list Name Version Rev Developer Notes core 16.04.1 394 canonical - pc 16.04-0.8 9 canonical - pc-kernel 4.4.0-45-4 37 canonical - root@ubuntu-core:~# 更新容器如果你一直关注着 Ubuntu Core 的开发，你应该知道上面的版本已经很老了。这是因为被用作 Ubuntu LXD 镜像的代码每隔几个月才会更新。Ubuntu Core 系统在重启时会检查更新并进行自动更新（更新失败会回退）。如果你想现在强制更新，你可以这样做：stgraber@dakara:~$ lxc exec ubuntu-core bash root@ubuntu-core:~# snap refresh pc-kernel (stable) 4.4.0-53-1 from 'canonical' upgraded core (stable) 16.04.1 from 'canonical' upgraded root@ubuntu-core:~# snap version snap 2.17 snapd 2.17 series 16 root@ubuntu-core:~# 然后…

在 LXD 2.3 及以上版本中管理网络
type: item
date: 2017-06-18T19:37:00+08:00
description: 介绍当 LXD 2.0 随着 Ubuntu 16.04 一起发布时，LXD 联网就简单了。要么你可以使用 lxd init 来配置，为你的容器自己提供一个 “lxdbr0” 网桥，要么使用一个已存在的物理接口。虽然这确实有效，但是有点混乱，因为大部分的桥接配置发生在 Ubuntu 打包的 LXD 之外。那些脚本只能支持一个桥接，并且没有通过 API 暴露，这使得远程配置有点痛苦。直到 LXD 2.3，LXD 终于发展了自己的网络管理 API ，并有相应的命令行工具。这篇文章试图来简述这些新的功能。基础联网在初始情况下，LXD 2.3 没有定义任何网络。lxd init 会为你设置一个，并且默认情况下将所有新的容器连接到它，但是让我们亲手尝试看下究竟发生了些什么。要创建一个新的带有随机 IPv4 和 IP6 子网，并启用 NAT 的网络，只需要运行：stgraber@castiana:~$ lxc network create testbr0 Network testbr0 created 你可以如下查看它的配置：stgraber@castiana:~$ lxc network show testbr0 name: testbr0 config: ipv4.address: 10.150.19.1/24 ipv4.nat: "true" ipv6.address: fd42:474b:622d:259d::1/64 ipv6.nat: "true" managed: true type: bridge usedby: [] 如果你不想要那些自动配置的子网，你可以这么做：stgraber@castiana:~$ lxc network create testbr0 ipv6.address=none ipv4.address=10.0.3.1/24 ipv4.nat=true Network testbr0 created 那就会这样：stgraber@castiana:~$ lxc network show testbr0 name: testbr0 config: ipv4.address: 10.0.3.1/24 ipv4.nat: "true" ipv6.address: none managed: true type: bridge usedby: [] 如果你的容器没有使用它，那么创建的网络对你也没什么用。要将你新创建的网络连接到所有容器，你可以这么做：stgraber@castiana:~$ lxc network attach-profile testbr0 default eth0 要将一个网络连接到一个已存在的容器中，你可以这么做：stgraber@castiana:~$ lxc network attach my-container default eth0 现在，假设你已经在机器中安装了 openvswitch，并且要将这个网桥转换成 OVS 网桥，只需更改为正确的驱动：stgraber@castiana:~$ lxc network set testbr0 bridge.driver openvswitch 如果你想要一次性做一系列修改。lxc network edit 可以让你在编辑器中交互编辑网络配置。静态租约及端口安全使用 LXD 管理 DHCP 服务器的一个好处是可以使得管理 DHCP 租约很简单。你所需要的是一个容器特定的网卡设备以及正确的属性设置。root@yak:~# lxc init ubuntu:16.04 c1 Creating c1 root@yak:~# lxc network attach testbr0 c1 eth0 root@yak:~# lxc config device set c1 eth0 ipv4.address 10.0.3.123 root@yak:~# lxc start c1 root@yak:~# lxc list c1 +------+---------+-------------------+------+------------+-----------+ | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS | +------+---------+-------------------+------+------------+-----------+ | c1 | RUNNING | 10.0.3.123 (eth0) | | PERSISTENT | 0 | +------+---------+-------------------+------+------------+-----------+ IPv…

LXD 2.0 系列（十二）：调试，及给 LXD 做贡献
type: item
date: 2017-03-09T16:50:00+08:00
description: 介绍终于要结束了！这个大约一年前开始的这系列文章的最后一篇博文。LXD 入门安装与配置你的第一个 LXD 容器资源控制镜像管理远程主机及容器迁移LXD 中的 DockerLXD 中的 LXD实时迁移LXD 和 JujuLXD 和 OpenStack调试，及给 LXD 做贡献如果你从一开始就关注了这个系列，你应该已经使用了 LXD 相当长的时间了，并且非常熟悉它的日常操作和功能。但如果出现问题怎么办？你可以做什么来自己跟踪问题？如果你不能，你应该记录什么信息，以便上游可以跟踪问题？如果你想自己解决问题或通过实现你需要的功能来帮助改善LXD怎么办？如何构建，测试和贡献 LXD 代码库？调试 LXD 并填写 bug 报告LXD 日志文件/var/log/lxd/lxd.log：这是 LXD 日志的主文件。为了避免它快速充满你的磁盘，默认只会记录 INFO、WARNING 或者 ERROR 级别的日志。你可以在 LXD 守护进程中使用 –debug 改变其行为。/var/log/lxd/CONTAINER/lxc.conf：每当你启动容器时，此文件将更新为传递给 LXC 的配置。这里会展示容器将如何配置，包括其所有的设备、绑定挂载等等。/var/log/lxd/CONTAINER/forkexec.log：这个文件包含 LXC 命令执行失败时产生的错误。这个情况是非常罕见的，因为 LXD 通常会在发生之前处理大多数错误。/var/log/lxd/CONTAINER/forkstart.log：这个文件包含 LXC 在启动容器时的错误信息。含 LXC 命令执行失败时产生的错误。CRIU 日志 (对于实时迁移)如果使用 CRIU 进行容器实时迁移或实时快照，则每次生成 CRIU 转储或恢复转储时都会记录额外的日志文件。这些日志也可以在 /var/log/lxd/CONTAINER/ 中找到，并且有时间戳，以便你可以找到与你最近的操作所匹配的那些日志。它们包含 CRIU 转储和恢复的所有内容的详细记录，并且比典型的迁移/快照错误消息更容器理解。LXD 调试消息如上所述，你可以使用 -debug 选项将守护进程切换为执行调试日志记录。另一种方法是连接到守护进程的事件接口，它将显示所有日志条目，而不管配置的日志级别（即使是远程工作）。举例说，对于 lxc init ubuntu:16.04 xen 来说，lxd.log 会是这样：INFO[02-24|18:14:09] Starting container action=start created=2017-02-24T23:11:45+0000 ephemeral=false name=xen stateful=false used=1970-01-01T00:00:00+0000 INFO[02-24|18:14:10] Started container action=start created=2017-02-24T23:11:45+0000 ephemeral=false name=xen stateful=false used=1970-01-01T00:00:00+0000 而 lxc monitor –type=logging 会是：metadata: context: {} level: dbug message: 'New events listener: 9b725741-ffe7-4bfc-8d3e-fe620fc6e00a' timestamp: 2017-02-24T18:14:01.025989062-05:00 type: logging metadata: context: ip: '@' method: GET url: /1.0 level: dbug message: handling timestamp: 2017-02-24T18:14:09.341283344-05:00 type: logging metadata: context: driver: storage/zfs level: dbug message: StorageCoreInit timestamp: 2017-02-24T18:14:09.341536477-05:00 type: logging metadata: context: ip: '@' method: GET url: /1.0/containers/xen level: dbug message: handling timestamp: 2017-02-24T18:14:09.347709394-05:00 type: logging metadata: context: ip: '@' method: PUT…

LXD 2.0 系列（十一）：LXD 和 OpenStack
type: item
date: 2017-03-08T18:27:00+08:00
description: 这是 LXD 2.0 系列介绍文章的第十一篇。LXD 入门安装与配置你的第一个 LXD 容器资源控制镜像管理远程主机及容器迁移LXD 中的 DockerLXD 中的 LXD实时迁移LXD 和 JujuLXD 和 OpenStack调试，及给 LXD 做贡献介绍首先对这次的延期抱歉。为了让一切正常我花了很长时间。我第一次尝试是使用 devstack 时遇到了一些必须解决问题。 然而即使这样，我还是不能够使网络正常。我终于放弃了 devstack，并使用用户友好的 Juju 尝试使用 “conjure-up” 部署完整的 Ubuntu OpenStack。它终于工作了！下面是如何运行一个完整的 OpenStack，使用 LXD 容器而不是 VM，并在 LXD 容器中运行所有这些（嵌套的！）。要求这篇文章假设你有一个可以工作的 LXD 设置，提供容器网络访问，并且你有一个非常强大的 CPU，大约 50GB 给容器空间和至少 16G B的内存。记住，我们在这里运行一个完整的 OpenStack，这东西不是很轻量！设置容器OpenStack 由大量不同做不同事情的组件组成。 一些需要一些额外的特权，为了可以使设置更简单，我们将使用特权容器。我们将配置支持嵌套的容器，预加载所有需要的内核模块，并允许它访问 /dev/mem（显然是需要的）。请注意，这意味着 LXD 容器的大部分安全特性对该容器被禁用。 然而由 OpenStack 自身产生的容器将是无特权的，并且可以正常使用 LXD 的安全特性。lxc launch ubuntu:16.04 openstack -c security.privileged=true -c security.nesting=true -c "linux.kernel_modules=iptable_nat, ip6table_nat, ebtables, openvswitch" lxc config device add openstack mem unix-char path=/dev/mem LXD 中有一个小 bug，它会尝试加载已经加载到主机上的内核模块。这已在LXD 2.5中得到修复，并将在LXD 2.0.6 中修复，但在此之前，可以使用以下方法：lxc exec openstack -- ln -s /bin/true /usr/local/bin/modprobe 我们需要加几条 PPA 并安装 conjure-up，它是我们用来安装 OpenStack 的部署工具。lxc exec openstack -- apt-add-repository ppa:conjure-up/next -y lxc exec openstack -- apt-add-repository ppa:juju/stable -y lxc exec openstack -- apt update lxc exec openstack -- apt dist-upgrade -y lxc exec openstack -- apt install conjure-up -y 最后一步是在容器内部配置 LXD 网络。所有问题都选择默认，除了：使用 dir 存储后端（ zfs 不在嵌套容器中用）不要配置 IPv6 网络（conjure-up/juju 不太兼容它）lxc exec openstack -- lxd init 现在配置完容器了，现在我们部署 OpenStack！用 conjure-up 部署 OpenStack如先前提到的，我们用 conjure-up 部署 OpenStack。这是一个很棒的用户友好的可以与 Juju 交互来部署复杂服务的工具。首先：lxc exec openstack -- sudo -u ubuntu -i conjure-up 选择 “OpenStack with NovaLXD”选择 “localhost” 作为部署目标（使用 LXD）点击 “Deploy all remaining applications”接下来会部署 OpenStack。整个过程会花费一个多小时，这取决于你运行的机器。你将看到所有服务会被分配一个容器，然后部署并最终互连。部署完成后会显示一个安装完成的界面。它会导入一些初始镜像、设置 SSH 权限、配置网络最后会显示面板的 IP 地址。访问面板并生成一个容器面板运行在一个容器中，因此你不能直接从浏览器中访问。最简单的方法是设置一条 NAT 规则：lxc exec openstack -- iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to <IP> 其中 <ip> 是 conjure-up…

LXD 2.0 系列（十）：LXD 和 Juju
type: item
date: 2017-03-07T14:04:00+08:00
description: 这是 LXD 2.0 系列介绍文章的第十篇。LXD 入门安装与配置你的第一个 LXD 容器资源控制镜像管理远程主机及容器迁移LXD 中的 DockerLXD 中的 LXD实时迁移LXD 和 JujuLXD 和 OpenStack调试，及给 LXD 做贡献介绍Juju 是 Canonical 的服务建模和部署工具。 它支持非常广泛的云服务提供商，使您能够轻松地在任何云上部署任何您想要的服务。此外，Juju 2.0 还支持 LXD，既适用于本地部署，也适合开发，并且可以在云实例或物理机上共同协作。本篇文章将关注本地使用，通过一个没有任何Juju经验的LXD用户来体验。要求本篇文章假设你已经安装了 LXD 2.0 并且配置完毕（看前面的文章），并且是在 Ubuntu 16.04 LTS 上运行的。设置 Juju第一件事是在 Ubuntu 16.04 上安装 Juju 2.0。这个很简单：stgraber@dakara:~$ sudo apt install juju Reading package lists... Done Building dependency tree Reading state information... Done The following additional packages will be installed: juju-2.0 Suggested packages: juju-core The following NEW packages will be installed: juju juju-2.0 0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. Need to get 39.7 MB of archives. After this operation, 269 MB of additional disk space will be used. Do you want to continue? [Y/n] Get:1 http://us.archive.ubuntu.com/ubuntu xenial-updates/main amd64 juju-2.0 amd64 2.0~beta7-0ubuntu1.16.04.1 [39.6 MB] Get:2 http://us.archive.ubuntu.com/ubuntu xenial-updates/main amd64 juju all 2.0~beta7-0ubuntu1.16.04.1 [9,556 B] Fetched 39.7 MB in 0s (53.4 MB/s) Selecting previously unselected package juju-2.0. (Reading database ... 255132 files and directories currently installed.) Preparing to unpack .../juju-2.0_2.0~beta7-0ubuntu1.16.04.1_amd64.deb ... Unpacking juju-2.0 (2.0~beta7-0ubuntu1.16.04.1) ... Selecting previously unselected package juju. Preparing to unpack .../juju_2.0~beta7-0ubuntu1.16.04.1_all.deb ... Unpacking juju (2.0~beta7-0ubuntu1.16.04.1) ... Processing triggers for man-db (2.7.5-1) ... Setting up juju-2.0 (2.0~beta7-0ubuntu1.16.04.1) ... Setting up juju (2.0~beta7-0ubuntu1.16.04.1) ... 安装完成后，我们可以使用 LXD 启动一个新的“控制器”。这意味着 Juju 不会修改你主机上的任何东西，它会在 LXD 容器中安装它的管理服务。现在我们创建一个“test”控制器：stgraber@dakara:~$ juju bootstrap localhost test Creating Juju controller "local.test" on localhost/localhost Bootstrapping model "admin" Starting new instance for initial controller Launching instance - juju-7…

LXD 2.0 系列（九）：实时迁移
type: item
date: 2017-03-04T18:17:00+08:00
description: 这是 LXD 2.0 系列介绍文章的第九篇。LXD 入门安装与配置你的第一个 LXD 容器资源控制镜像管理远程主机及容器迁移LXD 中的 DockerLXD 中的 LXD实时迁移LXD 和 JujuLXD 和 OpenStack调试，及给 LXD 做贡献介绍LXD 2.0 中的有一个尽管是实验性质的但非常令人兴奋的功能，那就是支持容器检查点和恢复。简单地说，检查点/恢复意味着正在运行的容器状态可以被序列化到磁盘，要么可以作为同一主机上的有状态快照，要么放到另一主机上相当于实时迁移。要求要使用容器实时迁移和有状态快照，你需要以下条件：一个非常新的 Linux 内核，4.4 或更高版本。CRIU 2.0，可能需要一些 cherry-pick 的提交，具体取决于你确切的内核配置。直接在主机上运行 LXD。 不能在容器嵌套下使用这些功能。对于迁移，目标主机必须至少实现源主机的指令集，目标主机内核必须至少提供与源主机相同的系统调用，并且在源主机上挂载的任何内核文件系统也必须可挂载到目标主机上。Ubuntu 16.04 LTS 已经提供了所有需要的依赖，在这种情况下，您只需要安装 CRIU 本身：apt install criu 使用 CRIU有状态快照一个普通的快照看上去像这样：stgraber@dakara:~$ lxc snapshot c1 first stgraber@dakara:~$ lxc info c1 | grep first first (taken at 2016/04/25 19:35 UTC) (stateless) 一个有状态快照看上去像这样：stgraber@dakara:~$ lxc snapshot c1 second --stateful stgraber@dakara:~$ lxc info c1 | grep second second (taken at 2016/04/25 19:36 UTC) (stateful) 这意味着所有容器运行时状态都被序列化到磁盘并且作为了快照的一部分。可以像你还原无状态快照那样还原一个有状态快照：stgraber@dakara:~$ lxc restore c1 second stgraber@dakara:~$ 有状态快照的停止/启动比方说你由于升级内核或者其他类似的维护而需要重启机器。与其等待重启后启动所有的容器，你可以：stgraber@dakara:~$ lxc stop c1 --stateful 容器状态将会写入到磁盘，会在下次启动时读取。你甚至可以看到像下面那样的状态：root@dakara:~# tree /var/lib/lxd/containers/c1/rootfs/state/ /var/lib/lxd/containers/c1/rootfs/state/ ├── cgroup.img ├── core-101.img ├── core-102.img ├── core-107.img ├── core-108.img ├── core-109.img ├── core-113.img ├── core-114.img ├── core-122.img ├── core-125.img ├── core-126.img ├── core-127.img ├── core-183.img ├── core-1.img ├── core-245.img ├── core-246.img ├── core-50.img ├── core-52.img ├── core-95.img ├── core-96.img ├── core-97.img ├── core-98.img ├── dump.log ├── eventfd.img ├── eventpoll.img ├── fdinfo-10.img ├── fdinfo-11.img ├── fdinfo-12.img ├── fdinfo-13.img ├── fdinfo-14.img ├── fdinfo-2.img ├── fdinfo-3.img ├── fdinfo-4.img ├── fdinfo-5.img ├── fdinfo-6.img ├── fdinfo-7.img ├── fdinfo-8.img ├── fdinfo-9.img ├── fifo-data.img ├── fifo.img ├── filelocks.img ├── fs-101.img ├── fs-113.img ├── fs-122.img ├── fs-183.img ├── fs-1.img ├── fs-245.img ├── fs-246.img ├── fs-50.img ├─…

LXD 2.0 系列（八）：LXD 中的 LXD
type: item
date: 2017-03-02T17:53:00+08:00
description: 这是 LXD 2.0 系列介绍文章的第八篇。LXD 入门安装与配置你的第一个 LXD 容器资源控制镜像管理远程主机及容器迁移LXD 中的 DockerLXD 中的 LXD实时迁移LXD 和 JujuLXD 和 OpenStack调试，及给 LXD 做贡献介绍在上一篇文章中，我介绍了如何在 LXD 中运行 Docker，这是一个访问由 Docker 提供的应用程序组合的很好方式，同时 Docker 还运行在 LXD 提供的安全环境中。我提到的一个情况是为你的用户提供一个 LXD 容器，然后让他们使用他们的容器来运行 Docker。那么，如果他们自己想要在其容器中使用 LXD 运行其他 Linux 发行版，或者甚至允许另一组人来访问运行在他们的容器中的 Linux 系统呢？原来 LXD 使得用户运行嵌套容器变得非常简单。嵌套 LXD最简单的情况可以使用 Ubuntu 16.04 镜像来展示。 Ubuntu 16.04 云镜像预装了 LXD。守护进程本身没有运行，因为它是由套接字激活的，所以它不使用任何资源，直到你真正使用它。让我们启动一个启用了嵌套的 Ubuntu 16.04 容器：lxc launch ubuntu-daily:16.04 c1 -c security.nesting=true 你也可以在一个已有的容器上设置 security.nesting：lxc config set <container name> security.nesting true 或者对所有的容器使用一个指定的配置文件：lxc profile set <profile name> security.nesting true 容器启动后，你可以从容器内部得到一个 shell，配置 LXD 并生成一个容器：stgraber@dakara:~$ lxc launch ubuntu-daily:16.04 c1 -c security.nesting=true Creating c1 Starting c1 stgraber@dakara:~$ lxc exec c1 bash root@c1:~# lxd init Name of the storage backend to use (dir or zfs): dir We detected that you are running inside an unprivileged container. This means that unless you manually configured your host otherwise, you will not have enough uid and gid to allocate to your containers. LXD can re-use your container's own allocation to avoid the problem. Doing so makes your nested containers slightly less safe as they could in theory attack their parent container and gain more privileges than they otherwise would. Would you like to have your containers share their parent's allocation (yes/no)? yes Would you like LXD to be available over the network (yes/no)? no Do you want to configure the LXD bridge (yes/no)? yes Warning: Stopping lxd.service, but it can still be activated by: lxd.socket LXD has been successfully configured. root@c1:~# lxc launch ubuntu:14.04 trusty Generating a client certificate. This may take a minute... If this is your first time using LXD, you should also run: sudo lxd init Creating trusty Retrieving image: 100% Starting trusty root@c1:~# lxc list +--------+---------+------------…

LXD 2.0 系列（七）：LXD 中的 Docker
type: item
date: 2017-02-24T16:14:00+08:00
description: 这是 LXD 2.0 系列介绍文章的第七篇。LXD 入门安装与配置你的第一个 LXD 容器资源控制镜像管理远程主机及容器迁移LXD 中的 DockerLXD 中的 LXD实时迁移LXD 和 JujuLXD 和 OpenStack调试，及给 LXD 做贡献为什么在 LXD 中运行 Docker正如我在系列的第一篇中简要介绍的，LXD 的重点是系统容器，也就是我们在容器中运行一个完全未经修改的 Linux 发行版。LXD 的所有意图和目的并不在乎容器中的负载是什么。它只是设置容器命名空间和安全策略，然后运行 /sbin/init 来生成容器，接着等待容器停止。应用程序容器，例如由 Docker 或 Rkt 所实现的应用程序容器是非常不同的，因为它们用于分发应用程序，通常在它们内部运行单个主进程，并且比 LXD 容器生命期更短暂。这两种容器类型不是相互排斥的，我们的确看到使用 Docker 容器来分发应用程序的价值。这就是为什么我们在过去一年中努力工作以便让 LXD 中运行 Docker 成为可能。这意味着，使用 Ubuntu 16.04 和 LXD 2.0，您可以为用户创建容器，然后可以像正常的 Ubuntu 系统一样连接到这些容器，然后运行 Docker 来安装他们想要的服务和应用程序。要求要让它正常工作要做很多事情，Ubuntu 16.04 上已经包含了这些：支持 CGroup 命名空间的内核（4.4 Ubuntu 或 4.6 主线内核）使用 LXC 2.0 和 LXCFS 2.0 的 LXD 2.0一个自定义版本的 Docker（或一个用我们提交的所有补丁构建的）Docker 镜像，其受限于用户命名空间限制，或者使父 LXD 容器成为特权容器（security.privileged = true）运行一个基础的 Docker 载荷说完这些，让我们开始运行 Docker 容器！首先你可以用下面的命令得到一个 Ubuntu 16.04 的容器：lxc launch ubuntu-daily:16.04 docker -p default -p docker -p default -p docker 表示 LXD 将 default 和 docker 配置文件应用于容器。default 配置文件包含基本网络配置，而 docker 配置文件告诉 LXD 加载几个必需的内核模块并为容器设置一些挂载。 docker 配置文件还支持容器嵌套。现在让我们确保容器是最新的并安装 docker：lxc exec docker -- apt update lxc exec docker -- apt dist-upgrade -y lxc exec docker -- apt install docker.io -y 就是这样！你已经安装并运行了一个 Docker 容器。现在让我们用两个 Docker 容器开启一个基础的 web 服务：stgraber@dakara:~$ lxc exec docker -- docker run --detach --name app carinamarina/hello-world-app Unable to find image 'carinamarina/hello-world-app:latest' locally latest: Pulling from carinamarina/hello-world-app efd26ecc9548: Pull complete a3ed95caeb02: Pull complete d1784d73276e: Pull complete 72e581645fc3: Pull complete 9709ddcc4d24: Pull complete 2d600f0ec235: Pull complete c4cf94f61cbd: Pull complete c40f2ab60404: Pull complete e87185df6de7: Pull complete 62a11c66eb65: Pull complete 4c5eea9f676d: Pull complete 498df6a0d074: Pull complete Digest: sha256:6a159db50cb9c0fbe127fb038ed5a33bb5a443fcdd925ec74bf578142718f516 Status: Downloaded newer image for carinamarina/hello-world-app:latest c8318f0401fb1e119e6c5bb23d1e706e8ca080f8e44b42613856ccd0bf8bfb0d stg…

LXD 2.0 系列（六）：远程主机及容器迁移
type: item
date: 2017-02-03T16:27:00+08:00
description: 这是 LXD 2.0 系列介绍文章的第六篇。LXD 入门安装与配置你的第一个 LXD 容器资源控制镜像管理远程主机及容器迁移LXD 中的 DockerLXD 中的 LXD实时迁移LXD 和 JujuLXD 和 OpenStack调试，及给 LXD 做贡献远程协议LXD 2.0 支持两种协议:LXD 1.0 API：这是在客户端和 LXD 守护进程之间使用的 REST API，以及在 LXD 守护进程间复制/移动镜像和容器时使用的 REST API。Simplestreams：Simplestreams 协议是 LXD 客户端和守护进程使用的只读、仅针对镜像的协议，用于客户端和 LXD 守护进程获取镜像信息以及从一些公共镜像服务器（如 Ubuntu 镜像）导入镜像。以下所有内容都将使用这两个协议中的第一个。安全LXD API 的验证是通过客户端证书在 TLS 1.2 上使用最近的密钥验证的。 当两个 LXD 守护进程必须直接交换信息时，源守护程序生成一个临时令牌，并通过客户端传输到目标守护程序。 此令牌仅可用于访问特定流，并且会被立即撤销，因此不能重新使用。为了避免中间人攻击，客户端工具还将源服务器的证书发送到目标服务器。这意味着对于特定的下载操作，目标服务器会被提供源服务器的 URL、所需资源的一次性访问令牌以及服务器应该使用的证书。 这可以防止中间人攻击，并且只允许临时访问所传输的对象。网络需求LXD 2.0 使用这样一种模型，某个操作的目标（接收端）直接连接到源以获取数据。这意味着你必须确保目标服务器可以直接连接到源、可以更新任何所需的防火墙。我们有个允许反向连接的计划，允许通过客户端代理本身以应对那些严格的防火墙阻止两台主机之间通信的罕见情况。与远程主机交互LXD 使用的是“远程”的概念，而不是让我们的用户总是提供主机名或 IP 地址，然后在他们想要与远程主机交互时验证证书信息。默认情况下，唯一真正的 LXD 远程配置是 local:，这也是默认的远程（所以你不必输入它的名称）。这个本地（local:）远程使用 LXD REST API 通过 unix 套接字与本地守护进程通信。添加一台远程主机假设你已经有两台装有 LXD 的机器：你的本机以及远程那台我们称为“foo”的主机。首先你需要确保“foo”正在监听网络，并设置了一个密码，以便得到一个远程 shell，运行：lxc config set core.https_address [::]:8443 lxc config set core.trust_password something-secure 在你本地 LXD 上，你需要使它对网络可见，这样我们可以从它传输容器和镜像：lxc config set core.https_address [::]:8443 现在已经在两端完成了守护进程的配置，你可以添加“foo”到你的本地客户端：lxc remote add foo 1.2.3.4 （将 1.2.3.4 替换成你的 IP 或者 FQDN）看上去像这样：stgraber@dakara:~$ lxc remote add foo 2607:f2c0:f00f:2770:216:3eff:fee1:bd67 Certificate fingerprint: fdb06d909b77a5311d7437cabb6c203374462b907f3923cefc91dd5fce8d7b60 ok (y/n)? y Admin password for foo: Client certificate stored at server: foo 你接着可以列出远端服务器，你可以在列表中看到“foo”：stgraber@dakara:~$ lxc remote list +-----------------+-------------------------------------------------------+---------------+--------+--------+ | NAME | URL | PROTOCOL | PUBLIC | STATIC | +-----------------+-------------------------------------------------------+---------------+--------+--------+ | foo | https://[2607:f2c0:f00f:2770:216:3eff:fee1:bd67]:8443 | lxd | NO | NO | +-----------------+-------------------------------------------------…

LXD 2.0 系列（五）：镜像管理
type: item
date: 2017-01-10T20:39:00+08:00
description: 这是 LXD 2.0 系列介绍文章的第五篇。LXD 入门安装与配置你的第一个 LXD 容器资源控制镜像管理远程主机及容器迁移LXD 中的 DockerLXD 中的 LXD实时迁移LXD 和 JujuLXD 和 OpenStack调试，及给 LXD 做贡献因为 lxd 容器管理有很多命令，因此这篇文章会很长。 如果你想要快速地浏览这些相同的命令，你可以尝试下我们的在线演示！容器镜像如果你以前使用过 LXC，你可能还记得那些 LXC “模板”，基本上都是导出一个容器文件系统以及一点配置的 shell 脚本。大多数模板是通过在本机上执行一个完整的发行版自举来生成该文件系统。这可能需要相当长的时间，并且无法在所有的发行版上可用，另外可能需要大量的网络带宽。回到 LXC 1.0，我写了一个“下载”模板，它允许用户下载预先打包的容器镜像，用模板脚本在中央服务器上生成，接着高度压缩、签名并通过 https 分发。我们很多用户从旧版的容器生成方式切换到了使用这种新的、更快更可靠的创建容器的方式。使用 LXD，我们通过全面的基于镜像的工作流程向前迈进了一步。所有容器都是从镜像创建的，我们在 LXD 中具有高级镜像缓存和预加载支持，以使镜像存储保持最新。与 LXD 镜像交互在更深入了解镜像格式之前，让我们快速了解下 LXD 可以让你做些什么。透明地导入镜像所有的容器都是由镜像创建的。镜像可以来自一台远程服务器并使用它的完整 hash、短 hash 或者别名拉取下来，但是最终每个 LXD 容器都是创建自一个本地镜像。这有个例子：lxc launch ubuntu:14.04 c1 lxc launch ubuntu:75182b1241be475a64e68a518ce853e800e9b50397d2f152816c24f038c94d6e c2 lxc launch ubuntu:75182b1241be c3 所有这些引用相同的远程镜像（在写这篇文章时），在第一次运行这些命令其中之一时，远程镜像将作为缓存镜像导入本地 LXD 镜像存储，接着从其创建容器。下一次运行其中一个命令时，LXD 将只检查镜像是否仍然是最新的（当不是由指纹引用时），如果是，它将创建容器而不下载任何东西。现在镜像被缓存在本地镜像存储中，你也可以从那里启动它，甚至不检查它是否是最新的：lxc launch 75182b1241be c4 最后，如果你有个名为“myimage”的本地镜像，你可以：lxc launch my-image c5 如果你想要改变一些自动缓存或者过期行为，在本系列之前的文章中有一些命令。手动导入镜像从镜像服务器中复制如果你想复制远程的某个镜像到你本地镜像存储，但不立即从它创建一个容器，你可以使用lxc image copy命令。它可以让你调整一些镜像标志，比如：lxc image copy ubuntu:14.04 local: 这只是简单地复制一个远程镜像到本地存储。如果您想要通过比记住其指纹更容易的方式来记住你引用的镜像副本，则可以在复制时添加别名：lxc image copy ubuntu:12.04 local: --alias old-ubuntu lxc launch old-ubuntu c6 如果你想要使用源服务器上设置的别名，你可以要求 LXD 复制下来：lxc image copy ubuntu:15.10 local: --copy-aliases lxc launch 15.10 c7 上面的副本都是一次性拷贝，也就是复制远程镜像的当前版本到本地镜像存储中。如果你想要 LXD 保持镜像最新，就像它在缓存中存储的那样，你需要使用 –auto-update 标志：lxc image copy images:gentoo/current/amd64 local: --alias gentoo --auto-update 导入 tarball如果某人给你提供了一个单独的 tarball，你可以用下面的命令导入：lxc image import <tarball> 如果你想在导入时设置一个别名，你可以这么做：lxc image import <tarball> --alias random-image 现在如果你被给了两个 tarball，要识别哪个是含有 LXD 元数据的。通常可以通过 tarball 的名称来识别，如果不行就选择最小的那个，元数据 tarball 包是很小的。 然后将它们一起导入：lxc image import <metadata tarball> <rootfs tarball> 从 URL 中导入lxc image import 也可以与指定的 URL 一起使用。如果你的一台 https Web 服务器的某个路…