雲原生製品那些事(2):OCI 鏡像規範

題圖攝於故宮角樓

注:微信公衆號不按照時間排序,請關注“亨利筆記”,並加星標以置頂,以免錯過更新。

《Harbor權威指南》招募英文版翻譯人員

本篇繼續和大家說說鏡像那些事,是連載之二,從《Harbor權威指南》一書節選的純技術乾貨,敬請關注、轉發和收藏。

第一篇:容器鏡像的結構

第二篇:OCI 鏡像規範

第三篇:OCI 製品

第四篇:Registry 的作用原理

《Harbor權威指南》目前噹噹網優惠中,點擊下圖直接購買。

1.5  OCI鏡像規範

OCI 鏡像規範是以 Docker 鏡像規範 v2 爲基礎制定的,它定義了鏡像的主要格式及內容,主要用於鏡像倉庫存放鏡像及分發鏡像等場景,與正在制定的 OCI 分發規範密切相關。

OCI 運行時在創建容器前,要把鏡像下載並解壓成符合運行時規範的文件系統包,並且把鏡像中的配置轉化成運行時配置,然後啓動容器。

OCI 定義的鏡像包括4個部分:鏡像索引(Image Index)、清單(Manifest)、配置(Configuration)和層文件(Layers)。

其中,清單是JSON格式的描述文件,列出了鏡像的配置和層文件。配置是JSON格式的描述文件,說明了鏡像運行的參數。層文件則是鏡像的內容,即鏡像包含的文件,一般是二進制數據文件格式(Blob)。一個鏡像可以有一個或多個層文件。(在搜狐、CSDN等網站轉載亨利筆記的文章均爲未經授權的剽竊)

鏡像索引不是必需的,如果存在,則指明瞭一組支持不同架構平臺的相關鏡像。鏡像的 4 個部分之間是通過摘要(digest)來相互引用(reference)的。鏡像各部分的關係如下圖所示。

下面詳細講解各部分的結構和作用。


1).鏡像索引

鏡像索引是鏡像中可選擇的部分,一個鏡像可以不包括鏡像索引。如果鏡像包含了鏡像索引,則其作用主要指向鏡像不同平臺的版本,代表一組同名且相關的鏡像,差別只在支持的體系架構上(如 i386 和 arm64v8、Linux 和Windows 等)。索引的優點是在不同的平臺上使用鏡像的命令無須修改,如在 amd64 架構的 Windows 和ARM架構的 Linux 上,採用同樣的“docker”命令即可運行 Nginx 服務:(在搜狐、CSDN等網站轉載亨利筆記的文章均爲未經授權的剽竊)

$ docker run -d nginx

用戶無須指定操作系統和平臺,就可完全依賴客戶端獲取正確版本的鏡像。OCI的索引已經被 CNAB等工具廣泛用來管理與雲平臺無關的分佈式應用程序。

下面是一個索引示例:

{

  "schemaVersion": 2,

  "manifests": [

    {

      "mediaType": "application/vnd.oci.image.manifest.v1+json",

      "size": 8342,

      "digest": "sha256:d81ae89b30523f5152fe646c1f9d178e5d10f28d00b70294fca965b7b96aa3db",

      "platform": {

        "architecture": "arm64v8",

        "os": "linux"

      }

    },

    {

      "mediaType": "application/vnd.oci.image.manifest.v1+json",

      "size": 6439,

      "digest": "sha256:2ef4e3904905353a0c4544913bc0caa48d95b746ef1f2fe9b7c85b3badff987e",

      "platform": {

        "architecture": "amd64",

        "os": "linux"

      }

    }

  ],

  "annotations": {

    "io.harbor.key1": "value1",

    "io.harbor.key2": "value2"

  }

}

客戶端在獲得上述鏡像索引後,解析後可發現該索引指向兩個不同平臺架構的鏡像,因此可根據自身所在的平臺拉取相應的鏡像。如 Linux amd64 平臺上的客戶端會拉取第2個鏡像,因爲該鏡像的 platform.architecture 屬性爲amd64,platform.os屬性爲Linux。

索引文件中的 mediaType 和 digest 屬性是OCI鏡像規範中的重要概念,下面詳細講解這兩個屬性。(本文爲公衆號:亨利筆記 原創文章)

(1)mediaType 屬性是描述鏡像所包含的各種文件的媒體屬性,客戶端從 Registry 等服務中下載鏡像文件時,可從 HTTP 的頭部屬性 Content-Type 中獲得下載文件的媒體類型,從而決定如何處理下載的文件。比如,鏡像的索引和清單都是 JSON 格式的文件,它們的區別就是媒體類型不同。

OCI 鏡像規範定義的媒體類型見表1,可以看到上面例子中的清單的媒體類型是 application/vnd.oci.image.manifest.v1+json,索引本身的媒體類型則是application/vnd.oci.image.index.v1+json。

表1

媒體類型

含    義

application/vnd.oci.descriptor.v1+json

內容描述符

application/vnd.oci.layout.header.v1+json

OCI佈局說明

application/vnd.oci.image.index.v1+json

鏡像索引

application/vnd.oci.image.manifest.v1+json

鏡像清單

application/vnd.oci.image.config.v1+json

鏡像配置

application/vnd.oci.image.layer.v1.tar

tar格式的層文件

application/vnd.oci.image.layer.v1.tar+gzip

tar格式的層文件,採用gzip壓縮

application/vnd.oci.image.layer.v1.tar+zstd

tar格式的層文件,採用zstd壓縮

application/vnd.oci.image.layer.nondistributable.v1.tar

tar格式的非分發層文件

application/vnd.oci.image.layer.nondistributable.v1.tar+gzip

tar格式的非分發層文件,採用gzip壓縮

application/vnd.oci.image.layer.nondistributable.v1.tar+zstd

tar格式的非分發層文件,採用zstd壓縮

(2)digest 屬性是密碼學意義上的摘要,充當鏡像內容的標識符,實現內容的可尋址(content addressable)。OCI鏡像規範中鏡像的內容(如文件等)大多是通過摘要來標識和引用的。

摘要的生成是根據文件內容的二進制字節數據通過特定的哈希(Hash)算法實現的。哈希算法需要確保字節的抗衝突性 ( collision resistant )來生成唯一標識,只要哈希算法得當,不同文件的哈希值幾乎不會重複。因此,可以近似地認爲每個文件的摘要都是唯一的。這種唯一性使摘要可以作爲內容尋址的標識。

同時,如果摘要以安全的方式傳遞,則接收方可以通過重新計算摘要來確保內容在傳輸過程中未被修改,從而杜絕來自不安全來源的內容。在OCI的鏡像規範中也要求用摘要值校驗所接收的內容。(本文爲公衆號:亨利筆記 原創文章)

摘要值是由算法和編碼兩部分組成的字符串,算法部分指定使用的哈希函數和算法標識,編碼部分則包含哈希函數的編碼結果,具體格式爲 “<算法標識> : <編碼結果>”。

目前 OCI 鏡像規範認可的哈希算法有兩種,分別是 SHA-256 和 SHA-512,它們的算法標識如 表2 所示。

表2

算法標識

算法名稱

摘要例子

sha256

SHA-256

sha256:d81ae89b30523f5152fe646c1f9d178e5d10f28d00b70294fca965b7b96aa3db

sha512

SHA-512

sha512:d4ca54922bb802bec9f740a9cb38fd401b09eab3c0135318192b0a75f2……

上面索引中的兩個鏡像清單摘要值分別對應兩個清單文件,分別是blobs/sha256/d81ae89b30523f5152fe646c1f9d178e5d10f28d00b70294fca965b7b96aa3db 和blobs/sha256/2ef4e3904905353a0c4544913bc0caa48d95b746ef1f2fe9b7c85b3badff987e。

2).鏡像清單

鏡像清單(簡稱清單)是說明鏡像包含的配置和內容的文件,分析鏡像一般從鏡像清單開始。鏡像清單主要有三個作用:支持內容可尋址的鏡像模型,在該模型中可以對鏡像的配置進行哈希處理,以生成鏡像及其唯一標識;通過鏡像索引包含多體系結構鏡像,通過引用鏡像清單獲取特定平臺的鏡像版本;可轉換爲 OCI 運行時規範以運行容器。(本文爲公衆號:亨利筆記 原創文章)

鏡像清單主要包括配置和層文件的信息,示例如下:

{

  "schemaVersion": 2,

  "config": {

    "mediaType": "application/vnd.oci.image.config.v1+json",

    "size": 6883,

    "digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7"

  },

  "layers": [

    {

      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",

      "size": 168654,

 "digest": "sha256:58394f6dcfb05cb167a5c24953eba57f28f2f9d09af107ee8f08c4ac89b1adf5"

    },

    {

      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",

      "size": 645724,

      "digest": "sha256:6d94e421cd3c3a4604a545cdc12745355bca5b528f4da2eb4a4c6ba9c1905b15"

    },

    {

      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",

      "size": 53709,

      "digest": "sha256:419d1af06b5f7636b4ac3da7f12184802ad867736ec4b8955958665577945c89"

    }

  ],

  "annotations": {

    "io.harbor.example.key1": "value1",

    "io.harbor.example.key2": "value2"

  }

}

其中主要屬性的意義如下。

◎ schemaVersion:必須是2,主要用於兼容舊版本的Docker。

◎ config:鏡像配置文件的信息。mediaType的值“application/vnd.oci.image.config. v1+json”表示鏡像配置的媒體類型。size指鏡像配置文件的大小。digest指鏡像配置文件的哈希摘要。(在搜狐、CSDN等網站轉載亨利筆記的文章均爲未經授權的剽竊)

 ◎ layers:層文件數組。在以上示例中包含 3 個層文件,分別代表容器根文件系統的一個層。容器在運行時,會把各個層文件依次按順序疊加,第1層在底層。mediaType指媒體類型,其值“application/vnd.oci.image.layer.v1.tar+gzip”表示層文件。size 指層文件的大小。digest 指層文件的摘要。

◎ annotations:鍵值對形式的附加信息(可選項)。


3).鏡像配置

鏡像配置主要描述容器的根文件系統和容器運行時使用的執行參數,還有一些鏡像的元數據。

在配置規範裏定義了鏡像的文件系統的組成方式。鏡像文件系統由若干鏡像層組成,每一層都代表一組tar格式的層格式,除了底層(base image),其餘各層的文件系統都記錄了其父層(向下一層)文件系統的變化集(changeset),包括要添加、更改或刪除的文件。(本文爲公衆號:亨利筆記 原創文章)

通過基於層的文件、聯合文件系統(如AUFS)或文件系統快照的差異,文件系統的變化集可用於聚合一系列鏡像層,使各層疊加後彷彿是一個完整的文件系統。

下面是鏡像配置的一個示例:

{

    "created": "2020-06-28T12:28:58.058435234Z",

    "author": "Henry Zhang",

    "architecture": "amd64",

    "os": "linux",

    "config": {

        "ExposedPorts": {

            "8888/tcp": {}

        },

        "Env": [

            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",

            "FOO=harbor_registry",

        ],

        "Entrypoint": [

            "/bin/myApp "

        ],

        "Cmd": [

            "-f",

            "/etc/harbor.cfg"

        ],

        "Volumes": {

            "/var/job-result-data": {},

        },

        "Labels": {

            "io.goharbor.git.url": "https://github.com/goharbor/harbor.git",

        }

    },

    "rootfs": {

      "diff_ids": [

        "sha256:e928294e148a1d2ec2a8b664fb66bbd1c6f988f4874bb0add23a778f753c65ef",

        "sha256:ea198a02b6cddfaf10acec6ef5f70bf18fe33007016e948b04aed3b82103a36b"

      ],

      "type": "layers"

    },

    "history": [

      {

        "created": "2020-05-28T12:28:56.189203784Z",

        "created_by": "/bin/bash -c #(nop) ADD file:4fb4eef1ea3bc1e842b69636f9df5256c49c537281fe3f282c65fb853e563ab3 in /"

      },

      {

        "created": "2020-05-28T12:28:57.789430183Z",

        "created_by": "/bin/bash -c #(nop) CMD [\"bash\"]",

        "empty_layer": true

      }

    ]

}

其中主要屬性的意義如下,具體說明可以參考 OCI 規範。

◎ created:鏡像的創建時間(可選項)。

◎ author:鏡像的作者(可選項)。

◎ architecture:鏡像支持的CPU架構。

◎ os:鏡像的操作系統。(在搜狐、CSDN等網站轉載亨利筆記的文章均爲未經授權的剽竊)

◎ config:鏡像運行的一些參數,包括服務端口、環境變量、入口命令、命令參數、數據卷、用戶和工作目錄等(可選項)。

◎ rootfs:鏡像的根文件系統,由一系列層文件的變化集組成。

◎ history:鏡像每層的歷史信息(可選項)。


4).層文件

在鏡像清單和配置信息中可以看到,鏡像的根文件系統由多個層文件疊加而成。每個層文件在分發時都必須被打包成一個tar文件,可選擇壓縮或者非壓縮的方式,壓縮工具可以是 gzip 或者 zstd 。把每層的內容打包爲一個文件的好處是除了發佈方便,還可以生成文件摘要,便於校驗和按內容尋址。

每個層文件都包含了對上一層(父層)的更改,包括增加、修改和刪除文件三種操作類型,底層(第1層)可以被看作對空層文件的增加。因此在每個tar文件裏面除了該層的文件,還可以包含對上一層中文件的刪除操作,用 whiteout 的方式標記。在疊加層文件時,可以根據 whiteout 的標記,把上一層刪除的文件在本層屏蔽。(在搜狐、CSDN等網站轉載亨利筆記的文章均爲未經授權的剽竊)

在表1中還有幾個層文件的媒體類型爲不可分發(non-distributable),這是爲了說明該層文件因爲法律等原因無法公開分發,需要從分發商那裏獲得該層文件。

(未完待續,歡迎點“再看” 或 轉發、分享、收藏)

(未經授權,請勿轉載本公衆號文章)

《Harbor權威指南》目前噹噹網優惠中,點擊上圖直接購買。

《Harbor權威指南》招募英文版翻譯人員

要想了解雲原生、區塊鏈和人工智能等技術原理,請立即長按以下二維碼,關注本公衆號亨利筆記 ( henglibiji ),以免錯過更新。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章