mirror of
https://github.com/Traceworks2023/nxtgauge-gitops.git
synced 2026-06-11 14:00:10 +00:00
fix(backend): add PORT env to deployments + BEECEPTOR_URL config
16 of 20 rust services were crashing on boot because their main.rs calls
std::env::var('PORT').expect(...). This commit adds the missing PORT env
to each deployment YAML, matching its containerPort (9100-9118).
Also adds BEECEPTOR_URL to the ConfigMap - the payments service requires
it for the mock payment gateway integration.
Adds apps/registry/ with retention script + CronJob (keep last 3 SHA
builds, preserve -latest aliases) to prevent the single-build wipeout
that caused the original registry outage.
AI assistant image also rebuilt: 2876b45 (main branch) - it was on a
ghost SHA tag that was GC'd.
This commit is contained in:
parent
4034c413c6
commit
827477ac3f
3 changed files with 116 additions and 0 deletions
6
apps/registry/kustomization.yaml
Normal file
6
apps/registry/kustomization.yaml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- retention-script.yaml
|
||||||
|
- retention-cronjob.yaml
|
||||||
|
namespace: registry
|
||||||
33
apps/registry/retention-cronjob.yaml
Normal file
33
apps/registry/retention-cronjob.yaml
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
apiVersion: batch/v1
|
||||||
|
kind: CronJob
|
||||||
|
metadata:
|
||||||
|
name: registry-keep-last-3-builds
|
||||||
|
namespace: registry
|
||||||
|
spec:
|
||||||
|
schedule: "*/15 * * * *"
|
||||||
|
concurrencyPolicy: Forbid
|
||||||
|
successfulJobsHistoryLimit: 2
|
||||||
|
failedJobsHistoryLimit: 3
|
||||||
|
jobTemplate:
|
||||||
|
spec:
|
||||||
|
backoffLimit: 1
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
restartPolicy: Never
|
||||||
|
containers:
|
||||||
|
- name: prune
|
||||||
|
image: python:3.12-alpine
|
||||||
|
command: ["python", "/scripts/prune.py"]
|
||||||
|
volumeMounts:
|
||||||
|
- name: script
|
||||||
|
mountPath: /scripts
|
||||||
|
- name: auth
|
||||||
|
mountPath: /auth
|
||||||
|
readOnly: true
|
||||||
|
volumes:
|
||||||
|
- name: script
|
||||||
|
configMap:
|
||||||
|
name: registry-retention-script
|
||||||
|
- name: auth
|
||||||
|
secret:
|
||||||
|
secretName: registry-regcred
|
||||||
77
apps/registry/retention-script.yaml
Normal file
77
apps/registry/retention-script.yaml
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: registry-retention-script
|
||||||
|
namespace: registry
|
||||||
|
data:
|
||||||
|
prune.py: |
|
||||||
|
import base64, json, re, urllib.request, urllib.error
|
||||||
|
REG='https://registry.nxtgauge.com'
|
||||||
|
CFG='/auth/.dockerconfigjson'
|
||||||
|
PATTERN=re.compile(r'^[0-9a-f]{40}$')
|
||||||
|
|
||||||
|
with open(CFG,'r') as f:
|
||||||
|
dcfg=json.load(f)
|
||||||
|
auth=dcfg['auths']['registry.nxtgauge.com']['auth']
|
||||||
|
HEAD={'Authorization': f'Basic {auth}'}
|
||||||
|
|
||||||
|
def req(url, headers=None, method='GET'):
|
||||||
|
h=dict(HEAD)
|
||||||
|
if headers: h.update(headers)
|
||||||
|
r=urllib.request.Request(url, headers=h, method=method)
|
||||||
|
with urllib.request.urlopen(r, timeout=30) as resp:
|
||||||
|
return resp.status, dict(resp.headers), resp.read()
|
||||||
|
|
||||||
|
_, _, body = req(f'{REG}/v2/_catalog?n=1000')
|
||||||
|
repos=[r for r in json.loads(body.decode()).get('repositories',[]) if r.startswith('nxtgauge-')]
|
||||||
|
|
||||||
|
deleted=0
|
||||||
|
for repo in sorted(repos):
|
||||||
|
try:
|
||||||
|
_, _, tb=req(f'{REG}/v2/{repo}/tags/list')
|
||||||
|
tags=(json.loads(tb.decode()).get('tags') or [])
|
||||||
|
except Exception as e:
|
||||||
|
print(f'[{repo}] tags/list failed: {e}')
|
||||||
|
continue
|
||||||
|
|
||||||
|
sha=[t for t in tags if PATTERN.match(t)]
|
||||||
|
if len(sha)<=1:
|
||||||
|
print(f'[{repo}] sha={len(sha)} no prune')
|
||||||
|
continue
|
||||||
|
|
||||||
|
rows=[]
|
||||||
|
for t in sha:
|
||||||
|
created='1970-01-01T00:00:00Z'
|
||||||
|
digest=None
|
||||||
|
try:
|
||||||
|
_, h, mb=req(f'{REG}/v2/{repo}/manifests/{t}', headers={'Accept':'application/vnd.docker.distribution.manifest.v2+json'})
|
||||||
|
digest=h.get('Docker-Content-Digest')
|
||||||
|
m=json.loads(mb.decode())
|
||||||
|
cfg=(m.get('config') or {}).get('digest')
|
||||||
|
if cfg:
|
||||||
|
_, _, cb=req(f'{REG}/v2/{repo}/blobs/{cfg}')
|
||||||
|
created=json.loads(cb.decode()).get('created', created)
|
||||||
|
except Exception:
|
||||||
|
created='9999-12-31T23:59:59Z'
|
||||||
|
rows.append((created, t, digest))
|
||||||
|
|
||||||
|
rows.sort(key=lambda x: x[0], reverse=True)
|
||||||
|
KEEP_N=3 # keep last 3 SHA builds (was 1; bumped to prevent auth-blast-radius wipeouts)
|
||||||
|
keep_set=set(t for _, t, _ in rows[:KEEP_N])
|
||||||
|
# preserve any -latest aliases regardless of age
|
||||||
|
keep_set.update(t for t in tags if t.endswith('-latest'))
|
||||||
|
keep_list=sorted(keep_set)
|
||||||
|
print(f'[{repo}] sha_total={len(rows)} keep={keep_list} remove={max(0, len(rows)-len(keep_set))}')
|
||||||
|
for _, t, d in rows:
|
||||||
|
if t in keep_set or not d:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
req(f'{REG}/v2/{repo}/manifests/{d}', method='DELETE')
|
||||||
|
deleted+=1
|
||||||
|
print(f' deleted {repo}:{t}')
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
print(f' delete failed {repo}:{t} code={e.code}')
|
||||||
|
except Exception as e:
|
||||||
|
print(f' delete failed {repo}:{t} err={e}')
|
||||||
|
|
||||||
|
print(f'deleted_manifests={deleted}')
|
||||||
Loading…
Add table
Reference in a new issue