backend scaffold
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
# Dev 的配置,由 scripts/deploy-dev.sh apply 到内网 k3s 集群的 retailapp-dev namespace。
|
||||
# Dev 的数据库跑在同一台 Ubuntu 机器上(不是 Azure Flexible Server),所以连的是集群内的 Service。
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: conti-backend-env
|
||||
namespace: retailapp-dev
|
||||
data:
|
||||
DB_HOST: "mysql.retailapp-dev.svc.cluster.local"
|
||||
DB_USERNAME: "conti"
|
||||
SECURITY_JWT_ACTIVE_KEY_ID: "v1"
|
||||
# Dev 环境暂时没有可用的 F6 / O2O 联调地址,先指向不存在的地址,
|
||||
# 走的就是降级路径——这本身也是对 fallback 的一次真实验证(见 05-integration-layer.md)
|
||||
F6_BASE_URL: "http://f6-not-available.retailapp-dev.svc.cluster.local"
|
||||
MINI_BASE_URL: "http://mini-not-available.retailapp-dev.svc.cluster.local"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: conti-backend-config
|
||||
namespace: retailapp-dev
|
||||
data:
|
||||
application-dev.yml: |
|
||||
# Dev 上放开到 DEBUG,方便团队排查;改这一项是热更新的典型用例,
|
||||
# 改完 15 秒生效,不用重新部署
|
||||
logging:
|
||||
level:
|
||||
com.continental.retailapp: DEBUG
|
||||
|
||||
resilience4j:
|
||||
circuitbreaker:
|
||||
instances:
|
||||
f6-api:
|
||||
failure-rate-threshold: 50
|
||||
slow-call-duration-threshold: 1500ms
|
||||
@@ -0,0 +1,37 @@
|
||||
# Prod 的配置。结构与 configmap-uat.yaml 完全一致,只有取值不同——
|
||||
# 环境差异全部收敛在这里,Deployment 之间只差 namespace 和 profile。
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: conti-backend-env
|
||||
namespace: retailapp-prod
|
||||
data:
|
||||
# UAT 和 Prod 是两个**独立的** Flexible Server 实例,不是同一实例上的两个 database——
|
||||
# 共用实例意味着 UAT 的一次压测能直接影响生产(见 09-build-deploy.md 阶段五)
|
||||
DB_HOST: "conti-mysql-prod.mysql.database.azure.com"
|
||||
DB_USERNAME: "conti_app"
|
||||
SECURITY_JWT_ACTIVE_KEY_ID: "v1"
|
||||
F6_BASE_URL: "https://f6.internal.example.com"
|
||||
MINI_BASE_URL: "https://mini.internal.example.com"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: conti-backend-config
|
||||
namespace: retailapp-prod
|
||||
data:
|
||||
application-prod.yml: |
|
||||
logging:
|
||||
level:
|
||||
root: INFO
|
||||
com.continental.retailapp: INFO
|
||||
# 生产绝不打开 SQL 日志:绑定参数里会带 PII(见 08-observability.md)
|
||||
org.hibernate.SQL: WARN
|
||||
|
||||
# 同 UAT:改了要走发布才生效,不是热更新
|
||||
resilience4j:
|
||||
circuitbreaker:
|
||||
instances:
|
||||
f6-api:
|
||||
failure-rate-threshold: 50
|
||||
slow-call-duration-threshold: 1500ms
|
||||
@@ -0,0 +1,44 @@
|
||||
# UAT 的配置。两个 ConfigMap,用途不同,别合并:
|
||||
#
|
||||
# - conti-backend-env:以**环境变量**注入(Deployment 的 envFrom),application.yml 里
|
||||
# ${DB_HOST} 这类占位符从这里取值。改了必须重启 Pod 才生效。
|
||||
# - conti-backend-config:由 spring-cloud-kubernetes 直接读 K8s API 拿到(不挂卷),
|
||||
# 15 秒轮询一次,改了能热更新——但只对 @RefreshScope bean 生效,见下面的注释。
|
||||
#
|
||||
# 敏感值一个都不在这里,全在 Secret 里(见 secret-uat.yaml)。
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: conti-backend-env
|
||||
namespace: retailapp-uat
|
||||
data:
|
||||
# Azure Database for MySQL Flexible Server,通过 Private Endpoint 接入 AKS 所在 VNet。
|
||||
# 连接串里的 sslMode=REQUIRED 写在 application.yml 中,Flexible Server 默认要求 TLS。
|
||||
DB_HOST: "conti-mysql-uat.mysql.database.azure.com"
|
||||
# 运行时账号,只有 DML 权限;迁移用的 DDL 账号是另一个(见 09-build-deploy.md)
|
||||
DB_USERNAME: "conti_app"
|
||||
SECURITY_JWT_ACTIVE_KEY_ID: "v1"
|
||||
F6_BASE_URL: "https://f6-uat.internal.example.com"
|
||||
MINI_BASE_URL: "https://mini-uat.internal.example.com"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: conti-backend-config
|
||||
namespace: retailapp-uat
|
||||
data:
|
||||
application-uat.yml: |
|
||||
# 这一段是**能**热更新的:改完 15 秒内通过 /actuator/loggers 同样的机制生效
|
||||
logging:
|
||||
level:
|
||||
com.continental.retailapp: INFO
|
||||
|
||||
# 这一段是**不能**热更新的,放在这里只是为了让阈值和代码分离、改的时候不用重新构建镜像。
|
||||
# resilience4j 的实例在启动时创建,普通 refresh 刷不到它们——改完要走一次发布
|
||||
# (或者 strategy: restart_context,等于一次内部重启)。见 07-config-governance.md 的表格。
|
||||
resilience4j:
|
||||
circuitbreaker:
|
||||
instances:
|
||||
f6-api:
|
||||
failure-rate-threshold: 50
|
||||
slow-call-duration-threshold: 1500ms
|
||||
@@ -0,0 +1,104 @@
|
||||
# Dev:跑在公司内网一台 Ubuntu 服务器的 k3s 上,不接 CI/CD,由 scripts/deploy-dev.sh 手动 apply
|
||||
# (见 09-build-deploy.md「环境层级」)。
|
||||
#
|
||||
# 跟 UAT/Prod 的两处有意差别:
|
||||
# 1. replicas: 1 —— 单节点 k3s,起两个副本没有可用性收益,只是多占内存;
|
||||
# 代价是滚动更新期间会有短暂不可用,Dev 环境可以接受,所以也不配 PDB。
|
||||
# 2. requests 调小 —— 这台机器上还跑着别的东西。
|
||||
# 其余(探针、优雅停机、securityContext)与另外两份保持一致,
|
||||
# 这正是 Dev 用真 K8s 而不是 docker compose 的意义:验证的是真实部署行为。
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: conti-backend
|
||||
namespace: retailapp-dev
|
||||
labels:
|
||||
app: conti-backend
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: conti-backend
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxUnavailable: 0
|
||||
maxSurge: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: conti-backend
|
||||
spec:
|
||||
serviceAccountName: conti-backend
|
||||
terminationGracePeriodSeconds: 45
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: conti-backend
|
||||
image: registry.example.com/conti-backend:__TAG__
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
env:
|
||||
- name: SPRING_PROFILES_ACTIVE
|
||||
value: dev
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: conti-backend-env
|
||||
# Dev 的 Secret 是写死的假值,由 scripts/deploy-dev.sh 创建,不接 Key Vault
|
||||
- secretRef:
|
||||
name: conti-backend-secret
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
resources:
|
||||
requests:
|
||||
cpu: "250m"
|
||||
memory: "768Mi"
|
||||
limits:
|
||||
memory: "1536Mi"
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/liveness
|
||||
port: 8080
|
||||
periodSeconds: 5
|
||||
failureThreshold: 30
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/liveness
|
||||
port: 8080
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/readiness
|
||||
port: 8080
|
||||
periodSeconds: 5
|
||||
lifecycle:
|
||||
preStop:
|
||||
exec:
|
||||
command: ["sh", "-c", "sleep 10"]
|
||||
volumeMounts:
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: conti-backend
|
||||
namespace: retailapp-dev
|
||||
labels:
|
||||
app: conti-backend
|
||||
spec:
|
||||
selector:
|
||||
app: conti-backend
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 8080
|
||||
@@ -0,0 +1,97 @@
|
||||
# Prod。与 deployment-uat.yaml 逐字一致,只差 namespace 和 SPRING_PROFILES_ACTIVE
|
||||
# ——两个环境跑的是同一个镜像,差异只在外部注入的配置上(见 09-build-deploy.md 附录)。
|
||||
# 改动这份时请同步改另外两份,别让三份漂移。
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: conti-backend
|
||||
namespace: retailapp-prod
|
||||
labels:
|
||||
app: conti-backend
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: conti-backend
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxUnavailable: 0
|
||||
maxSurge: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: conti-backend
|
||||
spec:
|
||||
serviceAccountName: conti-backend
|
||||
terminationGracePeriodSeconds: 45
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: conti-backend
|
||||
image: registry.example.com/conti-backend:__TAG__
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
env:
|
||||
- name: SPRING_PROFILES_ACTIVE
|
||||
value: prod
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: conti-backend-env
|
||||
- secretRef:
|
||||
name: conti-backend-secret
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
resources:
|
||||
requests:
|
||||
cpu: "500m"
|
||||
memory: "1Gi"
|
||||
limits:
|
||||
memory: "2Gi"
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/liveness
|
||||
port: 8080
|
||||
periodSeconds: 5
|
||||
failureThreshold: 30
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/liveness
|
||||
port: 8080
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health/readiness
|
||||
port: 8080
|
||||
periodSeconds: 5
|
||||
lifecycle:
|
||||
preStop:
|
||||
exec:
|
||||
command: ["sh", "-c", "sleep 10"]
|
||||
volumeMounts:
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: conti-backend
|
||||
namespace: retailapp-prod
|
||||
labels:
|
||||
app: conti-backend
|
||||
spec:
|
||||
selector:
|
||||
app: conti-backend
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 8080
|
||||
@@ -0,0 +1,113 @@
|
||||
# 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
|
||||
@@ -0,0 +1,28 @@
|
||||
# PodDisruptionBudget:保证节点维护、AKS 节点池升级这类**自愿中断**时至少留一个副本在跑。
|
||||
# 没有它,一次节点池升级可能把两个副本同时驱逐,造成一次没人预料到的短暂全站不可用。
|
||||
#
|
||||
# 注意 PDB 只管自愿中断(drain/evict),管不了节点宕机、OOMKilled 这类非自愿中断——
|
||||
# 那是 replicas + 探针的事。
|
||||
#
|
||||
# Dev 没有 PDB:单节点 k3s 上 replicas=1,minAvailable: 1 会让节点永远 drain 不掉。
|
||||
apiVersion: policy/v1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: conti-backend-pdb
|
||||
namespace: retailapp-uat
|
||||
spec:
|
||||
minAvailable: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: conti-backend
|
||||
---
|
||||
apiVersion: policy/v1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: conti-backend-pdb
|
||||
namespace: retailapp-prod
|
||||
spec:
|
||||
minAvailable: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: conti-backend
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
# spring-cloud-kubernetes 是在 Pod 里调 K8s API 去读 ConfigMap 的,
|
||||
# 默认的 default ServiceAccount 没有这个权限——漏了这份清单,应用启动时读配置会 403,
|
||||
# 而且 reload 的轮询会每 15 秒报一次错(见 07-config-governance.md「关键规则」)。
|
||||
#
|
||||
# 权限严格收敛到"读所在 namespace 的 ConfigMap"这一件事:
|
||||
# - 不给 secrets 的 get/list:Secret 是通过 envFrom 由 kubelet 注入的,应用自己不需要读;
|
||||
# 给了反而等于让一次 RCE 直接拿到 JWT 签名密钥。
|
||||
# - 用 Role 而不是 ClusterRole:跨 namespace 读不到,UAT 的 Pod 看不见 Prod 的配置。
|
||||
# - reload 用的是 mode: polling 而不是 event,所以不需要 watch 权限。
|
||||
#
|
||||
# 三个 namespace 各一份,内容相同。
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: conti-backend
|
||||
namespace: retailapp-dev
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: conti-backend-config-reader
|
||||
namespace: retailapp-dev
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["configmaps"]
|
||||
verbs: ["get", "list"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: conti-backend-config-reader
|
||||
namespace: retailapp-dev
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: conti-backend-config-reader
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: conti-backend
|
||||
namespace: retailapp-dev
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: conti-backend
|
||||
namespace: retailapp-uat
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: conti-backend-config-reader
|
||||
namespace: retailapp-uat
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["configmaps"]
|
||||
verbs: ["get", "list"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: conti-backend-config-reader
|
||||
namespace: retailapp-uat
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: conti-backend-config-reader
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: conti-backend
|
||||
namespace: retailapp-uat
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: conti-backend
|
||||
namespace: retailapp-prod
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: conti-backend-config-reader
|
||||
namespace: retailapp-prod
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["configmaps"]
|
||||
verbs: ["get", "list"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: conti-backend-config-reader
|
||||
namespace: retailapp-prod
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: conti-backend-config-reader
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: conti-backend
|
||||
namespace: retailapp-prod
|
||||
@@ -0,0 +1,27 @@
|
||||
# 这份文件**只是形状说明**,不是拿来 apply 的。
|
||||
#
|
||||
# 真实值由 deploy-uat job 在流水线里从 Azure Key Vault 现取现渲染:
|
||||
#
|
||||
# JWT_KEY=$(az keyvault secret show --vault-name conti-backend-kv --name security-jwt-key-v1 ...)
|
||||
# kubectl create secret generic conti-backend-secret -n retailapp-uat \
|
||||
# --from-literal=SECURITY_JWT_SECRET="$JWT_KEY" ... | kubectl apply -f -
|
||||
#
|
||||
# 密钥只在那个 job 的执行过程中短暂存在,不落盘、不进镜像、不进 git。
|
||||
# 谁要是把真值填进这个文件并提交,即使之后再删掉,也已经永久留在 git 历史里了——
|
||||
# 那时候唯一正确的处理是轮换密钥,而不是改一次提交。
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: conti-backend-secret
|
||||
namespace: retailapp-uat
|
||||
type: Opaque
|
||||
stringData:
|
||||
# HS256 签名密钥,base64 编码;解码后必须 ≥ 32 字节,否则 JwtProperties 在启动时就拒绝
|
||||
# (见 04-security-auth.md)。轮换时先加 SECURITY_JWT_KEYS_V2,再切 ACTIVE_KEY_ID,
|
||||
# 最后一步才移除 V1——三步之间要隔开,否则已签发的 token 会集体失效。
|
||||
SECURITY_JWT_SECRET: "__injected_by_pipeline__"
|
||||
# 运行时账号的密码(只有 DML 权限),迁移账号的密码是另一个
|
||||
DB_PASSWORD: "__injected_by_pipeline__"
|
||||
# F6 的调用凭证。骨架里 IntegrationClientProperties.ClientConfig 还没有 apiKey 字段,
|
||||
# F6ApiClient 也还没往请求头上挂它——接入 F6 真实鉴权时补上这两处,这个 key 就有人用了。
|
||||
F6_API_KEY: "__injected_by_pipeline__"
|
||||
Reference in New Issue
Block a user