文章目录
- 1、想法来源
- 2、初步设想
- 2.1 通过反向代理的方式访问后端Pod
- 3、架构设计
- 3.1 技术栈
- 3.2 架构设计
k8s编程operator系列:
k8s编程operator——(1) client-go基础部分
k8s编程operator——(2) client-go中的informer
k8s编程operator——(3) 自定义资源CRD
k8s编程operator——(4) kubebuilder & controller-runtime
k8s编程operator实战之云编码平台——①架构设计
k8s编程operator实战之云编码平台——②controller初步实现
1、想法来源
之前偶然接触到了腾讯的Cloud Studio平台,使用这个平台我们可以创建一个云上的IDE,我们在本地使用浏览器即可打开vscode来写代码。里面含有多种编程环境的模板,比如Java模板、Go模板等,如下图所示,使用Go模板我们可以创建一个含有Go环境的云空间,即开即用,无需我们自己配置环境,非常的方便。
启动后的工作空间如下图所示,而且当我们在云空间中启动一个http服务后,还可以在浏览器中访问到我们在云空间中启动的服务。
之后,我发现了更多这样的平台,包括CSDN的开发云、Github的codespaces等。
之后我就一直在想,这样一个平台是怎么样实现的?
2、初步设想
使用这些平台打开的IDE都是vscode
,而code-serve
r是vscode
的浏览器版本
,那么它们的实现肯定用到了code-server,关于code-server的搭建可以参考我之前的一篇博客:云vscode搭建–使用容器化部署
那么部署code-server除了使用Docker还可以使用Kubernetes,如果使用Docker显然是不太现实的,因为容器的管理是个问题,毕竟单台机器怎么能支持的了那么多容器呢?使用Kubernetes就可以管理这些运行着code-server的容器,解决了code-server的部署问题,接下来就是code-server的访问问题了,用户如何才能访问到自己的容器呢?
关于如何访问到Pod中的Code-Server,我想到了两种实现思路:
-
使用NodePort的方式做端口映射:
使用kubernetes的service,将运行用户code-server的Pod以NodePort
的方式暴露出来,用户可以通过服务器IP:port
的方式访问。优点:
实现简单缺点:
整个集群端口数量有限:65535,最多只能支撑6万多个用户同时使用 -
使用反向代理的方式:
运行在集群中的Pod可以在集群内通过PodIP来访问到,但是在外部访问不到,那么可以通过反向代理的方式来实现,在集群内运行反向代理服务器,根据用户信息获取用户的code-server运行的Pod的IP,然后将请求反向代理到Pod中。优点:
不会过多占用集群的端口,没有最大用户使用的限制,更加灵活缺点:
实现复杂
2.1 通过反向代理的方式访问后端Pod
说到反向代理,那我们通常能想到的软件就是nginx,nginx的性能非常强悍。但是通常我们在使用nginx做反向的代理的时候,后端IP都是写死的。一般用来做反向代理和负载均衡时,对于一个服务,后端的服务器都是一样的,根据负载均衡策略选择一个服务,如下所示:
但是我们现在的一个思路是,将不同的用户代理到属于他的工作空间:
那么我们就需要一个动态的反向代理。如果用户在创建用户空间时,我们就在nginx的配置文件中添加一条规则,然后重启nginx,是可以实现的。但是这样的方式显然很不合理,虽然nginx提供了热加载的功能,但是它本质也是启动了新的进程来替换旧的进程,所以频繁的重启nginx显示是不行的。
后来,我查询了很多资料包括通过网页的方式DEBUG其它云平台,我发现他们应该是通过openresty来实现的。
openresty是国人的一个项目,它是基于nginx的,使用openresty我们可以通过lua脚本来进行动态的反向代理。
实现的思路如下:
在为用户创建Pod时,获取到Pod的Ip地址。
然后生成UID,将UID和IP以键值对的方式存储到redis中。
在访问工作空间时,在路径中带上UID。
nginx在获取到请求后,使用lua脚本从路径中取出UID,然后从redis中查询出Pod的IP。
最后,将用户请求代理到Pod中。
那么如何针对不同的用户访问到自己的工作空间的问题也解决了,如果访问用户在工作空间中启动的服务也可以通过这样的方式来解决。
3、架构设计
3.1 技术栈
整个云编码平台的技术栈为:golang + gin + grpc + mysql + redis + kubebuilder + openresty + code-server + vue
整个平台的后端语言选择为go语言
- web开发使用的框架为gin
- kubebuilder用来开发k8s的controller
- grcp实现web调用controller来对Pod进行CRUD
- openresty用来做反向代理
- vue用来写前端页面
- mysql用来存储用户数据
- redis用来存储用户启动的工作空间信息
- code-server作为IDE
云编码平台的名称就为:Cloud Code
3.2 架构设计
Cloud Code的架构设计如下:
用户从创建工作空间到访问工作空间的流程如下:
- 用户访问web服务器来创建工作空间
- web服务器生成工作空间Space的信息,包括工作空间的名称、所属用户、创建使用的模板、规格(可以使用的资源大小,CPU、内存、存储)、SID(space id)
- 然后调用Cloud Code Controller的rpc来创建Pod
- Cloud Code Controller是用kubebuilder编写的一个K8S controller,用来实现对工作空间的Pod的CRUD以及状态的维护。
- 创建Pod后,获取Pod的IP,将SID(UID)以及Pod IP保存到redis中
- 用户访问工作空间
- 首先到openresty中,openresty根据url中的UID从redis中查询Pod的IP地址
- 使用Pod的IP将请求代理到用户的Code-Server中
要实现的几个程序如下:
Cloud Code Controller:
用来实现工作空间也就是Code-Server的Pod的CRUD,以及状态的维护。
Openresty lua动态反向代理脚本:
将用户的请求反向代理到其创建的Code-Server中。
Web服务器:
云编码平台的Web后端
前端页面:
页面展示