Kubernetes核心概念及核心组件使用与理解

什么是Kubernetes?


工作流程
在这里插入图片描述


Kubernetes是一个可移植性,可扩展的开源平台,用于管理容器化工作负载和服务,有助于声明性配置和自动化管理。它拥有庞大,快速发展的生态系统。
谷歌在2014年开源了Kubernetes项目。Kubernetes以谷歌在大规模运行生产工作负载方面的15年经验为基础,结合社区的最佳想法和实践。

	1.kubernetes是什么意思?
	2.我们为什么需要kubernetes以及它可以为我们做些什么?
	3.kubernetes是一个怎样的平台?
	4.kubernetes不是什么?
	5.为什么使用容器?
kubernetes是什么意思?

Kubernetes也称为k8s,kubernetes这个名字来源于希腊语,意为舵手和飞行员,而k8s则是将“ubernete”8个字母替换为“8”而得到的缩写。

我们为什么需要kubernetes以及它可以为我们做些什么?

kubernetes拥有许多的功能,可以认为它是:

1: 一个容器平台
2: 一个微服务平台
3: 便携式云平台,等等。

Kubernetes提供了以容器化为中心的管理环境,它代表用户工作负载协调计算,网络和存储基础架构。这提供了平带即服务(PaaS)的简单性,具有基础架构即服务(LaaS)的灵活性,并支持跨基础架构提供商的可移植性。

kubernetes是一个怎样的平台?

尽管kubernetes提供了很多的功能,但总会有新的方案从新功能中受益。可以简化特定程序的工作流程,以加快开发人员的速度,最初可接受的特殊编排通常需要大规模的健壮自动化。这就是为什么kubernetes被设计成一个平台,用于构建一个有组件和工具组成的生态系统,使其更容易部署,扩展和管理应用。
此外,kubernetes控制平面基于开发人员和用户可用的相同API构建,用户可以使用自己的API编写控制器,(列如调度程序),这些API可以通过命令行工具进行定位。
这种设计使得许多其他系统能够在Kubernetes上面构建。

kubernetes不是什么?

Kubernetes不是一个传统的,包罗万象的PaaS(平台即服务),由于Kubernetes在容器级而非硬件级运行,因此它提供了PasS产品常用的一些通用功能,例如:部署,扩展,负载均衡,日志记录和监控。然而,Kubernetes并不是完全统一的,而且这些默认解决方案是可选的和可插入的。Kubernetes为构建开发平台提供了构建快,但在重要的地方保留了用户的选择和灵活性。

Kubernetes:

1:不限制所支持的应用程序类型,Kubernetes的目标是支持多样化的工作负载,有状态和数据处理工作负载,如果有应用程序可以在容器中运行,那么它就可以更好地在Kubernetes上面运行。
2:不部署源代码,也不构建应用程序,持续集成,交付和部署(CI/CD)工作流程由偏好及技术要求决定。
3:不提供应用程序级服务,例如 消息总线 (例如:中间件),数据处理框架,数据库,高速缓存,也不提供集群存储系统(列如:Ceph)。在服务中,这些组件可以在Kubernetes中运行,可以通过便携式机制(列如:Open Service Broker) 在Kubernetes上运行的应用程序访问。
4:不指示记录,监控或警报解决方案。提供了一些集成作为概念证明,以收集和导出标准的机制。
5:不提供或者授权配置语言或者系统(例如:jsonnet)。它提供了一个声明性的API,可以通过任意形式的声明性规范来实现。
6:不提供或采用任何全面的机器配置,维护,管理或者自我修复。

此外,Kubernetes不仅仅是一个编排系统。实际上,它消除了编排的需要。业务流程的技术定义:首先执行A,然后运行B,然后运行C,相反,Kubernetes由一组独立的,可组合的控制流程组成,这些流程将当前状态持续推向所提供的所需状态,从何从A到C无关紧要,也不需要集中控制。这使得系统更易于使用,且功能更加强大,更具有伸缩性和可扩展性。

为什么使用容器?

部署应用程序的旧方法就是使用操作系统软件包管理器在主机上安装应用,这样做的缺点是将应用程序的可执行文件,配置,生命期彼此纠缠在一起,并与主机的操作系统纠缠在一起,可以构建不可变的虚拟机镜像以实现可预测的部署和回滚,但虚拟机是重量级且不可移植的。

而容器则是基于操作系统虚拟化,而不是硬件虚拟化部署的容器,这些容器彼此隔离并与主机隔离,无法看到彼此之间的进程,具有自己的文件系统,并且它们的计算机资源使用受到限制。比虚拟机更容易构建,与底层基础架构和主机文件系统分离,所有它们可以跨云和操作系统进行移植。

由于容器小而快,因此它们每个容器镜像中打包一个应用程序,这种一对一的应用程序到镜像关系解锁了容器的全部优势。使用容器,可以在构建/发布时而不是部署时创建不可变得容器镜像,因为每个应用程序不需要与应用程序的堆栈的其余部署组合。也不需要与生产基础结构环境结合。在构建/发布时容器镜像可以实现从开发到生产环境统一。同样,容器比VM更加透明,有利于监控和管理。容器的流程生命周期由基础架构管理而不是容器内的流程管理。最后,对于每个容器只有一个应用程序,管理容器就相当于管理容器的部署!




Kubernetes核心组件

kubernetes主要由以下几个组件组成:

  • etcd 保存了整个集群的状态.
  • kubectl 是 Kubernetes 客户端命令行工具(CLI).
  • apiserver 操作资源的唯一入口,并且提供了,认证,授权,验证,注册和发现机制.
  • kubelet 负责维护容器的生命周期,同时也负责,Volume(卷)和CNI(网络)的管理.
  • controller manager 负责维护集群的状态,比如故障检测,自动扩展,滚动升级等.
  • kube-proxy 负责为 server 提供 cluster 内部的服务发现和负载均衡
  • kube-scheduler 负责分配调度已经创建好的 pod 到集群内的节点上,并且监听 apiserver 查询还未分配 pod 的 node,然后根据调度策略为这些 pod 分配节点.

详情如下

kubeadm

所有的机器都需要初始化执行引擎和 kubelet,这是因为 kubeadm 依赖 kubelet 来启动 master 组件,像 kube-apiserver,kube-proxy等等,kubeadm 的提供让我们可以一键部署集群,是目前 Kubernetes 主推的部署方式.我们只需要执行
kubeadm init --config kubeadm-config.yaml
//或者不指定配置文件
kubeadm init --kubernetes-version=v1.12.0
这两个命令都会执行:
  • 系统检查,
  • 生成token,
  • 生成自签名 CA 证书 和 client 端证书,
  • 生成 kubeconfig 用于 kubelet 链接 apiserver,
  • 为 Master 组件生成 Static Pod manifests 并放到 /etc/kubernetes/manifests 目录中
  • 配置 RBAC 权限,设置污点
  • 创建其他服务,比如:kube-proxy,kube-dns
删除集群也同样非常简单:
kubeadm reset		

kubectl

kubectl配置:使用 kubectl 的第一步就是配置 kubernetes 集群以及认证方式包括, cluster信息:kubernetes server 地址, 用户信息:用户名密码, Context:cluster,用户信息以及 Namespaces 的组合.
kubernetes 提供了 kubectl 来管理集群,同时 kubelet 本身提供了大量的命令比如这里说一下怎么查看帮助命令:

kubectl options //查看全局选型
kubectl [command] --help //查看子命令帮助
kubectl explain [RESOURCE] //查看资源的定义
kubectl [command] [PARAMS] -o= //设置输出格式(如 json、yaml、jsonpath 等)
kubectl一些常用命令:

//创建(提供两种方式)
kubectl create -f xxx.yaml	
kubectl run xxx --image=xxx
//删除(提供两种方式)
kubectl delete -f xxx.yaml
kubectl delete <resource> xxx
//更新(提供两种方式)
kubectl set 
kubectl patch
//查询
kubectl get xxx
//容器内执行命令
kubectl exec -it <pod-name> sh
//日志查看
kubectl logs [-f] <pod-name>

apiserver

apiserver 提供了 kubernetes 各类资源的对象(pod,RC)增删改查以及 watch 等 http Rest接口,是系统的数据总线和数据中心, apiserver 主要提供的功能包括:
  • 集群之间管理的 REST API 接口,(包括认证授权,数据校验,以及集群状态变更)
  • 提供了其他模块之间的数据交互和通讯的枢纽,(其他模块只能通过 apiserver 查询或者修改数据,只有 apiserver 可以直接操作 etcd)
  • 是资源资源配额控制的入口
  • 拥有完善的集群安全机制

REST API
kube-apiserver 支持同时提供 http(6443端口)和 http API(127.0.0.1的8080端口),其中 http API 是非安全的是不建议生产环境使用的.
集群内部与 API Server 的交互
例:与 kube-scheduler,当 scheduler通过 API Server的 Watch接口监听到新建 pod副本的信息后,它就会检索所有符合该 pod要求的 node,开始执行 pod调度逻辑,调度成功之后将 pod绑定到 node上。
与 kubelet进行交互,每个 node上面的 kubelet会每隔一个时间周期,就会调用一次 API Server的 REST接口报告自身状态,API Server则是接收到这些状态,将这些状态保存到 etcd中,此外,kubelet也通过 API Server的 watch接口监听 pod信息,假如监听到新的 pod副本被分配到本节点上,则执行 pod对应的容器创建和启动逻辑,删除以及也是一样。


kubelet

kubelet会运行在每个节点上面,默认监听的是 10250端口,接收并执行 user发送的信息,管理 pod以及 pod中的容器,每个 kubelet 都会向 apiserver注册自身,监控节点和容器资源,并且定期向 apiserver汇报节点资源信息.

节点管理主要包括:

  • 启动参数 --register-node确认是否向 apiserver注册自己
  • 如果 kubelet没有选择自注册模式,则需要用户自己配置 node资源信息,同时需要告知 kubelet集群在 apiserver的位置.
  • kubelet在启动时通过 apiserver注册节点信息,并且定时向 apiserver发送节点信息, apiserver在得到消息后,向信息写入 etcd.

pod管理主要包括:

kubelet通过 PodSpec的方式工作,PodSpec是描述一个 Pod的 yaml或者 json对象,kubelet采用一组通过各种机制提供的 PodSpecs(apiserver),并确保这些 PodSpecs描述的 Pod正常运行.

  • 文件:启动参数 --config指定的配置目录下的文件,默认在 /etc/kubernetes/manifests下,每20秒检索一次
  • HTTP endpoint(URL):起订参数 --manifest-url设置,每20秒检索一次这个端点
  • API Server:通过 API Server监听 etcd,同步更新 pod清单
  • ATTP Server:kubelet监听 HTTP 请求,并相应简单的 API以提交新的 pod清单

通过 apiserver获取 pod清单并且创建修改 pod过程:
kubelet通过 apiserver client使用 Watch+List 的方式监听 “/registyr/node/$ 当前节点名”和 “/registry/pods”目录是获取的信息获取到同步缓存中,kubelet监听 etcd所有针对 pod的操作都会被 kubelet坚挺到,如果发现有新绑定到本节点的 pod,则按照 pod的清单进行创建.
发现本地的 pod被修改,kubelet会做出更新动作,如:删除 pod中的某个容器,则通过 Docker Client删除该容器,发现删除本节点的 pod,则删除相应的 pod,并且通过 Docker Client删除该 pod中的容器.

  • 为该 pod创建一个数据目录
  • 从 apiserver读取该 pod清单
  • 为该 pod挂载外部卷
  • 检查已经在节点上运行的 pod,如果该 pod没有容器或者 pause 容器,没有启动,则先停止 pod里所有的容器进程,如果 pod里有需要删除的容器,则删除这些容器
  • 用 “kubernetes/pause” 镜像为每个 Pod 创建一个容器,pause容器用于接管 pod中所有其他容器的网络,每创建一个新的 pod,kubelet都会先创建一个 pause容器,然后创建其他容器.
  • 为 pod中的每个容器做出下面处理:
    1:为容器计算出一个 hash值,然后用容器的名字去 Docker查询对应容器的 hash值,若查到容器,且两者的 hash值并不相同,则停止 docker中运行的容器,并停止相关联的 pause容器,若两者完全相同,则不做任何处理.

Pod的启动流程
在这里插入图片描述

这张图出自:	https://kubernetes.feisky.xyz/he-xin-yuan-li/index-1/kubelet

Static Pod

所有以非 apiserver方式创建的 pod都叫做 static pod ,kubelet将 static pod的状态汇报给 apiserver,apiserver为该 static pod创建一个 Mirror pod和其相匹配,Mirror pod的状态信息真是反映 static pod的状态,当 static pod被删除时,与之对应的 Mirror Pod也会被删除.

容器运行时

容器运行时(Container Runtime)是 kubernetes最总要的组件之一,真正负责管理镜像和容器的生命周期,kubelet通过 Container Runtime Interface与容器运行时交互,以管理容器和镜像.
Container Runtime Interface它将 kubelet与容器运行时解耦,将原来完全面向 pod级别的内部接口拆分面向 Sandbox和 Container的 gRPC接口,并将镜像管理和容器管理分离到不同的服务.
在这里插入图片描述
CRI最早从1.4版本就开始设计讨论和研发,在 v1.5中发布了第一个测试版,在v1.6中已经有了很多外部容器运行时,在 v1.7中又新增了 cri-containerd支持.

kubelet是kubernetes最为核心的部分,这里只写出了一部分,就不一一赘述了,大家可以参考下面网站内容
//https://github.com/kubernetes/kubernetes/tree/master/pkg/kubelet
//https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/
//https://kubernetes.feisky.xyz/he-xin-yuan-li/index-1/kubelet

kube-controller-manager

controller-manager则是很多很多控制器的集合,它的作用就好像人类的大脑一样通过 apiserver控制着整个集群并且确保集群处于预期的工作状态,其中就包括:
  • Replication Controller
  • Node Controller
  • CronJob Controller
  • Daemon Controller
  • Deployment Controller
  • Endpoint Controller
  • Garbage Collector
  • Namespace Controller
  • Job Controller
  • Pod AutoScaler
  • RelicaSet
  • Service Controller
  • ServiceAccount Controller
  • StatefulSet Controller
  • Volume Controller
  • Resource quota Controller

这里另外提一个叫做 cloud-controller-manager的控制器,它也是 kube-controller-manager的一部分,稍有不同的是只有用户启动 cloud-Provider的时候才会需要,用来提供云服务供应商的控制,它里面的控制器就比较少了:

  • Node Controller
  • Route Controller
  • Service Controller

高可用
在启动时设置 --leader-elect=true后,controller manager会使用多节点选主的方式选择主节点,只有主节点才会调用 StartControllers()启动所有控制器,而其他从节点则仅执行选主算法.
多节点选主的实现方法在 leaderelection.go文件它实现了两种资源锁( Endpoint或 ConfigMap,kube-controller-manager和 cloud-controller-manager都使用 Endpoint锁),通过更新资源的 Annotation,来确定主从关系.

高性能
从 Kubernetes1.7开始,所有需要监控资源变化情况的调用均推荐使
Informer,Informer提供了基于事件通知的只读缓存机制,可以注册资源变化的回调函数,并可以极大减少 API 的调用.


kube-proxy

kube-proxy在每台机器上面运行,用来监听 apiserver 和 server的变化,并且通过 iptables为服务配置负载均衡,目前仅支持TCP和UDP.
支持以下几种实现方式
  • usernamespace,最早实现负载均衡的方案,它是在用户的命名空间监听一个端口,所有访问通过 iptables转发到该端口,然后再内部负载均衡到实际的 pod,该方法效率较低,所以性能比较差.
  • iptables,比较主流的方法,该方法完全以 iptables的方式实现到 server之间的负载均衡,该方法的问题是在服务多是会产生大量的 iptables规则,会出现延时,大规模集群的情况下有着明显的性能问题.
  • ipvs:为解决 iptables 模式的性能问题,v1.11新增了 ipvs模式(v1.8 开始支持测试版,并在 v1.11 GA),采用增量式更新,并可以保证 service更新期间连接保持不断开.

iptables示例
在这里插入图片描述

图片出自:https://github.com/cilium/k8s-iptables-diagram

启动 kube-proxy

kube-proxy --kubeconfig=/var/lib/kubelet/kubeconfig --cluster-cidr=10.240.0.0/12 --feature-gates=ExperimentalCriticalPodAnnotation=true --proxy-mode=iptables

kube-proxy工作原理
在这里插入图片描述

该图出自:https://kubernetes.feisky.xyz/he-xin-yuan-li/index-1/kube-proxy

etcd


etcd在这里就没有那么多的事情了,etcd是基于 CoreOS基于 Raft开发的 key-value分布式存储,用于服务发现,共享配置,以及一些分布式锁,选主等.

etcd的主要功能

  • 基本的 key-value 存储
  • 监听机制
  • key 的过期及续约机制,用于监控和服务发现
  • 原子 CAS 和 CAD,用于分布式锁和 leader 选举

Etcd 基于 RAFT 的一致性

选举方法

  1. 初始启动时,节点处于 follower 状态并被设定一个 election timeout,如果在这一时间周期内没有收到来自 leader 的 heartbeat,节点将发起选举:将自己切换为 candidate 之后,向集群中其它 follower 节点发送请求,询问其是否选举自己成为 leader。

  2. 当收到来自集群中过半数节点的接受投票后,节点即成为 leader,开始接收保存 client 的数据并向其它的 follower 节点同步日志。如果没有达成一致,则 candidate 随机选择一个等待间隔(150ms ~ 300ms)再次发起投票,得到集群中半数以上 follower 接受的 candidate 将成为 leader

  3. leader 节点依靠定时向 follower 发送 heartbeat 来保持其地位。

  4. 任何时候如果其它 follower 在 election timeout 期间都没有收到来自 leader 的 heartbeat,同样会将自己的状态切换为 candidate 并发起选举。每成功选举一次,新 leader 的任期(Term)都会比之前 leader 的任期大 1。

日志复制

当前 Leader 收到客户端的日志(事务请求)后先把该日志追加到本地的 Log 中,然后通过 heartbeat 把该 Entry 同步给其他 Follower,Follower 接收到日志后记录日志然后向 Leader 发送 ACK,当 Leader 收到大多数(n/2+1)Follower 的 ACK 信息后将该日志设置为已提交并追加到本地磁盘中,通知客户端并在下个 heartbeat 中 Leader 将通知所有的 Follower 将该日志存储在自己的本地磁盘中。

安全性

安全性是用于保证每个节点都执行相同序列的安全机制,如当某个 Follower 在当前 Leader commit Log 时变得不可用了,稍后可能该 Follower 又会被选举为 Leader,这时新 Leader 可能会用新的 Log 覆盖先前已 committed 的 Log,这就是导致节点执行不同序列;Safety 就是用于保证选举出来的 Leader 一定包含先前 committed Log 的机制;

选举安全性(Election Safety):每个任期(Term)只能选举出一个 Leader

Leader 完整性(Leader Completeness):指 Leader 日志的完整性,当 Log 在任期 Term1 被 Commit 后,那么以后任期 Term2、Term3… 等的 Leader 必须包含该 Log;Raft 在选举阶段就使用 Term 的判断用于保证完整性:当请求投票的该 Candidate 的 Term 较大或 Term 相同 Index 更大则投票,否则拒绝该请求。

失效处理

  1. Leader 失效:其他没有收到 heartbeat 的节点会发起新的选举,而当 Leader 恢复后由于步进数小会自动成为 follower(日志也会被新 leader 的日志覆盖)

2)follower 节点不可用:follower 节点不可用的情况相对容易解决。因为集群中的日志内容始终是从 leader 节点同步的,只要这一节点再次加入集群时重新从 leader 节点处复制日志即可。

3)多个 candidate:冲突后 candidate 将随机选择一个等待间隔(150ms ~ 300ms)再次发起投票,得到集群中半数以上 follower 接受的 candidate 将成为 leader

ps:个人认为etcd并不是很难理解,所以没有细写,这里写的etcd出自:https://kubernetes.feisky.xyz/he-xin-yuan-li/index-1/etcd


参考网站:kubernetes.io
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章