开发者学堂课程【企业级运维之云原生与 Kubernets 实战课程:容器和 K8S 基础概念(下) 】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/913/detail/14493
容器和 K8S 基础概念(下)
摘要:本小节主要内容为 K8s 核心概念、Kubernetes 功能、Kubernetes 的架构、Kubernetes 核心组件(Master、Worker、Pod)等内容。
目录
Ÿ 什么是 Kubernetes
Ÿ Kubernetes 功能
Ÿ Kubernetes 的架构
Ÿ Kubernetes 核心概念
一、什么是 Kubernetes
Kubernetes 是一种容器编排工具。如第一讲说述,既然 Docker 已经提供了相关命令,为什么还需要容器编排工具呢?
Ÿ 与传统架构相比,微服务架构下会更依赖通过各微服务之间的协作来实现一个完整的业务流程,这种协作就是服务编排。编排涉及到 RPC、分布式事务等,需要有完善的编排框架来支撑;
Ÿ 以“部署容器化应用简单高效”为目的,为容器化应用部署调度、规划、更新、维护等提供机制的工具。
Docker 命令可以对 Nginx 和 Tomcat 进行相关管理,假如有成千上百台容器需要管理,要解决每个容器之间的依存关系,如反亲和,那么使用 Docker 进行管理就比较麻烦,这就需要一个工具对容器进行编排,减少不必要的劳动,使其更加友好的使用,容器编排工具 K8s 就这样产生了。
二、Kubernetes功能
1. 服务发现与负载均衡
Ÿ 假如在服务器上运行5个 Nginx 容器,提供相同的服务功能,且每个容器只有 1000QPS 流量能力,每个容器只分配了 2 CPU 。当流量被打满,通过扩容 CPU 是可以解决的,但是如果流量一直被打满,就需要上千个 CPU,在流量低谷时又不需要这么多的 CPU,该如何权衡花费?
Ÿ 这时候最好的方式就是:在流量很大的时候将流量分散到不同的容器里,这样每个容器只需要很小的 CPU,应用可以在一台宿主机上运行,也可以在很多宿主机上运行,而 k8s 满足了这样的需求,可以理解为通过前端的 vip 进行负载均衡将流量分发到不同的 Nginx 上。
2. 容器自动装箱
容器与容器之间如何结合?假如有两个容器,容器 A 和容器 B ,容器 A 为生产的容器,产生的日志需要被采集用于生产环境业务的分析;容器 B 需要分析容器 A 产生的日志,那么容器 A 和容器 B 需要在相同节点上,怎么将容器 A 和容器 B 绑定在一起呢?这就用到了容器自动装箱功能。
3. 存储编排
可以通过 K8s 实现将本地盘或者云盘等存储挂载到容器上。
4. 自动容器恢复
如上所述,有 5 个容器,假如一个容器挂掉,可以通过 K8s 进行恢复。
5. 自动发布与回滚
如在新发布的服务后,发现配置缺失,可以通过 K8s 回滚到之前版本。
6. 配置与密文管理
配置与密文管理是指 comfigmap 配置与 secret 管理,如在仓库里拉取镜像时需要进行身份验证,如果已定义完成密钥文件和配置,在进行交互时就会被引用,而不需要再输入账号密码。
7. 批量执行
容器通过 Job 或 Crontab Job 方式执行。
8. 水平伸缩
如上述 5 个 Nginx 容器,假如遇到双11节假日访问量剧增,5 个容器无法满足需求,如何通过流量的大小自动创建容器或者缩小容器副本数呢?可以通过 K8s 水平伸缩功能实现,阿里云也已经实现垂直伸缩,即内存和 CPU 大小可以进行伸缩。
9. Kubernetes--调度
Ÿ 下图中在紫色框外的为等待调度的容器,紫色框中为正在调度的容器,下面蓝色框中为已调度的容器,白色框框为节点。
Ÿ 假如白色框所有节点能满足等待调度容器的要求,则容器在调度时会首先筛选出满足要求的节点,然后对满足要求的节点进行打分,分数由高到低的排序,打分最高的节点会被调度,这就是 kubernetes 的调度机制,调度分 pending 和 running 状态。
Ÿ 假如白色框框节点已被占用,节点已无资源可被调度 Pod,而等待调度的 Pod 能否正常被调度,取决于该 Pod 的优先级设定,这里有 Priority Class 的概念,即对不同的 Pod 设置不同优先级,假如等待调度的 Pod 优先级高于已被调度的 Pod ,则被已被调度的 Pod 会被驱逐,进而优先级高的 Pod 会被调度。
10. Kubernetes--自动恢复
假如在 K8s 运行过程中,有个节点无响应失联导致 k8s 集群无法感知该节点上 Pod 的运行状态,超过一定阈值后,K8s 会判定该节点是不可调度不存在的,为维持副本数会在其他节点将该服务拉起,而失联节点上的 Pod 可能还是在运行的状态,因为节点的失联可能是节点上 kubelet 组件出现问题,无法感知到 K8s 集群是否已驱逐该 Pod。
假如业务流量很大,可以利用 HPA 弹性伸缩功能,将会自动生成一个 Pod 在其他节点上被拉起,来共同承担流量的压力。
三、Kubernetes 的架构
K8s 是 CS(Client-Server)架构,对集群的所有操作包括命令、页面等,都是访问的 Master 节点,由 Master 节点对输入的命令进行处理后发生到相关节点上进行具体操作。
1. Master
Master 节点主要有如下组件:
Ÿ API Server:大脑,处理输入命令
Ÿ Controller:控制器
Ÿ Deployment:有状态服务
Ÿ Statefulset:有状态服务
Ÿ Daemonset:可以在每个节点启动一个
Ÿ Job:只允许一次或者达到失败阈值
Ÿ Cronjob:定期执行 Job
Ÿ Scheduler:调度器
Ÿ Etcd:键值数据库,持久存储,保证业务的一致性,所有 Pod 的相关信息,包括副本信息,svc 等信息,都是以键值的方式存储在 Etcd 中,这样如果 Pod 被删除,通过 Etcd 的 watch 会读取 Pod 的原始信息进行拉起,来维持副本数一致。
在阿里云上,ACK 环境中 Master 这些组件是被阿里云托管和维护的,客户侧是不用维护的,客户侧可以看到是 Node 节点上的组件。
2. Node
K8s 的 Node 上有 Kubelet 和 Kube-proxy ,当 Scheduler 需要调度 Pod 到某个节点上,相关命令通过 Master 节点发送给 Node 节点上的 Kubelet,Kubelet 根据相关的调度信息调用 Runtime(Runtime 可能是 Containerd 也可能是 docker )拉取该 Pod。
假如该 Pod 需要挂载使用的是 Storage Plugin(存储插件)而非使用组件 Kubelet,为 Pod 提供IP可以调用 Network Plugin(网络插件),Kube-proxy 使用的是 Iptables 或 Ipvs。对于大规模的集群推荐使用 Ipvs,因为是幂等性的,可以快速找到负载均衡的定位,找到目的 IP。Kube-proxy 可以将流量转发到不同的 Pod 上。
3. Kubernetes 整体架构
如图,用户与 API Server 进行交互,将命令或者控制台上的相关操作发生给 API Server,API Server 根据要求再转发给 Controller Manager、Scheduler,再发送到整个 Node 节点上的 Kubelet、Kubeproxy。
四、Kubernetes 核心概念
1. Pod
一个 Pod 上至少有一个容器,Pod 是 K8s 最小的调度单元,Pod 会对每个容器设置 CPU 和 Memory 大小,为每个容器挂载不同的 Volume 及设置不同的环境变量。
Pod 状态:
Ÿ running:业务不一定是正常的,容器可能有多个,但至少有一个容器运行。
Ÿ succeed:正常退出:
Ÿ Terminating:容器正在被停止,可能因为宿主机空间满在被删除或i属性文件(不可删不可读的文件)。i 属性文件一般是程序在运行时调用了 rancher、finalizer 产生的,假如是 rancher,只需要改文件属性即可;finalizer 是在程序运行时可能产生了附属结构或关联的文件,需要其他程序将产生的附属结构或关联的文件删除,才能将 Pod 删除,否则无法直接将 Pod 删除。
Ÿ containercreating:容器在创建中,假如一直处于创建中,可能是挂载卷 volume 问题、资源限制时单位写错 memeory20OMi 而非 200 m(0.2 bytes 会导致 cgroup OOM)、内存碎片化等原因。
Ÿ pending:等待调度,假如没有分配节点可能是集群资源不够,Pod 设置的时候有没有 nodeselecter、污点、亲和性等等,假如已经分配节点了,节点上的磁盘满了或者节点上的 pod 的 ip 池不够,也会导致 Pending 状态。
Ÿ Imagepullbackoff:拉取镜像失败,有可能是网络、验证出了问题,或是用 http 方式拉取镜像而非 https 方式。
Ÿ crashloopbackoff:表明 pod 曾经正常运行,某种原因终止了,返回代码 code 0-127,0 代表正常终止,1-127 需要看 Pod 日志,一般和应用相关。
2. Volume
Volume 就是卷的概念,它是用来管理 Kubernetes 存储的,声明在 Pod 中的容器可以访问的文件目录,一个卷可以被挂载在 Pod 中一个或者多个容器的指定路径下面。
而 Volume 本身是一个抽象的概念,一个 Volume 可以去支持多种的后端的存储。比如说 Kubernetes 的 Volume 就支持了很多存储插件,它可以支持本地的存储,可以支持分布式的存储,比如说像 ceph,GlusterFS;它也可以支持云存储,比如说阿里云上的云盘、AWS 上的云盘、Google 上的云盘等等。
3. Deployment
Deployment 定义一组 Pod 的副本数目、版本等,通过控制器( Controller )维持 Pod 副本数目,假如对 Deployment 设置了 5 个副本数,删除了一个副本数也会自动恢复,Deployment 可以对 Pod 进行滚动升级、回滚等操作。
Deployment 通过 replicaset 创建 Pod,假如已有在运行的 Pod 服务,更新了 Pod的 Deployment,将会重新创建一个相同名字加一串字符的 replicaset,然后会自动按照 Deployment 设置的规则进行滚动更新,并将正在运行的 Pod 调度到新创建的 replicaset 下,旧的 replicaset 还会保存下来以便于回滚。
4. Service
SVC(Sevrice)可以在集群中提供一个 Vip,Vip 与 Pod 进行绑定,访问 Vip 时 Pod 会根据算法规则进行相关调度,这样就减少了 Pod 的访问压力。SVC 支持多种访问方式实现:
Ÿ ClusterIP:集群内分给集群内部使用的 SVC 的 IP;
Ÿ NodePort:会在每个节点上开放一个指定的端口;
Ÿ Loadblalancer:可以理解为 nodeport+SLB,流量流向是由 client->slb->node->pod
Ÿ Headless:通过 SVC 的名字访问;
Ÿ Extername:需要调用 a1iyuncheck.com 实现该功能。
5. Namespaces
Ÿ Namespace 是用来做一个集群内部的逻辑隔离的,它包括鉴权、资源管理等; Kubernetes 的每个资源,比如 Pod、Deployment、Service 都属于一个Namespace;
Ÿ 同一个 Namespace 中的资源需要命名的唯一性;
Ÿ 不同的 Namespace 中的资源可以重名。
Namespace 用例:阿里巴巴内部会有很多个 business units,在每一个 business units 之间,希望有一个视图上的隔离,并且在鉴权上也不一样,在 cuda 上面也不一样,就会使用 Namespace 来去给每一个 BU 提供隔离的机制。
本讲小结
下面以一个例子帮助理解 Kubernetes 架构中的这些组件,是如何互相进行交互的。
用户通过 UI 或者 CLI 提交一个 Pod 给 Kubernetes 进行部署,这个 Pod 请求首先会通过 CLI 或者 UI 提交给 Kubernetes API Server ,下一步 API Server 会把这个信息写入到它的存储系统 etcd,之后 Scheduler 会通过 API Server 的 watch 或者叫做 notification 机制得到这个信息:有一个 Pod 需要被调度。
这个时候 Scheduler 会根据它的内存状态进行一次调度决策,在完成这次调度之后,它会向 API Server report 说:“OK! 这个 Pod 需要被调度到某一个节点上。”
本讲主要内容:
1.K8s 和容器之间的区别,K8s 不等于容器,是容器的编排工具,实现了容器无法实现的功能,同时减少了对容器的维护压力。
2.K8s 的基本结构,Master 和 Worker 节点,Mater 节点上有 apiserver,controller,scheduler,etcd。Worker 节点有 kubelet、kube-proxy(iptables/ipvs) 实现了将 Pod 的 IP 加到 SVC 中。
3.Deployment,Pod 几种状态,SVC 流量类型及区别。
思考:为什么 K8s 最小的原子维度是 Pod,kubelet 命令的使用,怎么创建 deployment 和 SVC,怎么挂载卷,网络架构区别,这些问题将在下节课进行讲解。