(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可以做滚动更新)
如何监控容器(容器出现问题怎么办)
容器如何调度创建
数据安全性如何保证
用户:可以租用(购买|分配权限)云主机,用户就不需要考虑网络,DNS,硬件环境方面的问题。
运营商:(私有云或公有云平台)提供网络,存储,DNS(基础设施服务)
MYSQL\ES\R等服务都由平台提供了
钉钉:给每个公司提供一个系统,每个公司使用独立一套功能
财务管理软件:维护交给运营商维护,用户只需要使用其中的功能即可
站在用户角度:不需要服务器,用户只需要使用云服务器即可,在云服务器所有基础环境 ,软件环境都不需要 用户自己安装
未来:服务开发都是 serverless,企业都构建了自己的私有云环境,或者使用公有云环境(阿里云)
阿里将所有服务部署到云端之后,效率提升了60%
就是为了让应用程序(项目、服务软件)都 运行在云上的解决方案,这样的方案叫做云原生。
特点:
(1)容器化 —— 所有服务部署都必须部署在容器中
(2)微服务 —— web 服务架构、微服务架构
(3)CI、CD —— 可持续交互与可持续部署
(4)DevOps —— 开发与运维密不可分
1)kubernetes 是 Google 使用 go 语言开发,原来的系统是 borg 系统(也是云平台管理工具),Docker后来自己开发了容器管理平台 Docker Swarm,Google 表示不服,因此参照 borg 架构开发了 k8s 架构
2)k8s 架构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1FX9K7FA-1591151340036)(./Pic/k8s/arch1.jpg)]
关系:一个 master 对应多个 node 节点
master 节点
node 节点
k8s的作用:k8s是用来管理容器的,但不直接操作容器,最小操作单元是pod(间接地管理容器)
k8s的特点:
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)]
什么叫做副本控制器:用于控制pod副本的数量,使副本数量与预期数量保持一致。例如,我们提前设置replicas=3(有三个副本),因此创建三个pod。当有一个pod宕机之后,k8s会立刻创建一个新的,保证副本数量等于三个,这就是副本控制器的作用——永远保证副本数量为设定值。
副本控制器能通过标签选择器选择维护一组相关的服务(它自己的服务),那么它要怎么判断是自己的服务呢?这里就通过标签选择,比如
selector:
app = web
release = stable
ReplicationController和ReplicaSet两个副本控制器有什么区别:
在新版的k8s中,推荐使用Replicaset作为副本控制器(功能更强大),ReplicationController不再使用
虽然在企业中我们采用ReplicaSet作为副本控制器,但在实际中项目不断更新,项目的版本将会不停的发版,版本的变化如何做到服务的更新呢?我们做的是滚动更新,如下图,每当发布一个新的版本,每更新一个POD,就要干掉原有的POD。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AYqWfw7n-1591151340040)(./Pic/k8s/Deployment.png)]
那么滚动更新是由谁实现的呢?这就涉及到部署模型:因为事实上ReplicaSet是不支持滚动更新的,滚动更新是由Deployment支持的,通常两者一起使用,因此部署模型为如下结构:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DinzZ2cM-1591151340043)(./Pic/k8s/dep2.png)]
如果后一个版本出现问题,k8s也可以支持向前滚动。
StatefulSet和Deployment类似,区别就是StatefulSet是为了解决有状态服务容器化部署问题而产生的。
思考:MySQL使用容器化部署,存在怎样的问题?
因此容器是不太适合部署数据这样的有状态服务的,对于k8s而言,不能使用Deployment模型来部署有状态服务,通常情况下Deployment用于部署无状态服务,对于有状态服务的部署使用StatefulSet。
什么是有状态什么是无状态呢?
底层的数据存储借助PVC文件系统,而StatefulSet会保证POD重新建立后,hostname不会发生变化,POD就可以通过hostname来关联数据
pod的结构:根据前面所说,pod相当于一个容器,有独立的ip地址,也有自己的hostname,利用namespace进行资源隔离,独立沙箱环境。同时pod内部封装的是容器,可以封装一个,也可以封装一组相关的容器。
pod网络:有自己独立的ip地址,pod内部容器之间访问采用localhost访问。
一组相同的副本直接POD如何实现负载均衡访问,思考nginx能否做负载均衡:事实上pod是一个进程,是有生命周期的(宕机,版本更新),都会创建新的pod(ip地址发生变化,hostname发生变化),nginx做负载均衡不太合适,因为nginx不能识别出hostname的变化,因此在pod动态变化的前提下(且由于经常做滚动更新,变化速度比较快),nginx不能发现我们的服务。因此我们使用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
我们知道了一组相关的port做负载均衡会使用虚拟IP来做数据包转发,但service是节点(资源对象)是怎么实现数据包的转发呢?
我们已知的:
访问步骤:
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中的映射关系。
本文图片上传有些问题,若想获得更好的观看体验,欢迎访问我的个人博客主页 ~