Initial chart: odoosky-system namespace + local container registry (Distribution v2)

This commit is contained in:
Tower Deploy
2026-04-27 00:47:07 +03:00
parent 049144dc04
commit a1dbe14c20
4 changed files with 149 additions and 0 deletions

14
Chart.yaml Normal file
View File

@@ -0,0 +1,14 @@
apiVersion: v2
name: cluster-platform-v3
description: |
Per-cluster platform infrastructure for OdooSky v3. ArgoCD-managed
on every connected customer K8s cluster. Provides:
- odoosky-system namespace (where Tower spawns build Jobs and
stores cluster-private credentials sourced from OpenBao)
- Local container registry (Distribution v2). In-cluster
BuildKit Jobs push addon images here; the chart consumes
them as image volumes. Sovereignty + GFW resistance: no
cross-cluster image transfer.
type: application
version: 0.1.0
appVersion: "0.1.0"

7
templates/namespace.yaml Normal file
View File

@@ -0,0 +1,7 @@
apiVersion: v1
kind: Namespace
metadata:
name: {{ .Values.namespace }}
labels:
odoosky.io/component: platform
app.kubernetes.io/managed-by: {{ .Release.Service }}

92
templates/registry.yaml Normal file
View File

@@ -0,0 +1,92 @@
{{- if .Values.registry.enabled -}}
# Local container registry. Single replica — addon images are
# rebuildable from Gitea source, so we trade HA for simplicity.
# A node failure means a brief gap in image availability that
# Tower's ensureAddonImage can recover from on the next pull.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: registry
namespace: {{ .Values.namespace }}
labels:
odoosky.io/component: registry
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: {{ .Values.registry.persistence.size | quote }}
{{- with .Values.registry.persistence.storageClass }}
storageClassName: {{ . | quote }}
{{- end }}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: registry
namespace: {{ .Values.namespace }}
labels:
odoosky.io/component: registry
spec:
replicas: 1
# Recreate (not RollingUpdate): the PVC is RWO, so two registry
# pods overlapping would block on the volume mount.
strategy:
type: Recreate
selector:
matchLabels:
odoosky.io/component: registry
template:
metadata:
labels:
odoosky.io/component: registry
spec:
containers:
- name: registry
image: "{{ .Values.registry.image.repository }}:{{ .Values.registry.image.tag }}"
imagePullPolicy: {{ .Values.registry.image.pullPolicy }}
ports:
- name: http
containerPort: 5000
env:
# Allow image deletes via the API (Tower may garbage-collect
# unused addon-versions later).
- name: REGISTRY_STORAGE_DELETE_ENABLED
value: "true"
volumeMounts:
- name: data
mountPath: /var/lib/registry
resources:
{{- toYaml .Values.registry.resources | nindent 12 }}
readinessProbe:
httpGet:
path: /
port: 5000
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /
port: 5000
initialDelaySeconds: 30
periodSeconds: 30
volumes:
- name: data
persistentVolumeClaim:
claimName: registry
---
apiVersion: v1
kind: Service
metadata:
name: registry
namespace: {{ .Values.namespace }}
labels:
odoosky.io/component: registry
spec:
type: ClusterIP
ports:
- name: http
port: {{ .Values.registry.service.port }}
targetPort: 5000
selector:
odoosky.io/component: registry
{{- end }}

36
values.yaml Normal file
View File

@@ -0,0 +1,36 @@
# cluster-platform-v3 — defaults.
#
# Most knobs you'd flip live here so customer-cluster overlays can
# tune sizing without forking the chart.
namespace: odoosky-system
registry:
enabled: true
image:
repository: registry
tag: "2.8"
pullPolicy: IfNotPresent
# ClusterIP service hostname:
# registry.odoosky-system.svc.cluster.local:5000
# Used internally by build Jobs (push) and the Odoo Deployment's
# image volumes (pull). Plain HTTP — the registry never sees
# off-cluster traffic; node-side k3s registries.yaml whitelists
# the hostname for HTTP image pulls.
service:
port: 5000
# Storage. The registry survives node restarts but is recreatable —
# if the PVC is wiped, Tower's ensureAddonImage will rebuild any
# missing images from Gitea source on demand. So we don't need a
# large or replicated PV here.
persistence:
enabled: true
size: 10Gi
storageClass: "" # "" = use the cluster's default; on k3s that's local-path
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 500m
memory: 256Mi