您好,登錄后才能下訂單哦!
這篇文章主要介紹“CoreOS Rkt容器鏡像怎么制作”,在日常操作中,相信很多人在CoreOS Rkt容器鏡像怎么制作問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”CoreOS Rkt容器鏡像怎么制作”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
使用了開源軟件的人,未必都會有心情仔細閱讀各種開源協議的內容。大多數的使用容器產品用戶,也不見得要對容器規范的內容有很高的興致。
不過,為了更好的理解后面將要介紹到的相關工具,還是不妨稍微深入的了解一些AppC規范約定的內容。其內容歸納起來主要有四個方面,下面依次羅列出來,并與當下的主流容器Docker做一個簡要的對比。
PS:嚴格來說,AppC與AppC Spec兩個詞是有區別的。前者指的是CoreOS的App Container
這個項目,包括規范和相關的工具,而后者特指AppC中約定的容器規范。但在許多地方,特別是翻譯的文章中,經常看到這兩個詞被混用,因此一般也不必太講究了。
本質上說,容器鏡像就是符合特定目錄結構的文件壓縮包。鏡像中的內容在容器啟動后被展開,然后復制到一個獨立的namespace空間內,并通過cgroup限制容器能夠使用的系統資源。稍后在制作鏡像時,會詳細介紹AppC Spec規定的鏡像目錄結構。這里只先指出一點,AppC的鏡像沒有支持像Docker那樣的分層結構,這種設計簡化了容器運行時的一些操作,但帶來的弊端也是很明顯的:無法復用鏡像相同的部分。因此在磁盤空間的利用上造成了浪費,也增加了容器鏡像在網絡傳輸成本。
除了目錄的結構,鏡像還需要一個描述鏡像內容的文件,稱為“鏡像屬性清單文件(Image Manifest)”,其中定義的內容包括:鏡像的作者信息、容器暴露的端口、暴露的掛載點、所需的系統資源(CPU/內存)等。此外,AppC Spec的約定的屬性清單中,還會包含許多編排調度所需的信息,例如容器運行所依賴的其他容器、容器的標簽。
在這方面來說,AppC鏡像的信息量遠遠多于Docker鏡像。相當于囊括了Docker鏡像本身、Compose編排配置以及一部分Docker運行參數的內容。
此外,AppC規范也約定的鏡像ID和簽名的生成方法,關于鏡像ID和簽名的作用和在Rkt文章上篇中已經介紹過,稍后還會詳細介紹鏡像簽名的生成方法。
分發協議主要是約定鏡像下載使用的協議類型和URL的樣式。AppC的鏡像URL采用類似Docker的domain.com/image-name
這樣的格式,但其實際處理方式有些不同。此外,在沒有指定域名時,Docker會默認在官方的DockerHub尋找鏡像,AppC的鏡像沒有所謂“官方源”,因此也沒有這樣的規則。
Rkt/AppC目前支持以下幾種URL格式:
<域名>/<鏡像名>
<本地文件路徑>
https://<完整網絡路徑>
http://<完整網絡路徑>
docker://<與Docker一樣的鏡像URL>
第一種方式是AppC推薦的鏡像分發URL,這種方式有點像Docker Repository,但實際上只是HTTPS協議的簡寫方式。AppC會根據指導的域名和路徑依照約定的方式轉換為完整URL地址,然后下載指定的鏡像。
第二種方式相當于導入本地鏡像。值得一提的是,即便使用本地鏡像,AppC同樣要求鏡像有簽名認證,關于簽名文件的細節在后面的內容里會詳細討論。
第三種和第四種方式都是直接通過完整URL獲取鏡像,規范中并不推薦直接這樣使用裸的HTTPS的URL,因為這種命名過于隨意的鏡像地址不利于鏡像的管理和統一,特別是HTTP協議的URL更只應該在內網的環境中出現。
第五種方式不是AppC規范支持的協議類型,目前只是Rkt支持這種協議(本質上還是HTTP或HTTPS)。兼容Docker鏡像的URL,只需要在前面加上docker://
即可,下載后會自動轉換為AppC鏡像格式。由于Docker的鏡像倉庫不支持簽名認證,使用這種URL時,用戶需要顯示的加上參數--insecure-skip-verify
允許使用未認證的鏡像來源。
AppC規范中的容器編排和集群描述方式與Kubernetes十分相似,采用“容器組屬性清單文件(Pod Manifest)”描述。其中沿用了Kubernetes中諸如Pods
、labels
等用于在集群中進行調度策略的規劃和管理的概念。
Pods
直譯便是“豆莢”,它指的是由一系列相互關聯的容器組成的,能夠對外提供獨立服務功能的容器集合。例如將用于數據收集功能的容器、用于緩存服務的容器以及用于搜索服務的容器組合在一起,作為一個Pod
提供完整的數據查詢服務暴露給外部用戶。Pod
可以作為容器參與集群調度的單獨集合提供給集群管理器,在例如Kubernetes這樣的集群管理模型中,Pod
實際上就是進行服務跨節點調度的最小單位。
labels
用于標示具有同一類特性的容器,為容器的過濾和選擇提供了十分靈活的策略。許多的集群管理器都能夠在調度時利用選擇指定標簽對Pods
進行篩選。
考慮到CoreOS公司與谷歌共同合作的背景(已經推出了Tectonic CaaS平臺),這樣的設計為Kubernetes未來與符合AppC規范的容器進行深度集成提供了良好的技術基礎。
執行器,也就像是Rkt這樣的容器工具。這個部分規范了設計符合AppC Spec的容器執行器所需要遵循的原則和應該具備的功能。
例如,必須為每個容器提供唯一的UUID;在容器的運行上下文中必須至少提供一個本地Loopback網卡,以及0個至多個其他TCP/IP網卡;應該將容器中程序打印到Stdout和Stderr的日志進行收集和展示等細節。
其中還詳細約定了,對于鏡像屬性清單中的諸多屬性,執行器應當如何進行處理。這些內容對大部分的使用者而言都只能作為參考,還是需要以具體實現的容器產品文檔為準。
在AppC的項目中,除了一紙洋洋灑灑的規范文書以外,還提供了不少AppC鏡像相關的示范工具。不像Docker這種一個命令集成所有功能的玩法,這些工具中的每個只是關注于容器的某個方面功能。例如通用類型鏡像的制作、打包、格式轉換以及特定類型鏡像的制作等。
目前已有的工具主要包括:
Actool - 用于鏡像的構建和驗證
Docker2Aci - 用于將Docker導出的鏡像轉換為AppC鏡像
Goaci - 用于Golang語言的項目一鍵打包和構建鏡像的工具
Acbuild - 通過指令的方式構建鏡像
其中,Actool
和Acbuild
都是用于鏡像構建的工具,它們的區別類似于通過docker commit
和Dockerfile兩種方式構建鏡像。需要指出的是,前不久才剛剛建立的Acbuild
項目,現在還只是一個計劃,沒有發布任何實際可用的版本,其目的是替代之前的另一個項目baci
。后者已經無法使用并且不再繼續更新。
Goaci
的作用是獲取指定路徑的項目,進行自動編譯,然后把編譯后的可執行程序制作成一個鏡像,所有的這些操作只需要一條命令就可以完成:goaci <項目路徑>
,項目路徑支持所有go get
命令所支持的代碼托管網站,包括BitBucket、GitHub、Google Code和Launchpad等。不過,它只能用于使用Golang語言并托管在上述網站中的開源項目。不具有普遍的適用性。
下面將重點介紹Actool
和Docker2Aci
這兩個工具。為了方便非CoreOS系統用戶嘗鮮,也會介紹在這些工具在其他64位Linux發行版的安裝方法。
與鏡像制作相關的工具是Actool
,這個軟件已經預裝在CoreOS系統較新的版本上了,可以通過actool --help
命令驗證并獲得Actool的版本。其他64位Linux的用戶可以通過下面的命令安裝它:
wget https://github.com/AppC/spec/releases/download/v0.5.2/AppC-v0.5.2.tar.gz tar zxf AppC-v0.5.2.tar.gz sudo mv AppC-v0.5.2/actool /usr/local/bin/
說到構建鏡像,前面已經提到,新的命令式構建鏡像的工具Acbuild
目前還沒有發布任何可用版本。因此當下的情況是,構建AppC鏡像還只能手工創建鏡像屬性清單文件,拷貝容器中所需的文件,然后直接打包生成鏡像。索性,這樣創建鏡像除了失去諸如“基礎設施即代碼”的好處以外,并沒有多少值得非議的地方,構建流程本身并不復雜。
下面來制作一個十分樸素的AppC容器鏡像,這個鏡像中只包含一個可執行文件。
首先新建一個用于制作鏡像的工作目錄,例如AppC-image
:
>mkdir AppC-image
接下來,為了讓這個例子足夠簡單,我們需要一個能夠不依賴任何外部動態庫或運行時環境,能夠單獨運行的程序。我們寫一個C語言的“Hello World”吧。新建一個叫hello.c
的文件,內容如下:
#include <stdio.h> int main(int argc, char* argv[]) { printf("Hello AppC\n"); //隨便輸出點什么東西 return 0; }
然后,需要一個C語言編譯器,有些Linux系統已經自帶了這個東西,用gcc --version
命令可以驗證。如果沒有安裝,那么...大家看著辦吧,比如在Ubuntu系統下面可以通過apt-get來獲取:
sudo apt-get install gcc
CoreOS系統會稍微麻煩一點,需要借助一個額外的容器來完成。提示一下,Docker有一個官方的C/C++語言運行環境鏡像,就叫gcc
。可以docker pull gcc
或者rkt --insecure-skip-verify fetch docker://gcc
來獲取它,然后啟動一個容器,注意需要映射一個Volumn到主機上,方便編譯完成后將生成的可執行程序拷貝出來。
編譯的命令如下,其中的--static
參數是必須的,否則編譯出來的程序在執行時會需要依賴外部的動態庫:
gcc --static -o hello hello.c
在剛剛工作目錄里面新建一個叫rootfs
的目錄,將編譯生成的hello可執行文件拷貝進去。這個rootfs
目錄中的內容就是以后容器里所包含的文件內容了,因此建議在其中再建立一些標準的目錄結構,例如/bin
目錄,將可執行程序放到這個目錄里面。
mkdir -p AppC-image/rootfs/bin cp hello AppC-image/rootfs/bin/
現在鏡像的目錄結構已經成型了。下面就可以開始創建鏡像的屬性清單文件了,在工作目錄中新建一個名為manifest
的文件,內容如下:
{ "acKind": "ImageManifest", "acVersion": "0.5.2", "name": "my-app", "labels": [ {"name": "os", "value": "linux"}, {"name": "arch", "value": "amd64"} ], "app": { "exec": [ "/bin/hello" ], "user": "0", "group": "0" } }
此時,工作目錄里的文件結構應該是這樣的:
AppC-image ├── manifest └── rootfs └── bin └── hello
最后就可以用actool
命令構建鏡像了:
actool build AppC-image hello.aci
容器鏡像的來源無非有兩種:本地的或者遠程的。
因此對鏡像的驗證也就包含兩部分內容。
檢驗本地的文件是否符合AppC規范的鏡像
檢驗遠程的URL是否是有效的AppC鏡像地址
對于前一種情況,前面說過,容器鏡像其實就是符合一定標準結構的打包文件。
$ file hello.aci hello.aci: gzip compressed data
在AppC規范中,鏡像文件的后綴名應該是.aci
,但具有這個后綴名的打包文件未必就是正確的鏡像。因此需要一個方法來驗證鏡像文件的正確性,相應的命令是actool validate
。
直接執行這個命令時,actool只會通過命令的返回值表示驗證的結果,返回0表示驗證通過:
$ actool validate hello.aci $ echo $? 0
可以加上-debug
參數讓actool直接將結果打印在控制臺上:
$ actool -debug validate hello.aci hello.aci: valid app container image
對于后一種情況,URL的驗證,同樣可以通過actool工具完成,相應的命令是actool discover
。
這個命令會返回鏡像的實際下載地址:
$ actool discover coreos.com/etcd ACI: https://github.com/coreos/etcd/releases/download/latest/etcd -latest-linux-amd64.aci, ASC: https://github.com/coreos/etcd /releases/download/latest/etcd-latest-linux-amd64.aci.asc Keys: https://coreos.com/dist/pubkeys/aci-pubkeys.gpg
試一下在Rkt里面用過的Docker鏡像地址,會發現這個地址是無效的。
$ actool discover docker://ubuntu error fetching docker://ubuntu: Get https://docker?ac-discovery=1: dial tcp: lookup docker: no such host
這也證實了在前面說的,docker://
這種協議只是Rkt額外支持的鏡像獲取方式,并不是AppC的規范中的標準協議。
AppC的規范制定者們顯然很清楚,哪些輪子該重造,哪些輪子是可以直接復用的。在Docker的各種鏡像已然是鋪天蓋地的當下,一個新的容器工具想要最快積累鏡像數量,最好的辦法就是兼容Docker鏡像或者將Docker的鏡像進行轉換。
其實對于鏡像兼容這個問題,新標準們有各自不同的做法,紅帽的Nulecule選擇了支持Dockerfile格式,只需要把已有的鏡像代碼加上一些額外的配置文件,重新構建一次就可以。而AppC做過同樣的嘗試,(之前有個baci
項目就是干這個的,不過已經沒有更新了),效果上有些不倫不類,因此索性更干脆,提供個工具允許將任何的Docker鏡像導出后直接轉換成自己的鏡像格式。
下面就來說說從Docker到AppC鏡像的轉換,相應的工具是Docker2Aci
。
這個工具不論是在Ubuntu或者CoreOS上都沒有預裝,因此需要單獨安裝。這個工具還沒有正式發布,因此官方也沒有提供編譯好的二進制包,要獲得它只能從源代碼編譯。值得慶幸的是,Golang語言的編譯方式還是比較友好的,如果本地已經安裝了Golang語言的開發環境,可以直接通過go get github.com/AppC/docker2aci
命令完成整個下載和編譯的過程。
考慮到大多數用戶都是沒有Golang開發環境的,另一個比較簡單的辦法是:通過容器。因為,Docker官方已經提供了一個用于Golang開發的容器鏡像,名字就叫golang
。用下面一條命令就可以搞定編譯。
sudo docker run -v $(pwd):/pkg -i -t golang:1.4 /bin/bash -c "go get github.com/AppC/docker2aci; cp \$GOPATH/bin/docker2aci /pkg/"
編譯好的docker2aci
二進制文件會被拷貝到當前目錄,將它放到系統變量PATH所指的的任意目錄中即可,比如:
sudo mv docker2aci /usr/local/bin/
執行docker2aci --version
命令可以打印出軟件的使用幫助,證明已經成功安裝。
$ docker2aci Usage of docker2aci: docker2aci [--debug] [--nosquash] IMAGE Where IMAGE is [--image=IMAGE_NAME[:TAG]] FILEPATH or docker://[REGISTRYURL/]IMAGE_NAME[:TAG] Flags: -debug=false: Enables debug messages -image="": When converting a local file, it selects a particular image to convert. Format: IMAGE_NAME[:TAG] -nosquash=false: Don't squash layers and output every layer as ACI
將一個Docker鏡像導出,然后可以通過docker2aci
命令轉換成AppC鏡像。
$ docker pull ubuntu $ docker save -o ubuntu.docker ubuntu $ ./docker2aci ubuntu.docker ... ... Generated ACI(s): ubuntu-latest.aci
轉換后的鏡像會保存在當前目錄,并自動用“<鏡像>-<標簽>”的格式命名。
此外,比較實用的是,docker2aci
同樣支持docker://
協議的URL直接獲取網上的鏡像。
$ docker2aci docker://busybox ... ... Generated ACI(s): busybox-latest.aci
這個時候,如果直接用Rkt運行剛剛創建的hello.aci
鏡像,會發現Rkt提示由于找不到有效的簽名文件,因此拒絕運行這個鏡像。
$ sudo rkt run hello.aci error opening signature file: open /home/core/hello.aci.asc: no such file or directory
鏡像的簽名,是AppC引入的一種鏡像來源驗證機制,本質上是利用非對稱加密的標準數字簽名。通過將鏡像提供者的私鑰和鏡像文件本身加密生產一組簽名字符串,通過發布者提供的公鑰就能夠解開這串字符并得到與鏡像匹配的信息,這樣就能驗證鏡像是否是真的來自特定的作者或來源。
AppC的簽名算法是標準是RSA,采用的是開源的GPG實現,關于GPG的詳細介紹參考這篇文章。
首先準備一個密鑰配置文件,命名為gpg-batch
,內容如下:
%echo Generating a default key Key-Type: RSA Key-Length: 2048 Subkey-Type: RSA Subkey-Length: 2048 Name-Real: 你的英文名字 Name-Email: 你的郵箱地址 Name-Comment: ACI signing key Expire-Date: 0 Passphrase: 簽名時的密碼 %pubring rkt.pub %secring rkt.sec %commit %echo done
然后用下面的命令生成一個密鑰對:
gpg --batch --gen-key gpg-batch
執行完成后,在目錄中會多出rkt.sec
和rkt.pub
兩個文件,這就是私鑰和公鑰了。
然后就可以使用這對密鑰給鏡像簽名了:
gpg --no-default-keyring --armor --secret-keyring ./rkt.sec --keyring ./rkt.pub --output hello.aci.asc --detach-sig hello.aci
在提示輸入密碼時,輸入在gpg-batch
中設置的密碼。然后就獲得了hello.aci
鏡像的簽名文件hello.aci.asc
。
再次嘗試運行容器:
$ sudo rkt run hello.aci openpgp: signature made by unknown entity
這次提示的錯誤是,簽名文件雖然找到了,但是這個簽名的來源并沒有在信任列表中。為了將簽名添加到信任里面里面,首先要用rkt.sec
和rkt.pub
這兩個二進制的密鑰文件導出為一個文本的公鑰文件。
gpg --no-default-keyring --armor --secret-keyring ./rkt.sec --keyring ./rkt.pub --export 在gpg-batch中的郵箱 > pubkeys.gpg
然后將這個文本文件中的公鑰添加到Rkt的信任列表中。
$ sudo rkt trust --root pubkeys.gpg Prefix: "" Key: "pubkeys.gpg" GPG key fingerprint is: 37E2 6071 5382 5868 5A0D 1356 98A9 5E24 6E19 7AED Subkey fingerprint: 46AF 81E4 77D4 BFCA DFCE 73C6 3D94 79C2 2611 F243 Kelsey Hightower (ACI signing key) Are you sure you want to trust this key (yes/no)? yes Trusting "pubkeys.gpg" for prefix "". Added root key at "/etc/rkt/trustedkeys/root.d/37e26071538258685a0d135698a95e246e197aed"
這次運行容器,就可以看到容器中的Hello程序已經正確的執行了。
$ sudo rkt run hello.aci rkt: signature verified: Kelsey Hightower (ACI signing key) <kelsey.hightower@coreos.com> Hello AppC
最后簡單的介紹一下AppC的鏡像倉庫(Image Repository)。
AppC規范定義了獲取鏡像的URL,其形式大致是域名/鏡像路徑:版本
,例如CoreOS提供的包含Etcd的鏡像可以通過命令rkt fetch coreos.com/etcd:v2.0.9
來獲取。
這里只說兩個比較有意思的地方。
首先,AppC是沒有所謂“官方鏡像倉庫”的,所以URL中的域名
部分始終會存在。由CoreOS公司提供的鏡像被放在coreos.com
域名下的普通倉庫中。這一點也符合AppC標準開放化的初衷。
其次,AppC會對用戶的URL嘗試通過兩種方式解析。換句話說,鏡像倉庫的實現方式可以有兩種。第一種幾乎不需要額外的配置工作,將鏡像依照一定的命名規則放在域名的相應路徑下即可,例如coreos.com/etcd:v2.0.9
,如果使用第一種方式建倉庫,相應的鏡像就應該保存在https://coreos.com/etcd-v2.0.9-linux-amd64.aci
(當然,CoreOS的鏡像實際上是用的第二種方式,所以這個路徑不存在)。第二種方式更加靈活,但需要額外的程序來處理鏡像地址的映射,具體過程,不再詳述。
此外,前面介紹過,對于內網環境,還可以直接使用HTTP路徑獲取鏡像。舉個栗子,把之前制作好的鏡像文件hello.aci
和簽名文件hello.aci.asc
放到一個目錄里面,然后在這個目錄中啟動一個簡易的HTTP服務:
$ python -m SimpleHTTPServer Serving HTTP on 0.0.0.0 port 8000 ...
在任意另一個主機上就可以直接使用HTTP全路徑下載鏡像了。
$ sudo rkt fetch http://<服務器IP>:8000/hello.aci ... ... Downloading ACI: [ ] 1.26 KB/358 KB sha512-f7a2feff02a07ed7c604c14133b7aede
這種簡單粗暴到無以復加的方式,對于懶人們也許算得上是一種福利,然而不論是從安全性還是鏡像版本的可管理性上看來,其能力都相當弱。這從一個側面說明,一些為開發者們提供的便利通道,如果沒有規范的約束,可能帶來很大的隱患。在實際運用時,建議遵循AppC的URL解析規范設計倉庫為上策。
到此,關于“CoreOS Rkt容器鏡像怎么制作”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。