K8s基础总结
概念:
Kubernetes 是基于 Google 在过去十五年来大量生产环境中运行工作负载的经验。Kubernetes的实现参考了 Google 内部的资源调度框架,但并不是 Borg 的内部容器编排系统的开源,而是借鉴Google 从运行 Borg 获得的经验教训,形成了 Kubernetes 项目。
它使用 Label 和 Pod的概念来将容器划分为逻辑单元。Pods 是同地协作(co-located)容器的集合,这些容器被共同部署和调度,形成了一个服务,这是 Kubernetes和其他两个框架的主要区别。相比于基于相似度的容器调度方式(就像 Swarm 和 Mesos),这个方法简化了对集群的管理。
优势:
最流行等容器编排解决方案框架,基于 Google 庞大的生态圈及 社区产生的产品。通过 Pods 这一抽象的概念,解决 Container 之间的依赖于通信问题。Pods, Services, Deployments是独立 部署的部分,可以通过 Selector 提供更多的灵活性。内置服务注 册表和负载平衡。适用度更广,功能更强大,相较于 Mesos 来说节点规模较小。

曾经的三足鼎立,现在的一家独大

集群组件(交互):
控制面板组件和节点组件是一定存在的东西

borg---k8s的前生(谷歌)
主从架构,主节点分发任务,从节点执行任务
外部任务统一对接主节点
- 外部---客户端
- 内部---服务端
- 服务端又分为主从架构
schedule(调度器):负责找到对应的从节点去执行任务

k8s架构图
通过rest API去操作/调度node节点

注意事项一:
- 只有从节点才去部署对应的任务(区分主从节点---看看有没有pod就行)
- 主节点即可以作为主节点也可以作为从节点(通过配置也可以让其只作为主节点)
- k8s集群就是像上图中三部分组成,涉及三台机器(官方约定最小的集群配置:至少一个master,一个slave节点)
注意事项二:
所有的操作核心都汇聚于 api-server(k8s的关键组件,维护了k8s集群的操作,只要是k8s操作都需要经过该组件)
在Linux中我们通过命令行工具去执行k8s命令,k8s内部收到的不是命令,更像是一个rest请求,然后对我们的请求作出对应的响应
操作工具:
客户端:
- kubectl命令行工具(Linux)
- Dashboard可视化界面UI

master组件:

kube-controller-manager是控制平面的组件,负责运行 控制器 进程。
从逻辑上讲,每个控制器都是一个单独的进程, 但是为了降低复杂性,它们都被编译到同一个可执行文件,并在同一个进程中运行。
这些控制器包括:
- 节点控制器(Node Controller) :负责在节点出现故障时 进行通知和响应
- 任务控制器(Job Controller) :监测代表一次性任务的Job对象,然后创建 Pods 来运行这些任务直至完成
- 端点分片控制器(EndpointSlice controller) :填充端点分片(EndpointSlice)对象(以提供Service和 Pod之间的链接)。
- 服务账号控制器(ServiceAccount controller) :为新的命 名空间创建默认的服务账号(ServiceAccount) 。
结构关系图
node节点中是节点组件也就是从节点所需要的组件

注意:
- work node,计算节点,工作节点,负载节点
- 4层/7层指的是OSI 7层模型中的层数
附加组件:
- kube-dns负责为整个集群提供 DNS 服务
- 作为一个DNS帮我们管理整个集群里面的dns映射(domain name server)对本地域名进行管理----如何通过服务名的方式去访问到对应的ip
- Iingress Controller为服务提供外网入口
- Prometheus 提供资源监控(替换了上面图中的,这个是目前主流方案)
- Dashboard 提供 GUI
- Federation提供跨可用区的集群
- Fluentd-elasticsearch 提供集群日志采集、存储与查询
- ...
k8s架构图(就像ISO网络七层模型一样)
Ecosystem:生态系统。
- 就像附加组件,也就是一个一个应用,是基于k8s封装出来的生态
Interface:接口层,应用都需要调用接口api
governance:管理层,自动化管理应用/权限控制...
- 系统度量(如基础设施、容器和网络的度量),自动化(如自动 扩展、动态Provision等)以及策略管理(RBAC、Quota、 PSP,NetworkPolicy等)
Application:应用层(和部署相关)
- 部署(无状态应用、有状态应用、批处理任务、集群应用等)和路由(服务发现、DNS解析等)
Nucleus:核心层,最底层对应的功能实现(最基础的操作)
- Kubernetes最核心的功能,对外提供 API 构建商层的应用,对内提供插件式应用执行环境

有状态和无状态:

由于选举机制,官方推荐的pod集群数一般是单数,并且大于等于三
资源和对象
资源通过配置文件的形式描述-----资源清单(命令)
对比java来说:
- 资源---类
- 对象---基于类创建出来的对象
Kubernetes 中的所有内容都被抽象为"资源",如 Pod、Service、Node 等都是资源。“对象“就是“资源"的实例,是持久化的实体。如某个具体的 Pod、某个具体的 Node, Kubernetes 使用这些实体去表示整个集群的状态。
对象的创建、删除、修改都是通过“Kubernetes API",也就是"Api Server"组件提供的API接口,这些是RESTful风格的Api.与k8s的“万物皆对象”理念相符。命令行工具“kubectl”,实际上也是调用 kubernetes api.
K8s 中的资源类别有很多种,kubectl 可以通过配置文件来创建
对象的创建、删除、修改都是通过“Kubernetes API”,也就是"Api Server"组件提供的API接口,这些是RESTful风格的Api.与 k8s 的"万物皆对象"理念相符。命令行工具“kubectl",实际上也是调用 kubernetes api.
K8s 中的资源类别有很多种,kubectl 可以通过配置文件来创建这些"对象",配置文件更像是描述对象"属性"的文件,配置文件格式可以是 "JSON"或"YAML",常用"YAML".
对象规约和状态
规约(Spec)
"spec"是"规约"、"规格"的意思, spec是必需的,它描述了对象的期望状态(Desired State)——希望对象所具有的特征。当创建 Kubernetes 对象时,必须提供对象的规约,用来描述该对象的期望状态,以及关于对象的一些基本信息(例如名称)。
总结:通过声明式的方式去描述的,描述的是希望这个对象最终有什么样的能力(不是必须,是越接近越好)
规约是必须的,相当于初始化的作用,描述名称,描述命名空间,有几个副本。。。
状态(Status)
kubelet 需要将 spec 期望状态和 status 最终状态一致。(声明式api和定义式api)
表示对象的实际状态,该属性由 k8s自己维护,k8s 会通过一系列的控制器对对应对象进行管理,让对象尽可能的让实际状态与期望状态重合(规约是期望,状态是实际)。
资源清单:描述所有的资源,spec描述其中的期望状态(就像选配件一样,最终整合到一个yaml文件中)
资源的分类(元数据、集群、命名空间)

一、元数据(公共/全局资源):对pod资源的控制
元空间是一组键值对,用于描述 k8s 对象的属性。这些属性包括对象的名称、标签、注释、所属命名空间等。元空间可以用于控制对象的调度、管理对象的配置、以及监控对象的运行状况。
资源在做分类时,其实也就是为了让管理员更加清晰的区分资源能否跨集群使用,能否跨命名空间[ 将集群进行逻辑上的拆分成小集群 ]使用
Horizontal Pod Autoscaler (HPA)---自动扩容缩容
高峰期扩容至十台服务器,结束后缩容回来,可自定义指令识别进行执行
Pod自动扩容:可以根据CPU使用率或自定义指标(metrics)自动对 Pod 进行扩/缩容。
- 控制管理器每隔30s (可以通过-horizontal-pod-autoscalersync-period修改)查询metrics的资源使用情况
- 支持三种metrics类型
- 预定义metrics (比如Pod的CPU)以利用率的方式计算
- 自定义的Pod metrics,以原始值(raw value)的方式
- 计算自定义的object metrics
- 支持两种metrics查询方式: Heapster和自定义的REST API
- 支持多metrics
Pod Template---用于创建pod实例
spec中有template属性,当我需要复制当前pod,也就是扩容时,就去读取该pod的template,根据template创建出来一个一模一样的实例
Pod Template 是关于 Pod 的定义,但是被包含在其他的Kubernetes 对象中(例如 Deployment、StatefulSet、DaemonSet 等控制器)。控制器通过 Pod Template 信息来创建Pod
nacos
LimitRange---限制资源的使用
可以对集群内Request和Limits的配置做一个全局的统一的限制,相当于批量设置了某一个范围内(某个命名空间)的Pod的资源使用限制。
举例:比如我约定初始内容2G,最大内存5G,超过5个G就内存溢出
二、集群级
Namespace
Node
不像其他的资源(如Pod和Namespace) , Node本质上不是Kubernetes来创建的,Kubernetes只是管理 Node上的资源。虽然可以通过Manifest创建一个Node对象(如下json所示)但Kubernetes 也只是去检查是否真的是有这么一个Node,如果检查失败,也不会往上调度Pod,
ClusterRole(全局角色---权限组,比如管理员身份)
前情需要:基于rbac的概念。存在角色的划分,不同权限组
当前的意思就是该role应用于对集群的权限进行管理
ClusterRoleBinding(全局用户绑定---给用户绑定对应身份角色)
将权限组和哪个角色进行资源的绑定
三、命名空间级
- 工作负载型---Pod

pod更像是一个容器组,管理一组强依赖关系或者管理某个容器(类似宿主机的概念,network=host)
Pod(容器组)是 Kubernetes 中最小的可部署单元。一个 Pod(容器组)包含了一个应用程序容器(某些情况下是多个容器)、存储资源、一个唯一的网络IP地址、以及一些确定容器该如何运行的选项。Pod 容器组代表了 Kubernetes 中一个独立的应用程序运行实例,该实例可能由单个容器或者几个紧耦合在一起的容器组成。
Docker 是 Kubernetes Pod 中使用最广泛的容器引擎;
Kubernetes Pod 同时也支持其他类型的容器引擎。
Kubernetes 集群中的 Pod 存在如下两种使用途径:
- 一个 Pod 中只运行一个容器。"one-container-per-pod" 是Kubernetes 中最常见的使用方式。此时,您可以认为 Pod容器组是该容器的 wrapper, Kubernetes 通过 Pod 管理容器,而不是直接管理容器。
- 一个 Pod 中运行多个需要互相协作的容器。您可以将多个紧密耦合、共享资源且始终在一起运行的容器编排在同一个Pod 中
在docker中通过links来进行两个容器的绑定关系,防止因一个容器挂掉,导致该容器ip改变而访问不到的情况

两个强依赖关系的容器放在同一个pod中去进行管理,两个服务都通过中间服务pause(存储卷、文件系统的共享)进行资源的调度

副本
先引入"副本"的概念——一个Pod 可以被复制成多船,每一份可被称之为一个"副本",这些"副本"除了一些描述性的信息(Pod的名字、uid 等)不一样以外,其它信息都是一样的,譬如 Pod内部的容器、容器数量、容器里面运行的应用等的这些信息都是一样的,这些副本提供同样的功能。
Pod 的“控制器”通常包含一个名为“replicas"的属性。"replicas"属性则指定了特定Pod的副本的数量,当当前集群中该Pod的数量与该属性指定的值不一致时,k8s会采取一些策略去使得当前状态满足配置的要求。
其实pod的每一个控制器也就是一个pod实例
控制器---适用于无状态服务
RC和RS只有扩容和缩容的功能,现在基本用不到

实际上RS和RC的功能基本一致,目前唯一的一个区别就是RC只支持基于等式的selector,但RS还支持基于集合的selector(version in (v1.0, v2.0))-----RS可以根据pod定义的标签去指定哪个pod创建副本数
Deployment(现在都用这个,不用前两个++)
针对RS的更高层次的封装,提供了更丰富的部署相关的功能。
滚动升级/回滚:
新的出现后,销毁旧的,也会保留历史版本方便回滚
好处:没有将所有服务全部停掉,而是通过创建副本再依次替换的形式来进行pod中容器版本的迭代升级(无论如何都是有一个是可用的)
暂停和恢复
一次对于pod改五六个地方,但是又不能说一个文件全部改掉,必须一个一个去进行改动,因为会进行自动的滚动升级,就会导致频繁升级的资源浪费(暂停,一次性改完--->恢复,更新)
控制器---适用于有状态服务
StatefulSet

StatefulSet中每个Pod的DNS格式为statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local
Headless Service
服务名 =>访问路径(域名) =>ip
- IserviceName 为 Headless Service 的名字
- 0..N-1 为 Pod 所在的序号,从 0开始到 N-1
- statefulSetName 为 StatefulSet 的名字
- namespace为服务所在的namespace, Headless Servic和 StatefulSet 必须在相同的 namespace
- .cluster.local 为 Cluster Domain

有序部署:
有序部署,有序扩展,即 Pod 是有顺序的,在部署或者扩展的时 候要依据定义的顺序依次依次进行(即从 0到 N-1,在下一个 Pod 运行之前所有之前的 Pod 必须都是 Running 和 Ready 状 态),基于init containers来实现

控制器---守护进程(构建Pod---日志收集)
构建pod原理:基于一个选择器去将所有匹配上的pod都部署上守护进程,去监控应用(用了守护进程相当于构建了一个可以输出集群日志的pod)
DaemonSet 保证在每个 Node 上都运行一个容器副本,常用来部署一些集群的日志、监控或者其他系统管理应用。
典型的应用包括:
- 日志收集,比如 fluentd,logstash 等
- 系统监控,比如Prometheus Node Exporter, collectd,New Relic agent, Ganglia gmond 等
- 系统程序,比如 kube-proxy, kube-dns, glusterd, ceph 等

DaemonSet快速自动化的将我们的日志收集程序调度到各个匹配的节点上面,部署上日志收集程序后,就可以将当前节点下其他pod的日志进行一个输出了,最终上传到es里面对整体进行日志的管理
控制器---任务/定时任务
一次性任务,运行完成后Pod销毁,不再重新启动新容器。(比如跑什么脚本,或者下载什么容器,下载镜像,数据初始化等等)
注意:
- 一个任务也是一个pod,pod是k8s中的最小单元,对吧
- 不同于其他控制器(无状态服务,有状态服务,守护进程是持续运行着,而且一旦发现有问题还会自动恢复),任务执行完毕后就不会再执行。
种类:
- Job---任务
- CronJob---周期性执行的任务(定时任务)
- 服务发现
Service--k8s集群内部的网络通信(实现东西流量的,集群内跨节点的访问请求)
"Service"简写"svc"。Pod 不能直接提供给外网访问,而是应该 使用service。 Service就是把Pod暴露出来提供服务, Service才 是真正的"服务",它的中文名就叫"服务"。可以说 Service 是一个应用服务的抽象,定义了 Pod 逻辑集合和访问这个Pod集合的策略。Service代理Pod集合,对外表现为一个访问入口,访问该入口的请求将经过负载均衡,转发到后端Pod 中的容器。
东西流量和南北流量
- Service---东西流量
- Ingress---南北流量

实际应用举例:

- 存储
Volume---存储卷
数据卷,共享Pod中容器使用的数据。用来放持久化的数据,比如数据库数据。
- pv
- pvc
CSI
Container Storage Interface是由来自Kubernetes、MesosDocker 等社区成员联合制定的一个行业标准接口规范,旨在将任意存储系统暴露给容器化应用程序。
CSI 规范定义了存储提供商实现 CSI 兼容的 Volume Plugin 的最小操作集和部署建议。CSI 规范的主要焦点是声明 Volume Plugin必须实现的接口。
作用:实现各种Volume的接口规范(统一了配置规范)有点像Java中的JDBC,只要配置JDBC就可以兼容各种数据库,不需要单独去对某个进行配置
- 特殊类型配置
ConfigMap:
专门存储key-value类型的配置(属性什么的),然后将configMap加载到容器中,去加载到pod中,使得pod中的容器可以读取到configMap的数据
这样做的好处:将容器需要的各种数据暴露到外部(ConfigMap),当我们需要修改某些属性参数的时候,就可以通过修改ConfigMap达到修改配置的效果(修改ConfigMap,会自动帮我们更新容器,去拿到最新的数据)---解决容器配置在容器中固定死的问题,相当于环境变量
Secret:
和ConfigMap的作用一样,只是多了一个功能---加密功能,更能保证数据安全性的问题
Secret有三种类型:
- Service Account: 用来访问 Kubernetes API,由 Kubernetes 自动创建,并且会自动挂载到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目录中;
- Opaque(默认加密方式): base64 编码格式的 Secret,用来存储密码、密钥等;(对称加密)
- kubernetes.io/dockerconfigjson:用来存储私有 docker registry 的认证信息。
默认的加密方式几乎没什么作用:

DownwadrAPI
downwardAPI 这个模式和其他模式不一样的地方在于它不是为了存放容器的数据也不是用来进行容器和宿主机的数据交换的,而是让 pod 里的容器能够直接获取到这个 pod 对象本身的一些信息。
downwardAPI 提供了两种方式用于将 pod 的信息注入到容器内部:
- 环境变量:用于单个变量,可以将 pod 信息和容器信息直接注入容器内部
- volume 挂載:将 pod 信息生成为文件,直接挂載到容器内部中去
- 其他
Role:
定义命名空间级别的权限:
Role 是一组权限的集合,例如 Role 可以包含列出 Pod 权限及列 出Deployment 权限,Role 用于给某个 Namespace 中的资源进 行鉴权。
RoleBinding:
就是绑定资源的,将Role或者ClusterRole绑定到命名空间内,反之ClusterRoleBinding也差不多,将Role或者ClusterRole绑定到集群空间内。
好像之前见过啊(往上翻):

搭建K8s集群

