Docker 私有注册表作为 kubernetes pod-已删除的图像自动重新创建

Docker 私有注册表作为 kubernetes pod-已删除的图像自动重新创建

我运行docker private registry 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)此外,我还阅读了许多类似的帖子,例如

使用 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

假设我正在将一个图像推送到一个全新的注册表容器中,并且事先已经清除了持久存储。

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"

否则,即使添加unsupportedcurl -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 注册表 kubernetes pod 中,还有其他文件,这些文件保存着已删除映像似乎未被删除的配置,这些文件通过 docker push 调用激活已删除镜像的重新创建。除了树之外,我还应该看哪里

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

所以我可以删除所有对已删除图像的引用吗?

答案1

至少在注册表版本 2.7.0 中似乎存在缓存问题,如下所述这里这里

在上述线程中建议完全禁用缓存或每次都重新启动容器。

因为我使用 docker 注册表作为 kubernetes pod,所以对默认注册表配置文件的更改/etc/docker/registry/config.yml不会产生任何影响,因为 kubernetes 注册表 pod yaml 优先,这意味着必须在 pod yaml 中将配置设置为环境变量,形式为REGISTRY_variable下划线代表缩进级别,如下所述文档

所以解决方案是添加

- 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>

相关内容