<a target="_blank"></a>
如果你以前使用過 lxc,你可能還記得那些 lxc “模闆”,基本上都是導出一個容器檔案系統以及一點配置的 shell 腳本。
大多數模闆是通過在本機上執行一個完整的發行版自舉來生成該檔案系統。這可能需要相當長的時間,并且無法在所有的發行版上可用,另外可能需要大量的網絡帶寬。
回到 lxc 1.0,我寫了一個“下載下傳”模闆,它允許使用者下載下傳預先打包的容器鏡像,用模闆腳本在中央伺服器上生成,接着高度壓縮、簽名并通過 https 分發。我們很多使用者從舊版的容器生成方式切換到了使用這種新的、更快更可靠的建立容器的方式。
使用 lxd,我們通過全面的基于鏡像的工作流程向前邁進了一步。所有容器都是從鏡像建立的,我們在 lxd 中具有進階鏡像緩存和預加載支援,以使鏡像存儲保持最新。
在更深入了解鏡像格式之前,讓我們快速了解下 lxd 可以讓你做些什麼。
所有的容器都是由鏡像建立的。鏡像可以來自一台遠端伺服器并使用它的完整 hash、短 hash 或者别名拉取下來,但是最終每個 lxd 容器都是建立自一個本地鏡像。
這有個例子:
<code>lxc launch ubuntu:14.04 c1</code>
<code>lxc launch ubuntu:75182b1241be475a64e68a518ce853e800e9b50397d2f152816c24f038c94d6e c2</code>
<code>lxc launch ubuntu:75182b1241be c3</code>
所有這些引用相同的遠端鏡像(在寫這篇文章時),在第一次運作這些指令其中之一時,遠端鏡像将作為緩存鏡像導入本地 lxd 鏡像存儲,接着從其建立容器。
下一次運作其中一個指令時,lxd 将隻檢查鏡像是否仍然是最新的(當不是由指紋引用時),如果是,它将建立容器而不下載下傳任何東西。
現在鏡像被緩存在本地鏡像存儲中,你也可以從那裡啟動它,甚至不檢查它是否是最新的:
<code>lxc launch 75182b1241be c4</code>
最後,如果你有個名為“myimage”的本地鏡像,你可以:
<code>lxc launch my-image c5</code>
如果你想複制遠端的某個鏡像到你本地鏡像存儲,但不立即從它建立一個容器,你可以使用<code>lxc image copy</code>指令。它可以讓你調整一些鏡像标志,比如:
<code>lxc image copy ubuntu:14.04 local:</code>
這隻是簡單地複制一個遠端鏡像到本地存儲。
如果您想要通過比記住其指紋更容易的方式來記住你引用的鏡像副本,則可以在複制時添加别名:
<code>lxc image copy ubuntu:12.04 local: --alias old-ubuntu</code>
<code>lxc launch old-ubuntu c6</code>
如果你想要使用源伺服器上設定的别名,你可以要求 lxd 複制下來:
<code>lxc image copy ubuntu:15.10 local: --copy-aliases</code>
<code>lxc launch 15.10 c7</code>
上面的副本都是一次性拷貝,也就是複制遠端鏡像的目前版本到本地鏡像存儲中。如果你想要 lxd 保持鏡像最新,就像它在緩存中存儲的那樣,你需要使用 <code>–auto-update</code> 标志:
<code>lxc image copy images:gentoo/current/amd64 local: --alias gentoo --auto-update</code>
如果某人給你提供了一個單獨的 tarball,你可以用下面的指令導入:
<code>lxc image import <tarball></code>
如果你想在導入時設定一個别名,你可以這麼做:
<code>lxc image import <tarball> --alias random-image</code>
現在如果你被給了兩個 tarball,要識别哪個是含有 lxd 中繼資料的。通常可以通過 tarball 的名稱來識别,如果不行就選擇最小的那個,中繼資料 tarball 包是很小的。 然後将它們一起導入:
<code>lxc image import <metadata tarball> <rootfs tarball></code>
<code>lxc image import</code> 也可以與指定的 url 一起使用。如果你的一台 https web 伺服器的某個路徑中有<code>lxd-image-url</code> 和 <code>lxd-image-hash</code> 的标頭設定,那麼 lxd 就會把這個鏡像拉到鏡像存儲中。
可以參照例子這麼做:
<code>lxc image import https://dl.stgraber.org/lxd --alias busybox-amd64</code>
當拉取鏡像時,lxd 還會設定一些标頭,遠端伺服器可以檢查它們以傳回适當的鏡像。 它們是 <code>lxd-server-architectures</code> 和 <code>lxd-server-version</code>。
這相當于一個簡陋的鏡像伺服器。 它可以通過任何靜态 web 伺服器提供一中使用者友好的導入鏡像的方式。
現在我們本地已經有一些鏡像了,讓我們瞧瞧可以做些什麼。我們已經介紹了最主要的部分,可以從它們來建立容器,但是你還可以在本地鏡像存儲上做更多。
要列出所有的鏡像,運作 <code>lxc image list</code>:
<code>stgraber@dakara:~$ lxc image list</code>
<code>+---------------+--------------+--------+------------------------------------------------------+--------+----------+------------------------------+</code>
<code>| alias | fingerprint | public | description | arch | size | upload date |</code>
<code>| alpine-32 | 6d9c131efab3 | yes | alpine edge (i386) (20160329_23:52) | i686 | 2.50mb | mar 30, 2016 at 4:36am (utc) |</code>
<code>| busybox-amd64 | 74186c79ca2f | no | busybox x86_64 | x86_64 | 0.79mb | mar 30, 2016 at 4:33am (utc) |</code>
<code>| gentoo | 1a134c5951e0 | no | gentoo current (amd64) (20160329_14:12) | x86_64 | 232.50mb | mar 30, 2016 at 4:34am (utc) |</code>
<code>| my-image | c9b6e738fae7 | no | scientific linux 6 x86_64 (default) (20160215_02:36) | x86_64 | 625.34mb | mar 2, 2016 at 4:56am (utc) |</code>
<code>| old-ubuntu | 4d558b08f22f | no | ubuntu 12.04 lts amd64 (release) (20160315) | x86_64 | 155.09mb | mar 30, 2016 at 4:30am (utc) |</code>
<code>| w (11 more) | d3703a994910 | no | ubuntu 15.10 amd64 (release) (20160315) | x86_64 | 153.35mb | mar 30, 2016 at 4:31am (utc) |</code>
<code>| | 75182b1241be | no | ubuntu 14.04 lts amd64 (release) (20160314) | x86_64 | 118.17mb | mar 30, 2016 at 4:27am (utc) |</code>
你可以通過别名或者指紋來過濾:
<code>stgraber@dakara:~$ lxc image list amd64</code>
<code>+---------------+--------------+--------+-----------------------------------------+--------+----------+------------------------------+</code>
<code>| alias | fingerprint | public | description | arch | size | upload date |</code>
<code>| busybox-amd64 | 74186c79ca2f | no | busybox x86_64 | x86_64 | 0.79mb | mar 30, 2016 at 4:33am (utc) |</code>
<code>| w (11 more) | d3703a994910 | no | ubuntu 15.10 amd64 (release) (20160315) | x86_64 | 153.35mb | mar 30, 2016 at 4:31am (utc) |</code>
或者指定一個鏡像屬性中的鍵值對來過濾:
<code>stgraber@dakara:~$ lxc image list os=ubuntu</code>
<code>+-------------+--------------+--------+---------------------------------------------+--------+----------+------------------------------+</code>
<code>| alias | fingerprint | public | description | arch | size | upload date |</code>
<code>| old-ubuntu | 4d558b08f22f | no | ubuntu 12.04 lts amd64 (release) (20160315) | x86_64 | 155.09mb | mar 30, 2016 at 4:30am (utc) |</code>
<code>| w (11 more) | d3703a994910 | no | ubuntu 15.10 amd64 (release) (20160315) | x86_64 | 153.35mb | mar 30, 2016 at 4:31am (utc) |</code>
<code>| | 75182b1241be | no | ubuntu 14.04 lts amd64 (release) (20160314) | x86_64 | 118.17mb | mar 30, 2016 at 4:27am (utc) |</code>
要了解鏡像的所有資訊,你可以使用<code>lxc image info</code>:
<code>stgraber@castiana:~$ lxc image info ubuntu</code>
<code>fingerprint: e8a33ec326ae7dd02331bd72f5d22181ba25401480b8e733c247da5950a7d084</code>
<code>size: 139.43mb</code>
<code>architecture: i686</code>
<code>public: no</code>
<code>timestamps:</code>
<code>created: 2016/03/15 00:00 utc</code>
<code>uploaded: 2016/03/16 05:50 utc</code>
<code>expires: 2017/04/26 00:00 utc</code>
<code>properties:</code>
<code>version: 12.04</code>
<code>aliases: 12.04,p,precise</code>
<code>architecture: i386</code>
<code>description: ubuntu 12.04 lts i386 (release) (20160315)</code>
<code>label: release</code>
<code>os: ubuntu</code>
<code>release: precise</code>
<code>serial: 20160315</code>
<code>aliases:</code>
<code>- ubuntu</code>
<code>auto update: enabled</code>
<code>source:</code>
<code>server: https://cloud-images.ubuntu.com/releases</code>
<code>protocol: simplestreams</code>
<code>alias: precise/i386</code>
編輯鏡像的屬性和标志的簡單方法是使用:
<code>lxc image edit <alias or fingerprint></code>
這會打開預設文本編輯器,内容像這樣:
<code>autoupdate: true</code>
<code>aliases: 14.04,default,lts,t,trusty</code>
<code>architecture: amd64</code>
<code>description: ubuntu 14.04 lts amd64 (release) (20160314)</code>
<code>release: trusty</code>
<code>serial: "20160314"</code>
<code>version: "14.04"</code>
<code>public: false</code>
你可以修改任何屬性,打開或者關閉自動更新,或者标記一個鏡像是公共的(後面詳述)。
删除鏡像隻需要運作:
<code>lxc image delete <alias or fingerprint></code>
注意你不必移除緩存對象,它們會在過期後被 lxd 自動移除(預設上,在最後一次使用的 10 天後)。
如果你想得到目前鏡像的 tarball,你可以使用<code>lxc image export</code>,像這樣:
<code>stgraber@dakara:~$ lxc image export old-ubuntu .</code>
<code>output is in .</code>
<code>stgraber@dakara:~$ ls -lh *.tar.xz</code>
<code>-rw------- 1 stgraber domain admins 656 mar 30 00:55 meta-ubuntu-12.04-server-cloudimg-amd64-lxd.tar.xz</code>
<code>-rw------- 1 stgraber domain admins 156m mar 30 00:55 ubuntu-12.04-server-cloudimg-amd64-lxd.tar.xz</code>
lxd 現在支援兩種鏡像布局,unified 或者 split。這兩者都是有效的 lxd 格式,雖然後者在與其他容器或虛拟機一起運作時更容易重用其檔案系統。
lxd 專注于系統容器,不支援任何應用程式容器的“标準”鏡像格式,我們也不打算這麼做。
我們的鏡像很簡單,它們是由容器檔案系統,以及包含了鏡像制作時間、到期時間、什麼架構,以及可選的一堆檔案模闆的中繼資料檔案組成。
unified 鏡像格式是 lxd 在生成鏡像時使用的格式。它們是一個單獨的大型 tarball,包含 <code>rootfs</code> 目錄下的容器檔案系統,在 tarball 根目錄下有 <code>metadata.yaml</code> 檔案,任何模闆都放到 <code>templates</code> 目錄。
tarball 可以用任何方式壓縮(或者不壓縮)。鏡像散列是壓縮後的 tarball 的 sha256 。
這種格式最常用于滾動更新鏡像并已經有了一個壓縮檔案系統 tarball 時。
它們由兩個不同的 tarball 組成,第一個隻包含 lxd 使用的中繼資料, <code>metadata.yaml</code> 檔案在根目錄,任何模闆都在 <code>templates</code> 目錄。
第二個 tarball 隻包含直接位于其根目錄下的容器檔案系統。大多數發行版已經有這樣的 tarball,因為它們常用于引導新機器。 此鏡像格式允許不經修改就重用。
兩個 tarball 都可以壓縮(或者不壓縮),它們可以使用不同的壓縮算法。 鏡像散列是中繼資料的 tarball 和 rootfs 的 tarball 結合的 sha256。
典型的 <code>metadata.yaml</code> 檔案看起來像這樣:
<code>architecture: "i686"</code>
<code>creation_date: 1458040200</code>
<code>description: "ubuntu 12.04 lts server (20160315)"</code>
<code>os: "ubuntu"</code>
<code>release: "precise"</code>
<code>templates:</code>
<code>/var/lib/cloud/seed/nocloud-net/meta-data:</code>
<code>when:</code>
<code>- start</code>
<code>template: cloud-init-meta.tpl</code>
<code>/var/lib/cloud/seed/nocloud-net/user-data:</code>
<code>template: cloud-init-user.tpl</code>
<code>default: |</code>
<code>#cloud-config</code>
<code>{}</code>
<code>/var/lib/cloud/seed/nocloud-net/vendor-data:</code>
<code>template: cloud-init-vendor.tpl</code>
<code>/etc/init/console.override:</code>
<code>- create</code>
<code>template: upstart-override.tpl</code>
<code>/etc/init/tty1.override:</code>
<code>/etc/init/tty2.override:</code>
<code>/etc/init/tty3.override:</code>
<code>/etc/init/tty4.override:</code>
兩個唯一的必填字段是 <code>creation date</code>(unix 紀元時間)和 <code>architecture</code>。 其他都可以保持未設定,鏡像就可以正常地導入。
額外的屬性主要是幫助使用者弄清楚鏡像是什麼。 例如 <code>description</code> 屬性是在 <code>lxc image list</code> 中可見的。 使用者可以使用其它屬性的鍵/值對來搜尋特定鏡像。
相反,這些屬性使用者可以通過 <code>lxc image edit</code>來編輯,<code>creation date</code> 和 <code>architecture</code> 字段是不可變的。
模闆機制允許在容器生命周期中的某一點生成或重新生成容器中的一些檔案。
正如你在上面的例子中看到的,我們使用在 ubuntu 中使用它們來進行 <code>cloud-init</code> 并關閉一些 init 腳本。
lxd 專注于運作完整的 linux 系統,這意味着我們期望大多數使用者隻使用幹淨的發行版鏡像,而不是隻用自己的鏡像。
但是有一些情況下,你有自己的鏡像是有必要的。 例如生産伺服器上的預配置鏡像,或者建構那些我們沒有建構的發行版或者架構的鏡像。
目前使用 lxd 構造鏡像最簡單的方法是将容器變成鏡像。
可以這麼做:
<code>lxc launch ubuntu:14.04 my-container</code>
<code>lxc exec my-container bash</code>
<code><do whatever change you want></code>
<code>lxc publish my-container --alias my-new-image</code>
你甚至可以将一個容器過去的快照變成鏡像:
<code>lxc publish my-container/some-snapshot --alias some-image</code>
建構你自己的鏡像也很簡單。
生成容器檔案系統。這完全取決于你使用的發行版。對于 ubuntu 和 debian,它将用于啟動。
配置容器中該發行版正常工作所需的任何東西(如果需要任何東西)。
制作該容器檔案系統的 tarball,可選擇壓縮它。
根據上面描述的内容寫一個新的 <code>metadata.yaml</code> 檔案。
建立另一個包含 <code>metadata.yaml</code> 檔案的 tarball。
用下面的指令導入這兩個 tarball 作為 lxd 鏡像:<code>lxc image import <metadata tarball> <rootfs tarball> --alias some-name</code>
在一切都正常工作前你可能需要經曆幾次這樣的工作,調整這裡或那裡,可能會添加一些模闆和屬性。
所有 lxd 守護程式都充當鏡像伺服器。除非另有說明,否則加載到鏡像存儲中的所有鏡像都會被标記為私有,是以隻有受信任的用戶端可以檢索這些鏡像,但是如果要建立公共鏡像伺服器,你需要做的是将一些鏡像标記為公開,并確定你的 lxd 守護程序監聽網絡。
最簡單的共享鏡像的方式是運作一個公共的 lxd 守護程序。
你隻要運作:
<code>lxc config set core.https_address "[::]:8443"</code>
遠端使用者就可以添加你的伺服器作為公共伺服器:
<code>lxc remote add <some name> <ip or dns> --public</code>
他們就可以像使用任何預設的鏡像伺服器一樣使用它們。 由于遠端伺服器添加了 <code>-public</code> 選項,是以不需要身份驗證,并且用戶端僅限于使用已标記為 <code>public</code> 的鏡像。
要将鏡像設定成公共的,隻需使用 <code>lxc image edit</code> 編輯它們,并将 <code>public</code> 标志設定為 <code>true</code>。
如上所述,<code>lxc image import</code> 支援從靜态 https 伺服器下載下傳。 基本要求是:
伺服器必須支援具有有效證書的 https、tls 1.2 和 ec 算法。
當通路 <code>lxc image import</code> 提供的 url 時,伺服器必須傳回一個包含 <code>lxd-image-hash</code> 和<code>lxd-image-url</code> 的 http 标頭。
如果你想使它動态化,你可以讓你的伺服器查找 lxd 在請求鏡像時發送的 <code>lxd-server-architectures</code>和 <code>lxd-server-version</code> 的 http 标頭,這可以讓你傳回符合該伺服器架構的正确鏡像。
<code>ubuntu:</code> 和 <code>ubuntu-daily:</code> 遠端伺服器不使用 lxd 協定(<code>images:</code> 使用),而是使用稱為簡單流(simplestreams)的不同協定。
簡單流基本上是一個鏡像伺服器的描述格式,使用 json 來描述産品以及相關産品的檔案清單。
它被各種工具,如 openstack、juju、maas 等用來查找、下載下傳或者做鏡像系統,lxd 将它作為用于鏡像檢索的原生協定。
雖然這的确不是提供 lxd 鏡像的最簡單的方法,但是如果你的鏡像也被其它一些工具使用,那這也許值得考慮一下。
我希望這篇關于如何使用 lxd 管理鏡像以及建構和釋出鏡像文章讓你有所了解。對于以前的 lxc 而言,可以在一組全球分布式系統上得到完全相同的鏡像是一個很大的進步,并且引導了更多可複制性的發展方向。
原文釋出時間為:2017-01-10
本文來自雲栖社群合作夥伴“linux中國”