Snap简介(snap介绍

网友投稿 1841 2022-05-30

他山之石

在2011年,Cananical创建Ubuntu Touch项目,要把Ubuntu操作系统扩展

到手机和平板的时候,试图解决如下问题:

应用商店连接应用用户和应用开发者,

应用有限使用操作系统资源,应用之间隔离,

应用安全安装卸载升级回退。

这几个问题用已有的Advanced Package Tool方案(Apt)不能很好解决。比如

应用用户和应用开发者之间,隔着一个发行版开发商。

发行版

Linux最初并无发行版,Linux用户从开发者那里得到源码,自己编译,自己安装,

用户和开发者的界限模糊。后来发行版进来,承担了编译打包的工作,用户只需

安装就好了。

如今Linux有300+发行版。比如深度发行版,这是它的谱系:

debian     └── knoppix         └── morphix             └── hiwix hiweed                 └── deepin

略去深度血缘更近的不说,deepin祖上是debian。

欧拉发行版的谱系:

redhat └── redhat enterprise     └── centos         └── euleros

这些大小不一的发行版,犹如丛林一般,让人迷茫。应用从开发出来到用户使用,

就不得不穿越这丛林。

这事实上也造成了Linux应用生态的分裂。

应用打包格式

Linux应用打包有两大派系,rpm和deb。

围绕rpm包格式,有yum包管理,dnf包管理。deb包格式有apt包管理,aptitude

包管理。

发行版决定使用使用什么包格式,什么包管理。

包管理

包有版本,包和包之间有版本依赖,版本排斥,包安装可能失败,包卸载可能有

残留,包升级可能有种种不测。这像极了一片沼泽地,稍不留意就会陷进去。

举个例子。Python为规避发行版丛林,提出了自己的包管理pip,不想陷入了包

版本沼泽地。为走出沼泽地,提出virtualenv思想,把所有依赖的pip包打到一

处。一些开发者就用virtualenv方案打出python大包,做成rpm或deb包,重归丛

林。

灵魂宝石

于是Ubuntu Touch团队专门创建了Click项目来管理手机应用。

2017年,Ubuntu Touch不敌苹果和安卓的竞争,宣告失败。但Click项目存活

下来,改名Snappy,转身管理更广泛意义上的应用。也许Snappy这个名字听

起来太卡哇伊了,Snappy进一步改名Snap。

要知道灭霸打一个响指,可是灭掉了半个宇宙的人口。

还不是因为灭霸集齐了宇宙原石?

钢铁侠拼命打一个响指,灭掉的人们才能回来。

可娜塔莎永远也回不来了。

因为灵魂宝石。

Snap得到灵魂宝石:

+-----------+       +------------+      +------------+ | Developer +------>| Snapcraft  +----->| Snap Store | +-----------+       +------------+      +-----+------+                                               | update                                                    v        +-----------+       +------------+      +------------+ | End User  +------>|   Snap     +----->|   Snapd    | +-----------+       +-----+------+      +-----+------+                           | containerize      |                                  v                   |                            +------------+            |                            |   Snaps    |<-----------+ manage                     +------------+                                                               manage:                                     snap install lxd                         snap list lxd                            snap refresh lxd                         snap revert lxd                          snap remove lxd                       containerize:                                lxd --> /usr/bin/snap     /usr/bin/snap --> lxd snap

Ubuntu Touch Click永远也回不来了。

Snap Store

Snap Store,应用商店,允许应用开发者把自己开发的应用发布给用户。

去发行版

注意这和传统的应用仓库如APT或YUM有重要区别。传统的应用仓库,应用开发者

开发应用,发行版维护者打包上传应用到应用仓库之后,用户才能从应用仓库获

取应用。而Snap Sotre去掉了发行版维护者这个角色,直接让应用开发者发布应

用到应用商店供用户使用。

持续集成

那谁来打包呢?Snap Store引入自动持续集成,应用开发者完成Snap应用开发,

后面测试、打包、病毒扫描、发布都是自动的。Snap应用测试通过后,完成打包,

通过病毒扫描,就进入了发布流程。

发布管道

发布按如下管道依次进行:

edge,

beta,

candidate,

Snap简介(snap介绍)

stable

一般用户可以订阅Snap应用的稳定版。喜欢尝鲜的用户可以订阅Snap应用的beta

版。edge和beta可供开发人员自己测试使用。

以下是snapd应用的发布管道:

# snap info snapd type:         snapd snap-id:      PMrrV4ml8uWuEUDBT8dSGnKUYbevVhc4 tracking:     latest/stable refresh-date: 2 days ago, at 15:03 CST channels:   latest/stable:    2.46.1                    2020-09-16 (9287) 27MB -   latest/candidate: 2.46.1                    2020-09-08 (9287) 27MB -   latest/beta:      2.47~pre1+git733.g799ae88 2020-09-21 (9499) 28MB -   latest/edge:      2.47~pre1+git802.g8d37a7a 2020-09-22 (9517) 28MB - installed:          2.46.1                               (9287) 27MB snapd

可以看到edge 2.47~pre1+git802.g8d37a7a发布于2020-09-22,最新稳定版

2.46.1发布于2020-09-16。实际上早在2020-09-08你就可以从candidate得

到版本2.46.1进行尝试。

一次打包

开发者把应用打包为Snap应用有巨大的好处:他不需要为每个Linux发行版打包

应用了。Snap应用可以运行在几乎所有的Linux发行版。Snap应用做到了与发行

版无关。

可信开发者

分布式发布

由于Snap应用由开发者自己维护,应用的质量和及时更新并不能得到保证。以微

软的Skype为例,在Snap Store有超过一年的时间没有更新。在被人点名后一年

后,微软抓紧更新了几版。可见分布式发布的管理要比集中式发布管理更难。

Snap Store当前只有一个,由Cananical所有。Snap Store应用商店只是

门面,背后有一个完善的持续集成,发布系统。Snap Store的唯一性,也使

Snap应用的集中化管理成为可能。但要注意,Snap应用的发布,是分布式的。

Snap可以脱离Snap Store使用。比如可以从Snap Store下载[LXD]:

# snap download lxd Fetching snap "lxd" Fetching assertions for "lxd" Install the snap with:    snap ack lxd_17329.assert    snap install lxd_17329.snap

得到lxd_17329.assert和lxd_17329.snap后,就可以脱离Snap Store使用

了。

闭源

Snap Store的是闭源的。这一点饱受批评。Snap Store的闭源与

Cananical的开源做派格格不入。我想一个原因,是Snap Store开源不易,

撇开Snap Store的API不说(其实Snap Store的API已经事实上开源),

Snap Store背后有庞大的持续集成和发布系统,代码庞杂,很难开源。

另外Cananical也不太想让Snap Store开源,想对Snap应用施加更多管控。

Bret Barker曾经发布过一个Noise Snap Store,在README里他写,为避免

混淆删除了Noise Snap Store的代码。

代码其实没删:

# git clone https://github.com/noise/snapstore # cd snapstore # git checkout HEAD^^^ # ls #=> LICENSE  README.md  files  requirements.txt  snapcraft.yaml  store-wrapper.sh  store.py

往上跳3个Commit,基本功能是可以工作的。

通用包格式

和传统Linux包不同,Snap应用运行不依赖具体Linux发行版。同一个Snap应用可

以运行在Ubuntu 18.04,可以运行在CentOS 7.9, 可以运行在Fedora,可以运行

在欧拉2.09,可以运行在UOS 20.0,甚至可以运行在Windows WSL2。

SquashFS压缩

Snap包文件是压缩SuqashFS系统格式。以上节下载的lxd_17329.snap为例,可

以这样解包:

# unsquashfs lxd_17329.snap #=> Parallel unsquashfs: Using 8 processors 1418 inodes (4425 blocks) to write [================================================\] 4425/4425 100% created 1272 files created 122 directories created 146 symlinks created 0 devices created 0 fifos

文件解在当前squashfs-root目录:

# tree squashfs-root #=> squashfs-root ├── bin ├── etc ├── lib ├── lxc ├── lxcfs ├── meta │   ├── hooks │   │   ├── configure │   │   ├── install │   │   └── remove │   └── snap.yaml ├── share ├── snap ├── usr ├── wrappers ├── zfs-0.6 ├── zfs-0.7 └── zfs-0.8

基础镜像

其中squashfs-root/meta/snap.yaml是此snap的描述文件:

name: lxd version: '4.6' summary: LXD - the container lightervisor description: |-   LXD is a container manager for system containers... architectures: - arm64 assumes: - command-chain - snapd2.39 base: core18 confinement: strict grade: stable

这行base: core18,表明snap lxd基于snap core18。那core18是啥呢?

可以download下来看看:

# snap download core18 # unsquashfs core18_1888.snap #=> Parallel unsquashfs: Using 8 processors 9741 inodes (10104 blocks) to write [===========================================\] 10104/10104 100% created 7517 files created 1238 directories created 2011 symlinks created 4 devices created 0 fifos # cat squashfs-root/etc/os-release #=> NAME="Ubuntu Core" VERSION="18" ID=ubuntu-core PRETTY_NAME="Ubuntu Core 18" VERSION_ID="18"

可以看到core18其实就是Ubuntu Core 18。除了core18,还有core和

core20。其中core是Ubuntu Core 16, core20是Ubuntu Core 20。因此

你知道Snap应用的跨Linux发行版是如何实现的了吧?Snap应用运行在以Ubuntu

为核心的容器里,与各个发行版做到了解耦。因此Snap应用的开发者很开心了,

只需保证自己应用在[Ubuntu Core]欢快运行即可,比如考虑其他发行版的适配。

Snap应用的用户也开心,装Snap应用的时候不必考虑自己的Linux发行版是否支

持。Ubuntu发行版也很开心,自己用Snap应用统一了世界。而Linux其他发行版

就很悲催了。Snap应用统一Linux应用的时候,除Ubuntu之外的发行版存在还有

什么意义?

Snap打包

回到Snap包格式。Snap包格式是SquashFS的xz压缩格式,可以这样打包:

# mksquashfs squashfs-root core.snap -comp xz #=> Parallel mksquashfs: Using 8 processors Creating 4.0 filesystem on core.snap, block size 131072. [===============================================/] 8089/8089 100% Exportable Squashfs 4.0 filesystem, xz compressed, data block size 131072 Filesystem size 44670.64 Kbytes (43.62 Mbytes)         28.27% of uncompressed filesystem size (158015.07 Kbytes) Inode table size 90980 bytes (88.85 Kbytes)         24.35% of uncompressed inode table size (373578 bytes) Directory table size 98378 bytes (96.07 Kbytes)         41.36% of uncompressed directory table size (237842 bytes) Number of duplicate files found 166 Number of inodes 10770 Number of files 7517 Number of fragments 631 Number of symbolic links  2011 Number of device nodes 4 Number of fifo nodes 0 Number of socket nodes 0 Number of directories 1238 Number of ids (unique uids + gids) 6 Number of uids 1         root (0) Number of gids 6         root (0)         shadow (42)         crontab (105)         tty (5)         systemd-network (103)         mail (8)

广泛应用支持

和其他被架空发行版推出的应对包管理(如Flatpak)不同,Snap应用支持桌面应

用、服务端应用、IoT应用甚至诸如打印机驱动等的系统应用。代价是Snap只能

运行在以Systemd为初始化系统的发行版。还好Systemd已成为初始化系统的事实

标准。比如Snap在Windows WSL上运行不好,就是与WSL对Systemd的支持不好所

致。Snap在Windows WSL2上运行是可以的。

Snap运行时

Snap应用运行在以Ubuntu Core为基础的可配置容器里。容器执行安全策略,用

户可以通过容器这一层给应用权限,访问特定资源。

下面以lxd为例分析snap如何实现。

我们知道lxd基于core18,lxd和core18的文件系统挂载如下:

# snap list #=> Name    Version    Rev    Tracking       Publisher   Notes core    16-2.46.1  9994   latest/stable  canonical✓  core core18  20200724   1888   latest/stable  canonical✓  base lxd     4.6        17329  latest/stable  canonical✓  - # mount | grep .snap #=> /var/lib/snapd/snaps/core18_1888.snap on /snap/core18/1888 type squashfs (ro,nodev,relatime,x-gdu.hide) /var/lib/snapd/snaps/lxd_17329.snap on /snap/lxd/17329 type squashfs (ro,nodev,relatime,x-gdu.hide)

lxd对外提供两个命令lxd和lxc:

# ls -l /snap/bin/{lxd,lxc,lxd.lxc} #=> lrwxrwxrwx 1 root root 13 9月  22 02:09 lxd -> /usr/bin/snap lrwxrwxrwx 1 root root  7 9月  22 02:09 lxc -> lxd.lxc lrwxrwxrwx 1 root root 13 9月  22 02:09 lxd.lxc -> /usr/bin/snap

其中lxd与包同名,可以直接指向/usr/bin/snap,lxc先指向lxd.lxc,

然后lxd.lxc再指向/usr/bin/snap。

当我们运行lxd命令的时候,/usr/bin/snap被调用。/usr/bin/snap会先

看看自己叫什么名字,名字里有没有点。以lxd为例,里面没点,因此

/usr/bin/snap知道要去调用snaplxd里的lxd命令。以lxc为例,

lxd.lxc里有点,因此/usr/bin/snap知道调用snap lxd里的lxc命令。

无论那种情况,/usr/bin/snap都知道了snap包名。之后它就可以去读snap包

里的meta/snap.yaml文件了。meta/snap.yaml里有对这个snap的描述,包括

基于core¸ core18还是core20。于是/usr/bin/snap可以确定snap的基

础镜像。基础镜像确定后,/usr/bin/snap准备容器的文件系统,然后继续根

据meta/snap.yaml描述,应用资源使用策略,这时候AppArmor会派上用场。

一切准备完毕,最终在容器里调用用户所要运行的命令。

Snap运行时对容器技术使用,局限在文件系统命名空间,资源隔离,并不涉及网

络命名空间,用户命名空间等。因此习惯上被叫做Snap沙箱。

Snap沙箱依赖[AppArmor]安全模块。而一些发行版诸如Fedora以SELinux为默认

安全模块。因此Snap对SELinux也有支持。

应用更新

Snap应用更新有两个特色:

自动化,

可回退。

Snapd的坚守

Snap应用由snapd守护进程管理。snapd每天会去Snap Store查本地Snap应

用有没有可用更新,如果有,就把更新拿下来,应用到当前Snap应用上。

自动更新不可关闭

这看起来是个好用的功能,但常被系统管理员诟病。应用是否升级,何时升级应

该是系统管理员的事情,怎么snapd就私自定了?因此系统管理员们对

snapd大吐口水,要求禁止自动更新这个功能,但snapd不为所动,固执地认

为自己可做。长期的吐槽最终得到了两个改进:

自动更新不可关闭,但用户可以推迟更新,最长可推迟到60天后,

自动更新不可关闭,但开发者可以不更新一个发布管道,把更新发布到新的

发布管道。

以lxd为例,对自动更新的第2点做个说明:

# snap info lxd #=> ... channels:   latest/stable:    4.6         2020-09-21 (17329) 63MB -   latest/candidate: 4.6         2020-09-22 (17382) 63MB -   latest/beta:      ↑   latest/edge:      git-f1a7f8a 2020-09-23 (17390) 63MB -   4.6/stable:       4.6         2020-09-21 (17329) 63MB -   4.6/candidate:    4.6         2020-09-22 (17382) 63MB -   4.6/beta:         ↑   4.6/edge:         ↑   4.5/stable:       4.5         2020-09-18 (17303) 63MB -   4.5/candidate:    4.5         2020-09-17 (17283) 63MB -   4.5/beta:         ↑   4.5/edge:         ↑   4.4/stable:       4.4         2020-08-19 (16946) 66MB -   4.4/candidate:    4.4         2020-08-19 (16946) 66MB - ...

比如用户订阅4.5/stable发布管道,开发者把最新的更新发布到

4.6/stable(其实也就是latest/stable管道),那4.5/stable就基本停

止更新了。当然开发者也可以把一个安全补丁回溯到4.5/stable,这时候订阅

4.5/stable的用户又被迫更新了。

总之snap认为自动更新非有不可,是原则问题,绝不改变。

可回退

下面说说更新可回退。snap应用的安装非常简单,其实就是把squashfs文件挂

载一下,卸载是就是文件系统去载。以lxd为例:

snap list lxd #=> Name  Version  Rev    Tracking       Publisher   Notes lxd   4.6      17329  latest/stable  canonical✓  - # ls -l /var/snap/lxd/ 总用量 12 drwxr-xr-x 2 root root 4096 8月  29 18:30 17303 drwxr-xr-x 2 root root 4096 8月  29 18:30 17329 drwxr-xr-x 7 root root 4096 9月  22 02:09 common lrwxrwxrwx 1 root root    5 9月  22 02:09 current -> 17329

可看到current指向17329。现在回退:

# snap revert lxd lxd reverted to 4.5 # ls -l /var/snap/lxd drwxr-xr-x 2 root root 4096 8月  29 18:30 17303 drwxr-xr-x 2 root root 4096 8月  29 18:30 17329 drwxr-xr-x 7 root root 4096 9月  23 18:25 common lrwxrwxrwx 1 root root    5 9月  23 18:25 current -> 17303

可看到current指向了17303。snapd所做的就是改下指向,重启一下而已。

再更新回来:

# snap refresh lxd #=> lxd 4.6 from Canonical✓ refreshed # ls -l /var/snap/lxd 总用量 16 drwxr-xr-x 2 root root 4096 8月  29 18:30 17303 drwxr-xr-x 2 root root 4096 8月  29 18:30 17329 drwxr-xr-x 2 root root 4096 8月  29 18:30 17329.old drwxr-xr-x 7 root root 4096 9月  23 18:29 common lrwxrwxrwx 1 root root    5 9月  23 18:29 current -> 17329

变更与任务

这也是snap坚持自动更新的原因,因为更新过程简单,几乎不会出错。我们看

看每一步都做了什么:

# snap changes #=> ID   Status  Spawn               Ready               Summary 19   Done    18:25 CST  18:25 CST  Revert "lxd" snap 20   Done    18:29 CST  18:29 CST  Refresh "lxd" snap # snap tasks 19 Status  Spawn               Ready               Summary Done    18:25 CST  18:25 CST  Ensure prerequisites for "lxd" are available Done    18:25 CST  18:25 CST  Prepare snap "" (17303) Done    18:25 CST  18:25 CST  Stop snap "lxd" services Done    18:25 CST  18:25 CST  Remove aliases for snap "lxd" Done    18:25 CST  18:25 CST  Make current revision for snap "lxd" unavailable Done    18:25 CST  18:25 CST  Setup snap "lxd" (17303) security profiles Done    18:25 CST  18:25 CST  Make snap "lxd" (17303) available to the system Done    18:25 CST  18:25 CST  Automatically connect eligible plugs and slots of snap "lxd" Done    18:25 CST  18:25 CST  Set automatic aliases for snap "lxd" Done    18:25 CST  18:25 CST  Setup snap "lxd" aliases Done    18:25 CST  18:25 CST  Start snap "lxd" (17303) services Done    18:25 CST  18:25 CST  Run configure hook of "lxd" snap if present Done    18:25 CST  18:25 CST  Run health check of "lxd" snap # snap tasks 20 Status  Spawn               Ready               Summary Done    18:29 CST  18:29 CST  Ensure prerequisites for "lxd" are available Done    18:29 CST  18:29 CST  Prepare snap "" (17329) Done    18:29 CST  18:29 CST  Run pre-refresh hook of "lxd" snap if present Done    18:29 CST  18:29 CST  Stop snap "lxd" services Done    18:29 CST  18:29 CST  Remove aliases for snap "lxd" Done    18:29 CST  18:29 CST  Make current revision for snap "lxd" unavailable Done    18:29 CST  18:29 CST  Copy snap "lxd" data Done    18:29 CST  18:29 CST  Setup snap "lxd" (17329) security profiles Done    18:29 CST  18:29 CST  Make snap "lxd" (17329) available to the system Done    18:29 CST  18:29 CST  Automatically connect eligible plugs and slots of snap "lxd" Done    18:29 CST  18:29 CST  Set automatic aliases for snap "lxd" Done    18:29 CST  18:29 CST  Setup snap "lxd" aliases Done    18:29 CST  18:29 CST  Run post-refresh hook of "lxd" snap if present Done    18:29 CST  18:29 CST  Start snap "lxd" (17329) services Done    18:29 CST  18:29 CST  Clean up "lxd" (17329) install Done    18:29 CST  18:29 CST  Run configure hook of "lxd" snap if present Done    18:29 CST  18:29 CST  Run health check of "lxd" snap Done    18:29 CST  18:29 CST  Consider re-refresh of "lxd"

注意每次更新都被定义为一个变更(change),一个变更由多个任务(task)组

成。变更有原子性,是说如果一个变更里的某个任务失败,那整个变更会回退。

这是理想的情况。理想很丰满,现实很骨感,世界上还没有系统可以真正做到。

Snap开发

Snap的开发有一套工具,Snapcraft。Snapcraft支持大量构建工具以及编程语言,比如Go, Java, JavaScript,

Python, C/C++和Rust等。它也支持从多种源导入源码,比如git等。

Multipass

这套工具在各个Linux发行版,macOS,甚至Windows都可以正常工作。这很神奇

不是?背后的实现在Ubuntu的一个神奇的工具:Multipass。Multipass是一

个虚拟化工具,可以高效运行在Linux,MacOS以及Windows上。Snapcraft实际运

行在Multipass虚拟出来的Ubuntu虚机上。

开发

在Linux上,Snapcraft也可运行在LXD系统容器上。

Snapcraft在Snap Store里也有:

# snap install snapcraft --classic

之后可以按Snapcraft文档开发。

发布

把带上上传到Github,要在

snapcraft.io注册开发者账号,添加应用到Snap

Store。

这样发布流程就打通了。

云原生 Ubuntu 软件开发 容器

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:开源|性能优化利器:数据库审核平台Themis的选型与实践
下一篇:因为不会创建云服务器,我被实习生摆了一道
相关文章