比如我们这里简单列举到,实际上你基于这个 Kubernetes 去做一个 CICD 的持续交付平台是非常容易的。我们可以简单的设想一下,比如 Github Actions 这样的工具是非常酷的,但是如果你仔细去看它的代码,你会发现 Github Actions 里面每一个 Action 动作,它其实都是一个容器镜像,那么可想而知它背后很有可能就是一个容器品牌,当然它不见得是 Kubernetes 的,但是你基于 Kubernetes 这样的一个容器平台去构建一个 CICD 平台是比较容易的。一会儿我们会看到如何用代码去操作这个平台。当然这只是一个举例,其实 Kubernetes 适合的还有很多,比如像这里列举到的基础运维平台、业务应用托管、大数据、机器学习、以及边缘计算等等,Kubernetes 现在已经变成了一个非常通用的运维平台了。其实基本上可以说 Kubernets 适合运行各类软件,包括在线的、离线的业务,尤其是集群类软件,它都是可以去做的。

上图是 Kubernetes 的一个系统结构。在这个结构的中间部分,主控节点其实是少量的机器,一般来说主控节点如果是比较小的集群有可能就是一台集群,然后中等集群可能是三台服务器,或者大型的集群就是五到七台机器,一般而言七台及以上的集群是比较少见的。工作节点就是真正用来运行我们刚才讲的各类业务应用、各类的包括 CICD 工作负载的虚机所在,这个机器我们这里称为节点,其实可以是虚机,可以是物理机,这个当然都是没有问题的,在节点上真正去运行业务容器。
Kubernetes 集群中每个节点之间是如何通信的呢?如果大家看过 Kubernetes 代码的话,你会发现它其实是非常符合我们现在主流的所谓微服务、模块化的一个设计风格。那么集群内部从主控节点的设计来讲,它的内部是通过 API 进行调用的,这个如何理解呢?就是我们外面的人去调用包括 Kubectl 命令行,或是直接用 Restful API 去调用直接处理请求的 ApiServer,那么你在写入一些资源对象之后,比如我们稍后提到的 Pod,这些资源对象会被写入到 DB 里面,最终它会由这个集群的调度器来使用,调度器会把它下发到工作节点里面去,然后去运行。
工作节点想要配合主控节点工作的话,它就必须要有跟主控节点协作的一些组件,具体来讲,像 Kubelet、Kube-proxy 还有 Docker,也有可能是其它的容器运行时以及其它的一些扩展软件。那么这些组件它在工作节点上就能够与主控节点配合,来接收主控节点下发的相关指令,完成容器的一些启动,还有一些运维的指令等等。
那么主控节点除了刚才讲的把 Pod 作为一个调度之外呢,它还会需要去针对 API 里面的一些资源对象来做一些交互,比如稍后我们会接触到的一些编程的东西去做交互。所以控制管理器 Controller 是 Kubernetes 内部一个比较关键的概念,它是用来解析我们功能模块的一个关键逻辑所在,所以它会有一个 Control Manager,就是控制管理器。
Etcd 其实是它的数据库。如果把主控节点分成一个三层的架构,上面就是 Web API 层,中间就是逻辑层,下面就是数据库。其实也很简单的,这样一个结构看起来很简单,那么我们怎么样去用它呢?

一般来说,我们使用 Kubernetes 来部署一个应用时,通常分成这样的几个步骤:首先,我们需要手动编写 Yaml 文件。在一个团队里面,一般你的应用的结构会是比较固定的,所以你会倾向于把这些 Yaml 文件做成一个模板。当你需要更新这个模板时,你才会需要去修改它。而平常你会把它存储在一个仓库里面,这个模板也可以进行打包,现在社区里面有 Helm 工具可以帮助我们打包。它需要把模板先取下来做一个压缩,然后填充模板里面的参数,形成最终用来往集群上安装的 Yaml 文件内容,最后使用这些 Yaml 文件在集群中进行部署。如果是安装 .NET 应用的话,它最终就会被安装到我们的主控节点上面去运行。最终我们站点的用户会通过集群中的Service 或是 Load Balance 这种机制来访问到运行在容器里面的 Pod,大概是这样的一个模式。

总的来说,大概分成三个步骤:
1.第一个步骤就是制作 Yaml 模板。
2.第二个步骤就是我们将 Yaml 模板做一个参数化。参数化中有一个关键过程,我们需要去填写应用的容器镜像,因为容器镜像才是真正要用来部署的东西,所以你每次升级代码时,容器镜像版本都会改变。
3.第三个步骤就是把 Yaml 文件安装到集群上,完成部署。
所以在容器平台上去部署一个应用,基本上就是这三个阶段。

Kubernetes 平台其实除了可以部署应用之外,实际上它还提供了非常多的周边的一些功能。正是这些周边功能,使得它比起其它的容器编排平台而言,显得更加吸引人。在上图中我们可以看到:
1.容器周边服务:指它本身为运行 Pod 容器准备了很多抽象。比如说它的安全的上下文封装、网络模型、存储对接等等。
2.批量容器调度:它允许我们根据设置的 Label 标签、CPU 的情况来做一些调度,允许我们自己去写调度算法,所以它是一个具体高可扩展性的平台。
3.高级应用部署:在 Kubernetes 集群中,应用部署有很多种类型。比如你可以非常容易的做一个无停机的部署,包括滚动更新。还可以非常方便地去做灰度发布管理,当然前提是你需要配合一些流量管理软件,像 Isito 这样的软件在 Kubernetes 上面就配合的非常好。
4.应用运维:比如自动扩缩容,监控,故障的自动处置等等。其实这个平台都提供了非常好的工具。
5.集群定制接口:Kubernets 本身是一个非常具有可扩展性、可定制性的平台,就像一个操作系统一样,你可以在它里面去编程、去安装一些新的东西。

我们在谈 Kubernetes 基础组件开发的时候,我们就需要对 Kubernetes 基础组件与它上面的应用软件来做一个区分。
所谓的应用软件,它是相对于我们刚才谈的基础组件。如果我这里换一个词叫系统软件,可能大家会熟悉一点。以前大家在上计算机基础课程时,就知道电脑里面的软件通常分成两种,第一种叫做系统软件,第二种叫做应用软件。其实应用软件是我们大多数人经常接触的,比如电脑里面的 Word、PPT、Excel、浏览器等这些软件,其实它就属于应用软件。应用软件就是说你可以在它里面去实现一系列定制性的业务流程的软件,它不是操作系统本身自带的一些功能,它通常是提供这个软件里面的功能,它只在这个里面进行使用。
而系统软件作为对比,它是一种平台级别的东西。它是提供给这个电脑上、这个计算机里面、很多的其它应用软件可以共用的一种技术组件。
那么对于 Kubernetes 是一样的,在上图中列到了,我们称之为 Kubernetes OS。这其实是一种类比,就是说我们几乎可以把 Kubernetes 当做一个操作系统,如果你以这种视角来看待它,我们今天其实需要探讨是:如何在 Kubernetes 上面去开发系统软件。

要开发系统软件,就要考虑到日常我们是如何使用它的。实际上,Kubernetes 在使用的时候有很多种方法,一般作为业务开发人员,或是集群的业务运维人员,通常我们使用的一些工具就是可视化界面,命令行,还有 API 等等。但其实我们真正要去增加它里面的功能,更多是需要与 SDK 打交道,所以 SDK 面向的是它的生态开发者。从上到下我们会发现,越往上是越面向入门级的用户,越往下是越面向专业用户。

作为开发者,我们就知道这几种方式的软件开发难度自然是不一样的。面向界面的软件开发相对肯定是更难的。我们都知道如果你想去做一个 UI 的自动化测试本身就是很难的,而且实际上对于我们跟 Kubernetes 打交道做基础开发的话,就没必要用界面了,我们更多的反而是使用命令行、API 和 SDK 的方式,稍后我们会来介绍。

如果我们要对它来做开发,我们要关注些什么呢?就是基础知识,那么我们来简单的看一下上图的基础模型。
现在假如我是一个用户,我在最上面开始往集群中去 create 一个 pod 时,它会发生什么呢?pod.yaml 文件中包含了我要创建的这些内容,那么这些内容它首先会被 API Server 所接收到,然后尝试存到 DB 里面去。当然稍后我会介绍,它实际上不会直接存储还有一些动作的,那么它存储完了之后,会由 Scheduler 调度器来完成 Pod 的一个调度,然后把相关指令给到工作节点,工作节点会去运行我们的容器,有可能是 Docker,也有可能是 Containerd 等其它的容器运行时。Pod 启动之后的同时,就需要去为它配置一些网络、存储,当整个配置都就绪之后,我们的 Pod 才能够运行起来,以上就是它的一个概要的工作机制。

在了解了概要的工作机制之后,我们要考虑到接下来要对它做开发,我们可以在哪些场景对它做开发呢?在上图可以看到有三种切入点:
第一种是客户端:
1.我们可以开发 kubectl 的一个命令行插件,直接往里面增加或是定制客户端的行为。
第二种是主控节点,我们做的事情可以说非常多:
1.webhook:指的是我们对它资源的一个处理方式来做一些定制。
2.CRD:指的是我们能够为它提供一些定制的资源类型。比如我们可以给它开发一个 C# APP 运行 C# 代码。
3.Customized Scheduler:定制调度策略的开发。
4.APIService:把 API 的处理过程委托给另外一个程序。
5.CloudProvider:作为云厂商也可以对集群的托管行为进行一些定制。
第三种是工作节点:
1.DaemonSet:它是一种运行在所有工作节点上的应用,通常可以用来做一些在每个节点上都要做的功能,比如用来部署 CNI,或者做 Log 日志的收集等等。
2.CRI:运行容器的一个容器运行时。
3.CSI:为容器提供存储功能的驱动程序。
4.CNI:是为容器提供联网功能的一些机制。
以上这些东西都是我们可以使用第三方的代码来开发的。除了 kubectl,由于 kubectl 它本身是由 go 语言写的,所以 .NET 是没法在里面去开发的,因为开发的话它需要编译的,所以它不会把我们的代码编译进去。除了这个之外,其它的所有种类我们都可以用 C# 来开发。我们可以看到整个这个 Kubernetes 的一个可编程性是非常灵活、非常强大的。

上面我们花了这么大的篇幅来探讨什么是 Kubernets,以及它的可编程能力。那我们来简单的挑其中的几个场景来讲一下,在 .NET Core 里面,我们如何跟它去做一些这种程序上的交互:
1.如果我们把 Kubernetes 当做一个操作系统的话,我们可以开发它的客户端应用,对吧?能不能适合用 .NET Core 来开发呢?非常适合。因为 .NET Core 拥有完整的跟操作系统的进程打交道的能力,你可以去启动一个进程,你可以去调用相关的 Restful API,这些都是可以非常方便地完成我们的能力的。
2.Webhook 我们在上面有简单的介绍,它程序的格式,其实是一个这种 Web API,那 .NET Core 的话用来开发 Web API 可以说是我们最擅长这个工作之一。
3.CRD 它是一种运行在集群之内,其实也可以运行在集群之外的一种自定义程序,它其实就是一个你能运行的二进制程序就可以了。当然我们 .NET Core 是非常擅长于做这类的程序的。
4.DaemonSet 它往往是运行在宿主机上,或者是运行在宿主机上的容器,所以 .NET Core 都是非常擅长做这方面的开发。
以上就是我们第一部分的全部内容,关于第二部分“使用 .NET Core 与 Kubernetes 交互”以及第三部分 “使用 .NET Core 开发 Kubernetes 组件”的内容我们将会在后面的文章继续分享讲解。