Snap簡介(snap介紹)
他山之石
在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,
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有超過一年的時間沒有更新。在被人點名后一年
后,微軟抓緊更新了幾版??梢姺植际桨l布的管理要比集中式發布管理更難。
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?,F在回退:
#?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小時內刪除侵權內容。