蚊章汇 - LXC
type: channel
link: https://linuxcn.bwsl.wang/tag/LXC/
items: 什么是 CGManager？
items: 在 Ubuntu 上体验 LXD 容器
items: lxc exec 介绍
items: LXD 2.0 系列（五）：镜像管理
items: LXD 2.0 系列（四）：资源控制
items: LXD 2.0 系列（三）：你的第一个 LXD 容器
items: LXD 2.0 系列（二）：安装与配置
items: LXD 2.0 系列（一）：LXD 入门
items: 教你在 Ubuntu 上使用 LXC 容器
items: lmctfy：让我用集装箱为你的程式打包

什么是 CGManager？
type: item
date: 2018-03-05T08:28:00+08:00
description: CGManager 是一个核心的特权守护进程，通过一个简单的 D-Bus API 管理你所有的 cgroup。它被设计用来处理嵌套的 LXC 容器以及接受无特权的请求，包括解析用户名称空间的 UID/GID。组件cgmanager这个守护进程在宿主机上运行，​​将 cgroupfs 挂载到一个独立的挂载名称空间（所以它不能从宿主机上看到），绑定 /sys/fs/cgroup/cgmanager/sock 用于传入的 D-Bus 查询，并通常处理宿主机上直接运行的所有客户端。cgmanager 既接受使用 D-Bus + SCM 凭证的身份验证请求，用于在命名空间之间转换 uid、gid 和 pid，也可以使用简单的 “unauthenticated”（只是初始的 ucred）D-Bus 来查询来自宿主机级别的查询。cgproxy你可能会在两种情况下看到这个守护进程运行。在宿主机上，如果你的内核老于 3.8（没有 pidns 连接支持）或处于容器中（只有 cgproxy 运行）。cgproxy 本身并不做任何 cgroup 配置更改，而是如其名称所示，代理请求给主 cgmanager 进程。这是必要的，所以一个进程可以直接使用 D-Bus（例如使用 dbus-send）与 /sys/fs/cgroup/cgmanager/sock 进行通信。之后 cgproxy 将从该查询中得到 ucred，并对真正的 cgmanager 套接字进行身份验证的 SCM 查询，并通过 ucred 结构体传递参数，使它们能够正确地转换为 cgmanager 可以理解的宿主机命名空间 。cgm一个简单的命令行工具，与 D-Bus 服务通信，并允许你从命令行执行所有常见的 cgroup 操作。通信协议如上所述，cgmanager 和 cgproxy 使用 D-Bus。建议外部客户端（所以不要是 cgproxy）使用标准的 D-Bus API，不要试图实现 SCM creds 协议，因为它是不必要的，并且容易出错。相反，只要简单假设与 /sys/fs/cgroup/cgmanager/sock 的通信总是正确的。cgmanager API 仅在独立的 D-Bus 套接字上可用，cgmanager 本身不连接到系统总线，所以 cgmanager/cgproxy 不要求有运行中的 dbus 守护进程。你可以在这里阅读更多关于 D-Bus API。许可证CGManager 是免费软件，大部分代码是根据 GNU LGPLv2.1+ 许可条款发布的，一些二进制文件是在 GNU GPLv2 许可下发布的。该项目的默认许可证是 GNU LGPLv2.1+支持CGManager 的稳定版本支持依赖于 Linux 发行版以及它们自己承诺推出稳定修复和安全更新。你可以从 Canonical Ltd 获得对 Ubuntu LTS 版本的 CGManager 的商业支持。via: https://linuxcontainers.org/cgmanager/introduction/作者：Canonical Ltd. 译者：geekpi 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出

在 Ubuntu 上体验 LXD 容器
type: item
date: 2018-01-19T19:35:00+08:00
description: 本文的主角是容器，一种类似虚拟机但更轻量级的构造。你可以轻易地在你的 Ubuntu 桌面系统中创建一堆容器！虚拟机会虚拟出整个电脑让你来安装客户机操作系统。相比之下，容器复用了主机的 Linux 内核，只是简单地 包容 了我们选择的根文件系统（也就是运行时环境）。Linux 内核有很多功能可以将运行的 Linux 容器与我们的主机分割开（也就是我们的 Ubuntu 桌面）。Linux 本身需要一些手工操作来直接管理他们。好在，有 LXD（读音为 Lex-deeh），这是一款为我们管理 Linux 容器的服务。我们将会看到如何：在我们的 Ubuntu 桌面上配置容器，创建容器，安装一台 web 服务器，测试一下这台 web 服务器，以及清理所有的东西。设置 Ubuntu 容器如果你安装的是 Ubuntu 16.04，那么你什么都不用做。只要安装下面所列出的一些额外的包就行了。若你安装的是 Ubuntu 14.04.x 或 Ubuntu 15.10，那么按照 LXD 2.0 系列（二）：安装与配置 来进行一些操作，然后再回来。确保已经更新了包列表：sudo apt update sudo apt upgrade 安装 lxd 包：sudo apt install lxd 若你安装的是 Ubuntu 16.04，那么还可以让你的容器文件以 ZFS 文件系统的格式进行存储。Ubuntu 16.04 的 Linux kernel 包含了支持 ZFS 必要的内核模块。若要让 LXD 使用 ZFS 进行存储，我们只需要安装 ZFS 工具包。没有 ZFS，容器会在主机文件系统中以单独的文件形式进行存储。通过 ZFS，我们就有了写入时拷贝等功能，可以让任务完成更快一些。安装 zfsutils-linux 包（若你安装的是 Ubuntu 16.04.x）：sudo apt install zfsutils-linux 安装好 LXD 后，包安装脚本应该会将你加入 lxd 组。该组成员可以使你无需通过 sudo 就能直接使用 LXD 管理容器。根据 Linux 的习惯，你需要先登出桌面会话然后再登录 才能应用 lxd 的组成员关系。（若你是高手，也可以通过在当前 shell 中执行 newgrp lxd 命令，就不用重登录了）。在开始使用前，LXD 需要初始化存储和网络参数。运行下面命令：$ sudo lxd init Name of the storage backend to use (dir or zfs): zfs Create a new ZFS pool (yes/no)? yes Name of the new ZFS pool: lxd-pool Would you like to use an existing block device (yes/no)? no Size in GB of the new loop device (1GB minimum): 30 Would you like LXD to be available over the network (yes/no)? no Do you want to configure the LXD bridge (yes/no)? yes > You will be asked about the network bridge configuration. Accept all defaults and continue. Warning: Stopping lxd.service, but it can still be activated by: lxd.socket LXD has been successfully configured. $ _ 我们在一个（单独）的文件而不是块设备（即分区）中构建了一个文件系统来作为 ZFS 池，因此我们无需进行额外的分区操作。在本例中我指定了 30GB 大小，这个空间取之于根（/） 文件系统中。这个文件就是 /var/lib/lxd/zfs.img。行了！最初的配置完成了。若有问题，或者想了解其他信息，请阅读 https://www.stgraber.org/2016/03/15/lxd-2-0-installing-and-configuring-lxd-212/ 。创建第一个容器所有 LXD 的管理操作都可以通过 lxc 命令来进行。我们通过给 lxc 不同参数来管理容器。lxc list 可以列出所有已经安装的容器。很明显，这个列表现在是空的，但这表示我们的安装是没问题的。lxc image list 列出可以用来启动容器的（已经缓存的）镜像列表。很明显这个列表也是空的，但这也说明我们的安装是没问题的。lxc image…

lxc exec 介绍
type: item
date: 2017-08-06T17:26:00+08:00
description: 最近，我对 lxc exec 进行了几个改进。如果你不知道它的话我介绍一下，lxc exec 是 LXD 的客户端工具，使用 LXD 客户端 api 与 LXD 守护程序通信，并执行用户想要执行的各种程序，以下是你可以使用的一个例子：我们的主要目标之一就是使 lxc exec 与 ssh 类似，因为它是交互式或非交互式远程运行命令的标准。这使得 把 lxc exec 做得很好变得有点棘手。1、 处理后台任务一个长期存在的问题当然是如何正确处理后台任务。这是一个关于 LXD 2.7 实例的问题的例子：你可以看到，在后台执行任务将导致 lxc exec 无法退出。许多命令可以触发此问题：chb@conventiont|~ > lxc exec zest1 bash root@zest1:~# yes & y y y . . . 现在没有什么能救你了。yes 将会永远直接写入stdout。问题的根源在于 stdout 是一直打开着的，但这是必要的，因为它用以确保用户所启动的进程写入的任何数据实际上都是通过我们建立的 websocket 连接读取并发回的。假如你想这样，运行一个 shell 会话，然后在后台运行一个进程，并马上退出 shell。对不起，它并不能如预期那样。第一种并且原始的方法是一旦你检测到前台程序（例如 shell）已经退出就直接关闭 stdout。但这不像想得那么好，当你运行快速执行程序时，这个问题会变得明显，比如：lxc exec -- ls -al /usr/lib 这里 lxc exec 进程（和相关的 forkexec 进程。但现在不要考虑它，只要记住 Go + setns() 不相往来就行了……）会在 stdout 中所有的缓冲数据被读取之前退出。这种情况下将会导致截断输出，没有人想要这样。在尝试使用几个方法来解决问题之后，包括禁用 pty 缓冲（我告诉你，这不太漂亮，也没有如预期工作。）和其他奇怪的思路，我设法通过几个 poll() “技巧”（在某种意义上说一个“技巧”）解决了这个问题。现在你终于可以运行后台任务，并且可以完全退出了。如图：2、 报告由信号引起的退出码ssh 是一个很棒的工具。但有一件事，我一直以来不喜欢当 ssh 运行的命令接收到一个信号时， ssh 总是会报告 -1，也就是退出码 255。当你想要了解导致程序终止的信号时，这很烦人。这就是为什么我最近实施标准 shell 所使用的惯例 128 + n 来报告任何由信号导致的退出，其中 n 被定义为导致执行程序退出的信号量。例如，在 SIGKILL 信号上，你会看到 128 + SIGKILL = 137（计算其他致命信号的退出码作为读者的练习）。所以你可以这么做：chb@conventiont|~ > lxc exec zest1 sleep 100 现在，将 SIGKILL 发送到执行程序（不是 lxc exec本身，因为 SIGKILL 不可转发）。kill -KILL $(pidof sleep 100) 最后检查你程序的退出码：chb@conventiont|~ > echo $? 137 瞧。这显然只有当 a) 退出码没有超过 8 位计算壁垒，b）当执行程序不使用 137 来表示成功（这可真……有趣？！）。这两个论点似乎对我来说都不太有说服力。前者因为致命信号量不应该超过这个范围。后者因为（i）这是用户问题，（ii）这些退出代码实际上是保留的（我是这样认为。），（iii）你在本地或其他上面运行程序时会遇到同样的问题。我看到的主要优点是这能够回报执行程序细粒度的退出状态。注意，我们不会报告所有被信号杀死的程序实例。比如说，当你的程序能够处理 SIGTERM 并且完全退出时，LXD 没有简单的方法来检测到这个情况并报告说这个程序被信号杀死了。你只会简单地收到退出码 0。3、 转发信号这可能不太有趣（或者也许不是，谁知道呢），但我发现它非常有用。正如你在 SIGKILL 案例中看到的那样，我明确地指出，必须将 SIGKILL 发送到执行程序，而不是 lxc exec命令本身。这是因为 SIGKILL 在程序中无法处理。程序可以做的唯一的事情就是去死，像现在这样……像这个例子……马上（你明白了了吧……）。但是程序可以处理很多其他信号 SIGTERM、SIGHUP'，当然也可以处理SIGUSR1和SIGUSR2。因此，当你发送可以被lxc exec` 处理而不是被执行程序处理的信号时，较新版本的 LXD 会将信号转发到执行进程。这在脚本中非常方便。无论如何，我希望你觉得这篇小小的 lxc exec 文章/胡言乱语有用。享受 LXD 吧，这是与一只疯狂的美丽的野兽玩耍。请试试在线实验：https://linuxcontainers.org…

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 服务器的某个路…

LXD 2.0 系列（四）：资源控制
type: item
date: 2016-12-29T16:47:00+08:00
description: 这是 LXD 2.0 系列介绍文章的第四篇。LXD 入门安装与配置你的第一个 LXD 容器资源控制镜像管理远程主机及容器迁移LXD 中的 DockerLXD 中的 LXD实时迁移LXD 和 JujuLXD 和 OpenStack调试，及给 LXD 做贡献因为 LXD 容器管理有很多命令，因此这篇文章会很长。 如果你想要快速地浏览这些相同的命令，你可以尝试下我们的在线演示！可用资源限制LXD 提供了各种资源限制。其中一些与容器本身相关，如内存配额、CPU 限制和 I/O 优先级。而另外一些则与特定设备相关，如 I/O 带宽或磁盘用量限制。与所有 LXD 配置一样，资源限制可以在容器运行时动态更改。某些可能无法启用，例如，如果设置的内存值小于当前内存用量，但 LXD 将会试着设置并且报告失败。所有的限制也可以通过配置文件继承，在这种情况下每个受影响的容器将受到该限制的约束。也就是说，如果在默认配置文件中设置 limits.memory=256MB，则使用默认配置文件（通常是全都使用）的每个容器的内存限制为 256MB。我们不支持资源限制池，将其中的限制由一组容器共享，因为我们没有什么好的方法通过现有的内核 API 实现这些功能。磁盘这或许是最需要和最明显的需求。只需设置容器文件系统的大小限制，并对容器强制执行。LXD 确实可以让你这样做！不幸的是，这比它听起来复杂得多。 Linux 没有基于路径的配额，而大多数文件系统只有基于用户和组的配额，这对容器没有什么用处。如果你正在使用 ZFS 或 btrfs 存储后端，这意味着现在 LXD 只能支持磁盘限制。也有可能为 LVM 实现此功能，但这取决于与它一起使用的文件系统，并且如果结合实时更新那会变得棘手起来，因为并不是所有的文件系统都允许在线增长，而几乎没有一个允许在线收缩。CPU当涉及到 CPU 的限制，我们支持 4 种不同的东西：只给我 X 个 CPU 核心在这种模式下，你让 LXD 为你选择一组核心，然后为更多的容器和 CPU 的上线/下线提供负载均衡。容器只看到这个数量的 CPU 核心。给我一组特定的 CPU 核心（例如，核心1、3 和 5）类似于第一种模式，但是不会做负载均衡，你会被限制在那些核心上，无论它们有多忙。给我你拥有的 20％ 处理能力在这种模式下，你可以看到所有的 CPU，但调度程序将限制你使用 20％ 的 CPU 时间，但这只有在负载状态才会这样！所以如果系统不忙，你的容器可以跑得很欢。而当其他的容器也开始使用 CPU 时，它会被限制用量。每测量 200ms，给我 50ms（并且不超过）此模式与上一个模式类似，你可以看到所有的 CPU，但这一次，无论系统可能是多么空闲，你只能使用你设置的极限时间下的尽可能多的 CPU 时间。在没有过量使用的系统上，这可使你可以非常整齐地分割 CPU，并确保这些容器的持续性能。另外还可以将前两个中的一个与最后两个之一相结合，即请求一组 CPU，然后进一步限制这些 CPU 的 CPU 时间。除此之外，我们还有一个通用的优先级调节方式，可以告诉调度器当你处于负载状态时，两个争夺资源的容器谁会取得胜利。内存内存听起来很简单，就是给我多少 MB 的内存！它绝对可以那么简单。 我们支持这种限制以及基于百分比的请求，比如给我 10％ 的主机内存！另外我们在上层支持一些额外的东西。 例如，你可以选择在每个容器上打开或者关闭 swap，如果打开，还可以设置优先级，以便你可以选择哪些容器先将内存交换到磁盘！内存限制默认是“hard”。 也就是说，当内存耗尽时，内核将会开始杀掉你的那些进程。或者，你可以将强制策略设置为“soft”，在这种情况下，只要没有别的进程的情况下，你将被允许使用尽可能多的内存。一旦别的进程想要这块内存，你将无法分配任何内存，直到你低于你的限制或者主机内存再次有空余。网络 I/O网络 I/O 可能是我们看起来最简单的限制，但是相信我，实现真的不简单！我们支持两种限制。 第一个是对网络接口的速率限制。你可以设置入口和出口的限制，或者只是设置“最大”限制然后应用到出口和入口。这个只支持“桥接”和“p2p”类型接口。第二种是全局网络 I/O 优先级，仅当你的网络接口趋于饱和的时候再使用。块 I/O我把最古怪的放在最后。对于用户看起来它可能简单，但有一些情况下，它的结果并不会和你的预期一样。我们在这里支持的基本上与我在网络 I/O 中描述的相同。你可以直接设置磁盘的读写 IO 的频率和速率，并且有一个全局的块 I/O 优先级，它会通知 I/O 调度程序更倾向哪个。古怪的是如何设置以及在哪里应用这些限制。不幸的是，我们用于实现这些功能的底层使用的是完整的块设备。这意味着我们不能为每个路径设置每个分区的 I/O 限制。这也意味着当使用可以支…

LXD 2.0 系列（三）：你的第一个 LXD 容器
type: item
date: 2016-08-22T20:14:00+08:00
description: 这是 LXD 2.0 系列介绍文章的第三篇博客。LXD 入门安装与配置你的第一个 LXD 容器资源控制镜像管理远程主机及容器迁移LXD 中的 DockerLXD 中的 LXD实时迁移LXD 和 JujuLXD 和 OpenStack调试，及给 LXD 做贡献由于在管理 LXD 容器时涉及到大量的命令，所以这篇文章的篇幅是比较长的，如果你更喜欢使用同样的命令来快速的一步步实现整个过程，你可以尝试我们的在线示例！创建并启动一个新的容器正如我在先前的文章中提到的一样，LXD 命令行客户端预配置了几个镜像源。Ubuntu 的所有发行版和架构平台全都提供了官方镜像，但是对于其他的发行版也有大量的非官方镜像，那些镜像都是由社区制作并且被 LXC 上游贡献者所维护。Ubuntu如果你想要支持最为完善的 Ubuntu 版本，你可以按照下面的去做：lxc launch ubuntu: 注意，这里意味着会随着 Ubuntu LTS 的发布而变化。因此，如果用于脚本，你需要指明你具体安装的版本（参见下面）。Ubuntu14.04 LTS得到最新更新的、已经测试过的、稳定的 Ubuntu 14.04 LTS 镜像，你可以简单的执行：lxc launch ubuntu:14.04 在该模式下，会指定一个随机的容器名。如果你更喜欢指定一个你自己的名字，你可以这样做：lxc launch ubuntu:14.04 c1 如果你想要指定一个特定的体系架构（非主流平台），比如 32 位 Intel 镜像，你可以这样做：lxc launch ubuntu:14.04/i386 c2 当前的 Ubuntu 开发版本上面使用的“ubuntu:”远程仓库只会给你提供官方的并经过测试的 Ubuntu 镜像。但是如果你想要未经测试过的日常构建版本，开发版可能对你来说是合适的，你需要使用“ubuntu-daily:”远程仓库。lxc launch ubuntu-daily:devel c3 在这个例子中，将会自动选中最新的 Ubuntu 开发版本。你也可以更加精确，比如你可以使用代号名：lxc launch ubuntu-daily:xenial c4 最新的Alpine LinuxAlpine 镜像可以在“Images:”远程仓库中找到，通过如下命令执行：lxc launch images:alpine/3.3/amd64 c5 其他全部的 Ubuntu 镜像列表可以这样获得：lxc image list ubuntu: lxc image list ubuntu-daily: 全部的非官方镜像：lxc image list images: 某个给定的原程仓库的全部别名（易记名称）可以这样获得（比如对于“ubuntu:”远程仓库）：lxc image alias list ubuntu: 创建但不启动一个容器如果你想创建一个容器或者一批容器，但是你不想马上启动它们，你可以使用lxc init替换掉lxc launch。所有的选项都是相同的，唯一的不同就是它并不会在你创建完成之后启动容器。lxc init ubuntu: 关于你的容器的信息列出所有的容器要列出你的所有容器，你可以这样这做：lxc list 有大量的选项供你选择来改变被显示出来的列。在一个拥有大量容器的系统上，默认显示的列可能会有点慢（因为必须获取容器中的网络信息），你可以这样做来避免这种情况：lxc list --fast 上面的命令显示了另外一套列的组合，这个组合在服务器端需要处理的信息更少。你也可以基于名字或者属性来过滤掉一些东西：stgraber@dakara:~$ lxc list security.privileged=true +------+---------+---------------------+-----------------------------------------------+------------+-----------+ | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS | +------+---------+---------------------+-----------------------------------------------+------------+-----------+ | suse | RUNNING | 172.17.0.105 (eth0) | 2607:f2c0:f00f:2700:216:3eff:fef2:aff4 (eth0) | PERSISTENT | 0 | +------+---------+---------------------+------------------…

LXD 2.0 系列（二）：安装与配置
type: item
date: 2016-08-16T18:56:00+08:00
description: 这是 LXD 2.0 系列介绍文章的第二篇。LXD 入门安装与配置你的第一个 LXD 容器资源控制镜像管理远程主机及容器迁移LXD 中的 DockerLXD 中的 LXD实时迁移LXD 和 JujuLXD 和 OpenStack调试，及给 LXD 做贡献安装篇有很多种办法可以获得 LXD。我们推荐你配合最新版的 LXC 和 Linux 内核使用 LXD，这样就可以享受到它的全部特性。需要注意的是，我们现在也在慢慢的降低对旧版本 Linux 发布版的支持。Ubuntu 标准版所有新发布的 LXD 都会在发布几分钟后上传到 Ubuntu 开发版的安装源里。这个安装包然后就会作为 Ubuntu 用户的其他安装包源的种子。如果使用 Ubuntu 16.04，可以直接安装：sudo apt install lxd 如果运行的是 Ubuntu 14.04，则可以这样安装：sudo apt -t trusty-backports install lxd Ubuntu Core使用 Ubuntu Core 稳定版的用户可以使用下面的命令安装 LXD：sudo snappy install lxd.stgraber Ubuntu 官方 PPA使用其他 Ubuntu 发布版 —— 比如 Ubuntu 15.10 —— 的用户可以添加下面的 PPA（Personal Package Archive）来安装：sudo apt-add-repository ppa:ubuntu-lxc/stable sudo apt update sudo apt dist-upgrade sudo apt install lxd GentooGentoo 已经有了最新的 LXD 包，你可以直接安装：sudo emerge --ask lxd 使用源代码安装如果你曾经编译过 Go 语言的项目，那么从源代码编译 LXD 并不是十分困难。然而注意，你需要 LXC 的开发头文件。为了运行 LXD， 你的发布版需也要使用比较新的内核（最起码是 3.13）、比较新的 LXC （1.1.4 或更高版本）、LXCFS 以及支持用户子 uid/gid 分配的 shadow 文件。从源代码编译 LXD 的最新教程可以在上游 README里找到。Ubuntu 上的网络配置Ubuntu 的安装包会很方便的给你提供一个“lxdbr0”网桥。这个网桥默认是没有配置过的，只提供通过 HTTP 代理的 IPv6 的本地连接。要配置这个网桥并添加 IPv4 、 IPv6 子网，你可以运行下面的命令：sudo dpkg-reconfigure -p medium lxd 或者直接通过 LXD 初始化命令一步一步的配置：sudo lxd init 存储后端LXD 提供了几种存储后端。在开始使用 LXD 之前，你应该决定将要使用的后端，因为我们不支持在后端之间迁移已经生成的容器。各个后端特性比较表可以在这里找到。ZFS我们的推荐是 ZFS， 因为它能支持 LXD 的全部特性，同时提供最快和最可靠的容器体验。它包括了以容器为单位的磁盘配额、即时快照和恢复、优化后的迁移（发送/接收），以及快速从镜像创建容器的能力。它同时也被认为要比 btrfs 更成熟。要和 LXD 一起使用 ZFS ，你需要首先在你的系统上安装 ZFS。如果你是用的是 Ubuntu 16.04 ， 你只需要简单的使用命令安装：sudo apt install zfsutils-linux 在 Ubuntu 15.10 上你可以这样安装：sudo apt install zfsutils-linux zfs-dkms 如果是更旧的版本，你需要从 zfsonlinux PPA 安装：sudo apt-add-repository ppa:zfs-native/stable sudo apt update sudo apt install ubuntu-zfs 配置 LXD 只需要执行下面的命令：sudo lxd init 这条命令接下来会向你提问一些 ZFS 的配置细节，然后为你配置好 ZFS。btrfs如果 ZFS 不可用，那么 btrfs 可以提供相同级别的集成，但不能正确地报告容器内的磁盘使用情况（虽然配额仍然可用）。btrfs 同时拥有很好的嵌套属性，而这是 ZFS 所不具有的。也就是说如果你计划在 LXD 中再使用 LXD，那么 btrfs 就很值得你考虑。使用 btrfs 的话，LXD 不需要进行任何的配置，你只需要保证 /var/lib/lxd 保存在 btrfs 文件系统中，然后 LXD 就会自动为你使用 btrfs 了。LVM如果 ZFS 和 btrfs 都不是你想要的，你还可以考虑使用 LVM 以获得部分特性。 LXD 会以…

LXD 2.0 系列（一）：LXD 入门
type: item
date: 2016-07-26T16:59:00+08:00
description: 这是 LXD 2.0 系列介绍文章的第一篇。LXD 入门安装与配置你的第一个 LXD 容器资源控制镜像管理远程主机及容器迁移LXD 中的 DockerLXD 中的 LXD实时迁移LXD 和 JujuLXD 和 OpenStack调试，及给 LXD 做贡献关于 LXD 几个常见问题什么是 LXD ?简单地说， LXD 就是一个提供了 REST API 的 LXC 容器管理器。LXD 最主要的目标就是使用 Linux 容器而不是硬件虚拟化向用户提供一种接近虚拟机的使用体验。LXD 和 Docker/Rkt 又有什么关系呢 ?这是一个最常被问起的问题，现在就让我们直接指出其中的不同吧。LXD 聚焦于系统容器，通常也被称为架构容器。这就是说 LXD 容器实际上如在裸机或虚拟机上运行一般运行了一个完整的 Linux 操作系统。这些容器一般基于一个干净的发布镜像并会长时间运行。传统的配置管理工具和部署工具可以如在虚拟机、云实例和物理机器上一样与 LXD 一起使用。相对的， Docker 关注于短期的、无状态的、最小化的容器，这些容器通常并不会升级或者重新配置，而是作为一个整体被替换掉。这就使得 Docker 及类似项目更像是一种软件发布机制，而不是一个机器管理工具。这两种模型并不是完全互斥的。你完全可以使用 LXD 为你的用户提供一个完整的 Linux 系统，然后他们可以在 LXD 内安装 Docker 来运行他们想要的软件。为什么要用 LXD?我们已经持续开发并改进 LXC 好几年了。 LXC 成功的实现了它的目标，它提供了一系列很棒的用于创建和管理容器的底层工具和库。然而这些底层工具的使用界面对用户并不是很友好。使用它们需要用户有很多的基础知识以理解它们的工作方式和目的。同时，向后兼容旧的容器和部署策略也使得 LXC 无法默认使用一些安全特性，这导致用户需要进行更多人工操作来实现本可以自动完成的工作。我们把 LXD 作为解决这些缺陷的一个很好的机会。作为一个长时间运行的守护进程， LXD 可以绕开 LXC 的许多限制，比如动态资源限制、无法进行容器迁移和高效的在线迁移；同时，它也为创造新的默认体验提供了机会：默认开启安全特性，对用户更加友好。LXD 的主要组件LXD 是由几个主要组件构成的，这些组件都出现在 LXD 目录结构、命令行客户端和 API 结构体里。容器LXD 中的容器包括以下及部分：根文件系统（rootfs）配置选项列表，包括资源限制、环境、安全选项等等设备：包括磁盘、unix 字符/块设备、网络接口一组继承而来的容器配置文件属性（容器架构、暂时的还是持久的、容器名）运行时状态（当用 CRIU 来中断/恢复时）快照容器快照和容器是一回事，只不过快照是不可修改的，只能被重命名，销毁或者用来恢复系统，但是无论如何都不能被修改。值得注意的是，因为我们允许用户保存容器的运行时状态，这就有效的为我们提供了“有状态”的快照的功能。这就是说我们可以使用快照回滚容器的状态，包括快照当时的 CPU 和内存状态。镜像LXD 是基于镜像实现的，所有的 LXD 容器都是来自于镜像。容器镜像通常是一些纯净的 Linux 发行版的镜像，类似于你们在虚拟机和云实例上使用的镜像。所以可以「发布」一个容器：使用容器制作一个镜像并在本地或者远程 LXD 主机上使用。镜像通常使用全部或部分 sha256 哈希码来区分。因为输入长长的哈希码对用户来说不方便，所以镜像可以使用几个自身的属性来区分，这就使得用户在镜像商店里方便搜索镜像。也可以使用别名来一对一地将一个用户好记的名字映射到某个镜像的哈希码上。LXD 安装时已经配置好了三个远程镜像服务器（参见下面的远程一节）：“ubuntu”：提供稳定版的 Ubuntu 镜像“ubuntu-daily”：提供 Ubuntu 的每日构建镜像“images”： 社区维护的镜像服务器，提供一系列的其它 Linux 发布版，使用的是上游 LXC 的模板LXD 守护进程会从镜像上次被使用开始自动缓存远程镜像一段时间（默认是 10 天），超过时限后这些镜像才会失效。此外， LXD 还会自动更新远程镜像（除非指明不更新），所以本地的镜像会一直是最新版的。配置配置文件是一种在一个地方定义容器配置和容器设备，然后将其应用到一系列容器的方法。一个容器可以被应用多个配置文件。当构建最终容器配置时（即通常的扩展配置），这些配置文件都会按照他们定义顺序被应用到容器上，当有重名的配置键或设备时，新的会覆盖掉旧的。然后本地容器设置会在这些基础上应用，覆盖所有来自配置文件的选项。LXD 自带两种预配置的配置文件：“default”配置是自动应用在所有容器之上，除非用户提供了一系列替代的配置文件。目前这个配置文件只做一件事，为容器定义 eth0 网络设备…

教你在 Ubuntu 上使用 LXC 容器
type: item
date: 2014-11-27T15:56:00+08:00
description: 使用“容器”来保证主机环境的安全性，这个概念早在十年前就已经存在（例如 FreeBSD 的 jail 虚拟化技术），但是直到最近，随着部署云架构需求越来越多，像 LXC 和 Docker 这种 Linux 下的容器才成为被关注的焦点。当然，由于主流厂商（云服务商如亚马逊主推 AWS，微软主推 Azure；发行版如红帽、Ubuntu等）组成的强大靠山，Docker 已经被放在媒体的聚光灯下面，其实，Docker 里面所谓的“容器”技术是由 LXC 提供的。你只是一个普通的 Linux 用户，那 Docker/LXC 能为你带来什么好处呢？容器可以将你的应用在不同的 Linux 发行版之间迁移。想像一下这个场景：你正在用的发行版是 Debian，你喜欢它的稳定性，同时你又想玩一款最新的 Ubuntu 游戏，你不需要在电脑上装双系统然后重启进入 Ubuntu，也不需要在 Debian 上跑一个耗资源的 Ubuntu 虚拟机，你只需要简单地生成一个 Ubuntu 容器就够了。抛开 Docker 的好处不谈，让我们聊一下 LXC 容器的好处：我可以使用 libvirt 提供的接口来管理 LXC，这些接口和 Docker 没有任何关系。如果你有使用基于 libvirt 库的管理工具（例如 virt-manager 和 virsh），你就可以使用它们来管理 LXC 容器。在这篇教程中，我只介绍标准 LXC 容器管理工具的命令行操作，来教你如何在 Ubuntu 下创建和管理 LXC 容器。Ubuntu 下安装 LXC使用下面的命令安装 LXC 在用户态的工具：$ sudo apt-get install lxc 然后检查当前内核是否支持 LXC。如果所有结果都是“enable”，说明内核支持：$ lxc-checkconfig 安装完 LXC 工具后，就能看到 LXC 自动创建了一块桥接网卡（lxcbr0，可以在 /etc/lxc/default.conf 中设置）。当你创建了 LXC 容器后，它的网口会自动链接到这个桥接网卡上，然后这个容器就能和外部世界通信了。创建 LXC 容器为了在指定环境下（比如 Debian Wheezy 64位）创建 LXC 容器，你需要一个相应的 LXC 模板。幸运的是 LXC 提供的工具集成了一整套现成的 LXC 模板，你可以在 /usr/share/lxc/templates 目录下找到它们。 $ ls /usr/share/lxc/templates 一个 LXC 模板实质上就是一个脚本，用于创建指定环境下的容器。当你创建 LXC 容器时，你需要用到它们。比如你要新建 Ubuntu 容器，使用下面的命令即可：$ sudo lxc-create -n <container-name> -t ubuntu 默认情况下，这个命令会创建一个最小的 Ubuntu 环境，版本号与你的宿主机一致，我这边是“活泼的蝾螈”（版本号是13.10），64位。当然你也可以创建任何你喜欢的版本，只要在命令里面加一个版本参数即可。举个例子，创建 Ubuntu 14.10 的容器：$ sudo lxc-create -n <container-name> -t ubuntu -- --release utopic 这个命令就会下载安装指定环境下的软件包，创建新容器。整个过程需要几分钟时间，与容器的类型有关，所以，你可能需要耐心等待。下载安装完所有软件包后，LXC 容器镜像就创建完成了，你可以看到默认的登录界面。容器被放到 /var/lib/lxc/<容器名> 这个目录下，容器的根文件系统放在 /var/lib/lxc/<容器名>/rootfs 目录下。创建过程中下载的软件包保存在 /var/cache/lxc 目录下面，当你想另外建一个一样的容器时，可以省去很多下载时间。用下面的命令看看主机上所有的 LXC 容器：$ sudo lxc-ls --fancy NAME STATE IPV4 IPV6 AUTOSTART ------------------------------------ test-lxc STOPPED - - NO 使用下面的命令启动容器。参数“-d”将容器作为后台进程打开。如果没有指定这个参数，你可以在控制台界面上直接把容器的运行程序关闭（LCTT译注：Ctrl+C组合键）。$ sudo lxc-start -n <container-name> -d 打开容器后，看看状态：$ sudo lxc-ls --fancy NAME STATE IPV4 IPV6 AUTOSTART ----------------------------------------- lxc RUNNING 10.0.3.55 - NO…

lmctfy：让我用集装箱为你的程式打包
type: item
date: 2013-10-04T21:15:00+08:00
description: lmctfy (Let Me Contain That For you，发音是lem-kut-fee)是谷歌Google开发的容器栈，可以为Linux应用提供容器（container）。这些容器可以让一台机器上的不同应用使用相互隔离的资源，以独占的方式运行在同一台机器上。这些应用也可以拥有容器，因此能够创建和管理属于他们自己的子容器。这项项目旨在提供一组以用户的意图为原点的高级API，来实现对容器概念的抽象化。这些创建的容器自身也通过继承也可以拥有了自己的容器、也能够被其他的用户程序所管理。Lmctfy是为某些特定的场景（配置环境）设计、实现的，所以可能不能在所有场景（配置环境）中正常运作。我们的目标是为更多的场景（配置环境）提供更多的支持，所以你可以为这项项目贡献你的补丁或是在邮件列表中发送邮件，这样我们可以朝着既定的路线图前进。lmctfy 内包含一个C++库和一个CLI（命令行界面程序）最新进展lmctfy 还是一个在beta阶段的应用，目前仍在主要开发中。最新的版本是0.1。她目前只支持CPU和内存资源的隔离。点击查看我们的路线图来了解各部分的开发情况，点击查看贡献。从此开始这一节描述如何编译你的CLI，运行所有的UI测试，和初始化机器的细节。 CLI这节提供了一些CLI操作的例子，C++ 库描述了这个库的使用详情。依赖编译本程序需要使用make和g++4.7。 lmcfy使用了C++11，所以需要支持这项功能的编译器。我们在 Ubuntu 12.04+ 上测试过编译。如果有为其他环境的编译提供支持的补丁，我们很高兴而且希望这越多越好。lmctfy 依赖下列几个库，需要这些库存在于你的计算机系统里。Protocol BuffersgflagsRE2编译CLI编译lmctfy的CLI：make -j <线程数> lmctfyCLI程序会生成在 bin/lmctfy/cli/lmctfy编译C++库编译lmctfy的库：make -j <线程数> liblmctfy.a库文件会生成在 bin/liblmctfy.a.运行测试编译和运行所有的UI测试：make -j <线程数> check初始化lmctfy已经在 Ubuntu 12.04+ 上的 3.3 和 3.8 内核上测试过。 lmctfy在一台机器的所有容器都是运行它的时候运转得最好，所以不建议让她运行在LXC或者其他container系统上（尽管在某些特殊得配置下这能够跑起来）。为了运行lmctfy，我们必须首先初始化计算机。这只需要运行一次就可以，而且一般是在计算机第一次启动时候就完成了。当cgroup的hierarchies已经挂载了，接下来通常一个空的配置会可以让lmctfy自动监测到目前的挂载。lmctfy init ""如果cgroup的hierarchies没有被挂载，那么必须指明这些资源，这样lmctfy才可以挂载他们。目前版本需要以下cgroup的hierarchies资源cpu，cpuset，cpuacct，memory和freezer。 cpu和cpuacct 是目前唯一可以被共享挂载的，其他的必须被单独地挂载。具体配置说明可以查看lmctfy.proto中的InitSpec节。以下的例子是一个挂载了/dev/cgroup中的所有hierarachies的配置文件：lmctfy init " cgroup_mount:{ mount_path:'/dev/cgroup/cpu' hierarchy:CGROUP_CPU hierarchy:CGROUP_CPUACCT } cgroup_mount:{ mount_path:'/dev/cgroup/cpuset' hierarchy:CGROUP_CPUSET } cgroup_mount:{ mount_path:'/dev/cgroup/freezer' hierarchy:CGROUP_FREEZER } cgroup_mount:{ mount_path:'/dev/cgroup/memory' hierarchy:CGROUP_MEMORY }"这样，机器就可以被lmctfy使用、进行容器的操作。容器的命名容器的命名系统简化了文件系统的路径，因为以后只需要一系列容器的继承（容器的容器、子容器、子子容器）就可以了♪───Ｏ（≧∇≦）Ｏ──── ♪。容器名称允许的字符集：英文字母＋阿拉伯数字 ([a-zA-Z0-9]+)下划线 (\_)横县 (-)英文句号 (.)绝对路径是从容器（比如是/sys/subcont）的根目录(/)开始计算的。容器的名字也可以是相对的（比如subcont）。一般地（除非特殊情况说明），都是沿用一般的文件路径方式。例子 / : 容器的根目录 /sys : "sys…