registry · 集群私有镜像仓库

registry 是集群自托管的私有 OCI 镜像仓库,运行官方 distribution/registry v3,镜像的 blob 与 manifest 全部落在集群内 MinIO 的 registry bucket(S3 兼容存储)。它附带一个 joxit/docker-registry-ui 作为只读 Web 浏览界面,对外通过 Cloudflare tunnel + traefik 暴露在 registry.yldm.tech / registry.dunaifen.games

整套部署位于独立的 registry 命名空间,由两个 Deployment 组成:核心 registry(端口 5000 提供 OCI distribution API,5001 暴露 Prometheus 指标)与 registry-ui(端口 8080,反代到集群内 registry)。命名空间挂了独立的 ResourceQuota 与 LimitRange 做资源约束。

部署形态

核心仓库与 UI 各为单副本 Deployment,镜像版本固定写在 manifest 中(不经 argocd-image-updater 改写)。

  • Name
    命名空间
    Description
    registry(独立命名空间,namespace.yaml 显式创建)
  • Name
    工作负载
    Description
    两个 Deployment:registry(核心仓库)+ registry-ui(Web 界面)
  • Name
    registry 镜像
    Description
    registry:3.1.1(distribution v3),replicas 1
  • Name
    registry-ui 镜像
    Description
    joxit/docker-registry-ui:2.6.0,replicas 1
  • Name
    registry 端口
    Description
    5000(http,OCI distribution API)、5001(metrics,debug + Prometheus)
  • Name
    registry-ui 端口
    Description
    容器 8080,Service 暴露 80
  • Name
    存储
    Description
    无 PVC;blob/manifest 全部存到集群内 MinIO 的 S3 bucket registry(storage driver = s3)
  • Name
    安全上下文
    Description
    registry 以非 root(uid/gid 1000)运行,drop ALL caps、禁止提权、RuntimeDefault seccomp
  • Name
    资源约束
    Description
    命名空间级 ResourceQuota(pods 5、requests.cpu 500m / mem 512Mi、limits.cpu 3 / mem 2Gi)+ LimitRange 默认值

registry 容器 requests cpu 50m / mem 64Mi,limits cpu 1 / mem 512Mi;readiness 与 liveness 探针都打 /v2/(5000)。registry-ui 容器 requests cpu 10m / mem 32Mi,limits cpu 200m / mem 128Mi,readiness 探针打 /(8080)。manifest 未配置 nodeSelector/workload 标签、HPA/VPA 或 PDB。

配置与依赖

registry 的主配置由 ConfigMap registry-config 提供,以只读卷挂到 /etc/distribution(v3 默认配置路径;v2 时代是 /etc/docker/registry)。关键配置项:

配置说明
storage drivers3bucket registry,endpoint http://minio.minio.svc.cluster.local:9000,region us-east-1,forcepathstyle、secure=false
storage.redirect.disabletrue禁用 S3 presigned URL 重定向,registry 自己代理 blob 内容
storage.cache.blobdescriptorinmemoryblob descriptor 内存缓存
storage.delete.enabledtrue允许删除
http.addr:5000OCI API 监听端口
http.relativeurlstrue在 TLS 终止的 ingress 后生成代理无关的上传 Location URL
http.debug.addr:5001指标 + 健康端口,/metrics 开启 prometheus
health.storagedriverenabled,interval 10s,threshold 3存储驱动健康检查

S3 凭据不在 ConfigMap 里,而是经 ExternalSecret registry-s3 从 Vault(ClusterSecretStore vault-backend,KV 路径 registry/minio)拉取,同步成 Secret registry-s3,再以三个环境变量注入容器,与 config.ymlstorage.s3 合并:

  • Name
    REGISTRY_STORAGE_S3_ACCESSKEY
    Description
    remoteRef registry/minioaccess-key
  • Name
    REGISTRY_STORAGE_S3_SECRETKEY
    Description
    remoteRef registry/miniosecret-key
  • Name
    REGISTRY_HTTP_SECRET
    Description
    remoteRef registry/miniohttp-secret,上传/cookie 状态的 HMAC secret,从 Vault 取以保证跨重启稳定

ExternalSecret 的 refreshInterval 为 1h。核心运行时依赖是集群内 MinIO(applications/storage/minio/)与 Vault(凭据来源)。

registry-ui 通过环境变量配置,自带 nginx 同源反代到集群内 registry,免 CORS:NGINX_PROXY_PASS_URL=http://registry.registry.svc.cluster.local:5000SINGLE_REGISTRY=trueREGISTRY_TITLE="DNF Private Registry"DELETE_IMAGES=falseSHOW_CONTENT_DIGEST=trueSHOW_CATALOG_NB_TAGS=true

访问与监控

registry 核心 Service 为 NodePort(30500 → 5000),便于大体积镜像推送绕过 Cloudflare 代理的 100MB 请求体上限直连节点;另有 ClusterIP Service registry-metrics(5001)供指标抓取。registry-ui 为 ClusterIP(80 → 8080)。

对外入口经 Cloudflare tunnel + traefik(ingressClassName: traefik),且按 Cloudflare 账号做了拆分:

HostCloudflare tunnelTLS
registry.yldm.techNEW 账号 tunnel 2b822c22...cert-manager DNS-01 origin 证书(letsencrypt-prod,secret registry-tls)
registry.dunaifen.gamesOLD 账号 tunnel 79da7b14...Cloudflare 边缘 TLS,无 origin 证书
registry-ui.yldm.techNEW 账号 tunnel 2b822c22...cert-manager 证书(secret registry-ui-tls)
registry-ui.dunaifen.gamesOLD 账号 tunnel 79da7b14...Cloudflare 边缘 TLS

yldm.techdunaifen.games 分属不同 Cloudflare 账号,故 host 必须指向各自账号的 tunnel;cert-manager 的 DNS-01 只覆盖 yldm.tech/yldm.ai,所以只为 yldm.tech host 签 origin 证书,dunaifen.games 走 Cloudflare 边缘 TLS。registry 的 ingress 上放开了 body 上限(proxy-body-size: 0)并把读写超时拉到 600s,应对大镜像层。

监控方面:ServiceMonitor registry 通过 registry-metrics Service 的 metrics 端口(5001)按 30s 间隔抓取 /metrics,relabel 出 pod / namespace / service / job 标签。manifest 中未包含 PrometheusRule。

注意事项

几处 manifest 里以注释标注的关键约束:

  • redirect 必须禁用:MinIO 只在集群内可达(NetworkPolicy + 内部 DNS),不能把客户端 307 重定向到 presigned S3 URL,否则节点 containerd / 外部客户端会被重定向到 minio.minio.svc:9000 而拉取失败,所以 registry 自己代理 blob 内容。
  • 大镜像推送走 NodePort:Cloudflare 代理另有 100MB 请求体上限,大推送应直连 NodePort 30500,而非走 ingress。
  • ResourceQuota 的 limits.cpu 从 2 提到 3:留出滚动更新时第二个 registry pod(1 cpu)与旧 pod、registry-ui 并存的余量,否则默认 surge 会因配额死锁报 FailedCreate。
  • registry-ui 不能 drop ALL caps:joxit 入口用 sed 原地模板化 index.html / nginx 配置,需要以 root(默认)写文件,剥掉 DAC_OVERRIDE 会导致写权限被拒、CrashLoop,所以 UI 容器只设了禁止提权 + seccomp,未 drop caps。
  • v3 配置路径变更:distribution v3 默认配置路径是 /etc/distribution/config.yml(v2 时代是 /etc/docker/registry/config.yml),挂载路径已对应调整。

返回 storage 总览

评论