
把应用打包成镜像,只完成了第一小步。真实项目里出问题的是这些:
所以正确姿势不是“先上集群”,而是先把应用改造成可被编排的形态:
镜像不是越小越好,但大镜像会直接吃掉弹性和发布速度。多阶段构建是最基本的做法:
FROM golang:1.22 AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -trimpath -o /app ./cmd/server
FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=build /app /app
USER nonroot
ENTRYPOINT ["/app"]三个要点:构建阶段和运行阶段分离、固定基础镜像版本、默认非 root。再加上 .dockerignore 排除无关文件,镜像体积通常能降一个数量级。
可复现性同样重要:依赖版本锁定、构建参数显式声明、镜像打上不可变标签(用 commit hash,而不是 latest)。用 latest 的部署,等于放弃回滚能力。
判断标准很朴素:同一个镜像,能不能在开发、测试、生产三个环境跑起来而不用重新构建? 不能,就说明配置耦合了。
if env == "prod"。还有一个常被忽略的点:配置变更要能触发滚动更新。如果配置改了但 Pod 没重启,应用读的还是旧值,这种“改了没生效”的问题极难排查。
容器被终止时,K8s 先发 SIGTERM,等一段时间后 SIGKILL。如果应用收到信号立刻退出,正在处理的请求全部失败。
import signal, threading
from http.server import HTTPServer
stop = threading.Event()
def on_term(signum, frame):
stop.set() # 先停止接收新请求
server.shutdown() # 再排空已有连接
signal.signal(signal.SIGTERM, on_term)
signal.signal(signal.SIGINT, on_term)
server = HTTPServer(("0.0.0.0", 8080), Handler)
server.serve_forever()配套要设置合理的 terminationGracePeriodSeconds,并且让就绪探针在停机时先返回失败,把流量摘干净再退出。顺序错了,滚动发布就会间歇性 502。
很多人只配一个 livenessProbe,这是常见错误。三种探针职责不同:
startupProbe:
httpGet: { path: /healthz, port: 8080 }
failureThreshold: 30
periodSeconds: 2
readinessProbe:
httpGet: { path: /readyz, port: 8080 }
periodSeconds: 5
livenessProbe:
httpGet: { path: /healthz, port: 8080 }
periodSeconds: 10
failureThreshold: 3关键判断:liveness 只检查“进程自身是否健康”,不要把它做成依赖检查。 如果数据库抖动导致 liveness 失败,所有 Pod 会一起重启,把一次小故障放大成雪崩。依赖检查放 readiness 更合适。
不设 requests,调度器不知道该怎么分配;不设 limits,一个内存泄漏就能拖垮整个节点。
resources:
requests: { cpu: "200m", memory: "256Mi" }
limits: { cpu: "1", memory: "512Mi" }两条经验:
CPU limit 要谨慎:它会导致节流(throttling),表现为延迟毛刺。对延迟敏感的服务,有时只设 requests 不设 CPU limit 更合适,但要配合节点资源隔离。
容器是临时的,所以状态必须外置:
其中重启次数和 OOMKill 次数最值得盯。它们升高往往意味着资源配错或内存泄漏,而不是“偶发问题”。
云原生的价值之一是可回滚,但前提是每次发布都可标识、可追溯:
“回滚能力”要在设计阶段就做进去,而不是出事时临时想办法。
弹性不等于省钱。常见的成本失控原因:
最低要求:给资源打上团队、环境、服务标签,定期看利用率和闲置资源。没有成本可见性,就没有优化动力。
AI 很适合帮你做这些:
一个实用的审查提示词:
请审查下面 Kubernetes 部署清单,只输出问题表格:
问题类型 | 位置 | 风险说明 | 修改建议
重点检查:是否非 root 运行、是否设置 resources、探针是否合理、
是否使用 latest 标签、密钥是否硬编码、是否有优雅停机配置。
不要重写清单,不要评价业务逻辑。但资源规格定多少、可用性目标是多少、成本预算怎么分,必须人来做。AI 没有你的业务和账单。
云原生工程的正确姿势,不是“把应用塞进 Kubernetes”,而是先把应用改造成可被编排的形态:小镜像、非 root、配置分离、优雅启停、三种探针、资源边界、日志外置、发布可回滚、成本可归因。这些做到了,平台才真正发挥作用。
代码可以很少,但探针不能乱配,资源不能不给,密钥不能进镜像,回滚不能没有。记住一句话:云原生不是换一个部署平台,而是让应用具备被平台安全调度、弹性伸缩、可靠回滚的能力;应用不达标,平台再好也只是放大器。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。