Kubernetes最佳实践:生产环境配置规范
Kubernetes 最佳实践完全指南:生产环境配置规范
摘要:Kubernetes 在生产环境的稳定运行不是"装上就跑"——它需要从 Pod 资源配置、安全上下文、网络隔离、自动扩缩容、故障容忍、可观测性等多维度系统化规范。本文基于 Kubernetes 1.28+(覆盖 1.30 / 1.31),结合 CNCF、阿里云、字节跳动等大厂的实战经验,给出一份可直接落地的生产配置清单,每个资源都给出完整 YAML 示例 + 关键字段解释 + 常见坑点。
适用版本:Kubernetes 1.28 - 1.31(GA) 读者:SRE / 平台工程师 / 后端开发
一、生产环境配置核心原则
在开始看 YAML 之前,先记住这几条贯穿全文的原则:
- 声明式 + 版本化:所有 YAML 全部进 Git,走 GitOps(Argo CD / Flux)
- 最小权限:每个 ServiceAccount 只给能用到的 RBAC
- 资源可观测:每个 Pod 必须有 requests/limits,否则被驱逐都不知道为什么
- 故障自愈:Deployment 用 HPA + PDB + 多副本,避免单点
- 安全默认:Pod 跑非 root、只读文件系统、禁止特权升级
- 可声明验证:用
kube-linter/conftest/ OPA 在 CI 阶段拦截错误配置
二、Pod 配置规范(核心)
2.1 一个生产可用的 Pod 模板
apiVersion: v1
kind: Pod
metadata:
name: app-pod
namespace: prod
labels:
app: backend
version: v1.2.3
tier: api
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9090"
prometheus.io/path: "/metrics"
spec:
# 安全上下文(整个 Pod 生效)
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
fsGroupChangePolicy: OnRootMismatch
seccompProfile:
type: RuntimeDefault
# 服务账号
serviceAccountName: backend-sa
# 自动挂载(避免意外泄露 token)
automountServiceAccountToken: false
# 域名配置(k8s 默认)
dnsPolicy: ClusterFirst
dnsConfig:
options:
- name: ndots
value: "2"
# 优雅停机
terminationGracePeriodSeconds: 30
# 调度约束
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: backend
topologyKey: kubernetes.io/hostname
containers:
- name: app
image: registry.example.com/team/app:v1.2.3
imagePullPolicy: IfNotPresent
# 容器级安全
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
capabilities:
drop: ["ALL"]
# 端口定义
ports:
- name: http
containerPort: 8080
protocol: TCP
- name: metrics
containerPort: 9090
protocol: TCP
# 资源配置(**必填**)
resources:
requests:
cpu: "100m"
memory: "128Mi"
ephemeral-storage: "500Mi"
limits:
cpu: "500m"
memory: "256Mi"
ephemeral-storage: "1Gi"
# 探针(**三探针必填**)
startupProbe:
httpGet:
path: /healthz
port: http
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 30
livenessProbe:
httpGet:
path: /healthz
port: http
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: http
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 2
# 环境变量
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: TZ
value: "Asia/Shanghai"
# 数据卷
volumeMounts:
- name: tmp
mountPath: /tmp
- name: cache
mountPath: /app/cache
volumes:
- name: tmp
emptyDir: {}
- name: cache
emptyDir:
sizeLimit: 1Gi
2.2 关键字段详解
| 字段 | 为什么必填 |
|---|---|
resources.requests | 调度器用,没填可能被调度到资源不够的节点 |
resources.limits | 防止单 Pod 吃光节点资源 |
securityContext.runAsNonRoot | 防容器内提权 |
readOnlyRootFilesystem: true | 容器文件系统只读,攻击者无法写二进制 |
startupProbe | 慢启动应用避免被 liveness 误杀 |
livenessProbe | 死循环必须重启,但别用错路径导致重启风暴 |
readinessProbe | 控制 Service 后端流量,避免启动期收到请求 |
terminationGracePeriodSeconds | 优雅停机时长,配合 preStop hook 处理 in-flight 请求 |
imagePullPolicy: IfNotPresent | 减少每次重启拉镜像的网络开销 |
坑点 1:
livenessProbe的 path 必须真的存在且返回 200。如果健康检查挂,应用就被杀;恢复需要重新拉镜像启动,时间长。慢启动应用必须用startupProbe给宽限时间。 坑点 2:resources.requests和limits都填的话,QoS 类是Burstable;想让 Pod 享受Guaranteed(最稳定),requests == limits。BestEffort(无 requests)会被节点压力时最先驱逐。
三、Deployment 规范
3.1 多副本 + 滚动更新 + 历史保留
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-api
namespace: prod
labels:
app: backend
spec:
replicas: 3
revisionHistoryLimit: 10
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25% # 允许超出 replicas 25%
maxUnavailable: 0 # 滚动期间零停机
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
version: v1.2.3
spec:
# ... 同 Pod 模板部分,省略
3.2 关键字段
revisionHistoryLimit: 10:保留 10 个历史版本,方便回滚maxSurge + maxUnavailable:滚动策略参数,生产建议maxUnavailable: 0(不中断服务)strategy.type: RollingUpdate:默认即可;金丝雀用蓝绿或 Argo Rolloutsselector.matchLabels必须稳定:改 selector 等于创建新 Deployment
四、Service 规范
4.1 ClusterIP + 注解
apiVersion: v1
kind: Service
metadata:
name: backend-api
namespace: prod
labels:
app: backend
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9090"
spec:
type: ClusterIP
selector:
app: backend
ports:
- name: http
port: 80
targetPort: http # 引用 Pod 端口名
protocol: TCP
- name: metrics
port: 9090
targetPort: metrics
protocol: TCP
# k8s 1.30+ 可启用 trafficDistribution(v1.31 GA)
# internalTrafficPolicy: Cluster
4.2 Service 类型选型
| 类型 | 用途 |
|---|---|
ClusterIP | 集群内部访问(默认) |
NodePort | 简单暴露,端口 30000-32767(开发测试用) |
LoadBalancer | 云厂商集成,自动创建 LB(生产推荐) |
ExternalName | CNAME 别名,访问外部服务 |
坑点 3:生产不要用 NodePort 直接对外——它会暴露到所有节点 IP,安全风险大。NodePort 之上套一层 Ingress / Gateway API。
五、HPA 自动扩缩容
5.1 基于 CPU/Memory 的 HPA
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: backend-api-hpa
namespace: prod
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: backend-api
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleDown:
stabilizationWindowSeconds: 300 # 缩容缓冲 5 分钟
policies:
- type: Percent
value: 50
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 0 # 扩容立即响应
policies:
- type: Percent
value: 100
periodSeconds: 30
5.2 自定义指标 + KEDA
生产环境光 CPU/Memory 不够。推荐用 KEDA(事件驱动扩缩):
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: backend-api-keda
namespace: prod
spec:
scaleTargetRef:
name: backend-api
minReplicaCount: 3
maxReplicaCount: 100
triggers:
- type: prometheus
metadata:
serverAddress: http://prometheus.monitoring:9090
metricName: http_requests_per_second
query: |
sum(rate(http_requests_total{namespace="prod",service="backend-api"}[1m]))
threshold: "1000"
坑点 4:HPA 需要 metrics-server(或 KEDA Prometheus adapter),否则
kubectl get hpa显示<unknown>/70%。生产前先kubectl top nodes验证 metrics-server 工作。
六、PVC 持久化存储
6.1 动态 PVC + StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ssd-retain
provisioner: kubernetes.io/aws-ebs # 或 alicloud-disk / ceph-csi
parameters:
type: gp3
fsType: ext4
reclaimPolicy: Retain # 数据安全第一
volumeBindingMode: WaitForFirstConsumer # 等 Pod 调度再创建卷
allowVolumeExpansion: true
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-data
namespace: prod
spec:
storageClassName: ssd-retain
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 100Gi
坑点 5:
reclaimPolicy默认Delete,PVC 删除后云盘跟着删——数据没了。生产用Retain或手动Retain+定期备份。
6.2 挂载到 Pod
volumeMounts:
- name: data
mountPath: /app/data
volumes:
- name: data
persistentVolumeClaim:
claimName: app-data
七、NetworkPolicy 网络隔离
生产集群必须配 NetworkPolicy——默认所有 Pod 之间互通,是巨大安全风险。
7.1 默认拒绝所有入站
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: prod
spec:
podSelector: {} # 匹配所有 Pod
policyTypes:
- Ingress
# 可选:再加 Egress
7.2 允许前端访问后端 API
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-allow-frontend
namespace: prod
spec:
podSelector:
matchLabels:
app: backend
tier: api
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
坑点 6:NetworkPolicy 需要 CNI 插件支持(Calico / Cilium / Weave)。Flannel 不支持(无策略 enforcement)。装集群前先选好 CNI。
八、PodDisruptionBudget 故障容忍
8.1 标准 PDB
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: backend-api-pdb
namespace: prod
spec:
minAvailable: 2 # 至少保留 2 个 Pod 可用
# 或者用百分比
# minAvailable: 50%
selector:
matchLabels:
app: backend
坑点 7:节点维护、cluster-autoscaler 缩容时,PDB 防止"全部 Pod 被同时驱逐导致服务不可用"。生产必须有 PDB,否则一次节点升级就能让服务雪崩。
九、LimitRange 与 ResourceQuota
9.1 命名空间资源配额
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: prod
spec:
limits:
- type: Container
default:
cpu: "500m"
memory: "512Mi"
ephemeral-storage: "1Gi"
defaultRequest:
cpu: "100m"
memory: "128Mi"
max:
cpu: "2"
memory: "4Gi"
- type: PersistentVolumeClaim
max:
storage: 100Gi
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: prod-quota
namespace: prod
spec:
hard:
pods: "100"
requests.cpu: "50"
requests.memory: "100Gi"
limits.cpu: "100"
limits.memory: "200Gi"
persistentvolumeclaims: "50"
requests.storage: "1Ti"
坑点 8:用
LimitRange.default给 namespace 加默认值,Pod 没填 requests/limits 也会自动补上。这是防呆设计。
十、ServiceAccount 与 RBAC
10.1 最小权限 SA
apiVersion: v1
kind: ServiceAccount
metadata:
name: backend-sa
namespace: prod
automountServiceAccountToken: false # 默认不挂 token
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: backend-role
namespace: prod
rules:
- apiGroups: [""]
resources: ["configmaps", "secrets"]
resourceNames: ["backend-config"]
verbs: ["get", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: backend-rb
namespace: prod
subjects:
- kind: ServiceAccount
name: backend-sa
namespace: prod
roleRef:
kind: Role
name: backend-role
apiGroup: rbac.authorization.k8s.io
10.2 Pod 引用 SA
spec:
serviceAccountName: backend-sa
automountServiceAccountToken: true # 显式开
坑点 9:
automountServiceAccountToken: false时 Pod 内不会挂/var/run/secrets/kubernetes.io/serviceaccount/token——如果应用要调 k8s API 必须显式开。
十一、镜像拉取与镜像策略
11.1 私有仓库凭据
kubectl create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=team \
--docker-password=xxxxx \
--docker-email=team@example.com \
-n prod
spec:
imagePullSecrets:
- name: regcred
containers:
- name: app
image: registry.example.com/team/app:v1.2.3
11.2 镜像标签规范
| 标签 | 何时用 |
|---|---|
固定版本 v1.2.3 | 生产 ✅ 强烈推荐 |
摘要 @sha256:xxx | 最安全(不可变)✅ 极致推荐 |
latest | 永远不要 ❌ |
stable、main、dev | 仅开发环境 |
十二、Ingress 入口
12.1 生产 Ingress(nginx-ingress 示例)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: backend-api
namespace: prod
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- api.example.com
secretName: api-tls
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: backend-api
port:
number: 80
坑点 10:Ingress 必须配
ingressClassName,否则 controller 不接管。pathType: Prefix比ImplementationSpecific更明确,新版本推荐Prefix或Exact。
十三、健康检查与可观测性
13.1 三探针必填
| 探针 | 作用 | 何时失败 |
|---|---|---|
startupProbe | 慢启动保护 | 启动期不健康时不杀 |
livenessProbe | 死循环检测 | 重启 Pod |
readinessProbe | 流量控制 | Service 剔除该 Pod 后端 |
13.2 Prometheus 注解
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9090"
prometheus.io/path: "/metrics"
13.3 结构化日志
容器日志必须输出 JSON 到 stdout,让 Fluent Bit / Vector 收集:
# Python 示例
import logging, json
class JsonFormatter(logging.Formatter):
def format(self, record):
return json.dumps({
"ts": record.created,
"level": record.levelname,
"msg": record.getMessage(),
"logger": record.name,
})
logging.basicConfig(level=logging.INFO, handlers=[logging.StreamHandler()])
十四、命名规范
| 资源类型 | 规范 | 示例 |
|---|---|---|
| Namespace | <环境>-<业务线> | prod-payments, staging-search |
| Deployment | <业务>-<组件> | payments-api, payments-worker |
| Service | 同 Deployment | payments-api |
| ConfigMap | <业务>-<用途> | payments-config, payments-redis-conf |
| Secret | <业务>-<用途> | payments-db-cred |
| ServiceAccount | <业务>-sa | payments-sa |
| PVC | <业务>-<用途> | payments-data, payments-cache |
| Ingress | <业务>-ingress | payments-ingress |
避免:
- 名字带大写或下划线(DNS label 要求小写)
- 名字带
app、svc、k8s等保留字 - 太长(> 30 字符不利于 kubectl 输出)
十五、生产环境 Checklist
部署一个应用到生产前,逐项打勾:
- [ ] Pod 有
resources.requests和limits - [ ] Pod 有
securityContext.runAsNonRoot: true - [ ] Pod 有
readOnlyRootFilesystem: true - [ ] Pod 有
livenessProbe、readinessProbe(必要时startupProbe) - [ ] 镜像用固定 tag 或 sha256 digest,不用
latest - [ ] 镜像走私有仓库,配置了
imagePullSecrets - [ ] Deployment 有
revisionHistoryLimit,maxUnavailable: 0 - [ ] Service 端口引用 Pod 端口名(不写死数字)
- [ ] HPA 配置了 min/max 与缩容缓冲
- [ ] 有 PDB 防止雪崩
- [ ] 有 LimitRange 兜底
- [ ] 有 NetworkPolicy 限制入站
- [ ] ServiceAccount 是最小权限,绑定了具体 Role
- [ ] ConfigMap 用 cm 注入,敏感信息走 Secret
- [ ] 应用输出 JSON 日志到 stdout
- [ ] 暴露
/metrics给 Prometheus - [ ] YAML 在 Git 里走 GitOps
十六、写在最后
Kubernetes 的"最佳实践"不是一成不变的——它随版本演进、社区经验沉淀在变。但核心原则不会变:
- 声明式 + 版本化(YAML in Git)
- 最小权限(SA + RBAC + NetworkPolicy)
- 资源可观测(requests/limits/三探针/日志)
- 故障自愈(HPA + PDB + 多副本)
把这四点做好,集群就稳了一大半。剩下的细节(监控告警、CI/CD、混沌工程、灰度发布)会在后续文章里讲。
参考资源:
- Kubernetes 官方文档:https://kubernetes.io/docs/
- CNCF Kubernetes 最佳实践:https://www.cncf.io/projects/kubernetes/
- Kubernetes Hardening Guide(NSA/CISA):https://media.defense.gov/2022/Aug/29/2003083339/-1/-1/1/CTR_KUBERNETES_HARDENING_GUIDANCE.PDF
- KubeLinter 静态检查:https://github.com/stackrox/kube-linter
想看某个具体资源(比如 Gateway API / Argo Rollouts / cert-manager)的实战配置? 评论区告诉我,我单独写一篇。






