Zot
개요
Zot은 Lumie 플랫폼의 OCI 호환 컨테이너 레지스트리입니다. 경량화된 클라우드 네이티브 레지스트리로, 온디맨드 이미지 동기화와 S3 스토리지 백엔드를 지원합니다.
아키텍처
주요 기능
1. 온디맨드 이미지 동기화
외부 레지스트리에서 필요한 이미지를 자동으로 동기화:
{
"extensions": {
"sync": {
"enable": true,
"downloadDir": "/tmp/zot/sync",
"registries": [
{
"urls": ["https://registry-1.docker.io"],
"onDemand": true,
"tlsVerify": true,
"content": [
{"prefix": "library/**"},
{"prefix": "bitnami/**"},
{"prefix": "grafana/**"},
{"prefix": "kong/**"},
{"prefix": "aquasecurity/**"},
{"prefix": "falcosecurity/**"},
{"prefix": "velero/**"},
{"prefix": "rabbitmqoperator/**"},
{"prefix": "linuxserver/**"},
{"prefix": "codercom/**"},
{"prefix": "b4bz/**"},
{"prefix": "alpine/**"},
{"prefix": "sosedoff/**"},
{"prefix": "kiwigrid/**"},
{"prefix": "minio/**"},
{"prefix": "otwld/**"},
{"prefix": "bitnamilegacy/**"}
]
},
{
"urls": ["https://ghcr.io"],
"onDemand": true,
"tlsVerify": true,
"content": [
{"prefix": "cloudnative-pg/**"},
{"prefix": "kyverno/**"},
{"prefix": "tektoncd/**"},
{"prefix": "headlamp-k8s/**"},
{"prefix": "umami-software/**"},
{"prefix": "open-telemetry/**"},
{"prefix": "prymitive/**"},
{"prefix": "icoretech/**"},
{"prefix": "openclaw/**"}
]
},
{
"urls": ["https://quay.io"],
"onDemand": true,
"tlsVerify": true,
"content": [
{"prefix": "prometheus/**"},
{"prefix": "thanos/**"},
{"prefix": "prometheus-operator/**"},
{"prefix": "keycloak/**"}
]
},
{
"urls": ["https://registry.k8s.io"],
"onDemand": true,
"tlsVerify": true,
"content": [
{"prefix": "kube-state-metrics/**"},
{"prefix": "autoscaling/**"}
]
},
{
"urls": ["https://us-docker.pkg.dev"],
"onDemand": true,
"tlsVerify": true,
"content": [
{"prefix": "fairwinds-ops/**"}
]
},
{
"urls": ["https://gcr.io"],
"onDemand": true,
"tlsVerify": true,
"content": [
{"prefix": "kaniko-project/**"}
]
},
{
"urls": ["https://mirror.gcr.io"],
"onDemand": true,
"tlsVerify": true,
"content": [
{"prefix": "aquasec/**"}
]
}
]
}
}
}
2. S3 스토리지 백엔드
MinIO를 사용한 분산 스토리지:
{
"storage": {
"rootDirectory": "/tmp/zot",
"dedupe": false,
"gc": true,
"gcDelay": "1h",
"gcInterval": "24h",
"retention": {
"policies": [
{
"repositories": ["**"],
"deleteReferrers": true,
"keepTags": [{
"mostRecentlyPushedCount": 1
}]
}
]
},
"storageDriver": {
"name": "s3",
"regionendpoint": "http://minio.minio.svc.cluster.local:9000",
"region": "us-east-1",
"bucket": "zot",
"secure": false,
"skipverify": true
}
}
}
3. 이미지 보존 정책
자동 가비지 컬렉션과 보존 정책: deleteReferrers: true 옵션을 통해 참조되는 이미지도 함께 삭제하도록 설정되었습니다.
{
"storage": {
"gc": true,
"gcDelay": "1h",
"gcInterval": "24h",
"retention": {
"policies": [
{
"repositories": ["**"],
"deleteReferrers": true,
"keepTags": [{
"mostRecentlyPushedCount": 1
}]
}
]
}
}
}
설치 및 구성
Helm 배포
# bootstrap/zot/argocd.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: zot
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "1"
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
sources:
- repoURL: https://bjw-s-labs.github.io/helm-charts
chart: app-template
targetRevision: 3.6.1
helm:
valueFiles:
- $values/bootstrap/zot/helm-values.yaml
- repoURL: https://github.com/Lumie-Edu/lumie-infra.git
targetRevision: main
ref: values
path: charts/common
helm:
valueFiles:
- $values/bootstrap/zot/common-values.yaml
destination:
server: https://kubernetes.default.svc
namespace: zot
syncPolicy:
automated:
prune: true
selfHeal: true
allowEmpty: false
syncOptions:
- CreateNamespace=true
- PrunePropagationPolicy=foreground
- PruneLast=true
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m
managedNamespaceMetadata:
labels:
goldilocks.fairwinds.com/enabled: 'true'
minio-s3: enabled
revisionHistoryLimit: 10
컨테이너 설정
# helm-values.yaml
controllers:
zot:
type: deployment
replicas: 1
strategy: RollingUpdate
containers:
zot:
image:
repository: ghcr.io/project-zot/zot-linux-arm64
tag: v2.1.13
pullPolicy: IfNotPresent
env:
AWS_ACCESS_KEY_ID:
valueFrom:
secretKeyRef:
name: minio-s3-credentials
key: MINIO_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY:
valueFrom:
secretKeyRef:
name: minio-s3-credentials
key: MINIO_SECRET_ACCESS_KEY
AWS_REGION:
valueFrom:
secretKeyRef:
name: minio-s3-credentials
key: MINIO_REGION
probes:
startup:
enabled: true
custom: true
spec:
tcpSocket:
port: 5000
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 30
liveness:
enabled: true
custom: true
spec:
tcpSocket:
port: 5000
initialDelaySeconds: 30
periodSeconds: 10
readiness:
enabled: true
custom: true
spec:
tcpSocket:
port: 5000
initialDelaySeconds: 30
periodSeconds: 10
# Resource settings - increased for handling large image pushes
resources:
requests:
cpu: 50m
memory: 512Mi
limits:
memory: 512Mi
네트워킹
# Ingress 설정 (helm-values.yaml)
ingress:
zot:
className: traefik
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: zot.lumie-infra.com
paths:
- path: /
pathType: Prefix
service:
identifier: zot
port: http
tls:
- secretName: zot-tls
hosts:
- zot.lumie-infra.com
대용량 이미지 업로드(예: ~1.2GB Chromium 레이어 포함 report-svc) 시 타임아웃이 발생할 수 있습니다. platform/traefik-config/helmchartconfig.yaml에서 Traefik의 엔트리포인트 전역 readTimeout/writeTimeout을 1200초로 설정하여 처리합니다.
인증 및 권한
htpasswd 인증
# common-values.yaml
vaultStaticSecrets:
# htpasswd secret
- name: zot-htpasswd-vss
path: infrastructure/zot
destination:
name: zot-htpasswd
transformation:
templates:
htpasswd: "{{ .Secrets.ZOT_HTPASSWD }}"
접근 제어
{
"http": {
"accessControl": {
"repositories": {
"**": {
"anonymousPolicy": ["read"],
"defaultPolicy": ["read"],
"policies": [
{
"groups": ["admins"],
"actions": ["read", "create", "update", "delete"]
},
{
"users": ["admin"],
"actions": ["read", "create", "update", "delete"]
}
]
}
}
}
}
}
지원하는 외부 레지스트리
Zot은 온디맨드 동기화를 위해 다양한 외부 레지스트리를 지원합니다.
Docker Hub
{
"urls": ["https://registry-1.docker.io"],
"onDemand": true,
"tlsVerify": true,
"content": [
{"prefix": "library/**"},
{"prefix": "bitnami/**"},
{"prefix": "grafana/**"},
{"prefix": "kong/**"},
{"prefix": "aquasecurity/**"},
{"prefix": "falcosecurity/**"},
{"prefix": "velero/**"},
{"prefix": "rabbitmqoperator/**"},
{"prefix": "linuxserver/**"},
{"prefix": "codercom/**"},
{"prefix": "b4bz/**"},
{"prefix": "alpine/**"},
{"prefix": "sosedoff/**"},
{"prefix": "kiwigrid/**"},
{"prefix": "minio/**"},
{"prefix": "otwld/**"},
{"prefix": "bitnamilegacy/**"}
]
}
GitHub Container Registry (ghcr.io)
{
"urls": ["https://ghcr.io"],
"onDemand": true,
"tlsVerify": true,
"content": [
{"prefix": "cloudnative-pg/**"},
{"prefix": "kyverno/**"},
{"prefix": "tektoncd/**"},
{"prefix": "headlamp-k8s/**"},
{"prefix": "umami-software/**"},
{"prefix": "open-telemetry/**"},
{"prefix": "prymitive/**"},
{"prefix": "icoretech/**"},
{"prefix": "openclaw/**"}
]
}
Quay.io
{
"urls": ["https://quay.io"],
"onDemand": true,
"tlsVerify": true,
"content": [
{"prefix": "prometheus/**"},
{"prefix": "thanos/**"},
{"prefix": "prometheus-operator/**"},
{"prefix": "keycloak/**"}
]
}
Kubernetes Registry (registry.k8s.io)
{
"urls": ["https://registry.k8s.io"],
"onDemand": true,
"tlsVerify": true,
"content": [
{"prefix": "kube-state-metrics/**"},
{"prefix": "autoscaling/**"}
]
}
Google Artifact Registry (us-docker.pkg.dev)
{
"urls": ["https://us-docker.pkg.dev"],
"onDemand": true,
"tlsVerify": true,
"content": [
{"prefix": "fairwinds-ops/**"}
]
}
Google Container Registry (gcr.io)
{
"urls": ["https://gcr.io"],
"onDemand": true,
"tlsVerify": true,
"content": [
{"prefix": "kaniko-project/**"}
]
}
Google Container Registry Mirror (mirror.gcr.io)
{
"urls": ["https://mirror.gcr.io"],
"onDemand": true,
"tlsVerify": true,
"content": [
{"prefix": "aquasec/**"}
]
}
사용법
이미지 푸시
# Tekton에서 자동으로 수행
docker build -t zot.lumie-infra.com/my-app:latest .
docker push zot.lumie-infra.com/my-app:latest
이미지 풀
# Kubernetes에서 자동으로 수행
docker pull zot.lumie-infra.com/my-app:latest
이미지 목록 조회
# REST API 사용
curl -X GET https://zot.lumie-infra.com/v2/_catalog
# 특정 이미지의 태그 목록
curl -X GET https://zot.lumie-infra.com/v2/my-app/tags/list
모니터링
메트릭스
Prometheus 메트릭스 제공:
{
"extensions": {
"metrics": {
"enable": true,
"prometheus": {
"path": "/metrics"
}
}
}
}
웹 UI
검색 및 관리 UI 제공:
{
"extensions": {
"search": {
"enable": true
},
"ui": {
"enable": true
}
}
}
스토리지 관리
MinIO 연동
# MinIO S3 자격증명
vaultStaticSecrets:
# MinIO S3 credentials
- name: zot-minio-vss
path: infrastructure/minio
destination:
name: minio-s3-credentials
transformation:
templates:
MINIO_ACCESS_KEY_ID: "{{ .Secrets.MINIO_ROOT_USER }}"
MINIO_SECRET_ACCESS_KEY: "{{ .Secrets.MINIO_ROOT_PASSWORD }}"
MINIO_REGION: "us-east-1"
가비지 컬렉션
- 자동 실행: 24시간마다
- 지연 시간: 1시간 후 실행
- 보존 정책: 최신 1개 태그만 유지, 참조되는 이미지도 함께 삭제
성능 최적화
타임아웃 설정
Traefik HelmChartConfig(platform/traefik-config/helmchartconfig.yaml)에서 전역 엔트리포인트 타임아웃을 설정합니다. 이는 Kong 어노테이션 방식을 대체합니다:
ports:
websecure:
transport:
respondingTimeouts:
readTimeout: 1200s # 20분
writeTimeout: 1200s # 20분
idleTimeout: 600s
리소스 할당
resources:
requests:
cpu: 50m
memory: 512Mi
limits:
memory: 512Mi
보안 고려사항
TLS 설정
- 외부 접근: Let's Encrypt 인증서 사용
- 내부 통신: MinIO와의 비보안 연결 (클러스터 내부)
접근 제어
- 익명 읽기: 허용 (공개 이미지)
- 인증된 쓰기: admin 사용자만 가능
- htpasswd: Vault에서 관리
네트워크 보안
- Ingress: Traefik을 통한 외부 접근 (
className: traefik) - 내부 서비스: ClusterIP로 내부 접근만 허용
문제 해결
이미지 푸시 실패
# Zot 로그 확인
kubectl logs -n zot deployment/zot
# MinIO 연결 확인
kubectl exec -n zot deployment/zot -- wget -O- http://minio.minio.svc.cluster.local:9000/minio/health/live
동기화 문제
# 동기화 상태 확인
curl -X GET https://zot.lumie-infra.com/v2/_catalog
# 특정 이미지 동기화 강제 실행
docker pull zot.lumie-infra.com/library/alpine:latest
스토리지 문제
# MinIO 버킷 확인
kubectl exec -n minio deployment/minio -- mc ls local/zot
# 디스크 사용량 확인
kubectl exec -n zot deployment/zot -- df -h
백업 및 복구
이미지 백업
MinIO S3 버킷의 자동 백업을 통해 이미지 데이터 보호:
# Velero를 통한 백업 (자동)
kubectl get backups -n velero
메타데이터 백업
Zot 설정과 메타데이터는 Git 저장소에서 관리:
# 설정 백업 (Git)
git add bootstrap/zot/
git commit -m "backup zot configuration"