k8s-集群扩展

k8s-集群扩展

1 k8s有哪些扩展点?

kubernetes具备高可配、高扩展特性。自定义kubernetes集群大体上也分成两个方向,一个是配置,一个是扩展。配置又分成修改配置文件、标志与API resources两个小方向,扩展需要运行额外的程序或者服务。

Kubernetes 是一个可移植的、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。Kubernetes 拥有一个庞大且快速增长的生态系统。Kubernetes 的服务、支持和工具广泛可用[^1]。

虽然现在 Kubernetes 已经是容器编排的事实标准,其本身的功能也非常丰富并且灵活,但是也不能满足所有人的需求,在遇到 Kubernetes 提供的能力无法满足我们需求的时候,我们就可以利用其强大的扩展能力进行定制。

k8s-集群扩展_第1张图片

k8s-集群扩展_第2张图片

2 k8s扩展

如上图所示,从客户端到底层容器运行时,绝大部分地方 Kubernetes 都为我们预留了扩展点,我们从上往下一个一个的来看.

2.1 kubectl

kubectl 是我们平时和 Kubernetes 交互使用的最多的客户端工具,常见的运维操作都会通过 kubectl 来完成,kubectl 为我们提供了插件机制来方便扩展。

kubectl 插件其实就是以kubectl-为前缀的任意可执行文件 ,执行 kubectl 插件的时候可以通过 kubectl 插件名 参数 的方式运行插件。就像 Ubuntu 使用 apt 管理软件,mac 可以使用 brew 一样,kubectl 也有类似的插件管理工具 krew ,同时我们可以从 https://krew.sigs.Kubernetes.io/plugins/ 查找是否已经存在我们需要的插件.

通过为kubectl提供插件并配置扩展kubectl,属于二进制扩展。这种扩展只对集群中单个kubectl有效,不是全局范围。详细参考kubectl plugins。

【k8s】——kubectl 插件管理(krew)以及使用

client-go的使用及源码分析

2.2. APIServer

当用户觉得它现在的 API 接口不能满足需求时,用户就想自己开发一些 API 接口。Kubernetes 会提供这样一个机制,它能够使你的 API Server 遵循它的 API 规范,把你的 API Server 集成到 Kubernetes 中。

API Server 扩展带来的收益:

    • 扩展性;
    • 用户的 API Server 对 Kubernetes 不会做改动(这样 Kubernetes 社区就不需要去 review 用户的 API 实现);
    • 提供实现实验性的 API 的平台;
    • 保证新的 API 遵循 Kubernetes 的 API 规范。

这个机制能做什么?首先它的 aggregator 能提供一个注册 API Server 的 API 接口以及提供一个发现机制,然后能够代理用户的请求,发送到你特定的 API Server。

apiserver预留的挂载点,可以与远程服务挂钩,将请求转发出去由远程服务处理,自定义实现比如认证、其于内容的拦截、请求内容转换、删除处理等.

从 Kubernetes v1.7 版本之后 APIServer 引入了聚合层的功能,这个功能可以让每个开发者都能够实现聚合 API 服务暴露它们需要的接口,这个过程不需要重新编译 Kubernetes 的任何代码。

如果我们将下面这个资源提交给 Kubernetes 之后,用户在访问 API 服务器的 /apis/metrics.Kubernetes.io/v1beta1 路径时,会被转发到集群中的 metrics-server.kube-system.svc 服务上

{

“apiVersion”: “apiregistration.Kubernetes.io/v1”,

“kind”: “APIService”,

“metadata”: {

​ “name”: “v1beta1.metrics.Kubernetes.io”

},

“spec”: {

​ “service”: {

​ “name”: “metrics-server”,

​ “namespace”: “kube-system”

​ },

​ “group”: “metrics.Kubernetes.io”,

​ “version”: “v1beta1”,

​ “insecureSkipTLSVerify”: true,

​ “groupPriorityMinimum”: 100,

​ “versionPriority”: 100

}

}

除此之外无论是从 kubectl 还是 client-go 等其他客户端发起的请求都会发送到 APIServer 经过 认证 -> 鉴权 -> 准入控制 的步骤,这其中的每一步我们都可以对其进行扩展,而这其中用的最多的就是准入控制的扩展。

准入控制当中又会先经过,变更准入控制 MutatingAdmissionWebhook,然后再经过验证准入控制 ValidatingAdmissionWebhook,任何一个准入控制器返回了错误这个请求都会失败,例如这两个准入控制器我们可以做很多事情,例如注入 sidecar,验证资源,调整 pod 的配额等等。

admission webhooks是同步调用,需要部署webhook server,并创建对象ValidatingWebhookConfiguration 或 MutatingWebhookConfiguration来指向自己的 server,以ValidatingAdmissionWebhook为例:

部署 webhook:

k8s-集群扩展_第3张图片

配置:ValidatingWebhookConfiguration

k8s-集群扩展_第4张图片

Kubernetes Apiserver和Extension apiserver的介绍

Kubernetes v1.7新特性解析-准入控制扩展

2.3 Kubernetes 资源

在kubernetes中一切皆资源,Kubernetes 1.7之后,提供了CRD(CustomResourceDefinitions)的自定义资源二次开发能力来扩展kubernetesAPI,通过此扩展,可以向kubernetes API中增加新类型,会比修改kubernetes的源代码或者是创建自定义的API server来的更加的简洁和容易,并且不会随着kuberntetes内核版本的升级,而出现需要代码重新merger的需要,以及兼容性方面的问题。这一功能特性的提供大大提升了kubernetes的扩展能力。

创建自定义资源,即自定义 restful api.当你创建新的 CustomResourceDefinition(CRD)时,Kubernetes API 服务器会为你所 指定的每一个版本生成一个 RESTful 的 资源路径。CRD 可以是名字空间作用域的,也可以 是集群作用域的,取决于 CRD 的 scope 字段设置。和其他现有的内置对象一样,删除 一个名字空间时,该名字空间下的所有定制对象也会被删除。CustomResourceDefinition 本身是不受名字空间限制的,对所有名字空间可用。

apiVersion: apiextensions.k8s.io/v1

kind: CustomResourceDefinition

metadata:

# 名字必需与下面的 spec 字段匹配,并且格式为 ‘<名称的复数形式>.<组名>’

name: crontabs.stable.example.com

spec:

# 组名称,用于 REST API: /apis/<组>/<版本>

group: stable.example.com

# 列举此 CustomResourceDefinition 所支持的版本

versions:

​ - name: v1

​ # 每个版本都可以通过 served 标志来独立启用或禁止

​ served: true

​ # 其中一个且只有一个版本必需被标记为存储版本

​ storage: true

​ schema:

​ openAPIV3Schema:

​ type: object

​ properties:

​ spec:

​ type: object

​ properties:

​ cronSpec:

​ type: string

​ image:

​ type: string

​ replicas:

​ type: integer

# 可以是 Namespaced 或 Cluster

scope: Namespaced

names:

​ # 名称的复数形式,用于 URL:/apis/<组>/<版本>/<名称的复数形式>

​ plural: crontabs

​ # 名称的单数形式,作为命令行使用时和显示时的别名

​ singular: crontab

​ # kind 通常是单数形式的驼峰编码(CamelCased)形式。你的资源清单会使用这一形式。

​ kind: CronTab

​ # shortNames 允许你在命令行使用较短的字符串来匹配资源

​ shortNames:

​ - ct

Kubernetes CRD (CustomResourceDefinition) 自定义资源类型

2.4 Controller 控制器

首先,系统内置了很多控制器,大多数运行在kube-controller-manager程序之内。都是无限循环,不间断的监控用户期望并调整集群状态,使真实状态与用户期望状态匹配,用来实现自动化功能。控制器扩展就是用户自定义控制器,控制器通过kubernetes提供的API,读取对象的.spec,相当于用户期望,然后执行必要的动作,再更新对象的.status,相当于是实际状态。总之,控制器扩展就是用户自定义控制器。控制器可能运行在集群外,也可能是集群内。

Kubernetes 中资源的状态的维护都是 Controller 来实现的,Controller 会不断的尝试将一个资源调整为我们描述的状态,这其实也就是我们常说的声明式 api,声明式 api 背后具体的活都是 Controller 干的。Controller 一般会配合着 CRD 一起使用。

自定义controller开发的整个过程:

  1. 创建CRD(Custom Resource Definition),令k8s明白我们自定义的API对象;

  2. 编写代码,将CRD的情况写入对应的代码中,然后通过自动代码生成工具,将controller之外的informer,client等内容较为固定的代码通过工具生成;

  3. 编写controller,在里面判断实际情况是否达到了API对象的声明情况,如果未达到,就要进行实际业务处理,而这也是controller的通用做法;

  4. 实际编码,动手编写的文件

k8s自定义controller设计与实现

2.5 Schedule 调度器

调度器是一种特殊的控制器,负责监视 Pod 变化并将 Pod 分派给节点,调度器可以被直接替换掉或者是使用多个调度器.

在kubernetes的scheduler调度器的设计中为用户预留了两种扩展机制SchdulerExtender与Framework.

k8s支持自定义调度器。它原生的调度器有一些相应的调度策略、调度算法,但在业务场景中,这些调度策略可能并不能满足你的要求,这样你就可以自行写一个调度器。像 kubelet ,在社区有一个 Virtual-Kubelet 项目,它并不是 Kubernetes 原生的扩展性。

SchdulerExtender

图解kubernetes调度器SchedulerExtender扩展

Framework

使用scheduler-framework扩展原生k8s调度器

https://www.cnblogs.com/yangyuliufeng/p/14257928.html

2.6 CNI 网络插件

CNI 网络插件,全称 Container Network Interface(容器网络接口)包含一组用于开发插件去配置 Linux 容器中网卡的接口和框架。

Kubernetes 对接的第三方网络插件是按照这个规范来实现的。规范可以简单的理解为,它有一个 add 和 delete 接口,add 接口是增加网络,也就是将 Pod 挂到网络中去,而 delete 接口是销毁网络.

k8s设计了网络模型,但是把实现交给了网络插件,而CNI网络插件实现的最主要的功能就是POD跨宿主机资源互相访问.一般我们不会去对网络插件做定制开发,而是采用开源的组件.

外围都是单网络插件。社区从 2016 年初,就已经有要支持多网络的呼声,但在 Kubernetes 官方库中,一直都没能推进。这样做可能会对 Kubernetes 的 API 有太多改动,从而导致系统的不稳定性。而从插件侧支持多网络的,一个是 Intel 的 Multus 和中兴通讯的 Knitter。

k8s-集群扩展_第5张图片

Flannel:使用的是简单稳定的社区的Flannel CNI插件,配合阿里云的VPC的高速网络,能给集群高性能和稳定的容器网络体验,但功能偏简单,支持的特性少,例如:不支持基于Kubernetes标准的Network
Policy。

Terway:是阿里云容器服务自研的网络插件,将阿里云的弹性网卡分配给容器,支持基于Kubernetes标准的NetworkPolicy来定义容器间的访问策略,支持对单个容器做带宽的限流。对于不需要使用NetworkPolicy的用户,可以选择Flannel,其他情况建议选择Terway。

2.7 CSI 存储插件

CSI 存储插件,全称 Container Storage Interface,可以通过 CSI 接口支持不同的存储类型

Kubernetes 也要对接很多 vendor,像 Ceph,GulusterFS 等,它在长期的发展过程中,存储这部分很难稳定。所以 Kubernetes 提出了一些规范或是存储插件接口。

CSI(容器存储接口),在 Kubernetes 中它最初支持最原始的 HostPath、EmptyDir,后来就是 NFS 以及像 Ceph,Gluster 这一类的存储系统。这些存储系统也要在 Kubernetes 的代码库中做相应支持。在这种情况下,社区觉得这种方式扩展性还是太差,希望能够把它独立出一个接口,这就产生了 CSI。以上就是出现容器存储接口的动机。

kubernetes 存储插件CSI开发指导

2.8 CRI 容器运行时

CRI 容器运行时,全称 Container Runtime Interface,是一组用于管理容器运行时和镜像的 gRPC 接口,利用这个接口可以支持 docker、containerd 等不同的容器运行时.

随着容器运时开始遍地开花,比如说 rkt、Containerd、frakti 等,Kubernetes 需要支持他们并把相应的适配都编到 Kubernetes 中,也使 Kubernetes 变得越来越不稳定

Kubernetes容器运行时(CRI)简介

3 Operator

Kubernetes 是一个高度可扩展的系统,虽然它的扩展点这么多,但是一般来说我们接触的比较多的还是 自定义资源,控制器,准入控制,有些还会对 kubectl 和 调度器做一些扩展,其他的大部分使用成熟的开源组件就可以了。而 Operator 就会涉及到 自定义资源,控制器和准入控制。

Operator是CoreOS推出的旨在简化复杂有状态应用管理的框架,它是一个感知应用状态的控制器,通过扩展Kubernetes API来自动创建、管理和配置应用实例。

Operator 遵循 Kubernetes 的理念,Operator 模型基于 Kubernetes 中的两个概念结合而成:自定义资源和自定义控制器.它利用自定义资源管理应用及其组件, Operator 模式会封装你编写的任务自动化代码。

Operator与Controller区别:

  • 所有的Operator都是用了Controller模式,但并不是所有Controller都是Operator。只有当它满足: controller模式 + API扩展 + 专注于某个App/中间件时,才是一个Operator。

  • Operator就是使用CRD实现的定制化的Controller. 它与内置K8S Controller遵循同样的运行模式(比如 watch, diff, action)

  • Operator是特定领域的Controller实现

Operator 常见使用范围包括:

  • 按需部署应用

  • 获取/还原应用状态的备份

  • 处理应用代码的升级以及相关改动。例如,数据库 schema 或额外的配置设置

  • 发布一个 service,要求不支持 Kubernetes API 的应用也能发现它

  • 模拟整个或部分集群中的故障以测试其稳定性

  • 在没有内部成员选举程序的情况下,为分布式应用选择首领角色

从 Operator 理念的提出到现在已经有了很多工具可以帮助我们快速低成本的开发,其中最常用的就是 CoreOS 开源的 operator-sdk 和 k8s sig 小组维护的 kubebuilder,我们这个系列选用 kubebuilder。除了我们自己开发之外还可以在 https://operatorhub.io/ 上找到别人开发的现成的 Operator 进行使用.

由于Operator是管理有状态应用的强大工具,我们可以找到一些预制Operator来自CoreOS以及其他贡献者,比如etcd、Vault和Prometheus。这些都是不错的起点,但Operator真正价值来自于你对应用失败状态处理的最佳实践,以及Operator如何协同人工干预。

揭秘Kubernetes Operator(一)

[Kubernetes operator 模式开发实践](

你可能感兴趣的:(运维,kubernetes,docker,容器)