云原生的一些概念
“云原生”这个词被滥用得已经没什么意义了。每个厂商都说自己的产品是云原生的,每篇架构文章都声称某方案”符合云原生理念”。但真正用过这套东西的人知道,云原生不是一个技术标签,它是一种对系统如何失败和恢复的不同假设。
一个根本性的假设转变
传统运维假设基础设施是稳定的。机器不会随机消失,网络是可靠的,服务一旦部署就应该持续运行。运维的工作是在出问题时把系统恢复到正常状态。
云原生的基础假设是反过来的:一切都会失败。节点会挂,网络会抖,容器会被调度器随机驱逐。系统的设计目标不是”防止失败”,而是”在失败时保持可用”。
这个假设的转变,决定了云原生所有具体实践背后的逻辑。
三个关键概念
微服务不只是”把单体拆小”。拆分是为了让每个服务可以独立失败、独立恢复、独立扩容。如果拆分之后服务之间强耦合,部署时需要严格的顺序协调,那拆了反而更麻烦。微服务的价值在于故障隔离和独立演化,不在于拆分动作本身。
容器化解决的核心问题是环境一致性,而不是性能。Docker 的价值不是让应用跑得更快,是让应用在开发、测试、生产环境里的行为一致。消除”在我机器上能跑”这个问题,本质上是在降低人为错误率,也是让不可变基础设施(immutable infrastructure)成为可能的前提。
声明式 API 是云原生里最容易被误解的概念。声明式的核心不是 YAML 语法,是控制循环(control loop) 的设计模式:你描述期望状态,系统持续比对实际状态与期望状态,有偏差就自动修正。Kubernetes 里的各种 controller 都是这个模式的实现。
1 | |
上面这个 YAML 里没有任何”怎么做”的指令。没有”先启动 3 个 Pod”,没有”如果 Pod 失败了重启”。你只是告诉 Kubernetes “我要 3 个这样的 Pod 一直活着”,其余的是它的事。
相比之下,过程式的做法是:
1 | |
这种代码在分布式环境里很快会失控——竞态条件、部分失败、状态不一致,每一个都是 bug 温床。
三个常见误区
上了 Kubernetes 就是云原生。 K8s 是工具,不是终点。把一个设计不良的单体应用容器化扔进 K8s,只是把复杂性换了一个地方,还多了一层调试难度。
微服务越细越好。 服务拆分有真实成本:网络延迟、分布式事务、可观测性复杂度。合理的粒度取决于团队的认知负载上限和系统的边界清晰度,不取决于时髦程度。过度拆分比单体更难维护。
云原生是运维的事。 云原生架构的很多约束——无状态设计、优雅终止(graceful shutdown)、健康检查接口——需要在开发阶段就设计进去。开发不理解这些约束,运维层面无法弥补。
云原生本质上是一种对失败的设计态度。理解这一点,才能判断哪些实践是真正有价值的,哪些只是复杂性转移。