# UAT 环境的部署清单。这是三个环境里的"基准版本"—— # deployment-dev.yaml / deployment-prod.yaml 与它的差别只有 namespace、副本数和镜像 tag, # 其余(探针、优雅停机、securityContext、资源)三份完全一致, # 避免出现"UAT 好好的、生产漏配了一项"这类问题(见 07-config-governance.md)。 # # 内容来源:09-build-deploy.md「Deployment 清单」+ 08-observability.md「K8s 探针配置」 # + 07-config-governance.md「ConfigMap / Secret 示例」,三处合并成同一份可 apply 的清单。 apiVersion: apps/v1 kind: Deployment metadata: name: conti-backend namespace: retailapp-uat labels: app: conti-backend spec: replicas: 2 selector: matchLabels: app: conti-backend strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 0 # 更新期间不允许可用副本数低于 replicas,先起新的再停旧的 maxSurge: 1 # 同时只有一个新 Pod 启动,配合 Flyway 表级锁,不会并发迁移 template: metadata: labels: app: conti-backend spec: # Pod 要能读所在 namespace 的 ConfigMap(spring-cloud-kubernetes 走 K8s API), # 权限见同目录的 rbac.yaml serviceAccountName: conti-backend terminationGracePeriodSeconds: 45 # 必须 > preStop 等待(10) + 应用 graceful 超时(25) securityContext: runAsNonRoot: true # 镜像里 USER 写的是数字 10001,这条才校验得过 seccompProfile: type: RuntimeDefault containers: - name: conti-backend # 初始占位;实际版本由流水线的 `kubectl set image` 覆盖, # 部署的永远是 cut-release 打出来的那个不可变 tag(见 09-build-deploy.md 阶段三) image: registry.example.com/conti-backend:__TAG__ ports: - name: http containerPort: 8080 env: - name: SPRING_PROFILES_ACTIVE value: uat envFrom: # 非敏感的环境变量(DB_HOST / DB_USERNAME / F6_BASE_URL ...) - configMapRef: name: conti-backend-env # 敏感值(DB_PASSWORD / SECURITY_JWT_SECRET),由流水线从 Key Vault 现取现渲染 - secretRef: name: conti-backend-secret # 注:07 文档的示例里还把 conti-backend-config 挂成了 /app/config 卷。 # 这里没有挂——应用已经通过 spring.cloud.kubernetes.config.sources 直接读同一个 # ConfigMap,两条路都开着等于同一份配置有两个来源,出问题时说不清以谁为准; # 而且热更新只有走 spring-cloud-kubernetes 这条路才生效。 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: ["ALL"] resources: requests: cpu: "500m" memory: "1Gi" limits: memory: "2Gi" # 只限内存,不限 CPU:cfs 限流会让延迟毫无规律地抖动 startupProbe: # 启动阶段专用,跑通之前 liveness/readiness 都不生效 httpGet: path: /actuator/health/liveness port: 8080 periodSeconds: 5 failureThreshold: 30 # 最多给 150 秒完成 JVM 启动 + Flyway 迁移 livenessProbe: httpGet: path: /actuator/health/liveness port: 8080 periodSeconds: 10 readinessProbe: httpGet: path: /actuator/health/readiness port: 8080 periodSeconds: 5 lifecycle: preStop: exec: # 把 SIGTERM 推迟 10 秒,等 Endpoints 摘除在各节点生效, # 否则滚动更新期间会有零星 502(见 09-build-deploy.md) command: ["sh", "-c", "sleep 10"] volumeMounts: - name: tmp mountPath: /tmp # readOnlyRootFilesystem 的必需配套:内嵌 Tomcat 要可写的临时目录 volumes: - name: tmp emptyDir: {} --- apiVersion: v1 kind: Service metadata: name: conti-backend namespace: retailapp-uat labels: app: conti-backend spec: selector: app: conti-backend ports: - name: http port: 80 targetPort: 8080