Stéphane Graber 发布的文章

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:~#

然后重启一下 Ubuntu Core 系统,然后看看 snapd 的版本。

root@ubuntu-core:~# reboot
root@ubuntu-core:~# 

stgraber@dakara:~$ lxc exec ubuntu-core bash
root@ubuntu-core:~# snap version
snap 2.21
snapd 2.21
series 16
root@ubuntu-core:~#

你也可以像下面这样查看所有 snapd 的历史记录:

stgraber@dakara:~$ lxc exec ubuntu-core snap changes
ID  Status  Spawn                 Ready                 Summary
1   Done    2017-01-31T05:14:38Z  2017-01-31T05:14:44Z  Initialize system state
2   Done    2017-01-31T05:14:40Z  2017-01-31T05:14:45Z  Initialize device
3   Done    2017-01-31T05:21:30Z  2017-01-31T05:22:45Z  Refresh all snaps in the system

安装 Snap 软件包

以一个最简单的例子开始,经典的 Hello World:

stgraber@dakara:~$ lxc exec ubuntu-core bash
root@ubuntu-core:~# snap install hello-world
hello-world 6.3 from 'canonical' installed
root@ubuntu-core:~# hello-world
Hello World!

接下来让我们看一些更有用的:

stgraber@dakara:~$ lxc exec ubuntu-core bash
root@ubuntu-core:~# snap install nextcloud
nextcloud 11.0.1snap2 from 'nextcloud' installed

之后通过 HTTP 访问你的容器就可以看到刚才部署的 Nextcloud 实例。

如果你想直接通过 git 测试最新版 LXD,你可以这样做:

stgraber@dakara:~$ lxc config set ubuntu-core security.nesting true
stgraber@dakara:~$ lxc exec ubuntu-core bash
root@ubuntu-core:~# snap install lxd --edge
lxd (edge) git-c6006fb from 'canonical' installed
root@ubuntu-core:~# lxd init
Name of the storage backend to use (dir or zfs) [default=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) [default=yes]? 
Would you like LXD to be available over the network (yes/no) [default=no]? 
Would you like stale cached images to be updated automatically (yes/no) [default=yes]? 
Would you like to create a new network bridge (yes/no) [default=yes]? 
What should the new bridge be called [default=lxdbr0]? 
What IPv4 address should be used (CIDR subnet notation, “auto” or “none”) [default=auto]? 
What IPv6 address should be used (CIDR subnet notation, “auto” or “none”) [default=auto]? 
LXD has been successfully configured.

已经设置过的容器不能回退版本,但是可以在 Ubuntu Core 16 中运行另一个 Ubuntu Core 16 容器:

root@ubuntu-core:~# lxc launch images:ubuntu-core/16 nested-core
Creating nested-core
Starting nested-core 
root@ubuntu-core:~# lxc list
+-------------+---------+---------------------+-----------------------------------------------+------------+-----------+
|    NAME     |  STATE  |         IPV4        |                       IPV6                    |    TYPE    | SNAPSHOTS |
+-------------+---------+---------------------+-----------------------------------------------+------------+-----------+
| nested-core | RUNNING | 10.71.135.21 (eth0) | fd42:2861:5aad:3842:216:3eff:feaf:e6bd (eth0) | PERSISTENT | 0         |
+-------------+---------+---------------------+-----------------------------------------------+------------+-----------+

写在最后

如果你只是想试用一下 Ubuntu Core,这是一个不错的方法。对于 snap 包开发者来说,这也是一个不错的工具来测试你的 snap 包能否在不同的环境下正常运行。

如果你希望你的系统总是最新的,并且整体可复制,Ubuntu Core 是一个很不错的方案,不过这也会带来一些相应的限制,所以可能不太适合你。

最后是一个警告,对于测试来说,这些镜像是足够的,但是当前并没有被正式的支持。在不久的将来,官方的 Ubuntu server 可以完整的支持 Ubuntu Core LXD 镜像。

附录


来自: https://insights.ubuntu.com/2017/02/27/ubuntu-core-in-lxd-containers/

作者:Stéphane Graber 译者:aiwhj 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

介绍

当 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         |
+------+---------+-------------------+------+------------+-----------+

IPv6 也是相同的方法,但是换成 ipv6.address 属性。

相似地,如果你想要阻止你的容器更改它的 MAC 地址或者为其他 MAC 地址转发流量(比如嵌套),你可以用下面的命令启用端口安全:

root@yak:~# lxc config device set c1 eth0 security.mac_filtering true

DNS

LXD 在网桥上运行 DNS 服务器。除了设置网桥的 DNS 域( dns.domain 网络属性)之外,还支持 3 种不同的操作模式(dns.mode):

  • managed :每个容器都会有一条 DNS 记录,匹配它的名字以及已知的 IP 地址。容器无法通过 DHCP 改变这条记录。
  • dynamic :允许容器通过 DHCP 在 DNS 中自行注册。因此,在 DHCP 协商期间容器发送的任何主机名最终都出现在 DNS 中。
  • none : 针对那些没有任何本地 DNS 记录的递归 DNS 服务器。

默认的模式是 managed,并且典型的是最安全以及最方便的,因为它为容器提供了 DNS 记录,但是不允许它们通过 DHCP 发送虚假主机名嗅探其他的记录。

使用隧道

除了这些,LXD 还支持使用 GRE 或者 VXLAN 隧道连接到其他主机。

LXD 网络可以连接任何数量的隧道,从而轻松地创建跨多个主机的网络。这对于开发、测试和演示非常有用,生产环境通常更喜欢使用 VLAN 进行分割。

所以说,你想在主机 “edfu” 上有一个运行 IPv4 和 IPv6 的基础 “testbr0” 网络,并希望在主机 “djanet” 上使用它来生成容器。最简单的方法是使用组播 VXLAN 隧道。这种类型的隧道仅在两个主机位于同一物理段上时才起作用。

root@edfu:~# lxc network create testbr0 tunnel.lan.protocol=vxlan
Network testbr0 created
root@edfu:~# lxc network attach-profile testbr0 default eth0

它在主机 “edfu” 上定义了一个 “testbr0” 桥接,并为其他主机能加入它设置了一个组播 VXLAN。在这个设置中,“edfu” 为这个网络扮演了一个路由器角色,提供 DHCP、DNS 等等,其他主机只是通过隧道转发流量。

root@djanet:~# lxc network create testbr0 ipv4.address=none ipv6.address=none tunnel.lan.protocol=vxlan
Network testbr0 created
root@djanet:~# lxc network attach-profile testbr0 default eth0

现在你可以在任何一台主机上启动容器,并看到它们从同一个地址池中获取 IP,通过隧道直接互相通讯。

如先前所述,这个使用了组播,它通常在跨越路由器时无法很好工作。在这些情况下,你可以用单播模式使用 VXLAN 或者 GRE 隧道。

要使用 GRE 加入另一台主机,首先配置服务主机:

root@edfu:~# lxc network set testbr0 tunnel.nuturo.protocol gre
root@edfu:~# lxc network set testbr0 tunnel.nuturo.local 172.17.16.2
root@edfu:~# lxc network set testbr0 tunnel.nuturo.remote 172.17.16.9

接着是“客户端”主机:

root@nuturo:~# lxc network create testbr0 ipv4.address=none ipv6.address=none tunnel.edfu.protocol=gre tunnel.edfu.local=172.17.16.9 tunnel.edfu.remote=172.17.16.2
Network testbr0 created
root@nuturo:~# lxc network attach-profile testbr0 default eth0

如果你像使用 VXLAN,只要这么做:

root@edfu:~# lxc network set testbr0 tunnel.edfu.id 10
root@edfu:~# lxc network set testbr0 tunnel.edfu.protocol vxlan

还有:

root@nuturo:~# lxc network set testbr0 tunnel.edfu.id 10
root@nuturo:~# lxc network set testbr0 tunnel.edfu.protocol vxlan

这里需要隧道 id 以防与已经配置的多播 VXLAN 隧道冲突。

这就是如何使用最近的 LXD 简化跨主机联网了!

总结

LXD 使得从简单的单主机网络到数千个容器的非常复杂的跨主机网络的定义变得更加容易。它也使为一些容器定义一个新网络或者给容器添加第二个设备,并连接到隔离的私有网络变得很简单。

虽然这篇文章介绍了支持的大部分功能,但仍有一些可以微调 LXD 网络体验的窍门。可以在这里找到完整的列表:https://github.com/lxc/lxd/blob/master/doc/configuration.md

额外信息


via: https://www.stgraber.org/2016/10/27/network-management-with-lxd-2-3/

作者:Stéphane Graber 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

介绍

终于要结束了!这个大约一年前开始的这系列文章的最后一篇博文。

  1. LXD 入门
  2. 安装与配置
  3. 你的第一个 LXD 容器
  4. 资源控制
  5. 镜像管理
  6. 远程主机及容器迁移
  7. LXD 中的 Docker
  8. LXD 中的 LXD
  9. 实时迁移
  10. LXD 和 Juju
  11. LXD 和 OpenStack
  12. 调试,及给 LXD 做贡献

如果你从一开始就关注了这个系列,你应该已经使用了 LXD 相当长的时间了,并且非常熟悉它的日常操作和功能。

但如果出现问题怎么办?你可以做什么来自己跟踪问题?如果你不能,你应该记录什么信息,以便上游可以跟踪问题?

如果你想自己解决问题或通过实现你需要的功能来帮助改善LXD怎么办?如何构建,测试和贡献 LXD 代码库?

调试 LXD 并填写 bug 报告

LXD 日志文件

/var/log/lxd/lxd.log

这是 LXD 日志的主文件。为了避免它快速充满你的磁盘,默认只会记录 INFOWARNING 或者 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
    url: /1.0/containers/xen/state
  level: dbug
  message: handling
timestamp: 2017-02-24T18:14:09.357046302-05:00
type: logging

metadata:
  context: {}
  level: dbug
  message: 'New task operation: 2e2cf904-c4c4-4693-881f-57897d602ad3'
timestamp: 2017-02-24T18:14:09.358387853-05:00
type: logging

metadata:
  context: {}
  level: dbug
  message: 'Started task operation: 2e2cf904-c4c4-4693-881f-57897d602ad3'
timestamp: 2017-02-24T18:14:09.358578599-05:00
type: logging

metadata:
  context:
    ip: '@'
    method: GET
    url: /1.0/operations/2e2cf904-c4c4-4693-881f-57897d602ad3/wait
  level: dbug
  message: handling
timestamp: 2017-02-24T18:14:09.366213106-05:00
type: logging

metadata:
  context:
    driver: storage/zfs
  level: dbug
  message: StoragePoolInit
timestamp: 2017-02-24T18:14:09.369636451-05:00
type: logging

metadata:
  context:
    driver: storage/zfs
  level: dbug
  message: StoragePoolCheck
timestamp: 2017-02-24T18:14:09.369771164-05:00
type: logging

metadata:
  context:
    container: xen
    driver: storage/zfs
  level: dbug
  message: ContainerMount
timestamp: 2017-02-24T18:14:09.424696767-05:00
type: logging

metadata:
  context:
    driver: storage/zfs
    name: xen
  level: dbug
  message: ContainerUmount
timestamp: 2017-02-24T18:14:09.432723719-05:00
type: logging

metadata:
  context:
    container: xen
    driver: storage/zfs
  level: dbug
  message: ContainerMount
timestamp: 2017-02-24T18:14:09.721067917-05:00
type: logging

metadata:
  context:
    action: start
    created: 2017-02-24 23:11:45 +0000 UTC
    ephemeral: "false"
    name: xen
    stateful: "false"
    used: 1970-01-01 00:00:00 +0000 UTC
  level: info
  message: Starting container
timestamp: 2017-02-24T18:14:09.749808518-05:00
type: logging

metadata:
  context:
    ip: '@'
    method: GET
    url: /1.0
  level: dbug
  message: handling
timestamp: 2017-02-24T18:14:09.792551375-05:00
type: logging

metadata:
  context:
    driver: storage/zfs
  level: dbug
  message: StorageCoreInit
timestamp: 2017-02-24T18:14:09.792961032-05:00
type: logging

metadata:
  context:
    ip: '@'
    method: GET
    url: /internal/containers/23/onstart
  level: dbug
  message: handling
timestamp: 2017-02-24T18:14:09.800803501-05:00
type: logging

metadata:
  context:
    driver: storage/zfs
  level: dbug
  message: StoragePoolInit
timestamp: 2017-02-24T18:14:09.803190248-05:00
type: logging

metadata:
  context:
    driver: storage/zfs
  level: dbug
  message: StoragePoolCheck
timestamp: 2017-02-24T18:14:09.803251188-05:00
type: logging

metadata:
  context:
    container: xen
    driver: storage/zfs
  level: dbug
  message: ContainerMount
timestamp: 2017-02-24T18:14:09.803306055-05:00
type: logging

metadata:
  context: {}
  level: dbug
  message: 'Scheduler: container xen started: re-balancing'
timestamp: 2017-02-24T18:14:09.965080432-05:00
type: logging

metadata:
  context:
    action: start
    created: 2017-02-24 23:11:45 +0000 UTC
    ephemeral: "false"
    name: xen
    stateful: "false"
    used: 1970-01-01 00:00:00 +0000 UTC
  level: info
  message: Started container
timestamp: 2017-02-24T18:14:10.162965059-05:00
type: logging

metadata:
  context: {}
  level: dbug
  message: 'Success for task operation: 2e2cf904-c4c4-4693-881f-57897d602ad3'
timestamp: 2017-02-24T18:14:10.163072893-05:00
type: logging

lxc monitor 的格式有点不同于每个条目都缩合成一行的日志文件,但更重要的是,你可以看到所有 level:dbug 条目。

如何报告 bug

LXD 的 bug

最好报告 bug 的地方是 https://github.com/lxc/lxd/issues。确保完整填写了 bug 报告模板中的内容,这些信息可以节省我们我们时间来复现环境。

Ubuntu 的 bug

如果你发现 Ubuntu 包本身有问题,无法安装、升级或删除。或者遇到 LXD init 脚本的问题。报告此类错误的最好是在 Launchpad 上。

在 Ubuntu 系统上,你可以使用:ubuntu-bug lxd ,它将自动包括一些日志文件和包信息供我们查看。

CRIU 的 bug

与 CRIU 相关的 Bug,你可以通过 CRIU 的错误输出发现,你应该在 Launchpad 上报告这些:ubuntu-bug criu

请注意,通过 LXD 使用 CRIU 属于测试版功能,除非你愿意通过 Canonical 的支持合同付费支持,要么可能需要一段时间才能查看你的错误报告。

贡献给 LXD

LXD 用 Go 写成并托管在 Github。我们欢迎任外部的贡献。为 LXD 贡献不需要 CLA 或类似的法律协议签署,只是通常的开发者所有权证书(Signed-off-by: 行)。

在我们的问题追踪器工具中,我们列有许多潜在的功能需求,新的贡献者可以以此作为良好的起点。通常最好在开始处理代码先发出 issue,这样每个人都知道你正在做这项工作,以便我们可以提供一些早期反馈。

从源码源码构建 LXD

这里有上游的维护说明:https://github.com/lxc/lxd#building-from-source

你需要在 Github 上 fork 上游仓库,然后将你的更改推送到你的分支。我们建议每天 rebase 上游的 LXD,因为我们倾向于定期合并更改。

运行测试套件

LXD 维护了两套测试集,单元测试和集成测试。你可以用下面的命令测试所有:

sudo -E make check

要只运行单元测试,使用:

sudo -E go test ./...

要运行集成测试,使用:

cd test
sudo -E ./main.sh

后者支持相当多的环境变量来测试各种存储后端、禁用网络测试、使用 ramdisk 或只是调整日志输出。其中一些是:

  • LXD_BACKENDbtrfsdirlvmzfs” 之一(默认为 dir
    运行 LXD 存储驱动程序相关的所有测试。
  • LXD_CONCURRENTtruefalse(默认为 false
    这启用一些额外的并发测试。
  • LXD_DEBUGtruefalse(默认为 false
    记录所有 shell 命令,并在调试模式下运行所有​​ LXD 命令。
  • LXD_INSPECTtruefalse(默认为 false
    测试程序会在故障时挂起,以便你可以检查环境。
  • LXD_LOGS:将所有 LXD 日志文件转储到的目录(默认为 “”)
    所有生成的 LXD 守护进程的 logs 目录将被复制到此路径。
  • LXD_OFFLINEtruefalse(默认为 false
    禁用任何依赖于外部网络连接的测试。
  • LXD_TEST_IMAGE: unified 格式的 LXD 镜像的路径(默认为 “”)
    可以使用自定义测试镜像,而不是默认的最小 busybox 镜像。
  • LXD_TMPFStruefalse(默认为 false
    tmpfs 安装中运行整个测试套件,这会使用相当多的内存,但会使测试速度明显更快。
  • LXD_VERBOSEtruefalse(默认为 false
    不太极端的 LXD_DEBUG 版本。shell 命令仍然会记录,但 -debug 不会传递给 LXC 命令,LXD 守护进程只能使用 -verbose 运行。

测试程序将在实际运行之前提醒你任何缺失的依赖项。在相当快的机器上运行该测试可在 10 分钟内完成。

发送你的分支

发送拉取请求(PR)之前,你需要确认:

  • 你已经 rebase 了上游分支
  • 你的所有提交信息都包括 Signed-off-by: First Last <email> 这行
  • 已删除任何你的临时调试代码
  • 你已经将相关的提交 squash 在一起,以保持你的分支容易审查
  • 单元和集成测试全部通过

一切完成后,在 Github 上发起一个拉取请求。我们的 Jenkins 将验证提交是否全部有 signed-off,在 MacOS 和 Windows 上的测试将自动执行,如果看起来不错,我们将触发一个完整的 Jenkins 测试,它将在所有存储后端、32 位和 64 位以及我们关心的所有 Go 版本上测试你的分支。

假设我们有人触发了 Jenkins,这通常需要不到一个小时的时间。

一旦所有测试完成,我们对代码本身感到满意,你的分支将会被合并,你的代码会出现在下一个 LXD 发布中。如果更改适用于 LXD stable-2.0 分支,我们将为你向后移植。

总结

我希望这个系列的博客文章有助于你了解什么是 LXD,以及它可以做什么!

本系列的范围仅限于 LXD(2.0.x),但我们也为那些想要最新功能的用户提供每月功能版本。你可以找到一些其他涵盖了原来的 LXD 2.0系列文章中列出的功能的博客文章。

额外的信息

LXD 的主站在: https://linuxcontainers.org/lxd

LXD 的 GitHub 开发仓库: https://github.com/lxc/lxd

LXD 的邮件列表: https://lists.linuxcontainers.org

LXD 的 IRC 频道:#lxcontainers on irc.freenode.net

在线尝试 LXD: https://linuxcontainers.org/lxd/try-it


作者简介:我是 Stéphane Graber。我是 LXC 和 LXD 项目的领导者,目前在加拿大魁北克蒙特利尔的家所在的 Canonical 有限公司担任 LXD 的技术主管。


via: https://stgraber.org/2017/02/27/lxd-2-0-debugging-and-contributing-to-lxd-1212/

作者:Stéphane Graber 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

这是 LXD 2.0 系列介绍文章的第十一篇。

  1. LXD 入门
  2. 安装与配置
  3. 你的第一个 LXD 容器
  4. 资源控制
  5. 镜像管理
  6. 远程主机及容器迁移
  7. LXD 中的 Docker
  8. LXD 中的 LXD
  9. 实时迁移
  10. LXD 和 Juju
  11. LXD 和 OpenStack
  12. 调试,及给 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。整个过程会花费一个多小时,这取决于你运行的机器。你将看到所有服务会被分配一个容器,然后部署并最终互连。

Conjure-Up deploying OpenStack

部署完成后会显示一个安装完成的界面。它会导入一些初始镜像、设置 SSH 权限、配置网络最后会显示面板的 IP 地址。

访问面板并生成一个容器

面板运行在一个容器中,因此你不能直接从浏览器中访问。

最简单的方法是设置一条 NAT 规则:

lxc exec openstack -- iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to <IP>

其中 <ip> 是 conjure-up 在安装结束时给你的面板 IP 地址。

你现在可以获取 “openstack” 容器的 IP 地址(来自 lxc info openstack),并将浏览器指向:http:///horizon 。

第一次加载可能需要几分钟。 一旦显示了登录界面,输入默认登录名和密码(admin/openstack),你就会看到OpenStack的欢迎面板!

oslxd-dashboard

现在可以选择左边的 “Project” 选项卡,进入 “Instances” 页面。 要启动一个使用 nova-lxd 的新实例,点击 “Launch instance”,选择你想要的镜像,网络等,接着你的实例就产生了。

一旦它运行后,你可以为它分配一个浮动 IP,它将允许你从你的 “openstack” 容器中访问你的实例。

总结

OpenStack 是一个非常复杂的软件,你也不会想在家里或在单个服务器上运行它。 但是,不管怎样在你的机器上包含这些服务在一个容器中都是非常有趣的。

conjure-up 是部署这种复杂软件的一个很好的工具,背后使用 Juju 驱动部署,为每个单独的服务使用 LXD 容器,最后是实例本身。

它也是少数几个容器嵌套多层并实际上有意义的情况之一!

额外信息

conjure-up 网站: http://conjure-up.io

Juju 网站: http://www.ubuntu.com/cloud/juju

LXD 的主站在: https://linuxcontainers.org/lxd

LXD 的 GitHub 仓库: https://github.com/lxc/lxd

LXD 的邮件列表: https://lists.linuxcontainers.org

LXD 的 IRC 频道: #lxcontainers on irc.freenode.net

如果你不想或者不能在你的机器上安装 LXD ,你可以在 web 上试试在线版的 LXD。


作者简介:我是 Stéphane Graber。我是 LXC 和 LXD 项目的领导者,目前在加拿大魁北克蒙特利尔的家所在的 Canonical 有限公司担任 LXD 的技术主管。


via: https://www.stgraber.org/2016/10/26/lxd-2-0-lxd-and-openstack-1112/

作者:Stéphane Graber 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

这是 LXD 2.0 系列介绍文章的第十篇。

  1. LXD 入门
  2. 安装与配置
  3. 你的第一个 LXD 容器
  4. 资源控制
  5. 镜像管理
  6. 远程主机及容器迁移
  7. LXD 中的 Docker
  8. LXD 中的 LXD
  9. 实时迁移
  10. LXD 和 Juju
  11. LXD 和 OpenStack
  12. 调试,及给 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-745d1be3-e93d-41a2-80d4-fbe8714230dd-machine-0
Installing Juju agent on bootstrap instance
Preparing for Juju GUI 2.1.2 release installation
Waiting for address
Attempting to connect to 10.178.150.72:22
Logging to /var/log/cloud-init-output.log on remote host
Running apt-get update
Running apt-get upgrade
Installing package: curl
Installing package: cpu-checker
Installing package: bridge-utils
Installing package: cloud-utils
Installing package: cloud-image-utils
Installing package: tmux
Fetching tools: curl -sSfw 'tools from %{url_effective} downloaded: HTTP %{http_code}; time %{time_total}s; size %{size_download} bytes; speed %{speed_download} bytes/s ' --retry 10 -o $bin/tools.tar.gz <[https://streams.canonical.com/juju/tools/agent/2.0-beta7/juju-2.0-beta7-xenial-amd64.tgz]>
Bootstrapping Juju machine agent
Starting Juju machine agent (jujud-machine-0)
Bootstrap agent installed
Waiting for API to become available: upgrade in progress (upgrade in progress)
Waiting for API to become available: upgrade in progress (upgrade in progress)
Waiting for API to become available: upgrade in progress (upgrade in progress)
Bootstrap complete, local.test now available.

这会花费一点时间,这时你可以看到一个正在运行的一个新的 LXD 容器:

stgraber@dakara:~$ lxc list juju-
+-----------------------------------------------------+---------+----------------------+------+------------+-----------+
|                         NAME                        |  STATE  |          IPV4        | IPV6 |    TYPE    | SNAPSHOTS |
+-----------------------------------------------------+---------+----------------------+------+------------+-----------+
| juju-745d1be3-e93d-41a2-80d4-fbe8714230dd-machine-0 | RUNNING | 10.178.150.72 (eth0) |      | PERSISTENT | 0         |
+-----------------------------------------------------+---------+----------------------+------+------------+-----------+

在 Juju 这边,你可以确认它是有响应的,并且还没有服务运行:

stgraber@dakara:~$ juju status
[Services] 
NAME STATUS EXPOSED CHARM 

[Units] 
ID WORKLOAD-STATUS JUJU-STATUS VERSION MACHINE PORTS PUBLIC-ADDRESS MESSAGE 

[Machines] 
ID STATE DNS INS-ID SERIES AZ

你也可以在浏览器中访问 Juju 的 GUI 界面:

stgraber@dakara:~$ juju gui
Opening the Juju GUI in your browser.
If it does not open, open this URL:
https://10.178.150.72:17070/gui/97fa390d-96ad-44df-8b59-e15fdcfc636b/

Juju web UI

不过我更倾向使用命令行,因此我会在接下来使用。

部署一个 minecraft 服务

让我们先来一个简单的,部署在一个容器中使用一个 Juju 单元的服务。

stgraber@dakara:~$ juju deploy cs:trusty/minecraft
Added charm "cs:trusty/minecraft-3" to the model.
Deploying charm "cs:trusty/minecraft-3" with the charm series "trusty".

命令返回会很快,然而这不意味着服务已经启动并运行了。你应该使用 juju status 来查看:

stgraber@dakara:~$ juju status
[Services] 
NAME STATUS EXPOSED CHARM 
minecraft maintenance false cs:trusty/minecraft-3 

[Units] 
ID WORKLOAD-STATUS JUJU-STATUS VERSION MACHINE PORTS PUBLIC-ADDRESS MESSAGE 
minecraft/1 maintenance executing 2.0-beta7 1 10.178.150.74 (install) Installing java 

[Machines] 
ID STATE DNS INS-ID SERIES AZ 
1 started 10.178.150.74 juju-97fa390d-96ad-44df-8b59-e15fdcfc636b-machine-1 trusty 

我们可以看到它正在忙于在刚刚创建的 LXD 容器中安装 java。

stgraber@dakara:~$ lxc list juju-
+-----------------------------------------------------+---------+----------------------+------+------------+-----------+
|                         NAME                        |  STATE  |          IPV4        | IPV6 |    TYPE    | SNAPSHOTS |
+-----------------------------------------------------+---------+----------------------+------+------------+-----------+
| juju-745d1be3-e93d-41a2-80d4-fbe8714230dd-machine-0 | RUNNING | 10.178.150.72 (eth0) |      | PERSISTENT | 0         |
+-----------------------------------------------------+---------+----------------------+------+------------+-----------+
| juju-97fa390d-96ad-44df-8b59-e15fdcfc636b-machine-1 | RUNNING | 10.178.150.74 (eth0) |      | PERSISTENT | 0         |
+-----------------------------------------------------+---------+----------------------+------+------------+-----------+

过一会之后,如我们所见服务就部署完毕了:

stgraber@dakara:~$ juju status
[Services] 
NAME STATUS EXPOSED CHARM 
minecraft active false cs:trusty/minecraft-3 

[Units] 
ID WORKLOAD-STATUS JUJU-STATUS VERSION MACHINE PORTS PUBLIC-ADDRESS MESSAGE 
minecraft/1 active idle 2.0-beta7 1 25565/tcp 10.178.150.74 Ready 

[Machines] 
ID STATE DNS INS-ID SERIES AZ 
1 started 10.178.150.74 juju-97fa390d-96ad-44df-8b59-e15fdcfc636b-machine-1 trusty

这时你就可以启动你的 Minecraft 客户端了,将其指向 10.178.150.74,端口是 25565。现在可以在新的 minecraft 服务器上玩了!

当你不再需要它,只需运行:

stgraber@dakara:~$ juju destroy-service minecraft

只要等待几秒就好了。

部署一个更复杂的 web 应用

Juju 的主要工作是建模复杂的服务,并以可扩展的方式部署它们。

为了更好地展示,让我们部署一个 Juju “组合”。 这个组合是由网站,API,数据库,静态 Web 服务器和反向代理组成的基本 Web 服务。

所以这将扩展到 4 个互联的 LXD 容器。

stgraber@dakara:~$ juju deploy cs:~charmers/bundle/web-infrastructure-in-a-box
added charm cs:~hp-discover/trusty/node-app-1
service api deployed (charm cs:~hp-discover/trusty/node-app-1 with the series "trusty" defined by the bundle)
annotations set for service api
added charm cs:trusty/mongodb-3
service mongodb deployed (charm cs:trusty/mongodb-3 with the series "trusty" defined by the bundle)
annotations set for service mongodb
added charm cs:~hp-discover/trusty/nginx-4
service nginx deployed (charm cs:~hp-discover/trusty/nginx-4 with the series "trusty" defined by the bundle)
annotations set for service nginx
added charm cs:~hp-discover/trusty/nginx-proxy-3
service nginx-proxy deployed (charm cs:~hp-discover/trusty/nginx-proxy-3 with the series "trusty" defined by the bundle)
annotations set for service nginx-proxy
added charm cs:~hp-discover/trusty/website-3
service website deployed (charm cs:~hp-discover/trusty/website-3 with the series "trusty" defined by the bundle)
annotations set for service website
related mongodb:database and api:mongodb
related website:nginx-engine and nginx:web-engine
related api:website and nginx-proxy:website
related nginx-proxy:website and website:website
added api/0 unit to new machine
added mongodb/0 unit to new machine
added nginx/0 unit to new machine
added nginx-proxy/0 unit to new machine
deployment of bundle "cs:~charmers/bundle/web-infrastructure-in-a-box-10" completed

几秒后,你会看到 LXD 容器在运行了:

stgraber@dakara:~$ lxc list juju-
+-----------------------------------------------------+---------+-----------------------+------+------------+-----------+
|                         NAME                        |  STATE  |           IPV4        | IPV6 |    TYPE    | SNAPSHOTS |
+-----------------------------------------------------+---------+-----------------------+------+------------+-----------+
| juju-745d1be3-e93d-41a2-80d4-fbe8714230dd-machine-0 | RUNNING | 10.178.150.72 (eth0)  |      | PERSISTENT | 0         |
+-----------------------------------------------------+---------+-----------------------+------+------------+-----------+
| juju-97fa390d-96ad-44df-8b59-e15fdcfc636b-machine-2 | RUNNING | 10.178.150.98 (eth0)  |      | PERSISTENT | 0         |
+-----------------------------------------------------+---------+-----------------------+------+------------+-----------+
| juju-97fa390d-96ad-44df-8b59-e15fdcfc636b-machine-3 | RUNNING | 10.178.150.29 (eth0)  |      | PERSISTENT | 0         |
+-----------------------------------------------------+---------+-----------------------+------+------------+-----------+
| juju-97fa390d-96ad-44df-8b59-e15fdcfc636b-machine-4 | RUNNING | 10.178.150.202 (eth0) |      | PERSISTENT | 0         |
+-----------------------------------------------------+---------+-----------------------+------+------------+-----------+
| juju-97fa390d-96ad-44df-8b59-e15fdcfc636b-machine-5 | RUNNING | 10.178.150.214 (eth0) |      | PERSISTENT | 0         |
+-----------------------------------------------------+---------+-----------------------+------+------------+-----------+

几分钟后,所有的服务应该部署完毕并运行了:

stgraber@dakara:~$ juju status
[Services] 
NAME STATUS EXPOSED CHARM 
api unknown false cs:~hp-discover/trusty/node-app-1 
mongodb unknown false cs:trusty/mongodb-3 
nginx unknown false cs:~hp-discover/trusty/nginx-4 
nginx-proxy unknown false cs:~hp-discover/trusty/nginx-proxy-3 
website false cs:~hp-discover/trusty/website-3 

[Relations] 
SERVICE1 SERVICE2 RELATION TYPE 
api mongodb database regular 
api nginx-proxy website regular 
mongodb mongodb replica-set peer 
nginx website nginx-engine subordinate 
nginx-proxy website website regular 

[Units] 
ID WORKLOAD-STATUS JUJU-STATUS VERSION MACHINE PORTS PUBLIC-ADDRESS MESSAGE 
api/0 unknown idle 2.0-beta7 2 8000/tcp 10.178.150.98 
mongodb/0 unknown idle 2.0-beta7 3 27017/tcp,27019/tcp,27021/tcp,28017/tcp 10.178.150.29 
nginx-proxy/0 unknown idle 2.0-beta7 5 80/tcp 10.178.150.214 
nginx/0 unknown idle 2.0-beta7 4 10.178.150.202 
 website/0 unknown idle 2.0-beta7 10.178.150.202 

[Machines] 
ID STATE DNS INS-ID SERIES AZ 
2 started 10.178.150.98 juju-97fa390d-96ad-44df-8b59-e15fdcfc636b-machine-2 trusty 
3 started 10.178.150.29 juju-97fa390d-96ad-44df-8b59-e15fdcfc636b-machine-3 trusty 
4 started 10.178.150.202 juju-97fa390d-96ad-44df-8b59-e15fdcfc636b-machine-4 trusty 
5 started 10.178.150.214 juju-97fa390d-96ad-44df-8b59-e15fdcfc636b-machine-5 trusty

这时你就可以在 80 端口访问 http://10.178.150.214,并且会看到一个 Juju 学院页面。

Juju Academy web service

清理所有东西

如果你不需要 Juju 创建的容器并且不在乎下次需要再次启动,最简单的方法是:

stgraber@dakara:~$ juju destroy-controller test --destroy-all-models
WARNING! This command will destroy the "local.test" controller.
This includes all machines, services, data and other resources.

Continue [y/N]? y
Destroying controller
Waiting for hosted model resources to be reclaimed
Waiting on 1 model, 4 machines, 5 services
Waiting on 1 model, 4 machines, 5 services
Waiting on 1 model, 4 machines, 5 services
Waiting on 1 model, 4 machines, 5 services
Waiting on 1 model, 4 machines, 5 services
Waiting on 1 model, 4 machines, 5 services
Waiting on 1 model, 4 machines
Waiting on 1 model, 4 machines
Waiting on 1 model, 4 machines
Waiting on 1 model, 4 machines
Waiting on 1 model, 4 machines
Waiting on 1 model, 4 machines
Waiting on 1 model, 2 machines
Waiting on 1 model
Waiting on 1 model
All hosted models reclaimed, cleaning up controller machines

我们用下面的方式确认:

stgraber@dakara:~$ lxc list juju-
+------+-------+------+------+------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+-------+------+------+------+-----------+

总结

Juju 2.0 内置的 LXD 支持使得可以用一种非常干净的方式来测试各种服务。

在 Juju charm store 中有很多预制的“组合”可以用来部署,甚至可以用多个“charm”来组合你想要的架构。

Juju 与 LXD 是一个完美的解决方案,从一个小的 Web 服务到大规模的基础设施都可以简单开发,这些都在你自己的机器上,并且不会在你的系统上造成混乱!

额外信息

Juju 网站: http://www.ubuntu.com/cloud/juju

Juju charm store : https://jujucharms.com

LXD 的主站在: https://linuxcontainers.org/lxd

LXD 的 GitHub 仓库: https://github.com/lxc/lxd

LXD 的邮件列表: https://lists.linuxcontainers.org

LXD 的 IRC 频道: #lxcontainers on irc.freenode.net

如果你不想或者不能在你的机器上安装 LXD ,你可以在 web 上试试在线版的 LXD


作者简介:我是 Stéphane Graber。我是 LXC 和 LXD 项目的领导者,目前在加拿大魁北克蒙特利尔的家所在的Canonical 有限公司担任 LXD 的技术主管。


via: https://www.stgraber.org/2016/06/06/lxd-2-0-lxd-and-juju-1012/

作者:Stéphane Graber 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

这是 LXD 2.0 系列介绍文章的第九篇。

  1. LXD 入门
  2. 安装与配置
  3. 你的第一个 LXD 容器
  4. 资源控制
  5. 镜像管理
  6. 远程主机及容器迁移
  7. LXD 中的 Docker
  8. LXD 中的 LXD
  9. 实时迁移
  10. LXD 和 Juju
  11. LXD 和 OpenStack
  12. 调试,及给 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
├── fs-52.img
├── fs-95.img
├── fs-96.img
├── fs-97.img
├── fs-98.img
├── ids-101.img
├── ids-113.img
├── ids-122.img
├── ids-183.img
├── ids-1.img
├── ids-245.img
├── ids-246.img
├── ids-50.img
├── ids-52.img
├── ids-95.img
├── ids-96.img
├── ids-97.img
├── ids-98.img
├── ifaddr-9.img
├── inetsk.img
├── inotify.img
├── inventory.img
├── ip6tables-9.img
├── ipcns-var-10.img
├── iptables-9.img
├── mm-101.img
├── mm-113.img
├── mm-122.img
├── mm-183.img
├── mm-1.img
├── mm-245.img
├── mm-246.img
├── mm-50.img
├── mm-52.img
├── mm-95.img
├── mm-96.img
├── mm-97.img
├── mm-98.img
├── mountpoints-12.img
├── netdev-9.img
├── netlinksk.img
├── netns-9.img
├── netns-ct-9.img
├── netns-exp-9.img
├── packetsk.img
├── pagemap-101.img
├── pagemap-113.img
├── pagemap-122.img
├── pagemap-183.img
├── pagemap-1.img
├── pagemap-245.img
├── pagemap-246.img
├── pagemap-50.img
├── pagemap-52.img
├── pagemap-95.img
├── pagemap-96.img
├── pagemap-97.img
├── pagemap-98.img
├── pages-10.img
├── pages-11.img
├── pages-12.img
├── pages-13.img
├── pages-1.img
├── pages-2.img
├── pages-3.img
├── pages-4.img
├── pages-5.img
├── pages-6.img
├── pages-7.img
├── pages-8.img
├── pages-9.img
├── pipes-data.img
├── pipes.img
├── pstree.img
├── reg-files.img
├── remap-fpath.img
├── route6-9.img
├── route-9.img
├── rule-9.img
├── seccomp.img
├── sigacts-101.img
├── sigacts-113.img
├── sigacts-122.img
├── sigacts-183.img
├── sigacts-1.img
├── sigacts-245.img
├── sigacts-246.img
├── sigacts-50.img
├── sigacts-52.img
├── sigacts-95.img
├── sigacts-96.img
├── sigacts-97.img
├── sigacts-98.img
├── signalfd.img
├── stats-dump
├── timerfd.img
├── tmpfs-dev-104.tar.gz.img
├── tmpfs-dev-109.tar.gz.img
├── tmpfs-dev-110.tar.gz.img
├── tmpfs-dev-112.tar.gz.img
├── tmpfs-dev-114.tar.gz.img
├── tty.info
├── unixsk.img
├── userns-13.img
└── utsns-11.img

0 directories, 154 files

还原容器也很简单:

stgraber@dakara:~$ lxc start c1

实时迁移

实时迁移基本上与上面的有状态快照的停止/启动相同,除了容器目录和配置被移动到另一台机器上。

stgraber@dakara:~$ lxc list c1
+------+---------+-----------------------+----------------------------------------------+------------+-----------+
| NAME |  STATE  |          IPV4         |                     IPV6                     |    TYPE    | SNAPSHOTS |
+------+---------+-----------------------+----------------------------------------------+------------+-----------+
| c1   | RUNNING | 10.178.150.197 (eth0) | 2001:470:b368:4242:216:3eff:fe19:27b0 (eth0) | PERSISTENT | 2         |
+------+---------+-----------------------+----------------------------------------------+------------+-----------+

stgraber@dakara:~$ lxc list s-tollana:
+------+-------+------+------+------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+-------+------+------+------+-----------+

stgraber@dakara:~$ lxc move c1 s-tollana:

stgraber@dakara:~$ lxc list c1
+------+-------+------+------+------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+-------+------+------+------+-----------+

stgraber@dakara:~$ lxc list s-tollana:
+------+---------+-----------------------+----------------------------------------------+------------+-----------+
| NAME |  STATE  |          IPV4         |                     IPV6                     |    TYPE    | SNAPSHOTS |
+------+---------+-----------------------+----------------------------------------------+------------+-----------+
| c1   | RUNNING | 10.178.150.197 (eth0) | 2001:470:b368:4242:216:3eff:fe19:27b0 (eth0) | PERSISTENT | 2         |
+------+---------+-----------------------+----------------------------------------------+------------+-----------+

限制

正如我之前说的,容器的检查点/恢复还是非常新的功能,我们还在努力地开发这个功能、修复已知的问题。我们确实需要更多的人来尝试这个功能,并给我们反馈,但我不建议在生产中使用这个功能。

我们跟踪的问题列表在 Launchpad上

我们估计在带有 CRIU 的 Ubuntu 16.04 上带有几个服务的基本的 Ubuntu 容器能够正常工作。然而在更复杂的容器、使用了设备直通、复杂的网络服务或特殊的存储配置下可能会失败。

要是有问题,CRIU 会尽可能地在转储时失败,而不是在恢复时。在这种情况下,源容器将继续运行,快照或迁移将会失败,并生成一个日志文件用于调试。

在极少数情况下,CRIU 无法恢复容器,在这种情况下,源容器仍然存在但将被停止,并且必须手动重新启动。

发送 bug 报告

我们正在跟踪 Launchpad 上关于 CRIU Ubuntu 软件包的检查点/恢复相关的错误。大多数修复 bug 工作是在上游的 CRIU 或 Linux 内核上进行,但是这种方式我们更容易跟踪。

要提交新的 bug 报告,请看这里。

请务必包括:

  • 你运行的命令和显示给你的错误消息
  • lxc info 的输出(*)
  • lxc info <container name>的输出
  • lxc config show -expanded <container name> 的输出
  • dmesg(*)的输出
  • /proc/self/mountinfo 的输出(*)
  • lxc exec <container name> - cat /proc/self/mountinfo 的输出
  • uname -a(*)的输出
  • /var/log/lxd.log(*)的内容
  • /etc/default/lxd-bridge(*)的内容
  • /var/log/lxd/<container name>/ 的 tarball(*)

如果报告迁移错误,而不是状态快照或有状态停止的错误,请将上面所有含有(*)标记的源与目标主机的信息发来。

额外信息

CRIU 的网站在: https://criu.org

LXD 的主站在: https://linuxcontainers.org/lxd

LXD 的 GitHub 仓库: https://github.com/lxc/lxd

LXD 的邮件列表: https://lists.linuxcontainers.org

LXD 的 IRC 频道: #lxcontainers on irc.freenode.net


作者简介:我是 Stéphane Graber。我是 LXC 和 LXD 项目的领导者,目前在加拿大魁北克蒙特利尔的家所在的Canonical 有限公司担任 LXD 的技术主管。


via: https://stgraber.org/2016/04/25/lxd-2-0-live-migration-912/

作者:Stéphane Graber 译者:geekpi 校对:wxy

本文由 LCTT 组织翻译,Linux中国 荣誉推出