Files
easyai-ai-gateway/deploy/kubernetes/production/application.yaml
T
wangbo 971540a2a4 feat(deploy): 增加三节点 K3s 高可用迁移能力
新增 WireGuard 全互联、三 server embedded-etcd K3s、CloudNativePG 双实例、Barman OSS 备份、双 NGINX、Kubernetes Secret/RBAC 与本地旧文件按严格 24 小时清理。

新增维护窗口数据迁移、digest 固定滚动发布、应用回滚、跨节点文件 E2E、节点和数据库故障演练、CNPG 恢复与 etcd 快照验收脚本;洛杉矶仅作为带 NoSchedule 污点的仲裁节点。

所有生产 Secret 只在执行时从 0600 本地环境和旧生产容器导入,仓库不保存凭据;公网入口保持人工 DNS 故障切换边界。

验证:bash -n、ShellCheck、kubectl kustomize、Node 语法检查、Secret 扫描、OSS put/head/delete 实测。
2026-07-28 04:37:31 +08:00

440 lines
11 KiB
YAML

apiVersion: apps/v1
kind: Deployment
metadata:
name: easyai-api-ningbo
labels:
app.kubernetes.io/name: easyai-api
app.kubernetes.io/component: api
app.kubernetes.io/part-of: easyai-ai-gateway
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app.kubernetes.io/name: easyai-api
easyai.io/site: ningbo
template:
metadata:
labels:
app.kubernetes.io/name: easyai-api
app.kubernetes.io/component: api
app.kubernetes.io/part-of: easyai-ai-gateway
easyai.io/site: ningbo
spec:
serviceAccountName: easyai-ai-gateway
terminationGracePeriodSeconds: 90
nodeSelector:
easyai.io/site: ningbo
easyai.io/workload: "true"
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: api
image: easyai-api
imagePullPolicy: IfNotPresent
envFrom:
- configMapRef:
name: easyai-ai-gateway-config
- secretRef:
name: easyai-ai-gateway-runtime
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
ports:
- name: http
containerPort: 8088
readinessProbe:
httpGet:
path: /api/v1/readyz
port: http
initialDelaySeconds: 3
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 6
livenessProbe:
httpGet:
path: /api/v1/healthz
port: http
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 6
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 10"]
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: "2"
memory: 2Gi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
readOnlyRootFilesystem: true
volumeMounts:
- name: application-data
mountPath: /app/data
- name: temporary-files
mountPath: /tmp
volumes:
- name: application-data
emptyDir:
sizeLimit: 5Gi
- name: temporary-files
emptyDir:
sizeLimit: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: easyai-api-hongkong
labels:
app.kubernetes.io/name: easyai-api
app.kubernetes.io/component: api
app.kubernetes.io/part-of: easyai-ai-gateway
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app.kubernetes.io/name: easyai-api
easyai.io/site: hongkong
template:
metadata:
labels:
app.kubernetes.io/name: easyai-api
app.kubernetes.io/component: api
app.kubernetes.io/part-of: easyai-ai-gateway
easyai.io/site: hongkong
spec:
serviceAccountName: easyai-ai-gateway
terminationGracePeriodSeconds: 90
nodeSelector:
easyai.io/site: hongkong
easyai.io/workload: "true"
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: api
image: easyai-api
imagePullPolicy: IfNotPresent
envFrom:
- configMapRef:
name: easyai-ai-gateway-config
- secretRef:
name: easyai-ai-gateway-runtime
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
ports:
- name: http
containerPort: 8088
readinessProbe:
httpGet:
path: /api/v1/readyz
port: http
initialDelaySeconds: 3
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 6
livenessProbe:
httpGet:
path: /api/v1/healthz
port: http
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 6
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 10"]
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: "2"
memory: 2Gi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
readOnlyRootFilesystem: true
volumeMounts:
- name: application-data
mountPath: /app/data
- name: temporary-files
mountPath: /tmp
volumes:
- name: application-data
emptyDir:
sizeLimit: 5Gi
- name: temporary-files
emptyDir:
sizeLimit: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: easyai-web-ningbo
labels:
app.kubernetes.io/name: easyai-web
app.kubernetes.io/component: web
app.kubernetes.io/part-of: easyai-ai-gateway
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app.kubernetes.io/name: easyai-web
easyai.io/site: ningbo
template:
metadata:
labels:
app.kubernetes.io/name: easyai-web
app.kubernetes.io/component: web
app.kubernetes.io/part-of: easyai-ai-gateway
easyai.io/site: ningbo
spec:
automountServiceAccountToken: false
terminationGracePeriodSeconds: 30
nodeSelector:
easyai.io/site: ningbo
easyai.io/workload: "true"
securityContext:
runAsNonRoot: true
runAsUser: 101
runAsGroup: 101
fsGroup: 101
fsGroupChangePolicy: OnRootMismatch
seccompProfile:
type: RuntimeDefault
containers:
- name: web
image: easyai-web
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 3
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 6
livenessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 6
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 500m
memory: 256Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
add: ["NET_BIND_SERVICE"]
readOnlyRootFilesystem: true
volumeMounts:
- name: nginx-cache
mountPath: /var/cache/nginx
- name: nginx-run
mountPath: /var/run
volumes:
- name: nginx-cache
emptyDir:
sizeLimit: 128Mi
- name: nginx-run
emptyDir:
sizeLimit: 16Mi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: easyai-web-hongkong
labels:
app.kubernetes.io/name: easyai-web
app.kubernetes.io/component: web
app.kubernetes.io/part-of: easyai-ai-gateway
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app.kubernetes.io/name: easyai-web
easyai.io/site: hongkong
template:
metadata:
labels:
app.kubernetes.io/name: easyai-web
app.kubernetes.io/component: web
app.kubernetes.io/part-of: easyai-ai-gateway
easyai.io/site: hongkong
spec:
automountServiceAccountToken: false
terminationGracePeriodSeconds: 30
nodeSelector:
easyai.io/site: hongkong
easyai.io/workload: "true"
securityContext:
runAsNonRoot: true
runAsUser: 101
runAsGroup: 101
fsGroup: 101
fsGroupChangePolicy: OnRootMismatch
seccompProfile:
type: RuntimeDefault
containers:
- name: web
image: easyai-web
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 3
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 6
livenessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 6
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 500m
memory: 256Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
add: ["NET_BIND_SERVICE"]
readOnlyRootFilesystem: true
volumeMounts:
- name: nginx-cache
mountPath: /var/cache/nginx
- name: nginx-run
mountPath: /var/run
volumes:
- name: nginx-cache
emptyDir:
sizeLimit: 128Mi
- name: nginx-run
emptyDir:
sizeLimit: 16Mi
---
apiVersion: v1
kind: Service
metadata:
name: api
labels:
app.kubernetes.io/name: easyai-api
app.kubernetes.io/component: api
app.kubernetes.io/part-of: easyai-ai-gateway
spec:
type: NodePort
externalTrafficPolicy: Local
selector:
app.kubernetes.io/name: easyai-api
ports:
- name: http
port: 8088
targetPort: http
nodePort: 30088
---
apiVersion: v1
kind: Service
metadata:
name: web
labels:
app.kubernetes.io/name: easyai-web
app.kubernetes.io/component: web
app.kubernetes.io/part-of: easyai-ai-gateway
spec:
type: NodePort
externalTrafficPolicy: Local
selector:
app.kubernetes.io/name: easyai-web
ports:
- name: http
port: 80
targetPort: http
nodePort: 30178
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: easyai-api
spec:
minAvailable: 1
selector:
matchLabels:
app.kubernetes.io/name: easyai-api
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: easyai-web
spec:
minAvailable: 1
selector:
matchLabels:
app.kubernetes.io/name: easyai-web