跟着Kubernetes学设计—声明式or命令式

2023-09-20 08:43:29 浏览数 (1)

我们知道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 也算是一种命令式与声明式混合风格的编程语言了,但需要注意的是函数式编程只是声明式编程的一个子集

0 人点赞