FEAT(zot): add Zot container registry

- ARM64 image (ghcr.io/project-zot/zot-linux-arm64:v2.1.13)
- htpasswd authentication via Vault ExternalSecret
- Ingress at zot0213.kro.kr with Let's Encrypt TLS
- local-path storage (50Gi)
- Prometheus metrics enabled
This commit is contained in:
2026-01-07 14:31:04 +09:00
parent 9c0fddb0ef
commit 03f17000e9
4 changed files with 194 additions and 0 deletions

44
zot/argocd.yaml Normal file
View File

@@ -0,0 +1,44 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: zot
namespace: argocd
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/zot/helm-values.yaml
- repoURL: https://github.com/K3S-HOME/storage.git
targetRevision: main
ref: values
- repoURL: https://github.com/K3S-HOME/storage.git
targetRevision: main
path: zot
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'
revisionHistoryLimit: 10

128
zot/helm-values.yaml Normal file
View File

@@ -0,0 +1,128 @@
# Zot Registry using bjw-s/app-template
# ARM64 container registry for on-premise CI/CD
controllers:
zot:
type: statefulset
strategy: RollingUpdate
containers:
zot:
image:
repository: ghcr.io/project-zot/zot-linux-arm64
tag: v2.1.13
pullPolicy: IfNotPresent
probes:
liveness:
enabled: true
custom: true
spec:
tcpSocket:
port: 5000
initialDelaySeconds: 5
periodSeconds: 10
readiness:
enabled: true
custom: true
spec:
tcpSocket:
port: 5000
initialDelaySeconds: 5
periodSeconds: 10
resources:
requests:
cpu: 10m
memory: 128Mi
limits:
memory: 512Mi
pod:
tolerations:
- key: "node-role.kubernetes.io/master"
operator: "Exists"
effect: "NoExecute"
service:
zot:
controller: zot
ports:
http:
port: 5000
ingress:
zot:
className: traefik
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: zot0213.kro.kr
paths:
- path: /
pathType: Prefix
service:
identifier: zot
port: http
tls:
- secretName: zot-tls
hosts:
- zot0213.kro.kr
persistence:
data:
type: persistentVolumeClaim
accessMode: ReadWriteOnce
size: 50Gi
storageClass: local-path
globalMounts:
- path: /var/lib/registry
config:
type: configMap
name: zot-config
globalMounts:
- path: /etc/zot/config.json
subPath: config.json
readOnly: true
htpasswd:
type: secret
name: zot-htpasswd
globalMounts:
- path: /etc/zot/htpasswd
subPath: htpasswd
readOnly: true
configMaps:
config:
data:
config.json: |
{
"storage": {
"rootDirectory": "/var/lib/registry",
"gc": true,
"gcDelay": "1h",
"gcInterval": "24h"
},
"http": {
"address": "0.0.0.0",
"port": "5000",
"auth": {
"htpasswd": {
"path": "/etc/zot/htpasswd"
}
}
},
"log": {
"level": "info"
},
"extensions": {
"metrics": {
"enable": true,
"prometheus": {
"path": "/metrics"
}
},
"search": {
"enable": true
},
"ui": {
"enable": true
}
}
}

4
zot/kustomization.yaml Normal file
View File

@@ -0,0 +1,4 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- manifests/secret.yaml

18
zot/manifests/secret.yaml Normal file
View File

@@ -0,0 +1,18 @@
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: zot-htpasswd-secret
namespace: zot
spec:
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: vault-backend
target:
name: zot-htpasswd
creationPolicy: Owner
data:
- secretKey: htpasswd
remoteRef:
key: zot
property: HTPASSWD