应用架构师在K8s上的核心工作不是写YAML,而是定义约束。生产集群的约束有三条:其一,同一份应用清单必须能部署到 dev/staging/prod 多集群,差异只能通过 overlay 表达,禁止复制粘贴;其二,所有工作负载必须有资源请求/限制、探针、PDB,否则调度器与驱逐器无法做出正确决策;其三,任何有状态服务必须显式声明拓扑与故障域。下面给出可落地的实现。
base 只描述"应用是什么",overlay 只描述"环境差异":
# base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata: { name: order-api }
spec:
replicas: 3
strategy:
rollingUpdate: { maxSurge: 1, maxUnavailable: 0 } # 零不可用滚动
selector: { matchLabels: { app: order-api } }
template:
metadata: { labels: { app: order-api } }
spec:
topologySpreadConstraints: # 跨AZ打散
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector: { matchLabels: { app: order-api } }
containers:
- name: app
image: registry/order-api:PLACEHOLDER # overlay 覆盖
resources:
requests: { cpu: 500m, memory: 512Mi }
limits: { memory: 1Gi } # 不设CPU limit,避免节流
readinessProbe:
httpGet: { path: /healthz, port: 8080 }
periodSeconds: 5
livenessProbe:
httpGet: { path: /livez, port: 8080 }
failureThreshold: 3
startupProbe: # 慢启动保护
httpGet: { path: /livez, port: 8080 }
failureThreshold: 30
periodSeconds: 2# overlays/prod/kustomization.yaml
resources: [../../base]
images:
- name: registry/order-api
newName: registry.prod/order-api
newTag: v1.8.2
patches:
- target: { kind: Deployment, name: order-api }
patch: |-
- op: replace
path: /spec/replicas
value: 6要点:limits 只设内存不设 CPU,是把 CPU 当作可压缩资源;设 CPU limit 会导致 CFS 节流,P99 抖动明显。这是架构层面的默认约定,应由准入策略强制。
滚动发布、节点排空、集群升级都会驱逐 Pod。没有 PDB,运维动作会瞬间打掉全部副本:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata: { name: order-api-pdb }
spec:
minAvailable: 75%
selector: { matchLabels: { app: order-api } }
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata: { name: business-critical }
value: 100000
globalDefault: false
description: "核心交易链路,驱逐顺序最后"PDB 与 maxUnavailable: 0 必须配合使用:前者保护主动驱逐,后者保护滚动更新,二者覆盖的故障路径不同。
架构师最容易犯的错是让 HPA 基于 CPU 扩缩。CPU 是滞后指标,且与 QPS 非线性。生产应以请求并发/队列深度为指标,用 KEDA 驱动:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata: { name: order-api }
spec:
scaleTargetRef: { name: order-api }
minReplicaCount: 3
maxReplicaCount: 30
cooldownPeriod: 300
triggers:
- type: prometheus
metadata:
serverAddress: http://prometheus.monitoring:9090
query: |
sum(rate(http_requests_in_flight{app="order-api"}[1m]))
threshold: "20" # 每副本承载20并发
advanced:
horizontalPodAutoscalerConfig:
behavior:
scaleDown:
stabilizationWindowSeconds: 300 # 防抖,避免震荡stabilizationWindowSeconds 是必需的:没有它,流量瞬时回落会引发反复扩缩,成本与稳定性双输。
数据库类负载需要稳定网络标识与独立存储。架构上要求 podAntiAffinity 保证每副本落在不同节点,否则单节点故障会导致多数派丢失:
apiVersion: apps/v1
kind: StatefulSet
metadata: { name: pg }
spec:
serviceName: pg-headless
replicas: 3
template:
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: kubernetes.io/hostname
labelSelector: { matchLabels: { app: pg } }
containers:
- name: postgres
image: postgres:16
volumeMounts: [{ name: data, mountPath: /var/lib/postgresql/data }]
volumeClaimTemplates:
- metadata: { name: data }
spec:
accessModes: [ReadWriteOnce]
storageClassName: local-ssd # 本地盘,需配合node亲和
resources: { requests: { storage: 200Gi } }GitOps 落地用 Argo CD 的 ApplicationSet 按 overlay 生成多集群应用,配合 Argo Rollouts 做金丝雀(10% → 30% → 100%,按错误率与 P99 自动推进或回滚)。验收清单应固化为准入策略(Kyverno/Gatekeeper):未设 resources、缺 readinessProbe、无 PDB 的 Deployment 一律拒绝创建。
架构师的价值在于把上述约束变成平台默认值,而不是逐个项目 review YAML。约束前移、差异收敛到 overlay、弹性基于真实业务指标——这三条决定了K8s集群是可运维的资产还是事故来源。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。