feat(k8s): 新增 core 真应用(前端+Django API+Celery worker)构建与部署

- core/frontend: Vite 多阶段镜像 + nginx 同源反代 /api,/admin,/static(零 CORS)
- core/backend: Django gunicorn 镜像 + entrypoint(自动 migrate/collectstatic)+ WhiteNoise
- k8s/core: api/worker/web Deployment+Service + ingress(airshelf-web.airlabs.art)
- workflow: 追加 core 前后端 build/push,从 core/backend/.env 套生产覆盖生成 env Secret 后部署
- .gitignore 放行 core/backend/.env;.env 白名单加入 airshelf-web 域名
- 含前端 WIP 还原改动

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
zyc
2026-06-05 10:21:41 +08:00
co-authored by Claude Opus 4.8
parent cfdcd84a30
commit d41e487f08
37 changed files with 4108 additions and 456 deletions
+70
View File
@@ -0,0 +1,70 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: airshelf-core-api
labels:
app: airshelf-core-api
spec:
replicas: 1
selector:
matchLabels:
app: airshelf-core-api
template:
metadata:
labels:
app: airshelf-core-api
spec:
imagePullSecrets:
- name: cr-pull-secret
containers:
- name: airshelf-core-api
image: ${CI_REGISTRY_IMAGE}/airshelf-core-api:latest
imagePullPolicy: Always
# No command override: the image ENTRYPOINT (docker-entrypoint.sh) runs
# migrate + collectstatic, then the default CMD (gunicorn) is exec'd.
ports:
- containerPort: 8000
envFrom:
- secretRef:
name: airshelf-core-env
livenessProbe:
httpGet:
path: /api/health/
port: 8000
httpHeaders:
- name: Host
value: airshelf-web.airlabs.art
initialDelaySeconds: 20
periodSeconds: 15
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /api/health/
port: 8000
httpHeaders:
- name: Host
value: airshelf-web.airlabs.art
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "768Mi"
cpu: "1000m"
---
apiVersion: v1
kind: Service
metadata:
name: airshelf-core-api
spec:
selector:
app: airshelf-core-api
ports:
- protocol: TCP
port: 8000
targetPort: 8000
+24
View File
@@ -0,0 +1,24 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: airshelf-core-ingress
annotations:
kubernetes.io/ingress.class: "traefik"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
traefik.ingress.kubernetes.io/router.middlewares: "default-redirect-https@kubernetescrd"
spec:
tls:
- hosts:
- airshelf-web.airlabs.art
secretName: airshelf-core-tls
rules:
- host: airshelf-web.airlabs.art
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: airshelf-core-web
port:
number: 80
+59
View File
@@ -0,0 +1,59 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: airshelf-core-web
labels:
app: airshelf-core-web
spec:
replicas: 1
selector:
matchLabels:
app: airshelf-core-web
template:
metadata:
labels:
app: airshelf-core-web
spec:
imagePullSecrets:
- name: cr-pull-secret
containers:
- name: airshelf-core-web
image: ${CI_REGISTRY_IMAGE}/airshelf-core-web:latest
imagePullPolicy: Always
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
resources:
requests:
memory: "32Mi"
cpu: "20m"
limits:
memory: "128Mi"
cpu: "150m"
---
apiVersion: v1
kind: Service
metadata:
name: airshelf-core-web
spec:
selector:
app: airshelf-core-web
ports:
- protocol: TCP
port: 80
targetPort: 80
+43
View File
@@ -0,0 +1,43 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: airshelf-core-worker
labels:
app: airshelf-core-worker
spec:
replicas: 1
selector:
matchLabels:
app: airshelf-core-worker
template:
metadata:
labels:
app: airshelf-core-worker
spec:
imagePullSecrets:
- name: cr-pull-secret
containers:
- name: airshelf-core-worker
image: ${CI_REGISTRY_IMAGE}/airshelf-core-api:latest
imagePullPolicy: Always
# Celery worker connects to the external (Volcano managed) Redis broker
# configured via the airshelf-core-env secret. Uses `args` (not `command`)
# so the image ENTRYPOINT still runs but skips migrate/collectstatic ($1=celery).
args: ["celery", "-A", "airshelf.celery:app", "worker", "-l", "info", "--concurrency", "2"]
envFrom:
- secretRef:
name: airshelf-core-env
livenessProbe:
exec:
command: ["sh", "-c", "celery -A airshelf.celery:app inspect ping"]
initialDelaySeconds: 40
periodSeconds: 60
timeoutSeconds: 15
failureThreshold: 3
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "768Mi"
cpu: "1000m"