我们知道k8s是基于声明式设计的系统,我们只管告诉k8s我们想要达到的系统状态,至于怎么达到,是k8s自身需要处理的事情,比如下面的yaml:
代码语言:javascript复制apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
当然k8s也支持命令式的交互动作,比如
代码语言:javascript复制// 创建
$ kubectl create -f nginx.yaml
// 修改后更新
$ kubectl replace -f nginx.yaml
Kubernetes 通过声明式方式实现的 Controller,每个组件都只需要和 ETCD 这样的状态中心交互,完成自己的任务后把状态更新到 ETCD 中即可。如果失败则反复重试,直到失败条件解除。虽然任务的完成时间不可控,但可达到最终一致。
声明式方式增加了复杂性,对于开发来说可能更难调试,而使用命令式模型,所见即所得,你所想要达到的效果就是程序命令执行完成的样子,除非发生错误。
有的人说,越接近现实的表达就叫越“声明式”(declarative),越接近计算机的执行过程就叫越“命令式”(imperative),这个比较形象。
越是声明式,意味着下层要做更多的东西,或者说能力越强。也意味着效率的损失。越是命令式,意味着上层对下层有更多的操作空间,可以按照自己特定的需求要求下层按照某种方式来处理。
声明式(declarative)是结果导向的,命令式(imperative)是过程导向的。它们都有自己适用的场景和局限,其实在我们的日常使用的编程语言中,或多或少都有两者的身影。
显然,声明式语言对用户更友好,用户可以关心更少的细节。更重要的是:它允许多种底层实现方式,保持目标不变的同时不断优化。
而命令式的好处自然是它的表达能力了,图灵完备的语言可以表达任何的可计算问题。
更极端一点,所有的 DSL (HTML, XML, SQL) 都是声明式的,你写出一条 SQL 语句,只是为了告诉数据库你要什么,然后数据库就会给你对应的数据,而不是通过数据库的 API 去取。
代码语言:javascript复制SELECT * FROM Test WHERE name='ts'
正如我之前文章里面介绍的 GraphQL,也是声明式的, 因为它把网络请求变得声明式了:
代码语言:javascript复制query {
posts {
id, title, content
}
}
使用过java语言的,不知道有没有一种体会,Java 8 增加了 Lambda 表达式这一新特性,允许我们以函数式风格进行编程,所以Java 也算是一种命令式与声明式混合风格的编程语言了,但需要注意的是函数式编程只是声明式编程的一个子集