Kubernetes 核心原理及实战中使用方法
认识 kubernetes 架构及应用场景kubernetes(k8s) 在企业中的应用场景构建自动化运维平台(1) 中小型企业,使用 k8s 构建一套自动化运维平台(降本增效)(2) 大型互联网公司更要使用,实现更高效的运作方式充分利用服务器资源服务无缝衔接服务部署模式变迁&服务部署模式变化的思考云架构 & 云原生kubernetes 架构原理深入认识 kubernetes 核心
欢迎关注公众号K的笔记阅读博主更多优质学习内容
认识 kubernetes 架构及应用场景
kubernetes(k8s) 在企业中的应用场景
构建自动化运维平台
(1) 中小型企业,使用 k8s 构建一套自动化运维平台(降本增效)
(2) 大型互联网公司更要使用,实现更高效的运作方式
充分利用服务器资源
怎么理解充分利用服务器资源这一条呢,我们举个例子:假设并发量200请求,服务器是两核心CPU,4G内存,其中静态请求150个,比如访问CDN、nginx、缓存等,动态请求50个,主要是访问数据库,把数据读入内存,我们来估算服务器资源(只考虑内存,不考虑程序员RT与CPU切换时间):
静态+动态 = 150*2M + 50 *10M = 800M
也就是说200个请求占用了800M内存
我们可以估算这台服务器的并发能力QPS为 200*4 = 8000,但实际上 800 QPS 是无法达到的,我们需要考虑 response time,cpu切换时间,内存等等,因此实际上我们会给它安排 300 QPS,此时先然无法充分利用服务器资源,有很多资源被浪费掉了。而 k8s 使用类似 Docker 的容器化方式,也就是我们在其中部署多个容器,将服务器资源做隔离,容器中部署的就是 web 服务。
服务无缝衔接
那么服务的无缝迁移又该怎么理解呢?首先我们开发时应该有三种环境,分别是是开发环境、测试环境和生产环境。在开发 web 项目时有许多配套服务,在测试环境中这些环境也必须存在,测试完之后产品就可以上线,但这时会出现一个问题:项目在测试时没有毛病,但一旦上市生产就出现了很大的问题,这经常是环境的不一致性造成的,这时候往往就会花费大量精力去调试环境,非常麻烦,而容器化方式可以做到服务无缝迁移。也就是说我们可以把 JDK、MQ、ES、MySQL 等做成一个个镜像,这些镜像可以脱离我们的依赖环境,因此这些镜像可以做到无缝迁移。
服务部署模式变迁&服务部署模式变化的思考
我们考虑下面几个问题:
服务部署模式是怎么变迁的。
- 物理机部署:就是直接把服务部署到物理机上(不能充分利用物理机资源)
- 虚拟化(虚拟机)方式,也就是通过虚拟机将物理资源进行隔离部署服务,将服务部署到虚拟机上,但虚拟机本身就非常占用资源,因此我们寻求一种更好的方式
- 使用容器化方式进行部署(容器更轻量级,运行更快)
服务部署模式变化,带来哪些问题?
-
前提条件:SOA架构,微服务架构的模式下,项目拆分越来越多,服务越来越多,这么多服务我们是怎么管理?
-
虚拟机服务部署方式(openstack)
-
容器化部署模式(k8s)
容器我们可以认为是一个更轻量级的虚拟机,使用了与虚拟机不同的技术,因此与openstack用于管理虚拟机类似, k8s 就是用来管理容器的。
-
-
面临问题:
-
如何对服务进行横向扩展(不能 简单地加机器,会影响服务)
-
容器宕机如何解决,数据怎么恢复
-
重新发布新的版本如何在线上快速更新,更新后不影响业务(k8s可以做滚动更新)
-
如何监控容器(容器出现问题怎么办)
-
容器如何调度创建
-
数据安全性如何保证
-
云架构 & 云原生
云和 k8s 是什么关系
- 云就是使用容器构建的一套服务集群网络,云由大量容器构成,不同容器有不同功能
- k8s 就是用来管理云中的容器
云架构
iaas 基础设施即服务
用户:可以租用(购买|分配权限)云主机,用户就不需要考虑网络,DNS,硬件环境方面的问题。
运营商:(私有云或公有云平台)提供网络,存储,DNS(基础设施服务)
paas 平台即服务
MYSQL\ES\R等服务都由平台提供了
saas 软件即服务(目前很多系统都是该系统)
钉钉:给每个公司提供一个系统,每个公司使用独立一套功能
财务管理软件:维护交给运营商维护,用户只需要使用其中的功能即可
serverless 无服务
站在用户角度:不需要服务器,用户只需要使用云服务器即可,在云服务器所有基础环境 ,软件环境都不需要 用户自己安装
未来:服务开发都是 serverless,企业都构建了自己的私有云环境,或者使用公有云环境(阿里云)
阿里将所有服务部署到云端之后,效率提升了60%
云原生
就是为了让应用程序(项目、服务软件)都 运行在云上的解决方案,这样的方案叫做云原生。
特点:
(1)容器化 —— 所有服务部署都必须部署在容器中
(2)微服务 —— web 服务架构、微服务架构
(3)CI、CD —— 可持续交互与可持续部署
(4)DevOps —— 开发与运维密不可分
kubernetes 架构原理
1)kubernetes 是 Google 使用 go 语言开发,原来的系统是 borg 系统(也是云平台管理工具),Docker后来自己开发了容器管理平台 Docker Swarm,Google 表示不服,因此参照 borg 架构开发了 k8s 架构
2)k8s 架构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1FX9K7FA-1591151340036)(./Pic/k8s/arch1.jpg)]
关系:一个 master 对应多个 node 节点
master 节点
- api server:k8s 网关,所有指令请求都必须经过 api server
- scheduler:调度器,使用调度算法,将请求资源调度给某一个 node 节点
- controller 控制器:维护 k8s 资源对象(添加、删除、更新、修改)
- etcd:存储资源对象,服务的注册与发现
node 节点
- docker:运行容器的基础环境,容器引擎
- kuberlet:在每个 node 节点都存在一份,在 node 节点上的资源操作指令由其执行
- kube-proxy:代理服务,负载均衡
- fluentd:日志收集服务
- pod:是 k8s 管理的基本单位,内部是容器,也即是 k8s 不直接管理容器,而是管理 pod
深入认识 kubernetes 核心组件原理
pod的核心原理
k8s的作用:k8s是用来管理容器的,但不直接操作容器,最小操作单元是pod(间接地管理容器)
k8s的特点:
- 一个master有一群node节点与之对应
- master节点不存储容器,只负责调度、网关、控制器、资源对象存储
- 容器是存储在node节点(容器是存储在pod内部)
- pod内部都可以有一个容器,或者是多个容器
- kubelet负责本地的pod维护
- kube-proxy负责在多个pod之间做负载均衡
pod是什么呢:pod也是一个容器,但这个容器中装的是docker创建的容器,也就是pod是用来封装容器的容器,pod是一个虚拟化分组(pod有自己的地址,主机名),相当于一台独立的沙箱环境(主机),可以封装一个容器或多个容器
pod用来干什么:通常情况下,在服务部署时使用pod来管理一组相关服务(一个pod要么部署一个服务,要么部署一组相关的服务),所谓的一组相关的服务,即为链式调用的调用链路上的服务。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cieWbksy-1591151340037)(./Pic/k8s/pod1.png)]
web服务集群如何实现:只需要复制多方pod的副本即可,这也是k8s管理的先进之处,k8s如果继续扩容、缩容,只需要控制pod的数量即可
pod底层网络,数据存储是如何进行的:pod内部容器创建之前必须先创建pause容器,服务容器之间的访问使用localhost访问,性能非常高,实际就像访问本地服务一样
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tIbIoE1Q-1591151340039)(./Pic/k8s/pod2.png)]
ReplicaSet副本控制器
什么叫做副本控制器:用于控制pod副本的数量,使副本数量与预期数量保持一致。例如,我们提前设置replicas=3(有三个副本),因此创建三个pod。当有一个pod宕机之后,k8s会立刻创建一个新的,保证副本数量等于三个,这就是副本控制器的作用——永远保证副本数量为设定值。
副本控制器能通过标签选择器选择维护一组相关的服务(它自己的服务),那么它要怎么判断是自己的服务呢?这里就通过标签选择,比如
selector:
app = web
release = stable
ReplicationController和ReplicaSet两个副本控制器有什么区别:
- ReplicaSet
- 单选
- 复合选择
- ReplicationController
- 单选
在新版的k8s中,推荐使用Replicaset作为副本控制器(功能更强大),ReplicationController不再使用
Deployment资源部署对象
- 服务部署结构模型
- 滚动更新
虽然在企业中我们采用ReplicaSet作为副本控制器,但在实际中项目不断更新,项目的版本将会不停的发版,版本的变化如何做到服务的更新呢?我们做的是滚动更新,如下图,每当发布一个新的版本,每更新一个POD,就要干掉原有的POD。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AYqWfw7n-1591151340040)(./Pic/k8s/Deployment.png)]
那么滚动更新是由谁实现的呢?这就涉及到部署模型:因为事实上ReplicaSet是不支持滚动更新的,滚动更新是由Deployment支持的,通常两者一起使用,因此部署模型为如下结构:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DinzZ2cM-1591151340043)(./Pic/k8s/dep2.png)]
如果后一个版本出现问题,k8s也可以支持向前滚动。
StatefulSet部署有状态服务
StatefulSet和Deployment类似,区别就是StatefulSet是为了解决有状态服务容器化部署问题而产生的。
思考:MySQL使用容器化部署,存在怎样的问题?
- 容器是有生命周期的,一旦宕机,数据丢失
- pod部署:pod有生命周期,但重启pod集群副本时数据可能丢失
因此容器是不太适合部署数据这样的有状态服务的,对于k8s而言,不能使用Deployment模型来部署有状态服务,通常情况下Deployment用于部署无状态服务,对于有状态服务的部署使用StatefulSet。
什么是有状态什么是无状态呢?
- 有状态服务
- 有实时的的数据需要存储
- 有状态服务集群中,把某一个服务抽离出去,一段时间后再加入机器网络,如果集群网络无法使用就被称为有状态服务
- 无状态服务
- 无实时的的数据需要存储
- 有状态服务集群中,把某一个服务抽离出去,一段时间后再加入机器网络,对集群网络没有影响
底层的数据存储借助PVC文件系统,而StatefulSet会保证POD重新建立后,hostname不会发生变化,POD就可以通过hostname来关联数据
kubernetes 的服务的注册与发现(核心)
pod在生产环境中的访问流程
pod的结构:根据前面所说,pod相当于一个容器,有独立的ip地址,也有自己的hostname,利用namespace进行资源隔离,独立沙箱环境。同时pod内部封装的是容器,可以封装一个,也可以封装一组相关的容器。
pod网络:有自己独立的ip地址,pod内部容器之间访问采用localhost访问。
pod如何对外网提供服务
- 前提思考:pod有PODID和hostname,pod是虚拟的资源对象(进程),没有对应的实体(物理机,物理网卡),单独的POD不能直接对外提供访问,对外提供访问一定要有物理机,通过端口访问
- 解决方案:POD如果想要对外提供访问,必须绑定物理机的端口,(在物理及上开启端口,让这个端口和POD的端口建立映射),这样就可以通过物理机进行数据包的转发
- 总结为步骤:①先通过物理机IP+port进行访问NODE节点;②数据包转发
pod如何实现负载均衡访问
一组相同的副本直接POD如何实现负载均衡访问,思考nginx能否做负载均衡:事实上pod是一个进程,是有生命周期的(宕机,版本更新),都会创建新的pod(ip地址发生变化,hostname发生变化),nginx做负载均衡不太合适,因为nginx不能识别出hostname的变化,因此在pod动态变化的前提下(且由于经常做滚动更新,变化速度比较快),nginx不能发现我们的服务。因此我们使用service VIP实现负载均衡。
利用service来实现负载均衡
- POD IP:pod的ip地址
- NODE IP:物理机的IP地址
- cluster IP:虚拟化IP,是由k8s抽象出的service对象,这个service对象是一个VIP的资源对象
Kubernetes 这样定义Service :逻辑上的一组 Pod,一种可以访问Pod的策略,通常称之为微服务。 这一组 Pod 能够被 Service 访问到,通常是通过selector实现的。当我们调用某个服务时并不关心调用了哪个Pod,对外提供服务一组的 Pod 实际上可能会发生变化(是否能提供服务,或者在销毁中,或者在创建中),而Service 能够解耦这种关联。
在 Kubernetes 集群中,每个Node运行一个 kube-proxy代理进程。kube-proxy 负责为 Service实现了一种VIP(虚拟 IP)。
以下为Service资源对象:
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
labels:
app: nginx
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
selector:
app: nginx
Service如何实现负载均衡
我们知道了一组相关的port做负载均衡会使用虚拟IP来做数据包转发,但service是节点(资源对象)是怎么实现数据包的转发呢?
我们已知的:
- service和pod都是一个进行,因此service也不能对外网提供服务
- service和pod之间可以直接进行通信,它们的通信属于局域网通信
- 把请求交给service后,service使用(ipstables,ipvs)来做数据包分发
访问步骤:
- 在物理机上绑定端口
- 通过ip:port访问
- 访问完成之后将请求转交给service
- service将数据包分发给相应的pod
service对象是如何与pod建立关联的?
每一组相同的pod(副本)会有相同的标签,通过标签选择器(selector),service对一组相同的副本提供服务,如果是需要访问另一组,则需在创建一个service。因此不同的业务会有不同的service。然后service将对应的POD的IP地址存储到endpoints中,由此将service和相应的pod关联起来了。
当pod宕机或者发布了新的版本,service怎么发现pod发生了变化?
主要是依靠kube-proxy组件,k8s安装后每个节点都运行着这个组件。kube-proxy进程将监听所有的pod,一旦发现pod有变化,就会更新service中endpoint中的映射关系。
本文图片上传有些问题,若想获得更好的观看体验,欢迎访问我的个人博客主页 ~
更多推荐
所有评论(0)