企业级运维之云原生与Kubernets实战课程
第一章第2讲 容器和K8s核心概念(下)
摘要:本小节主要内容为K8s核心概念、Kubernetes功能、Kubernetes的架构、Kubernetes核心组件(Master、Worker、Pod)等内容。
视频地址:https://developer.aliyun.com/learning/course/913/detail/14493
目录
- 什么是 Kubernetes
- Kubernetes功能
- Kubernetes的架构
- Kubernetes核心概念
一、什么是 Kubernetes
Kubernetes是一种容器编排工具。如第一讲说述,既然Docker已经提供了相关命令,为什么还需要容器编排工具呢?
- 与传统架构相比,微服务架构下会更依赖通过各微服务之间的协作来实现一个完整的业务流程,这种协作就是服务编排。编排涉及到RPC、分布式事务等,需要有完善的编排框架来支撑;
- 以“部署容器化应用简单高效”为目的,为容器化应用部署调度、规划、更新、维护等提供机制的工具。
Docker命令可以对Nginx和Tomcat进行相关管理,假如有成千上百台容器需要管理,要解决每个容器之间的依存关系,如反亲和,那么使用Docker进行管理就比较麻烦,这就需要一个工具对容器进行编排,减少不必要的劳动,使其更加友好的使用,容器编排工具K8s就这样产生了。
二、Kubernetes功能
1. 服务发现与负载均衡
- 假如在服务器上运行5个Nginx容器,提供相同的服务功能,且每个容器只有1000QPS流量能力,每个容器只分配了2CPU。当流量被打满,通过扩容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而非200m(0.2bytes会导致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,怎么挂载卷,网络架构区别,这些问题将在下节课进行讲解。