Docker

Docker 私有系統資料庫作為 kubernetes pod - 已刪除的圖像自動重新創建

  • November 3, 2021

我將 docker 私有系統資料庫 v2.7.0 作為具有服務和持久卷的 kubernetes pod 執行,這要歸功於 Varun Kumar G 教程,這是我設置中唯一成功的方法,讓 kubernetes 從我的私有 docker 系統資料庫中提取我的3 個節點 - 本地 - 帶有 ubuntu 20.04 lts kvms 的集群

問題在於從 kubernetes pod docker registry v2.7.0 中刪除圖像(必須使用以前的版本,因為最新的 v2.7.1 不適用於 htpasswd)。此外,我已經閱讀了很多類似的主題,例如thisthisthis

使用 docker registry v2.7.1作為 docker 容器執行,我可以毫無問題地刪除圖像,

但是使用 docker registry v2.7.0作為 kubernetes pod執行,通常的刪除步驟導致無法再次推送已刪除的映像,即使在成功刪除 blob 並手動刪除/var/lib/registry/docker/registry/v2/repositories/.

下面是系統資料庫 pod yaml

apiVersion: v1
kind: Pod
metadata:
 name: dockreg-pod
 labels:
   app: mregistry
spec:
 containers:
 - name: registry
   image: registry:2.7.0
   imagePullPolicy: IfNotPresent
   volumeMounts:
   - name: repo-vol
     mountPath: "/var/lib/registry"
   - name: certs-vol
     mountPath: "/certs"
     readOnly: true
   - name: auth-vol
     mountPath: "/auth"
     readOnly: true
   env:
   - name: REGISTRY_AUTH
     value: "htpasswd"
   - name: REGISTRY_AUTH_HTPASSWD_REALM
     value: "Registry Realm"
   - name: REGISTRY_AUTH_HTPASSWD_PATH
     value: "/auth/htpasswd"
   - name: REGISTRY_HTTP_TLS_CERTIFICATE
     value: "/certs/tls.crt"
   - name: REGISTRY_HTTP_TLS_KEY
     value: "/certs/tls.key"
   - name: REGISTRY_STORAGE_DELETE_ENABLED
     value: "true"
 volumes:
 - name: repo-vol
   persistentVolumeClaim:
     claimName: repo-pvc
 - name: certs-vol
   secret:
     secretName: certs-secret
 - name: auth-vol
   secret:
     secretName: auth-secret
 restartPolicy: Always
 nodeName: spring

以下是持久卷 yaml

apiVersion: v1
kind: PersistentVolume
metadata:
 name: repo-pv
 labels:
   type: prstore
spec:
 capacity:
   storage: 7Gi
 volumeMode: Filesystem
 accessModes:
 - ReadWriteOnce
 persistentVolumeReclaimPolicy: Retain
 storageClassName: local-storage
 local:
   fsType: ext4
   path: /root/repo
 nodeAffinity:
   required:
     nodeSelectorTerms:
     - matchExpressions:
       - key: kubernetes.io/hostname
         operator: In
         values:
         - spring
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: repo-pvc
 labels:
   type: prstore
spec:
 selector:
   matchLabels: 
     type: prstore
 volumeMode: Filesystem
 storageClassName: local-storage
 accessModes:
 - ReadWriteOnce
 resources:
   requests:
     storage: 7Gi

假設我在一個全新的系統資料庫 pod 上推送一個圖像,並且預先清除了持久性儲存。

root@sea:scripts# docker push dockreg:5000/mubu4:v4
The push refers to repository [dockreg:5000/mubu4]
9f54eef41275: Pushed 
v4: digest: sha256:7bd0d9a9821815dccb5c53c18cea04591ec633e2e529c5cdd39681169589c17f size: 529

刪除圖像似乎按預期工作,直到我再次嘗試推送已刪除的圖像,此時我遇到了可怕的Layer already exists錯誤。

正如您可能在上面看到的,我在系統資料庫 pod 環境中包含以下內容,

- name: REGISTRY_STORAGE_DELETE_ENABLED
     value: "true"

否則我會unsupported從呼叫中得到一個錯誤curl -X DELETE,即使在添加之後

delete:
   enabled: true

/etc/docker/registry/config.yml吊艙內,

version: 0.1
log:
 fields:
   service: registry
storage:
 cache:
   blobdescriptor: inmemory
 filesystem:
   rootdirectory: /var/lib/registry
 delete:
   enabled: true
http:
 addr: :5000
 headers:
   X-Content-Type-Options: [nosniff]
health:
 storagedriver:
   enabled: true
   interval: 10s
   threshold: 3

這似乎對我的案例沒有影響。

以下是刪除步驟

curl -u alexander:sofianos \
> -vsk -H "Accept: \
> application/vnd.docker.distribution.manifest.v2+json" \
> -X DELETE \
> https://dockreg:5000/v2/mubu4/manifests/sha256:\
> 7bd0d9a9821815dccb5c53c18cea04591ec633e2e529c5cdd39681169589c17f

上面列印了以下內容

> DELETE /v2/mubu4/manifests/sha256:7bd0d9a9821815dccb5c53c18cea04591ec633e2e529c5cdd39681169589c17f HTTP/2
> Host: dockreg:5000
> authorization: Basic YWxleGFuZGVyOnNvZmlhbm9z
> user-agent: curl/7.68.0
> accept: application/vnd.docker.distribution.manifest.v2+json
> 
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
< HTTP/2 202 
< docker-distribution-api-version: registry/2.0
< x-content-type-options: nosniff
< content-length: 0
< date: Sat, 30 Oct 2021 13:25:53 GMT
< 
* Connection #0 to host dockreg left intact

這似乎是有序的。

下面,從系統資料庫 pod 中刪除 blob

root@sea:scripts# kubectl exec -it dockreg-pod -- sh
/ # bin/registry garbage-collect  /etc/docker/registry/config.yml
mubu4

0 blobs marked, 3 blobs and 0 manifests eligible for deletion
blob eligible for deletion: sha256:7b1a6ab2e44dbac178598dabe7cff59bd67233dba0b27e4fbd1f9d4b3c877a54
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/7b/7b1a6ab2e44dbac178598dabe7cff59bd67233dba0b27e4fbd1f9d4b3c877a54  go.version=go1.11.2 instance.id=82a101ee-47f4-4f4f-bc79-76d774b0924b service=registry
blob eligible for deletion: sha256:7bd0d9a9821815dccb5c53c18cea04591ec633e2e529c5cdd39681169589c17f
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/7b/7bd0d9a9821815dccb5c53c18cea04591ec633e2e529c5cdd39681169589c17f  go.version=go1.11.2 instance.id=82a101ee-47f4-4f4f-bc79-76d774b0924b service=registry
blob eligible for deletion: sha256:ecb35fc8715f5ab1d9053ecb2f2d9ebbec4a59c0a0615d98de53bc29f7285085
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/ec/ecb35fc8715f5ab1d9053ecb2f2d9ebbec4a59c0a0615d98de53bc29f7285085  go.version=go1.11.2 instance.id=82a101ee-47f4-4f4f-bc79-76d774b0924b service=registry

最後,手動刪除儲存庫映像

/ # rm -rf /var/lib/registry/docker/registry/v2/repositories/mubu4

在我的持久儲存上,系統資料庫現在看起來像這樣

root@spring:repo# tree
.
└── docker
   └── registry
       └── v2
           ├── blobs
           │   └── sha256
           │       ├── 7b
           │       └── ec
           └── repositories

8 directories, 0 files

但是當我再次嘗試推送已刪除的圖像時,我得到了

root@sea:scripts# docker push dockreg:5000/mubu4:v4
The push refers to repository [dockreg:5000/mubu4]
9f54eef41275: Layer already exists 
v4: digest: sha256:7bd0d9a9821815dccb5c53c18cea04591ec633e2e529c5cdd39681169589c17f size: 529

在我的系統資料庫中,我之前刪除的 mubu4 圖像文件夾已通過上述推送命令神秘地重新創建

root@spring:repo# tree
.
└── docker
   └── registry
       └── v2
           ├── blobs
           │   └── sha256
           │       ├── 7b
           │       └── ec
           └── repositories
               └── mubu4
                   └── _manifests
                       ├── revisions
                       │   └── sha256
                       │       └── 7bd0d9a9821815dccb5c53c18cea04591ec633e2e529c5cdd39681169589c17f
                       │           └── link
                       └── tags
                           └── v4
                               ├── current
                               │   └── link
                               └── index
                                   └── sha256
                                       └── 7bd0d9a9821815dccb5c53c18cea04591ec633e2e529c5cdd39681169589c17f
                                           └── link

19 directories, 3 files

我還嘗試用

root@spring:repo# rm -rf *

無濟於事。之後嘗試推送已刪除的圖像,仍然輸出完全相同的Layer already exists錯誤,並且系統資料庫樹再次自動重新創建,看起來與上述樹輸出中的完全相同。

問題是我還能嘗試什麼來完成這項工作,和/或替代地,

從上面的測試可以看出,在 docker registry kubernetes pod 中,還有其他文件保存著已刪除鏡像似乎沒有被刪除的配置,這些文件通過 docker push 呼叫啟動已刪除鏡像的重新創建。除了樹我應該往哪裡看

/var/lib/registry/docker/registry/v2/

所以我可以刪除對已刪除圖像的所有引用?

似乎至少在此處此處描述的系統資料庫版本 2.7.0 中存在記憶體問題。

建議在上述執行緒中完全禁用記憶體或每次重新啟動容器。

因為我將 docker 系統資料庫用作 kubernetes pod,所以更改了預設系統資料庫配置文件,即。/etc/docker/registry/config.yml沒有任何效果,因為 kubernetes 系統資料庫 pod yaml 優先,這意味著必須在 pod yaml 中將配置設置為環境變數,REGISTRY_variable下劃線表示縮進級別,如docs中所述。

所以解決方案是添加

- name: REGISTRY_STORAGE_CACHE_BLOBDESCRIPTOR
 value: ""

到 pod yaml 中的容器環境,以便完全禁用記憶體,否則如果系統資料庫作為 docker 容器執行,我們可以在以下內容中使用config.yml

storage:
 cache:
   blobdescriptor: ""

另一種方法是在每次刪除圖像時重新啟動 pod:

kubectl exec <pod_name> -c <container_name> -- reboot

或者如果它是一個 docker 容器

docker restart <registry_container>

引用自:https://serverfault.com/questions/1082200