早在半年前,公司开始推行容器化部署方案 AppOS,虽然发布界面过于极客,十分晦涩,不过仔细研究起来真的以为十分强大,容器化推行后,计算资源(CPU、内存)的利用率能够极大提升,下降服务器数量,从而节约技术成本。html
恰巧,若干个朋友所在创业公司最近也在尝试作微服务、容器化。架构上摒弃 SOA 的 dubbo,加入Spring Cloud阵营;部署方案上从过去的云服务器直接部署,升级到基于Kubernetes集群的容器化部署。docker
微服务这个概念从开发者的视角理解和SOA的差别不大,按照业务领域细粒度的拆分系统为若干服务,服务仅访问对应的数据库,按照项目组,服务独立开发,部署和迭代。服务之间的调用,经过RPC完成。数据库
用几张图,直观、简明扼要的阐述一下在Spring Cloud中相关的概念~api
上图中,展现了一个简单的系统,该系统有几个组件。bash
核心组件中涉及到服务消费方和服务提供方是经过RPC调用实现的,经过注册中心,服务消费方发现服务提供方,顺其天然就引入了客户端负载均衡和熔断相关的概念。消费方手持若干个提供方的实例,最简单的方式就是轮流调用,这就是客户端负载均衡了;若是一个服务提供方在过去一段时间内,故障比例达到阈值,那么能够暂时设置它为不可用,这就是熔断了。在Spring Cloud里提供了相关的内置组件,Ribbon和Hystrix。服务器
固然一切都不绝对,Spring Cloud的一个优点就是社区里有不少兼容性良好的备选方案,在 musical.ly 的Spring Cloud架构实践中提到:团队对框架自己作了较多的改造,替换了更友好的注册中心 Consul,采用了 gRPC 做为远程调用框架,用 Protobuf 做为序列化框架,替换了熔断和限流方案,集成了故障诊断和追踪功能等等,这些改造对业务是透明的。网络
采用Spring Cloud后,不一样业务能够拆分红不一样的项目,均可以单独部署。可使用Jenkins搭建一套简单的持续集成和持续交付方案。开发人员推代码到Git仓库后,会触发Jenkins的构建动做,进一步的还能够用Jenkins执行不一样环境下的发布脚本,固然脚本还能够执行备份,以及回滚的动做。架构
执行到这里,该体系方案就能够支持一个公司走很远了,那Kubernetes又有什么勇武之地。app
假设公司进一步发展,流量和业务都极具增多,会出现两个比较常见的问题负载均衡
理想的情况下,若是把运维手里的机器,都经过一个入口、统一管理起来,统一掌握集群的资源使用,须要对集群扩容或缩容的状况,只要增长或者回收服务器;须要对某个服务扩容缩容,只要简单的设置一下 replicas 数量。那该多好。(固然Kubernetes远远比这个功能多的多)
若是有过Docker的使用经验,就很容易理解K8S,最初使用docker的用途可能仅仅是用它搭建CI/CD,一条命令启动Gitlab,再一条命令启动一个Jenkins,一切超级简单。不少教程里,都会把若干微服务,放在一台服务器中的docker里运行,你会发现服务注册,服务发现都很简单。
可是,当容器运行在不一样的服务器上的时候,问题就来了,你甚至发现跨主机都容器之间都不能通讯。
K8S来源于谷歌,高富帅的出身,决定了刚出道就自带各类光环。市场占有率已经超过70%,已经成为了容器管理的主流工具。在实践中,由于大量的资料实践的背景都是GPE上的K8S集群,网络、存储等基础设施都由平台提供,一切都以为好简单,可是一旦尝试自建私有的K8S集群,却发现世界却充满敌意,甚至基本的网络插件都须要本身安装。
谷歌虽好,而且提供 $300 的代金券和一年试用期很厚道,可是谷歌不是你想访问就能够访问。幸亏阿里云也提供了Kubernetes集群服务,虽然价格比买ECS贵,不过相比一个运维团队的开销和各类不断踩坑感受也是划算的。
本文先介绍一些基础概念,而后介绍若是在阿里云的K8S集群上,部署Spring Cloud的微服务的实践。
集群是一组节点,这些节点能够是物理服务器或者虚拟机,之上安装了Kubernetes平台。下图展现这样的集群。注意该图为了强调核心概念有所简化。这里能够看到一个典型的Kubernetes架构图。
K8S中最基础的调度单位是Pod,它有网络,有存储。Pod里面运行着一个或者若干个docker容器。同一个Pod里的容器共享同一个网络命名空间,可使用localhost互相通讯。能够理解成Pod就是一台主机,docker容器是运行在主机上的进程。
咱们通常不会手动本身建立Pod,这样很难管理。利用Replication Controller,能够定义Pod运行内容,副本的个数等信息,它的升级版本是 ReplicaSet。如今已经建立了Pod的一些副本,那么在这些副本上如何均衡负载呢?咱们须要的是Service。
能够把一组Pod组成服务 Service,Service有一个虚拟的ClusterIP,服务访问能够经过ClusterIP做为统一请求入口,由于一个 Service 对应一组Pod,因此能够作到负载均衡。服务能够经过 NodePort,LoadBalancer的方式暴露对外服务。注意 type = LoadBalancer须要云服务平台提供基础的服务,自建的K8S集群默认是没有这个东西的。若是在阿里云上定义服务 type = LoadBalancer 后,你会发现,在管理后台的负载均衡页面,会增长一个负载均衡器
为了下降成本,笔者从阿里云采购了最低配置的K8S集群,包含 3个Master节点,还有2个Node节点。基本都是最低配置,天天成本30块钱。预先准备好了一份手脚架代码,包括几个基本项目
须要首先部署注册中心 eureka-server, 而后部署服务提供方 demo-service 和 消费方demo-provider,最后部署 api-gateway。
那么手里是代码,对面是K8S集群,怎么部署上去呢,答案是 镜像服务。
阿里的镜像服务是一个选择,固然也能够选择其它的,能够经过CI/CD方案,自动把构建后的镜像,Tag后,推到镜像服务提供的Registry中,而后就可使用了。
例如在镜像仓库中,有以下镜像:http://registry.cn-beijing.aliyuncs.com/tianming/demo-service:latest,经过书写YAML文件,定义RC
apiVersion: v1
kind: ReplicationController
metadata:
name: demo-service
spec:
replicas: 2
selector:
app: demo-service
template:
metadata:
labels:
app: demo-service
spec:
containers:
- name: demo-service
image: registry.cn-beijing.aliyuncs.com/tianming/demo-service:latest
ports:
- containerPort: 8081
黑色字体部分,将要发布服务的镜像了,这里设置了副本数是 2,经过执行下面的bash命令就能够建立 RC了
kubectl create -f demo-service-rc.yaml
而后能够执行
kubectl get pods
查看容器是否被正确建立,若是pod有状态异常,例如 Error 等能够经过describe命令查看建立失败的缘由,这个命令颇有用,能够帮咱们搞定不少问题。
kubectl describe pod demo-service-xxx
固然这还不够,咱们还须要定义服务,以及服务暴露的接口:
apiVersion: v1
kind: Service
metadata:
name: demo-service
spec:
type: LoadBalancer
ports:
- port: 8081
selector:
app: demo-service
这样服务就创建好,由于设置了 LoadBalancer,因此能够经过 external ip 在外部网络访问到。在 Prod 环境中,咱们不会这样作,通常只有 api-gateway 项目才会对外暴露访问端口。
按照这样的方式,依次部署其它服务,若是有一套可行的 CI/CD 方案,那么后续的发布,扩容缩容,都将易如反掌。
若是你是一个初创公司的CTO,没什么人手搭建集群,本身也没有精力学习K8S。在架构选型上,能够只用Spring Cloud的微服务组件,而后在云主机上部署;若是你有能力学习K8S,可是没有精力和人力搭建自建K8S集群,能够购买云厂商的集群服务,有了这套东西,至少不再用担忧将来扩容的痛苦了,而且做为架构的发展的相对终极形态,短时间内也不会有重构的需求,等将来有人力财力,再迁回自建的K8S集群,也是易如反掌。
整体来说,文章仍是有些浅了,实践中的坑和优化的选项,仍是要远远大于此文的。