<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          清理鏡像庫(kù)空間的一個(gè)思路

          共 3590字,需瀏覽 8分鐘

           ·

          2020-11-08 12:32

          最近遇到一個(gè)有趣的狀況,某鏡像倉(cāng)庫(kù)占用了大量的磁盤空間。通常要解決這種問題,給 Registry 發(fā)刪除指令,并進(jìn)行 GC 就可以了。然而很多時(shí)候,所有鏡像都正常,在刪除多個(gè) Tag 甚至是 Repository 之后,問題仍然沒能緩解,原理也很容易理解——?jiǎng)h除的鏡像雖然大,可能只是復(fù)用了一些比較大的層,刪除鏡像并不會(huì)真正的發(fā)出,所以還是需要對(duì)鏡像庫(kù)的存儲(chǔ)進(jìn)行更多的了解,進(jìn)行進(jìn)一步的統(tǒng)計(jì),在層一級(jí)對(duì)鏡像倉(cāng)庫(kù)進(jìn)行分析,才能獲取更有效的途徑。

          Docker Registry Exporter

          首先發(fā)現(xiàn)了一個(gè)有意思的項(xiàng)目:DockerRegistryExporter,這個(gè)項(xiàng)目是一個(gè) Python 編寫的 Prometheus Exporter,其中包含四個(gè) Gauge:

          -repository_tags_total:按鏡像計(jì)算的 Tag 數(shù)量。
          -repository_revisions_total:按鏡像計(jì)算的版本數(shù)量。
          -repository_tag_layers_total:以鏡像和 Tag 計(jì)算的 Layer 數(shù)量。
          -repository_tag_size_bytes:以鏡像和 Tag 計(jì)算的文件尺寸。

          該鏡像使用掛卷的方式,直接對(duì)鏡像庫(kù)文件系統(tǒng)進(jìn)行掃描,例如:

          containers:
          - image: registry:2
          name: registry
          ports:
          - containerPort: 5000
          name: http
          protocol: TCP
          readinessProbe:
          httpGet:
          path: /
          port: 5000
          initialDelaySeconds: 1
          timeoutSeconds: 1
          livenessProbe:
          httpGet:
          path: /
          port: 5000
          initialDelaySeconds: 1
          timeoutSeconds: 1
          volumeMounts:
          - name: storage
          mountPath: /var/lib/registry

          - image: skyuk/docker-registry-exporter:v1.0.0
          name: registry-exporter
          args:
          - /var/lib/registry/docker/registry/v2
          ports:
          - containerPort: 8080
          name: http
          protocol: TCP
          volumeMounts:
          - name: storage
          mountPath: /var/lib/registry

          volumes:
          - name: storage
          persistentVolumeClaim:
          claimName: registry

          通過Sidecar的部署方式和Registry容器共享文件系統(tǒng),可以定時(shí)輸出監(jiān)控指標(biāo),例如:

          $ curl http://registry:8080
          # HELP repository_tag_size_bytes Size of eachtag
          # TYPE repository_tag_size_bytes gauge
          repository_tag_size_bytes{repository="org/image1", tag="0.3.0"} 162749959.0
          repository_tag_size_bytes{repository="org/image2", tag="1009140546"} 226608092.0
          ...

          然而這并不能滿足我的要求,關(guān)于引用的數(shù)據(jù)并沒有體現(xiàn),另外前面也提到,我們需要比較精確地獲得鏡像版本、Tag 和 Layer 之間的引用關(guān)系以及各自的尺寸,用 PromQL 有點(diǎn)別扭。

          我做了個(gè)奇怪的事情

          這并不是一個(gè)很常見的需求,只能是一個(gè)清理之前的準(zhǔn)備動(dòng)作,目前看來我需要找到的就是引用數(shù)量少、但是體量比較大的 Layer,但是誰知道以后會(huì)需要什么新的標(biāo)準(zhǔn)呢?干脆把這些東西寫入到數(shù)據(jù)庫(kù)里算了,把這些東西寫入數(shù)據(jù)庫(kù)之后,還掌握 SQL 這樣傳統(tǒng)才藝的程序員就可以隨便搞一搞其它條件了。

          關(guān)于鏡像倉(cāng)庫(kù)的一點(diǎn)基礎(chǔ)

          鏡像庫(kù)根目錄中有兩個(gè)子目錄:blobs 中保存了所有的 Layer,而 repositories 中則是以鏡像為單位保存的元數(shù)據(jù)。

          首先看看鏡像的數(shù)據(jù)

          $ tree/org/repo/gameserver
          .
          ├── revisions
          │ └── sha256
          │ └── ecfb0206e8b...
          │ └── link
          └── tags
          └── latest
          ├── current
          │ └── link
          └── index
          └── sha256
          └── ecfb020...
          └── link

          每個(gè)鏡像的 Manifests 有兩個(gè)目錄,分別承載的是版本和 Tag,正常來說 Tag 和版本是一致的,但實(shí)際上在一些特別情況下,這兩個(gè)數(shù)量可能是不一致的,就會(huì)導(dǎo)致只用 Tag 已經(jīng)無法拉取該鏡像,屬于一種半孤立狀態(tài),應(yīng)該說是需要清除的。

          兩個(gè)目錄中的link文件中包含的是一個(gè)哈希碼,可以使用這個(gè)哈希碼在_layers中查找到該鏡像的版本/tag 對(duì)應(yīng)的清單層,使用這個(gè)字符串可以在根_layer中查到對(duì)應(yīng)的目錄,目錄下面的data文件中就是每個(gè)層的具體數(shù)據(jù),對(duì)于清單層,其中會(huì)是一個(gè)json字符串:

          {
          "schemaVersion": 2,
          "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
          "config": {
          "mediaType": "application/vnd.docker.container.image.v1+json",
          "size": 2694,
          "digest": "sha256:7929bcd70e47d3726d55a870b2ca11c25792758f3ba8b4ff136811f0809af636"
          }
          ,
          "layers": [
          {
          "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
          "size": 2546278,
          "digest": "sha256:3db1cceb1cccb362634e914bfe76d329c64d148262a9e139a046337d82e1aeec"
          },
          {
          "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
          "size": 32,
          "digest": "sha256:4f4fb700ef54461cfa02571ae0db9a0dc1e0cdb5577484a6d75e68dc38e8acc1"
          }
          ]
          }

          這里看到清單中包含兩個(gè)主節(jié)點(diǎn),configlayer,至此,一個(gè)鏡像是由三種不同的層構(gòu)成的:清單、Config 和 Layer。我們關(guān)注的主要是 Layer,其中的 data 文件包含的就是各層的具體內(nèi)容,清單和 Config 中都是文本,Layer 通常都是二進(jìn)制的,也是我們要關(guān)注的主要內(nèi)容。

          接下來的問題就順理成章了,把 Repository、Tag、Revision 以及 Layer 的關(guān)系建立起來,隨便用個(gè) SQL 語(yǔ)句,就能夠按照具體需求對(duì)“引用少、尺寸大”的 Layer 進(jìn)行過濾了。

          相關(guān)鏈接

          • Docker Registry Exporterhttps://github.com/sky-uk/docker-registry-exporter

          瀏覽 26
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  大香蕉国产伊人在线 | 中国女人性爱毛片 | 美女被操在线播放 | 老逼综合| 欧美在线视频播放 |