etcd 是 CoreOS 团队发起的开源项目,是一个管理配置信息和服务发现(service discovery)的项目,它的目标是构建一个高可用的分布式键值(key-value)数据库,基于 Go 语言实现。
etcd基于其优秀的特点,可广泛的应用于以下场景:
HAProxy是可提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,是免费、快速并且可靠的一种解决方案。HAProxy非常适用于并发大(并发达1w以上)web站点,这些站点通常又需要会话保持或七层处理。HAProxy的运行模式使得它可以很简单安全的整合至当前的架构中,同时可以保护web服务器不被暴露到网络上。
HAProxy负载均衡策略非常多,常见的有如下8种:
四层负载均衡器也称为4层交换机,主要通过分析IP层及TCP/UDP层的流量实现基于IP加端口的负载均衡,如常见的LVS、F5等;
七层负载均衡器也称为7层交换机,位于OSI的最高层,即应用层,此负载均衡器支持多种协议,如HTTP、FTP、SMTP等。7层负载均衡器可根据报文内容,配合一定的负载均衡算法来选择后端服务器,即“内容交换器”。如常见的HAProxy、Nginx。
三者都是软件负载均衡产品。
Heartbeat是Linux-HA项目中的一个组件,它提供了心跳检测和资源接管、集群中服务的监测、失效切换等功能。heartbeat最核心的功能包括两个部分,心跳监测和资源接管。心跳监测可以通过网络链路和串口进行,而且支持冗余链路,它们之间相互发送报文来告诉对方自己当前的状态,如果在指定的时间内未收到对方发送的报文,那么就认为对方失效,这时需启动资源接管模块来接管运行在对方主机上的资源或者服务。
Keepalived 是一个基于VRRP协议来实现的LVS服务高可用方案,可以解决静态路由出现的单点故障问题。
在一个LVS服务集群中通常有主服务器(MASTER)和备份服务器(BACKUP)两种角色的服务器,但是对外表现为一个虚拟IP,主服务器会发送VRRP通告信息给备份服务器,当备份服务器收不到VRRP消息的时候,即主服务器异常的时候,备份服务器就会接管虚拟IP,继续提供服务,从而保证了高可用性。
core模块为keepalived的核心,负责主进程的启动、维护及全局配置文件的加载和解析。
vrrp模块是来实现VRRP协议的。
check负责健康检查,常见的方式有端口检查及URL检查。
Keepalived工作在TCP/IP模型的第三、四和五层,即网络层、传输层和应用层。
网络层,Keepalived采用ICMP协议向服务器集群中的每个节点发送一个ICMP的数据包,如果某个节点没有返回响应数据包,则认为此节点发生了故障,Keepalived将报告次节点失效,并从服务器集群中剔除故障节点。
传输层,Keepalived利用TCP的端口连接和扫描技术来判断集群节点是否正常。如常见的web服务默认端口80,ssh默认端口22等。Keepalived一旦在传输层探测到相应端口没用响应数据返回,则认为此端口发生异常,从而将此端口对应的节点从服务器集群中剔除。
应用层,可以运行FTP、telnet、smtp、dns等各种不同类型的高层协议,Keepalived的运行方式也更加全面化和复杂化,用户可以通过自定义Keepalived的工作方式,来设定监测各种程序或服务是否正常,若监测结果与设定的正常结果不一致,将此服务对应的节点从服务器集群中剔除。
Keepalived通过完整的健康检查机制,保证集群中的所有节点均有效从而实现高可用。
LVS是linux virtual server的简写linux虚拟服务器,是一个虚拟的服务器集群系统,可以在unix/linux平台下实现负载均衡集群功能。
LVS的主要作用是:通过LVS提供的负载均衡技术实现一个高性能、高可用的服务器群集。因此LVS主要可以实现:
LVS 有三种负载均衡的模式,分别是VS/NAT(nat 模式)、VS/DR(路由模式)、VS/TUN(隧道模式)。
原理:首先负载均衡器接收到客户的请求数据包时,根据调度算法决定将请求发送给哪个后端的真实服务器(RS)。然后负载均衡器就把客户端发送的请求数据包的目标IP地址及端口改成后端真实服务器的IP地址(RIP)。真实服务器响应完请求后,查看默认路由,把响应后的数据包发送给负载均衡器,负载均衡器在接收到响应包后,把包的源地址改成虚拟地址(VIP)然后发送回给客户端。
优点:集群中的服务器可以使用任何支持TCP/IP的操作系统,只要负载均衡器有一个合法的IP地址。
缺点:扩展性有限,当服务器节点增长过多时,由于所有的请求和应答都需要经过负载均衡器,因此负载均衡器将成为整个系统的瓶颈。
原理:首先负载均衡器接收到客户的请求数据包时,根据调度算法决定将请求发送给哪个后端的真实服务器(RS)。然后负载均衡器就把客户端发送的请求报文封装一层IP隧道(T-IP)转发到真实服务器(RS)。真实服务器响应完请求后,查看默认路由,把响应后的数据包直接发送给客户端,不需要经过负载均衡器。
优点:负载均衡器只负责将请求包分发给后端节点服务器,而RS将应答包直接发给用户。所以,减少了负载均衡器的大量数据流动,负载均衡器不再是系统的瓶颈,也能处理很巨大的请求量。
缺点:隧道模式的RS节点需要合法IP,这种方式需要所有的服务器支持“IP Tunneling”。
直接路由模式(VS-DR)
原理:首先负载均衡器接收到客户的请求数据包时,根据调度算法决定将请求发送给哪个后端的真实服务器(RS)。然后负载均衡器就把客户端发送的请求数据包的目标MAC地址改成后端真实服务器的MAC地址(R-MAC)。真实服务器响应完请求后,查看默认路由,把响应后的数据包直接发送给客户端,不需要经过负载均衡器。
优点:负载均衡器只负责将请求包分发给后端节点服务器,而RS将应答包直接发给用户。所以,减少了负载均衡器的大量数据流动,负载均衡器不再是系统的瓶颈,也能处理很巨大的请求量。
缺点:需要负载均衡器与真实服务器RS都有一块网卡连接到同一物理网段上,必须在同一个局域网环境。
LVS调度器用的调度方法基本分为两类:
固定调度算法:rr,wrr,dh,sh
代理服务器是一个位于客户端和原始(资源)服务器之间的服务器,为了从原始服务器取得内容,客户端向代理服务器发送一个请求并指定目标原始服务器,然后代理服务器向原始服务器转交请求并将获得的内容返回给客户端。
CAP理论指出了在分布式系统中需要满足的三个条件,主要包括:
CAP 理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,最多只能同时较好的满足两个。
Kubernetes是一个全新的基于容器技术的分布式系统支撑平台。是Google开源的容器集群管理系统(谷歌内部:Borg)。在Docker技术的基础上,为容器化的应用提供部署运行、资源调度、服务发现和动态伸缩等一系列完整功能,提高了大规模容器集群管理的便捷性。并且具有完备的集群管理能力,多层次的安全防护和准入机制、多租户应用支撑能力、透明的服务注册和发现机制、內建智能负载均衡器、强大的故障发现和自我修复能力、服务滚动升级和在线扩容能力、可扩展的资源自动调度机制以及多粒度的资源配额管理能力。
Docker 提供容器的生命周期管理和,Docker 镜像构建运行时容器。它的主要优点是将将软件/应用程序运行所需的设置和依赖项打包到一个容器中,从而实现了可移植性等优点。
Kubernetes 用于关联和编排在多个主机上运行的容器。
Minikube 是一种可以在本地轻松运行一个单节点 Kubernetes 群集的工具。
Kubectl 是一个命令行工具,可以使用该工具控制Kubernetes集群管理器,如检查群集资源,创建、删除和更新组件,查看应用程序。
Kubelet 是一个代理服务,它在每个节点上运行,并使从服务器与主服务器通信。
在集群管理方面,Kubernetes将集群中的机器划分为一个Master节点和一群工作节点Node。其中,在Master节点运行着集群管理相关的一组进程kube-apiserver、kube-controller-manager和kube-scheduler,这些进程实现了整个集群的资源管理、Pod调度、弹性伸缩、安全控制、系统监控和纠错等管理能力,并且都是全自动完成的。
Kubernetes作为一个完备的分布式系统支撑平台,其主要优势:
Kubernetes当前存在的缺点(不足)如下:
Kubernetes Master控制组件,调度管理整个系统(集群),包含如下组件:
Replication Controller用来管理Pod的副本,保证集群中存在指定数量的Pod副本。当定义了RC并提交至Kubernetes集群中之后,Master节点上的Controller Manager组件获悉,并同时巡检系统中当前存活的目标Pod,并确保目标Pod实例的数量刚好等于此RC的期望值,若存在过多的Pod副本在运行,系统会停止一些Pod,反之则自动创建一些Pod。
kube-proxy 运行在所有节点上,它监听 apiserver 中 service 和 endpoint 的变化情况,创建路由规则以提供服务 IP 和负载均衡功能。简单理解此进程是Service的透明代理兼负载均衡器,其核心功能是将到某个Service的访问请求转发到后端的多个Pod实例上。
看完本文希望读者能够了解到,Docker 的基本原理,Kubernetes 是怎么工作的, 对于前端 Kubernetes 有哪些优势与玩法。
Docker 和传统部署方式最大的不同在于,它将不会限制我们使用任何工具,任何语言,任何版本的 runtime,Docker 将我们的应用看成一个只提供网络服务的盒子(也即容器),Kubernetes 则是对这些盒子进行更多自动化的操作,自动创建,自动重启,自动扩容,自动调度,这个过程称之为容器编排。
在今天,容器编排技术给 Web 应用带来了巨大的灵活性,让我们轻松创建需要的程序对外提供服务。和传统的 IaaS 相比,不需要去关心云主机申请,云主机配置等信息,也不需考虑云主机故障导致的服务不可用,由 Kubernetes 的副本控制器帮我们完成云主机故障发生后容器迁移。
本篇文章和大家一起,回顾一下从 Docker 到 Kubernetes 的一些相关内容,最后再看看 Kubernetes 在前端领域有哪些优势和新玩法。
默认 Docker 存储位置为 /var/lib/docker,所有的镜像,容器,卷都会在这里,如果你使用了多硬盘,或者挂载了 SSD 不在 / 上,需要修改默认路径(graph)到合适位置,配置文件为 /etc/docker/, 服务器上收到的将是主机网卡的 ip。
Bridge 模式由于多了一层 NAT 转换所以效率会比 Host 模式差一些,但是能够很好的隔离外部网络环境,让容器独享 ip 且具有完整的端口空间。
上面四种网络模式是 Docker 自带的几种工作方式,但是部署 Kubernetes 需要所有的容器都工作在一个局域网中,所以在部署集群时需要多主机网络插件的支持。
多主机网络解决方案有 CNCF 推出的 CNI 规范以及 Docker 自带的 CNM 方案,但是目前大家用的最多的还是 CNI 规范,其中一种实现就是 Flannel。
Flannel 使用了报文嵌套技术来解决多主机网络互通问题,将原始报文进行封包,指定包ip为目的主机地址,等包到达主机后再进行拆包传送到对应的容器。下图显示 flannel 使用效率更高的 UDP 协议来在主机间传输报文。
目前主流跨主机通信目前常用的有三种,各有优缺,视场景选择:
在小规模场景下使用 Docker 可以一键部署应用确实很方便,达到了一键部署的目的,但是当出现需要在几百台主机上进行多副本部署,需要管理这么多主机的运行状态以及服务的故障时需要在其他主机重启服务,想象一下就知道手动的方式不是一种可取的方案,这时候就需要利用 Kubernetes 这种更高维度的编排工具来管理了。Kubernetes 简称 K8S, 简单说 K8S 就是抽象了硬件资源,将 N 台物理机或云主机抽象成一个资源池,容器的调度交给 K8S 就像亲妈一样照顾我们的容器,CPU 不够用就调度到一台足够使用的机器上,内存不满足要求就会寻找一台有足够内存的机器在上面创建对应的容器,服务因为某些原因挂了, K8S 还会帮我们自动迁移重启, 简直无微不至,至尊享受。我们作为开发者只关心自己的代码,应用的健康由 K8S 保证。
这里就不介绍具体的安装方式了,如果使用 Windows 或者 MacOS 可以直接使用 Docker Desktop 下的 Kubernetes 选项一键安装单主机集群,也可以使用 kind 工具 在本地模拟多集群 K8S。
K8S 调度的基本单位为 pod, 一个 pod 表示一个或多个容器。引用一本书里所说
之所以没有使用容器作为调度单位,是因为单一的容器没有构成服务的概念;例如 Web 应用做了前后端分例,需要一个 NodeJS 与 Tomcat 才能组成一个完整的服务,这样就需要部署两个容器来实现一个完整的服务,虽然也可以把他们都放到一个容器里,但这显然违反了一个容器即一个进程的核心思想 --《Service Mesh实战 - 用 istio软负载实现服务网格》
IaaS 就是 Infrastructure as a service, 所谓基础设施即服务,开发者想要上线一个新应用需要申请主机,ip, 域名等一系列资源,然后登录主机自行搭建所需环境,部署应用上线,这样不仅不利于大规模操作,而且还增加了出错的可能,运维或开发这常常自己写脚本自动化完成,遇到一些差异再手动修改脚本,非常痛苦。
K8S 则是将基础设施可编程化,由原来的人工申请改为一个清单文件自动创建,开发者只需要提交一份文件,K8S 将会自动为你分配创建所需的资源。对这些设施的 CRUD 都可以通过程序的方式自动化操作。
为了了解 K8S 的基础概念,下面来部署一个 Node SSR 应用:
初始化应用模板
创建好工程后给添加一个 Dockerfile 用来构建服务的镜像
这时候我们一共部署了两个版本的应用,而且都已经就绪状态。
当我们用其他的方式已经验证 test 版本服务可用时, 例如配另外一个 Service 用来测试(Good), 这时候可以下面一条指令切换当前的 Service 到 test 应用上。
执行完这条命令后,刷新页面可以看到如下。
通过切换 Service 的方式很轻松就实现了蓝绿发布的功能,而且是瞬间完成,因为 Service 是 K8S 里比较轻量的资源,不会和隔壁 Nginx 一样修改配置就要重启服务影响整个线上服务。当然实际生产环境会比演示更加严谨,可能有专门的平台以及审核人员进行每个操作的二次验证。
对于蓝绿, 灰度发布方式,使用 K8S 可以较为轻松地实现,让我们能够有更多的方式去验证想法。不过如果想实现更加高级的流量分配方案(例如A/B发布),需要复杂的流量管理策略 (鉴权,认证),就需要用到服务网格了。
Istio 是目前比较流行的服务网格框架,相比于 K8S 注重运行容器的管理, Istio 则是更注重容器之间组成的服务网格的流量传输。
下图是 Istio 捕获的官方示例的 bookinfo 微服务中服务的拓扑结构和一些数据指标。
使用 Istio 有两个明显的好处:
例如,我们可以轻松对的不同版本的 review 应用的 v1, v2, v3 版本进行动态权重分配。
不仅仅可以对流量权重分配,而且还可以制定一些A/B方案,例如根据 URL 是否匹配请求不同的版本应用,或者根据 Header 种下的 Cookie 进行用户的区分,从而请求不同的应用。当然,面对行业场景不同,Istio 还会诞生很多有趣的玩法。
不过缺点同样存在,Istio 实际上也是一个很复杂的系统,会对性能造成影响,而且会占用不小的系统资源。
K8S 是划时代的,随着未来的发展微服务化,云原生化将会是我们的应用的主要形式,对于前端而言 K8S 无疑会改变现有前端的开发方式和前端架构,让前端能够更迅速地扩展,更稳定地交付,应用之间的联系也会愈加紧密。沉寂已久的前端下一个三年相信将会是微服务架构的天下,K8S 作为微服务架构基础设施层也将会被越来越多的公司团队所重视。